Updated ImGuizmo.

This commit is contained in:
Branimir Karadžić 2016-09-12 21:05:48 -07:00
parent b906f3445c
commit 3ce80020ec
2 changed files with 131 additions and 42 deletions

View File

@ -1,5 +1,5 @@
// https://github.com/CedricGuillemet/ImGuizmo
// v 1.03 WIP
// v 1.04 WIP
//
// The MIT License(MIT)
//
@ -25,6 +25,7 @@
//
// -------------------------------------------------------------------------------------------
// History :
// 2016/09/11 Behind camera culling. Scaling Delta matrix not multiplied by source matrix scales. local/world rotation and translation fixed. Display message is incorrect (X: ... Y:...) in local mode.
// 2016/09/09 Hatched negative axis. Snapping. Documentation update.
// 2016/09/04 Axis switch and translation plan autohiding. Scale transform stability improved
// 2016/09/01 Mogwai changed to Manipulate. Draw debug cube. Fixed inverted scale. Mixing scale and translation/rotation gives bad results.
@ -40,43 +41,65 @@
//
// -------------------------------------------------------------------------------------------
// Example
//
// static ImGuizmo::OPERATION mCurrentGizmoOperation(ImGuizmo::TRANSLATE);
// static ImGuizmo::MODE mCurrentGizmoMode(ImGuizmo::LOCAL);
//
// // Maya shortcut keys
// if (ImGui::IsKeyPressed(90)) // w Key
// mCurrentGizmoOperation = ImGuizmo::TRANSLATE;
// if (ImGui::IsKeyPressed(69)) // e Key
// mCurrentGizmoOperation = ImGuizmo::ROTATE;
// if (ImGui::IsKeyPressed(82)) // r Key
// mCurrentGizmoOperation = ImGuizmo::SCALE;
//
// if (ImGui::RadioButton("Translate", mCurrentGizmoOperation == ImGuizmo::TRANSLATE))
// mCurrentGizmoOperation = ImGuizmo::TRANSLATE;
// ImGui::SameLine();
// if (ImGui::RadioButton("Rotate", mCurrentGizmoOperation == ImGuizmo::ROTATE))
// mCurrentGizmoOperation = ImGuizmo::ROTATE;
// ImGui::SameLine();
// if (ImGui::RadioButton("Scale", mCurrentGizmoOperation == ImGuizmo::SCALE))
// mCurrentGizmoOperation = ImGuizmo::SCALE;
//
// float matrixTranslation[3], matrixRotation[3], matrixScale[3];
// ImGuizmo::DecomposeMatrixToComponents(gizmoMatrix.m16, matrixTranslation, matrixRotation, matrixScale);
// ImGui::InputFloat3("Tr", matrixTranslation, 3);
// ImGui::InputFloat3("Rt", matrixRotation, 3);
// ImGui::InputFloat3("Sc", matrixScale, 3);
// ImGuizmo::RecomposeMatrixFromComponents(matrixTranslation, matrixRotation, matrixScale, gizmoMatrix.m16);
//
// if (ImGui::RadioButton("Local", mCurrentGizmoMode == ImGuizmo::LOCAL))
// mCurrentGizmoMode = ImGuizmo::LOCAL;
// ImGui::SameLine();
// if (ImGui::RadioButton("World", mCurrentGizmoMode == ImGuizmo::WORLD))
// mCurrentGizmoMode = ImGuizmo::WORLD;
//
// ImGuizmo::Manipulate(gCurrentCamera->mView.m16, gCurrentCamera->mProjection.m16, mCurrentGizmoOperation, mCurrentGizmoMode, gizmoMatrix.m16);
//
#if 0
void EditTransform(const Camera& camera, matrix_t& matrix)
{
static ImGuizmo::OPERATION mCurrentGizmoOperation(ImGuizmo::ROTATE);
static ImGuizmo::MODE mCurrentGizmoMode(ImGuizmo::WORLD);
if (ImGui::IsKeyPressed(90))
mCurrentGizmoOperation = ImGuizmo::TRANSLATE;
if (ImGui::IsKeyPressed(69))
mCurrentGizmoOperation = ImGuizmo::ROTATE;
if (ImGui::IsKeyPressed(82)) // r Key
mCurrentGizmoOperation = ImGuizmo::SCALE;
if (ImGui::RadioButton("Translate", mCurrentGizmoOperation == ImGuizmo::TRANSLATE))
mCurrentGizmoOperation = ImGuizmo::TRANSLATE;
ImGui::SameLine();
if (ImGui::RadioButton("Rotate", mCurrentGizmoOperation == ImGuizmo::ROTATE))
mCurrentGizmoOperation = ImGuizmo::ROTATE;
ImGui::SameLine();
if (ImGui::RadioButton("Scale", mCurrentGizmoOperation == ImGuizmo::SCALE))
mCurrentGizmoOperation = ImGuizmo::SCALE;
float matrixTranslation[3], matrixRotation[3], matrixScale[3];
ImGuizmo::DecomposeMatrixToComponents(matrix.m16, matrixTranslation, matrixRotation, matrixScale);
ImGui::InputFloat3("Tr", matrixTranslation, 3);
ImGui::InputFloat3("Rt", matrixRotation, 3);
ImGui::InputFloat3("Sc", matrixScale, 3);
ImGuizmo::RecomposeMatrixFromComponents(matrixTranslation, matrixRotation, matrixScale, matrix.m16);
if (mCurrentGizmoOperation != ImGuizmo::SCALE)
{
if (ImGui::RadioButton("Local", mCurrentGizmoMode == ImGuizmo::LOCAL))
mCurrentGizmoMode = ImGuizmo::LOCAL;
ImGui::SameLine();
if (ImGui::RadioButton("World", mCurrentGizmoMode == ImGuizmo::WORLD))
mCurrentGizmoMode = ImGuizmo::WORLD;
}
static bool useSnap(false);
if (ImGui::IsKeyPressed(83))
useSnap = !useSnap;
ImGui::Checkbox("", &useSnap);
ImGui::SameLine();
vec_t snap;
switch (mCurrentGizmoOperation)
{
case ImGuizmo::TRANSLATE:
snap = config.mSnapTranslation;
ImGui::InputFloat3("Snap", &snap.x);
break;
case ImGuizmo::ROTATE:
snap = config.mSnapRotation;
ImGui::InputFloat("Angle Snap", &snap.x);
break;
case ImGuizmo::SCALE:
snap = config.mSnapScale;
ImGui::InputFloat("Scale Snap", &snap.x);
break;
}
ImGuizmo::Manipulate(camera.mView.m16, camera.mProjection.m16, mCurrentGizmoOperation, mCurrentGizmoMode, matrix.m16, NULL, useSnap ? &snap.x : NULL);
}
#endif
#pragma once
namespace ImGuizmo

