Updated ImGuizmo.
This commit is contained in:
parent
a0975b5f41
commit
54e183806b
27
3rdparty/dear-imgui/widgets/gizmo.h
vendored
27
3rdparty/dear-imgui/widgets/gizmo.h
vendored
@ -1,5 +1,5 @@
|
||||
// https://github.com/CedricGuillemet/ImGuizmo
|
||||
// v 1.04 WIP
|
||||
// v 1.61 WIP
|
||||
//
|
||||
// The MIT License(MIT)
|
||||
//
|
||||
@ -105,18 +105,21 @@ void EditTransform(const Camera& camera, matrix_t& matrix)
|
||||
|
||||
namespace ImGuizmo
|
||||
{
|
||||
// call inside your own window and before Manipulate() in order to draw gizmo to that window.
|
||||
IMGUI_API void SetDrawlist();
|
||||
|
||||
// call BeginFrame right after ImGui_XXXX_NewFrame();
|
||||
void BeginFrame();
|
||||
IMGUI_API void BeginFrame();
|
||||
|
||||
// return true if mouse cursor is over any gizmo control (axis, plan or screen component)
|
||||
bool IsOver();
|
||||
IMGUI_API bool IsOver();
|
||||
|
||||
// return true if mouse IsOver or if the gizmo is in moving state
|
||||
bool IsUsing();
|
||||
IMGUI_API bool IsUsing();
|
||||
|
||||
// enable/disable the gizmo. Stay in the state until next call to Enable.
|
||||
// gizmo is rendered with gray half transparent color when disabled
|
||||
void Enable(bool enable);
|
||||
IMGUI_API void Enable(bool enable);
|
||||
|
||||
// helper functions for manualy editing translation/rotation/scale with an input float
|
||||
// translation, rotation and scale float points to 3 floats each
|
||||
@ -130,13 +133,16 @@ namespace ImGuizmo
|
||||
// ImGuizmo::RecomposeMatrixFromComponents(matrixTranslation, matrixRotation, matrixScale, gizmoMatrix.m16);
|
||||
//
|
||||
// These functions have some numerical stability issues for now. Use with caution.
|
||||
void DecomposeMatrixToComponents(const float *matrix, float *translation, float *rotation, float *scale);
|
||||
void RecomposeMatrixFromComponents(const float *translation, const float *rotation, const float *scale, float *matrix);
|
||||
IMGUI_API void DecomposeMatrixToComponents(const float *matrix, float *translation, float *rotation, float *scale);
|
||||
IMGUI_API void RecomposeMatrixFromComponents(const float *translation, const float *rotation, const float *scale, float *matrix);
|
||||
|
||||
void SetRect(float x, float y, float width, float height);
|
||||
IMGUI_API void SetRect(float x, float y, float width, float height);
|
||||
// default is false
|
||||
IMGUI_API void SetOrthographic(bool isOrthographic);
|
||||
|
||||
// Render a cube with face color corresponding to face normal. Usefull for debug/tests
|
||||
void DrawCube(const float *view, const float *projection, float *matrix);
|
||||
IMGUI_API void DrawCube(const float *view, const float *projection, const float *matrix);
|
||||
IMGUI_API void DrawGrid(const float *view, const float *projection, const float *matrix, const float gridSize);
|
||||
|
||||
// call it when you want a gizmo
|
||||
// Needs view and projection matrices.
|
||||
@ -147,6 +153,7 @@ namespace ImGuizmo
|
||||
TRANSLATE,
|
||||
ROTATE,
|
||||
SCALE,
|
||||
BOUNDS,
|
||||
};
|
||||
|
||||
enum MODE
|
||||
@ -155,5 +162,5 @@ namespace ImGuizmo
|
||||
WORLD
|
||||
};
|
||||
|
||||
void Manipulate(const float *view, const float *projection, OPERATION operation, MODE mode, float *matrix, float *deltaMatrix = 0, float *snap = 0, float *localBounds = NULL, float *boundsSnap = NULL);
|
||||
IMGUI_API void Manipulate(const float *view, const float *projection, OPERATION operation, MODE mode, float *matrix, float *deltaMatrix = 0, float *snap = 0, float *localBounds = NULL, float *boundsSnap = NULL);
|
||||
};
|
||||
|
317
3rdparty/dear-imgui/widgets/gizmo.inl
vendored
317
3rdparty/dear-imgui/widgets/gizmo.inl
vendored
@ -30,7 +30,7 @@ namespace ImGuizmo
|
||||
static const float ZPI = 3.14159265358979323846f;
|
||||
static const float RAD2DEG = (180.f / ZPI);
|
||||
static const float DEG2RAD = (ZPI / 180.f);
|
||||
|
||||
static const float gGizmoSizeClipSpace = 0.1f;
|
||||
const float screenRotateSize = 0.06f;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -140,6 +140,7 @@ namespace ImGuizmo
|
||||
};
|
||||
|
||||
vec_t makeVect(float _x, float _y, float _z = 0.f, float _w = 0.f) { vec_t res; res.x = _x; res.y = _y; res.z = _z; res.w = _w; return res; }
|
||||
vec_t makeVect(ImVec2 v) { vec_t res; res.x = v.x; res.y = v.y; res.z = 0.f; res.w = 0.f; return res; }
|
||||
vec_t vec_t::operator * (float f) const { return makeVect(x * f, y * f, z * f, w *f); }
|
||||
vec_t vec_t::operator - () const { return makeVect(-x, -y, -z, -w); }
|
||||
vec_t vec_t::operator - (const vec_t& v) const { return makeVect(x - v.x, y - v.y, z - v.z, w - v.w); }
|
||||
@ -477,9 +478,9 @@ namespace ImGuizmo
|
||||
MOVE_X,
|
||||
MOVE_Y,
|
||||
MOVE_Z,
|
||||
MOVE_XY,
|
||||
MOVE_XZ,
|
||||
MOVE_YZ,
|
||||
MOVE_ZX,
|
||||
MOVE_XY,
|
||||
MOVE_SCREEN,
|
||||
ROTATE_X,
|
||||
ROTATE_Y,
|
||||
@ -488,8 +489,7 @@ namespace ImGuizmo
|
||||
SCALE_X,
|
||||
SCALE_Y,
|
||||
SCALE_Z,
|
||||
SCALE_XYZ,
|
||||
BOUNDS
|
||||
SCALE_XYZ
|
||||
};
|
||||
|
||||
struct Context
|
||||
@ -569,6 +569,9 @@ namespace ImGuizmo
|
||||
float mHeight = 0.f;
|
||||
float mXMax = 0.f;
|
||||
float mYMax = 0.f;
|
||||
float mDisplayRatio = 1.f;
|
||||
|
||||
bool mIsOrthographic = false;
|
||||
};
|
||||
|
||||
static Context gContext;
|
||||
@ -580,15 +583,16 @@ namespace ImGuizmo
|
||||
static const ImU32 directionColor[3] = { 0xFF0000AA, 0xFF00AA00, 0xFFAA0000 };
|
||||
|
||||
// Alpha: 100%: FF, 87%: DE, 70%: B3, 54%: 8A, 50%: 80, 38%: 61, 12%: 1F
|
||||
static const ImU32 planeBorderColor[3] = { 0xFFAA0000, 0xFF0000AA, 0xFF00AA00 };
|
||||
static const ImU32 planeColor[3] = { 0x610000AA, 0x6100AA00, 0x61AA0000 };
|
||||
static const ImU32 selectionColor = 0x8A1080FF;
|
||||
static const ImU32 inactiveColor = 0x99999999;
|
||||
static const ImU32 translationLineColor = 0xAAAAAAAA;
|
||||
static const char *translationInfoMask[] = { "X : %5.3f", "Y : %5.3f", "Z : %5.3f", "X : %5.3f Y : %5.3f", "Y : %5.3f Z : %5.3f", "X : %5.3f Z : %5.3f", "X : %5.3f Y : %5.3f Z : %5.3f" };
|
||||
static const char *translationInfoMask[] = { "X : %5.3f", "Y : %5.3f", "Z : %5.3f",
|
||||
"Y : %5.3f Z : %5.3f", "X : %5.3f Z : %5.3f", "X : %5.3f Y : %5.3f",
|
||||
"X : %5.3f Y : %5.3f Z : %5.3f" };
|
||||
static const char *scaleInfoMask[] = { "X : %5.2f", "Y : %5.2f", "Z : %5.2f", "XYZ : %5.2f" };
|
||||
static const char *rotationInfoMask[] = { "X : %5.2f deg %5.2f rad", "Y : %5.2f deg %5.2f rad", "Z : %5.2f deg %5.2f rad", "Screen : %5.2f deg %5.2f rad" };
|
||||
static const int translationInfoIndex[] = { 0,0,0, 1,0,0, 2,0,0, 0,1,0, 1,2,0, 0,2,1, 0,1,2 };
|
||||
static const int translationInfoIndex[] = { 0,0,0, 1,0,0, 2,0,0, 1,2,0, 0,2,0, 0,1,0, 0,1,2 };
|
||||
static const float quadMin = 0.5f;
|
||||
static const float quadMax = 0.8f;
|
||||
static const float quadUV[8] = { quadMin, quadMin, quadMin, quadMax, quadMax, quadMax, quadMax, quadMin };
|
||||
@ -633,6 +637,62 @@ namespace ImGuizmo
|
||||
rayDir = Normalized(rayEnd - rayOrigin);
|
||||
}
|
||||
|
||||
static float GetSegmentLengthClipSpace(const vec_t& start, const vec_t& end)
|
||||
{
|
||||
vec_t startOfSegment = start;
|
||||
startOfSegment.TransformPoint(gContext.mMVP);
|
||||
if (fabsf(startOfSegment.w)> FLT_EPSILON) // check for axis aligned with camera direction
|
||||
startOfSegment *= 1.f / startOfSegment.w;
|
||||
|
||||
vec_t endOfSegment = end;
|
||||
endOfSegment.TransformPoint(gContext.mMVP);
|
||||
if (fabsf(endOfSegment.w)> FLT_EPSILON) // check for axis aligned with camera direction
|
||||
endOfSegment *= 1.f / endOfSegment.w;
|
||||
|
||||
vec_t clipSpaceAxis = endOfSegment - startOfSegment;
|
||||
clipSpaceAxis.y /= gContext.mDisplayRatio;
|
||||
float segmentLengthInClipSpace = sqrtf(clipSpaceAxis.x*clipSpaceAxis.x + clipSpaceAxis.y*clipSpaceAxis.y);
|
||||
return segmentLengthInClipSpace;
|
||||
}
|
||||
|
||||
static float GetParallelogram(const vec_t& ptO, const vec_t& ptA, const vec_t& ptB)
|
||||
{
|
||||
vec_t pts[] = { ptO, ptA, ptB };
|
||||
for (unsigned int i = 0; i < 3; i++)
|
||||
{
|
||||
pts[i].TransformPoint(gContext.mMVP);
|
||||
if (fabsf(pts[i].w)> FLT_EPSILON) // check for axis aligned with camera direction
|
||||
pts[i] *= 1.f / pts[i].w;
|
||||
}
|
||||
vec_t segA = pts[1] - pts[0];
|
||||
vec_t segB = pts[2] - pts[0];
|
||||
segA.y /= gContext.mDisplayRatio;
|
||||
segB.y /= gContext.mDisplayRatio;
|
||||
vec_t segAOrtho = makeVect(-segA.y, segA.x);
|
||||
segAOrtho.Normalize();
|
||||
float dt = segAOrtho.Dot3(segB);
|
||||
float surface = sqrtf(segA.x*segA.x + segA.y*segA.y) * fabsf(dt);
|
||||
return surface;
|
||||
}
|
||||
|
||||
inline vec_t PointOnSegment(const vec_t & point, const vec_t & vertPos1, const vec_t & vertPos2)
|
||||
{
|
||||
vec_t c = point - vertPos1;
|
||||
vec_t V;
|
||||
|
||||
V.Normalize(vertPos2 - vertPos1);
|
||||
float d = (vertPos2 - vertPos1).Length();
|
||||
float t = V.Dot3(c);
|
||||
|
||||
if (t < 0.f)
|
||||
return vertPos1;
|
||||
|
||||
if (t > d)
|
||||
return vertPos2;
|
||||
|
||||
return vertPos1 + V * t;
|
||||
}
|
||||
|
||||
static float IntersectRayPlane(const vec_t & rOrigin, const vec_t& rVector, const vec_t& plan)
|
||||
{
|
||||
float numer = plan.Dot3(rOrigin) - plan.w;
|
||||
@ -657,6 +717,12 @@ namespace ImGuizmo
|
||||
gContext.mHeight = height;
|
||||
gContext.mXMax = gContext.mX + gContext.mWidth;
|
||||
gContext.mYMax = gContext.mY + gContext.mXMax;
|
||||
gContext.mDisplayRatio = width / height;
|
||||
}
|
||||
|
||||
IMGUI_API void SetOrthographic(bool isOrthographic)
|
||||
{
|
||||
gContext.mIsOrthographic = isOrthographic;
|
||||
}
|
||||
|
||||
void SetDrawlist()
|
||||
@ -734,7 +800,16 @@ namespace ImGuizmo
|
||||
gContext.mCameraEye = viewInverse.v.position;
|
||||
gContext.mCameraRight = viewInverse.v.right;
|
||||
gContext.mCameraUp = viewInverse.v.up;
|
||||
gContext.mScreenFactor = 0.1f * GetUniform(gContext.mModel.v.position, gContext.mViewProjection);
|
||||
|
||||
// compute scale from the size of camera right vector projected on screen at the matrix position
|
||||
vec_t pointRight = viewInverse.v.right;
|
||||
pointRight.TransformPoint(gContext.mViewProjection);
|
||||
gContext.mScreenFactor = gGizmoSizeClipSpace / (pointRight.x / pointRight.w - gContext.mMVP.v.position.x / gContext.mMVP.v.position.w);
|
||||
|
||||
vec_t rightViewInverse = viewInverse.v.right;
|
||||
rightViewInverse.TransformVector(gContext.mModelInverse);
|
||||
float rightLength = GetSegmentLengthClipSpace(makeVect(0.f, 0.f), rightViewInverse);
|
||||
gContext.mScreenFactor = gGizmoSizeClipSpace / rightLength;
|
||||
|
||||
ImVec2 centerSSpace = worldToPos(makeVect(0.f, 0.f), gContext.mMVP);
|
||||
gContext.mScreenSquareCenter = centerSSpace;
|
||||
@ -754,9 +829,8 @@ namespace ImGuizmo
|
||||
colors[0] = (type == MOVE_SCREEN) ? selectionColor : 0xFFFFFFFF;
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
int colorPlaneIndex = (i + 2) % 3;
|
||||
colors[i + 1] = (type == (int)(MOVE_X + i)) ? selectionColor : directionColor[i];
|
||||
colors[i + 4] = (type == (int)(MOVE_XY + i)) ? selectionColor : planeColor[colorPlaneIndex];
|
||||
colors[i + 4] = (type == (int)(MOVE_YZ + i)) ? selectionColor : planeColor[i];
|
||||
colors[i + 4] = (type == MOVE_SCREEN) ? selectionColor : colors[i + 4];
|
||||
}
|
||||
break;
|
||||
@ -770,6 +844,8 @@ namespace ImGuizmo
|
||||
for (int i = 0; i < 3; i++)
|
||||
colors[i + 1] = (type == (int)(SCALE_X + i)) ? selectionColor : directionColor[i];
|
||||
break;
|
||||
case BOUNDS:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -779,11 +855,11 @@ namespace ImGuizmo
|
||||
}
|
||||
}
|
||||
|
||||
static void ComputeTripodAxisAndVisibility(int axisIndex, vec_t& dirPlaneX, vec_t& dirPlaneY, bool& belowAxisLimit, bool& belowPlaneLimit)
|
||||
static void ComputeTripodAxisAndVisibility(int axisIndex, vec_t& dirAxis, vec_t& dirPlaneX, vec_t& dirPlaneY, bool& belowAxisLimit, bool& belowPlaneLimit)
|
||||
{
|
||||
const int planNormal = (axisIndex + 2) % 3;
|
||||
dirPlaneX = directionUnary[axisIndex];
|
||||
dirPlaneY = directionUnary[(axisIndex + 1) % 3];
|
||||
dirAxis = directionUnary[axisIndex];
|
||||
dirPlaneX = directionUnary[(axisIndex + 1) % 3];
|
||||
dirPlaneY = directionUnary[(axisIndex + 2) % 3];
|
||||
|
||||
if (gContext.mbUsing)
|
||||
{
|
||||
@ -796,34 +872,34 @@ namespace ImGuizmo
|
||||
}
|
||||
else
|
||||
{
|
||||
vec_t dirPlaneNormalWorld;
|
||||
dirPlaneNormalWorld.TransformVector(directionUnary[planNormal], gContext.mModel);
|
||||
dirPlaneNormalWorld.Normalize();
|
||||
// new method
|
||||
float lenDir = GetSegmentLengthClipSpace(makeVect(0.f, 0.f, 0.f), dirAxis);
|
||||
float lenDirMinus = GetSegmentLengthClipSpace(makeVect(0.f, 0.f, 0.f), -dirAxis);
|
||||
|
||||
vec_t dirPlaneXWorld(dirPlaneX);
|
||||
dirPlaneXWorld.TransformVector(gContext.mModel);
|
||||
dirPlaneXWorld.Normalize();
|
||||
float lenDirPlaneX = GetSegmentLengthClipSpace(makeVect(0.f, 0.f, 0.f), dirPlaneX);
|
||||
float lenDirMinusPlaneX = GetSegmentLengthClipSpace(makeVect(0.f, 0.f, 0.f), -dirPlaneX);
|
||||
|
||||
vec_t dirPlaneYWorld(dirPlaneY);
|
||||
dirPlaneYWorld.TransformVector(gContext.mModel);
|
||||
dirPlaneYWorld.Normalize();
|
||||
float lenDirPlaneY = GetSegmentLengthClipSpace(makeVect(0.f, 0.f, 0.f), dirPlaneY);
|
||||
float lenDirMinusPlaneY = GetSegmentLengthClipSpace(makeVect(0.f, 0.f, 0.f), -dirPlaneY);
|
||||
|
||||
vec_t cameraEyeToGizmo = Normalized(gContext.mModel.v.position - gContext.mCameraEye);
|
||||
float dotCameraDirX = cameraEyeToGizmo.Dot3(dirPlaneXWorld);
|
||||
float dotCameraDirY = cameraEyeToGizmo.Dot3(dirPlaneYWorld);
|
||||
|
||||
// compute factor values
|
||||
float mulAxisX = (dotCameraDirX > 0.f) ? -1.f : 1.f;
|
||||
float mulAxisY = (dotCameraDirY > 0.f) ? -1.f : 1.f;
|
||||
float mulAxis = (lenDir < lenDirMinus && fabsf(lenDir - lenDirMinus) > FLT_EPSILON) ? -1.f : 1.f;
|
||||
float mulAxisX = (lenDirPlaneX < lenDirMinusPlaneX && fabsf(lenDirPlaneX - lenDirMinusPlaneX) > FLT_EPSILON) ? -1.f : 1.f;
|
||||
float mulAxisY = (lenDirPlaneY < lenDirMinusPlaneY && fabsf(lenDirPlaneY - lenDirMinusPlaneY) > FLT_EPSILON) ? -1.f : 1.f;
|
||||
dirAxis *= mulAxis;
|
||||
dirPlaneX *= mulAxisX;
|
||||
dirPlaneY *= mulAxisY;
|
||||
|
||||
belowAxisLimit = fabsf(dotCameraDirX) < angleLimit;
|
||||
belowPlaneLimit = (fabsf(cameraEyeToGizmo.Dot3(dirPlaneNormalWorld)) > planeLimit);
|
||||
// for axis
|
||||
float axisLengthInClipSpace = GetSegmentLengthClipSpace(makeVect(0.f, 0.f, 0.f), dirAxis * gContext.mScreenFactor);
|
||||
|
||||
float paraSurf = GetParallelogram(makeVect(0.f, 0.f, 0.f), dirPlaneX * gContext.mScreenFactor, dirPlaneY * gContext.mScreenFactor);
|
||||
belowPlaneLimit = (paraSurf > 0.0025f);
|
||||
belowAxisLimit = (axisLengthInClipSpace > 0.02f);
|
||||
|
||||
// and store values
|
||||
gContext.mAxisFactor[axisIndex] = mulAxisX;
|
||||
gContext.mAxisFactor[axisIndex] = mulAxis;
|
||||
gContext.mAxisFactor[(axisIndex + 1) % 3] = mulAxisY;
|
||||
gContext.mAxisFactor[(axisIndex + 2) % 3] = mulAxisY;
|
||||
gContext.mBelowAxisLimit[axisIndex] = belowAxisLimit;
|
||||
gContext.mBelowPlaneLimit[axisIndex] = belowPlaneLimit;
|
||||
}
|
||||
@ -870,10 +946,22 @@ namespace ImGuizmo
|
||||
ImU32 colors[7];
|
||||
ComputeColors(colors, type, ROTATE);
|
||||
|
||||
vec_t cameraToModelNormalized = Normalized(gContext.mModel.v.position - gContext.mCameraEye);
|
||||
vec_t cameraToModelNormalized;
|
||||
if (gContext.mIsOrthographic)
|
||||
{
|
||||
matrix_t viewInverse;
|
||||
viewInverse.Inverse(*(matrix_t*)&gContext.mViewMat);
|
||||
cameraToModelNormalized = viewInverse.v.dir;
|
||||
}
|
||||
else
|
||||
{
|
||||
cameraToModelNormalized = Normalized(gContext.mModel.v.position - gContext.mCameraEye);
|
||||
}
|
||||
|
||||
cameraToModelNormalized.TransformVector(gContext.mModelInverse);
|
||||
|
||||
gContext.mRadiusSquareCenter = screenRotateSize * gContext.mHeight;
|
||||
|
||||
for (int axis = 0; axis < 3; axis++)
|
||||
{
|
||||
ImVec2 circlePos[halfCircleSegmentCount];
|
||||
@ -948,16 +1036,16 @@ namespace ImGuizmo
|
||||
|
||||
for (unsigned int i = 0; i < 3; i++)
|
||||
{
|
||||
vec_t dirPlaneX, dirPlaneY;
|
||||
vec_t dirPlaneX, dirPlaneY, dirAxis;
|
||||
bool belowAxisLimit, belowPlaneLimit;
|
||||
ComputeTripodAxisAndVisibility(i, dirPlaneX, dirPlaneY, belowAxisLimit, belowPlaneLimit);
|
||||
ComputeTripodAxisAndVisibility(i, dirAxis, dirPlaneX, dirPlaneY, belowAxisLimit, belowPlaneLimit);
|
||||
|
||||
// draw axis
|
||||
if (belowAxisLimit)
|
||||
{
|
||||
ImVec2 baseSSpace = worldToPos(dirPlaneX * 0.1f * gContext.mScreenFactor, gContext.mMVP);
|
||||
ImVec2 worldDirSSpaceNoScale = worldToPos(dirPlaneX * gContext.mScreenFactor, gContext.mMVP);
|
||||
ImVec2 worldDirSSpace = worldToPos((dirPlaneX * scaleDisplay[i]) * gContext.mScreenFactor, gContext.mMVP);
|
||||
ImVec2 baseSSpace = worldToPos(dirAxis * 0.1f * gContext.mScreenFactor, gContext.mMVP);
|
||||
ImVec2 worldDirSSpaceNoScale = worldToPos(dirAxis * gContext.mScreenFactor, gContext.mMVP);
|
||||
ImVec2 worldDirSSpace = worldToPos((dirAxis * scaleDisplay[i]) * gContext.mScreenFactor, gContext.mMVP);
|
||||
|
||||
if (gContext.mbUsing)
|
||||
{
|
||||
@ -969,7 +1057,7 @@ namespace ImGuizmo
|
||||
drawList->AddCircleFilled(worldDirSSpace, 6.f, colors[i + 1]);
|
||||
|
||||
if (gContext.mAxisFactor[i] < 0.f)
|
||||
DrawHatchedAxis(dirPlaneX * scaleDisplay[i]);
|
||||
DrawHatchedAxis(dirAxis * scaleDisplay[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1014,14 +1102,14 @@ namespace ImGuizmo
|
||||
bool belowPlaneLimit = false;
|
||||
for (unsigned int i = 0; i < 3; ++i)
|
||||
{
|
||||
vec_t dirPlaneX, dirPlaneY;
|
||||
ComputeTripodAxisAndVisibility(i, dirPlaneX, dirPlaneY, belowAxisLimit, belowPlaneLimit);
|
||||
vec_t dirPlaneX, dirPlaneY, dirAxis;
|
||||
ComputeTripodAxisAndVisibility(i, dirAxis, dirPlaneX, dirPlaneY, belowAxisLimit, belowPlaneLimit);
|
||||
|
||||
// draw axis
|
||||
if (belowAxisLimit)
|
||||
{
|
||||
ImVec2 baseSSpace = worldToPos(dirPlaneX * 0.1f * gContext.mScreenFactor, gContext.mMVP);
|
||||
ImVec2 worldDirSSpace = worldToPos(dirPlaneX * gContext.mScreenFactor, gContext.mMVP);
|
||||
ImVec2 baseSSpace = worldToPos(dirAxis * 0.1f * gContext.mScreenFactor, gContext.mMVP);
|
||||
ImVec2 worldDirSSpace = worldToPos(dirAxis * gContext.mScreenFactor, gContext.mMVP);
|
||||
|
||||
drawList->AddLine(baseSSpace, worldDirSSpace, colors[i + 1], 3.f);
|
||||
|
||||
@ -1038,7 +1126,7 @@ namespace ImGuizmo
|
||||
// Arrow head end
|
||||
|
||||
if (gContext.mAxisFactor[i] < 0.f)
|
||||
DrawHatchedAxis(dirPlaneX);
|
||||
DrawHatchedAxis(dirAxis);
|
||||
}
|
||||
|
||||
// draw plane
|
||||
@ -1050,7 +1138,7 @@ namespace ImGuizmo
|
||||
vec_t cornerWorldPos = (dirPlaneX * quadUV[j * 2] + dirPlaneY * quadUV[j * 2 + 1]) * gContext.mScreenFactor;
|
||||
screenQuadPts[j] = worldToPos(cornerWorldPos, gContext.mMVP);
|
||||
}
|
||||
drawList->AddPolyline(screenQuadPts, 4, planeBorderColor[i], true, 1.0f);
|
||||
drawList->AddPolyline(screenQuadPts, 4, directionColor[i], true, 1.0f);
|
||||
drawList->AddConvexPolyFilled(screenQuadPts, 4, colors[i + 4]);
|
||||
}
|
||||
}
|
||||
@ -1084,7 +1172,7 @@ namespace ImGuizmo
|
||||
return false;
|
||||
}
|
||||
|
||||
static void HandleAndDrawLocalBounds(float *bounds, matrix_t *matrix, float *snapValues)
|
||||
static void HandleAndDrawLocalBounds(float *bounds, matrix_t *matrix, float *snapValues, OPERATION operation)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImDrawList* drawList = gContext.mDrawList;
|
||||
@ -1188,7 +1276,8 @@ namespace ImGuizmo
|
||||
float t2 = (float)j * stepLength + stepLength * 0.5f;
|
||||
ImVec2 worldBoundSS1 = ImLerp(worldBound1, worldBound2, ImVec2(t1, t1));
|
||||
ImVec2 worldBoundSS2 = ImLerp(worldBound1, worldBound2, ImVec2(t2, t2));
|
||||
drawList->AddLine(worldBoundSS1, worldBoundSS2, 0xAAAAAA + anchorAlpha, 3.f);
|
||||
//drawList->AddLine(worldBoundSS1, worldBoundSS2, 0x000000 + anchorAlpha, 3.f);
|
||||
drawList->AddLine(worldBoundSS1, worldBoundSS2, 0xAAAAAA + anchorAlpha, 2.f);
|
||||
}
|
||||
vec_t midPoint = (aabb[i] + aabb[(i + 1) % 4] ) * 0.5f;
|
||||
ImVec2 midBound = worldToPos(midPoint, boundsMVP);
|
||||
@ -1197,12 +1286,31 @@ namespace ImGuizmo
|
||||
bool overBigAnchor = ImLengthSqr(worldBound1 - io.MousePos) <= (AnchorBigRadius*AnchorBigRadius);
|
||||
bool overSmallAnchor = ImLengthSqr(midBound - io.MousePos) <= (AnchorBigRadius*AnchorBigRadius);
|
||||
|
||||
int type = NONE;
|
||||
vec_t gizmoHitProportion;
|
||||
|
||||
switch (operation)
|
||||
{
|
||||
case TRANSLATE: type = GetMoveType(&gizmoHitProportion); break;
|
||||
case ROTATE: type = GetRotateType(); break;
|
||||
case SCALE: type = GetScaleType(); break;
|
||||
case BOUNDS: break;
|
||||
}
|
||||
if (type != NONE)
|
||||
{
|
||||
overBigAnchor = false;
|
||||
overSmallAnchor = false;
|
||||
}
|
||||
|
||||
|
||||
unsigned int bigAnchorColor = overBigAnchor ? selectionColor : (0xAAAAAA + anchorAlpha);
|
||||
unsigned int smallAnchorColor = overSmallAnchor ? selectionColor : (0xAAAAAA + anchorAlpha);
|
||||
|
||||
drawList->AddCircleFilled(worldBound1, AnchorBigRadius, bigAnchorColor);
|
||||
drawList->AddCircleFilled(midBound, AnchorSmallRadius, smallAnchorColor);
|
||||
drawList->AddCircleFilled(worldBound1, AnchorBigRadius, 0xFF000000);
|
||||
drawList->AddCircleFilled(worldBound1, AnchorBigRadius-1.2f, bigAnchorColor);
|
||||
|
||||
drawList->AddCircleFilled(midBound, AnchorSmallRadius, 0xFF000000);
|
||||
drawList->AddCircleFilled(midBound, AnchorSmallRadius-1.2f, smallAnchorColor);
|
||||
int oppositeIndex = (i + 2) % 4;
|
||||
// big anchor on corners
|
||||
if (!gContext.mbUsingBounds && gContext.mbEnable && overBigAnchor && CanActivate())
|
||||
@ -1319,24 +1427,23 @@ namespace ImGuizmo
|
||||
io.MousePos.y >= gContext.mScreenSquareMin.y && io.MousePos.y <= gContext.mScreenSquareMax.y)
|
||||
type = SCALE_XYZ;
|
||||
|
||||
const vec_t direction[3] = { gContext.mModel.v.right, gContext.mModel.v.up, gContext.mModel.v.dir };
|
||||
// compute
|
||||
for (unsigned int i = 0; i < 3 && type == NONE; i++)
|
||||
{
|
||||
vec_t dirPlaneX, dirPlaneY;
|
||||
vec_t dirPlaneX, dirPlaneY, dirAxis;
|
||||
bool belowAxisLimit, belowPlaneLimit;
|
||||
ComputeTripodAxisAndVisibility(i, dirPlaneX, dirPlaneY, belowAxisLimit, belowPlaneLimit);
|
||||
dirPlaneX.TransformVector(gContext.mModel);
|
||||
dirPlaneY.TransformVector(gContext.mModel);
|
||||
ComputeTripodAxisAndVisibility(i, dirAxis, dirPlaneX, dirPlaneY, belowAxisLimit, belowPlaneLimit);
|
||||
|
||||
const int planNormal = (i + 2) % 3;
|
||||
|
||||
const float len = IntersectRayPlane(gContext.mRayOrigin, gContext.mRayVector, BuildPlan(gContext.mModel.v.position, direction[planNormal]));
|
||||
const float len = IntersectRayPlane(gContext.mRayOrigin, gContext.mRayVector, BuildPlan(gContext.mModel.v.position, dirAxis));
|
||||
vec_t posOnPlan = gContext.mRayOrigin + gContext.mRayVector * len;
|
||||
|
||||
const float dx = dirPlaneX.Dot3((posOnPlan - gContext.mModel.v.position) * (1.f / gContext.mScreenFactor));
|
||||
const float dy = dirPlaneY.Dot3((posOnPlan - gContext.mModel.v.position) * (1.f / gContext.mScreenFactor));
|
||||
if (belowAxisLimit && dy > -0.1f && dy < 0.1f && dx > 0.1f && dx < 1.f)
|
||||
const ImVec2 posOnPlanScreen = worldToPos(posOnPlan, gContext.mViewProjection);
|
||||
const ImVec2 axisStartOnScreen = worldToPos(gContext.mModel.v.position + dirAxis * gContext.mScreenFactor * 0.1f, gContext.mViewProjection);
|
||||
const ImVec2 axisEndOnScreen = worldToPos(gContext.mModel.v.position + dirAxis * gContext.mScreenFactor, gContext.mViewProjection);
|
||||
|
||||
vec_t closestPointOnAxis = PointOnSegment(makeVect(posOnPlanScreen), makeVect(axisStartOnScreen), makeVect(axisEndOnScreen));
|
||||
|
||||
if ((closestPointOnAxis - makeVect(posOnPlanScreen)).Length() < 12.f) // pixel size
|
||||
type = SCALE_X + i;
|
||||
}
|
||||
return type;
|
||||
@ -1364,9 +1471,15 @@ namespace ImGuizmo
|
||||
|
||||
if (Dot(Normalized(localPos), gContext.mRayVector) > FLT_EPSILON)
|
||||
continue;
|
||||
vec_t idealPosOnCircle = Normalized(localPos);
|
||||
idealPosOnCircle.TransformVector(gContext.mModelInverse);
|
||||
ImVec2 idealPosOnCircleScreen = worldToPos(idealPosOnCircle * gContext.mScreenFactor, gContext.mMVP);
|
||||
|
||||
float distance = localPos.Length() / gContext.mScreenFactor;
|
||||
if (distance > 0.9f && distance < 1.1f)
|
||||
//gContext.mDrawList->AddCircle(idealPosOnCircleScreen, 5.f, 0xFFFFFFFF);
|
||||
ImVec2 distanceOnScreen = idealPosOnCircleScreen - io.MousePos;
|
||||
|
||||
float distance = makeVect(distanceOnScreen).Length();
|
||||
if (distance < 8.f) // pixel size
|
||||
type = ROTATE_X + i;
|
||||
}
|
||||
|
||||
@ -1383,29 +1496,32 @@ namespace ImGuizmo
|
||||
io.MousePos.y >= gContext.mScreenSquareMin.y && io.MousePos.y <= gContext.mScreenSquareMax.y)
|
||||
type = MOVE_SCREEN;
|
||||
|
||||
const vec_t direction[3] = { gContext.mModel.v.right, gContext.mModel.v.up, gContext.mModel.v.dir };
|
||||
|
||||
// compute
|
||||
for (unsigned int i = 0; i < 3 && type == NONE; i++)
|
||||
{
|
||||
vec_t dirPlaneX, dirPlaneY;
|
||||
vec_t dirPlaneX, dirPlaneY, dirAxis;
|
||||
bool belowAxisLimit, belowPlaneLimit;
|
||||
ComputeTripodAxisAndVisibility(i, dirPlaneX, dirPlaneY, belowAxisLimit, belowPlaneLimit);
|
||||
ComputeTripodAxisAndVisibility(i, dirAxis, dirPlaneX, dirPlaneY, belowAxisLimit, belowPlaneLimit);
|
||||
dirAxis.TransformVector(gContext.mModel);
|
||||
dirPlaneX.TransformVector(gContext.mModel);
|
||||
dirPlaneY.TransformVector(gContext.mModel);
|
||||
|
||||
const int planNormal = (i + 2) % 3;
|
||||
|
||||
const float len = IntersectRayPlane(gContext.mRayOrigin, gContext.mRayVector, BuildPlan(gContext.mModel.v.position, direction[planNormal]));
|
||||
const float len = IntersectRayPlane(gContext.mRayOrigin, gContext.mRayVector, BuildPlan(gContext.mModel.v.position, dirAxis));
|
||||
vec_t posOnPlan = gContext.mRayOrigin + gContext.mRayVector * len;
|
||||
|
||||
const ImVec2 posOnPlanScreen = worldToPos(posOnPlan, gContext.mViewProjection);
|
||||
const ImVec2 axisStartOnScreen = worldToPos(gContext.mModel.v.position + dirAxis * gContext.mScreenFactor * 0.1f, gContext.mViewProjection);
|
||||
const ImVec2 axisEndOnScreen = worldToPos(gContext.mModel.v.position + dirAxis * gContext.mScreenFactor, gContext.mViewProjection);
|
||||
|
||||
vec_t closestPointOnAxis = PointOnSegment(makeVect(posOnPlanScreen), makeVect(axisStartOnScreen), makeVect(axisEndOnScreen));
|
||||
|
||||
if ((closestPointOnAxis - makeVect(posOnPlanScreen)).Length() < 12.f) // pixel size
|
||||
type = MOVE_X + i;
|
||||
|
||||
const float dx = dirPlaneX.Dot3((posOnPlan - gContext.mModel.v.position) * (1.f / gContext.mScreenFactor));
|
||||
const float dy = dirPlaneY.Dot3((posOnPlan - gContext.mModel.v.position) * (1.f / gContext.mScreenFactor));
|
||||
if (belowAxisLimit && dy > -0.1f && dy < 0.1f && dx > 0.1f && dx < 1.f)
|
||||
type = MOVE_X + i;
|
||||
|
||||
if (belowPlaneLimit && dx >= quadUV[0] && dx <= quadUV[4] && dy >= quadUV[1] && dy <= quadUV[3])
|
||||
type = MOVE_XY + i;
|
||||
type = MOVE_YZ + i;
|
||||
|
||||
if (gizmoHitProportion)
|
||||
*gizmoHitProportion = makeVect(dx, dy, 0.f);
|
||||
@ -1422,9 +1538,11 @@ namespace ImGuizmo
|
||||
if (gContext.mbUsing)
|
||||
{
|
||||
ImGui::CaptureMouseFromApp();
|
||||
const float len = IntersectRayPlane(gContext.mRayOrigin, gContext.mRayVector, gContext.mTranslationPlan);
|
||||
const float len = fabsf(IntersectRayPlane(gContext.mRayOrigin, gContext.mRayVector, gContext.mTranslationPlan)); // near plan
|
||||
vec_t newPos = gContext.mRayOrigin + gContext.mRayVector * len;
|
||||
|
||||
|
||||
|
||||
// compute delta
|
||||
vec_t newOrigin = newPos - gContext.mRelativeOrigin * gContext.mScreenFactor;
|
||||
vec_t delta = newOrigin - gContext.mModel.v.position;
|
||||
@ -1480,12 +1598,25 @@ namespace ImGuizmo
|
||||
// find new possible way to move
|
||||
vec_t gizmoHitProportion;
|
||||
type = GetMoveType(&gizmoHitProportion);
|
||||
if (CanActivate() && type != NONE)
|
||||
if(type != NONE)
|
||||
{
|
||||
ImGui::CaptureMouseFromApp();
|
||||
}
|
||||
if (CanActivate() && type != NONE)
|
||||
{
|
||||
gContext.mbUsing = true;
|
||||
gContext.mCurrentOperation = type;
|
||||
const vec_t movePlanNormal[] = { gContext.mModel.v.up, gContext.mModel.v.dir, gContext.mModel.v.right, gContext.mModel.v.dir, gContext.mModel.v.right, gContext.mModel.v.up, -gContext.mCameraDir };
|
||||
vec_t movePlanNormal[] = { gContext.mModel.v.right, gContext.mModel.v.up, gContext.mModel.v.dir,
|
||||
gContext.mModel.v.right, gContext.mModel.v.up, gContext.mModel.v.dir,
|
||||
-gContext.mCameraDir };
|
||||
|
||||
vec_t cameraToModelNormalized = Normalized(gContext.mModel.v.position - gContext.mCameraEye);
|
||||
for (unsigned int i = 0; i < 3; i++)
|
||||
{
|
||||
vec_t orthoVector = Cross(movePlanNormal[i], cameraToModelNormalized);
|
||||
movePlanNormal[i].Cross(orthoVector);
|
||||
movePlanNormal[i].Normalize();
|
||||
}
|
||||
// pickup plan
|
||||
gContext.mTranslationPlan = BuildPlan(gContext.mModel.v.position, movePlanNormal[type - MOVE_X]);
|
||||
const float len = IntersectRayPlane(gContext.mRayOrigin, gContext.mRayVector, gContext.mTranslationPlan);
|
||||
@ -1505,9 +1636,12 @@ namespace ImGuizmo
|
||||
{
|
||||
// find new possible way to scale
|
||||
type = GetScaleType();
|
||||
if (CanActivate() && type != NONE)
|
||||
if(type != NONE)
|
||||
{
|
||||
ImGui::CaptureMouseFromApp();
|
||||
}
|
||||
if (CanActivate() && type != NONE)
|
||||
{
|
||||
gContext.mbUsing = true;
|
||||
gContext.mCurrentOperation = type;
|
||||
const vec_t movePlanNormal[] = { gContext.mModel.v.up, gContext.mModel.v.dir, gContext.mModel.v.right, gContext.mModel.v.dir, gContext.mModel.v.up, gContext.mModel.v.right, -gContext.mCameraDir };
|
||||
@ -1591,6 +1725,11 @@ namespace ImGuizmo
|
||||
{
|
||||
type = GetRotateType();
|
||||
|
||||
if(type != NONE)
|
||||
{
|
||||
ImGui::CaptureMouseFromApp();
|
||||
}
|
||||
|
||||
if (type == ROTATE_SCREEN)
|
||||
{
|
||||
applyRotationLocaly = true;
|
||||
@ -1598,7 +1737,6 @@ namespace ImGuizmo
|
||||
|
||||
if (CanActivate() && type != NONE)
|
||||
{
|
||||
ImGui::CaptureMouseFromApp();
|
||||
gContext.mbUsing = true;
|
||||
gContext.mCurrentOperation = type;
|
||||
const vec_t rotatePlanNormal[] = { gContext.mModel.v.right, gContext.mModel.v.up, gContext.mModel.v.dir, -gContext.mCameraDir };
|
||||
@ -1740,12 +1878,14 @@ namespace ImGuizmo
|
||||
case SCALE:
|
||||
HandleScale(matrix, deltaMatrix, type, snap);
|
||||
break;
|
||||
case BOUNDS:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (localBounds && !gContext.mbUsing)
|
||||
HandleAndDrawLocalBounds(localBounds, (matrix_t*)matrix, boundsSnap);
|
||||
HandleAndDrawLocalBounds(localBounds, (matrix_t*)matrix, boundsSnap, operation);
|
||||
|
||||
if (!gContext.mbUsingBounds)
|
||||
{
|
||||
@ -1760,11 +1900,13 @@ namespace ImGuizmo
|
||||
case SCALE:
|
||||
DrawScaleGizmo(type);
|
||||
break;
|
||||
case BOUNDS:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DrawCube(const float *view, const float *projection, float *matrix)
|
||||
void DrawCube(const float *view, const float *projection, const float *matrix)
|
||||
{
|
||||
matrix_t viewInverse;
|
||||
viewInverse.Inverse(*(matrix_t*)view);
|
||||
@ -1816,5 +1958,16 @@ namespace ImGuizmo
|
||||
gContext.mDrawList->AddConvexPolyFilled(faceCoordsScreen, 4, directionColor[normalIndex] | 0x808080);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawGrid(const float *view, const float *projection, const float *matrix, const float gridSize)
|
||||
{
|
||||
matrix_t res = *(matrix_t*)matrix * *(matrix_t*)view * *(matrix_t*)projection;
|
||||
|
||||
for (float f = -gridSize; f <= gridSize; f += 1.f)
|
||||
{
|
||||
gContext.mDrawList->AddLine(worldToPos(makeVect(f, 0.f, -gridSize), res), worldToPos(makeVect(f, 0.f, gridSize), res), 0xFF808080);
|
||||
gContext.mDrawList->AddLine(worldToPos(makeVect(-gridSize, 0.f, f), res), worldToPos(makeVect(gridSize, 0.f, f), res), 0xFF808080);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user