View File

@ -491,11 +491,13 @@ namespace ImGuizmo
ImDrawList* mDrawList;
MODE mMode;
matrix_t mViewMat;
matrix_t mProjectionMat;
matrix_t mModel;
matrix_t mModelInverse;
matrix_t mModelSource;
matrix_t mModelSourceInverse;
matrix_t mMVP;
matrix_t mViewProjection;
@ -526,6 +528,7 @@ namespace ImGuizmo
vec_t mRotationVectorSource;
float mRotationAngle;
float mRotationAngleOrigin;
//vec_t mWorldToLocalAxis;
// scale
vec_t mScale;
@ -646,6 +649,7 @@ namespace ImGuizmo
static void ComputeContext(const float *view, const float *projection, float *matrix, MODE mode)
{
gContext.mMode = mode;
gContext.mViewMat = *(matrix_t*)view;
gContext.mProjectionMat = *(matrix_t*)projection;
@ -662,6 +666,7 @@ namespace ImGuizmo
gContext.mModelScaleOrigin.Set(gContext.mModelSource.v.right.Length(), gContext.mModelSource.v.up.Length(), gContext.mModelSource.v.dir.Length());
gContext.mModelInverse.Inverse(gContext.mModel);
gContext.mModelSourceInverse.Inverse(gContext.mModelSource);
gContext.mViewProjection = gContext.mViewMat * gContext.mProjectionMat;
gContext.mMVP = gContext.mModel * gContext.mViewProjection;
@ -1101,6 +1106,7 @@ namespace ImGuizmo
static void HandleTranslation(float *matrix, float *deltaMatrix, int& type, float *snap)
{
ImGuiIO& io = ImGui::GetIO();
bool applyRotationLocaly = gContext.mMode == LOCAL || type == MOVE_SCREEN;
// move
if (gContext.mbUsing)
@ -1125,8 +1131,18 @@ namespace ImGuizmo
if (snap)
{
vec_t cumulativeDelta = gContext.mModel.v.position + delta - gContext.mMatrixOrigin;
ComputeSnap(cumulativeDelta, snap);
if (applyRotationLocaly)
{
cumulativeDelta.TransformVector(gContext.mModelSourceInverse);
ComputeSnap(cumulativeDelta, snap);
cumulativeDelta.TransformVector(gContext.mModelSource);
}
else
{
ComputeSnap(cumulativeDelta, snap);
}
delta = gContext.mMatrixOrigin + cumulativeDelta - gContext.mModel.v.position;
}
// compute matrix & delta
@ -1134,6 +1150,8 @@ namespace ImGuizmo
deltaMatrixTranslation.Translation(delta);
if (deltaMatrix)
memcpy(deltaMatrix, deltaMatrixTranslation.m16, sizeof(float) * 16);
matrix_t res = gContext.mModelSource * deltaMatrixTranslation;
*(matrix_t*)matrix = res;
@ -1230,11 +1248,15 @@ namespace ImGuizmo
matrix_t deltaMatrixScale;
deltaMatrixScale.Scale(gContext.mScale * gContext.mScaleValueOrigin);
if (deltaMatrix)
memcpy(deltaMatrix, deltaMatrixScale.m16, sizeof(float) * 16);
matrix_t res = deltaMatrixScale * gContext.mModel;
*(matrix_t*)matrix = res;
if (deltaMatrix)
{
deltaMatrixScale.Scale(gContext.mScale);
memcpy(deltaMatrix, deltaMatrixScale.m16, sizeof(float) * 16);
}
if (!io.MouseDown[0])
gContext.mbUsing = false;
@ -1245,6 +1267,7 @@ namespace ImGuizmo
static void HandleRotation(float *matrix, float *deltaMatrix, int& type, float *snap)
{
ImGuiIO& io = ImGui::GetIO();
bool applyRotationLocaly = gContext.mMode == LOCAL || type == ROTATE_SCREEN;
if (!gContext.mbUsing)
{
@ -1255,7 +1278,14 @@ namespace ImGuizmo
gContext.mCurrentOperation = type;
const vec_t rotatePlanNormal[] = { gContext.mModel.v.right, gContext.mModel.v.up, gContext.mModel.v.dir, -gContext.mCameraDir };
// pickup plan
gContext.mTranslationPlan = BuildPlan(gContext.mModel.v.position, rotatePlanNormal[type - ROTATE_X]);
if (applyRotationLocaly)
{
gContext.mTranslationPlan = BuildPlan(gContext.mModel.v.position, rotatePlanNormal[type - ROTATE_X]);
}
else
{
gContext.mTranslationPlan = BuildPlan(gContext.mModelSource.v.position, directionUnary[type - ROTATE_X]);
}
const float len = IntersectRayPlane(gContext.mRayOrigin, gContext.mRayVector, gContext.mTranslationPlan);
vec_t localPos = gContext.mRayOrigin + gContext.mRayVector * len - gContext.mModel.v.position;
@ -1274,7 +1304,9 @@ namespace ImGuizmo
ComputeSnap(&gContext.mRotationAngle, &snapInRadian);
}
vec_t rotationAxisLocalSpace;
rotationAxisLocalSpace.TransformVector(makeVect(gContext.mTranslationPlan.x, gContext.mTranslationPlan.y, gContext.mTranslationPlan.z, 0.f), gContext.mModelInverse);
rotationAxisLocalSpace.Normalize();
matrix_t deltaRotation;
deltaRotation.RotationAxis(rotationAxisLocalSpace, gContext.mRotationAngle - gContext.mRotationAngleOrigin);
@ -1283,8 +1315,18 @@ namespace ImGuizmo
matrix_t scaleOrigin;
scaleOrigin.Scale(gContext.mModelScaleOrigin);
if (applyRotationLocaly)
{
*(matrix_t*)matrix = scaleOrigin * deltaRotation * gContext.mModel;
}
else
{
matrix_t res = gContext.mModelSource;
res.v.position.Set(0.f);
*(matrix_t*)matrix = scaleOrigin * deltaRotation * gContext.mModel;
*(matrix_t*)matrix = res * deltaRotation;
((matrix_t*)matrix)->v.position = gContext.mModelSource.v.position;
}
if (deltaMatrix)
{
@ -1348,6 +1390,13 @@ namespace ImGuizmo
// set delta to identity
if (deltaMatrix)
((matrix_t*)deltaMatrix)->SetToIdentity();
// behind camera
vec_t camSpacePosition;
camSpacePosition.TransformPoint(makeVect(0.f, 0.f, 0.f), gContext.mMVP);
if (camSpacePosition.z < 0.001f)
return;
// --
int type = NONE;
if (gContext.mbEnable)
@ -1399,6 +1448,23 @@ namespace ImGuizmo
directionUnary[normalIndex] - directionUnary[perpXIndex] - directionUnary[perpYIndex],
directionUnary[normalIndex] - directionUnary[perpXIndex] + directionUnary[perpYIndex],
};
// clipping
bool skipFace = false;
for (unsigned int iCoord = 0; iCoord < 4; iCoord++)
{
vec_t camSpacePosition;
camSpacePosition.TransformPoint(faceCoords[iCoord] * 0.5f * invert, gContext.mMVP);
if (camSpacePosition.z < 0.001f)
{
skipFace = true;
break;
}
}
if (skipFace)
continue;
// 3D->2D
ImVec2 faceCoordsScreen[4];
for (unsigned int iCoord = 0; iCoord < 4; iCoord++)
faceCoordsScreen[iCoord] = worldToPos(faceCoords[iCoord] * 0.5f * invert, res);