From 3ce80020eccc8a5fa9ae49b68ddafcbb0f6abfcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Mon, 12 Sep 2016 21:05:48 -0700 Subject: [PATCH] Updated ImGuizmo. --- 3rdparty/ocornut-imgui/widgets/gizmo.h | 97 +++++++++++++++--------- 3rdparty/ocornut-imgui/widgets/gizmo.inl | 76 +++++++++++++++++-- 2 files changed, 131 insertions(+), 42 deletions(-) diff --git a/3rdparty/ocornut-imgui/widgets/gizmo.h b/3rdparty/ocornut-imgui/widgets/gizmo.h index 8b9bd6a97..7b398fefe 100644 --- a/3rdparty/ocornut-imgui/widgets/gizmo.h +++ b/3rdparty/ocornut-imgui/widgets/gizmo.h @@ -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 diff --git a/3rdparty/ocornut-imgui/widgets/gizmo.inl b/3rdparty/ocornut-imgui/widgets/gizmo.inl index 9f53ea22f..e9ba5ed05 100644 --- a/3rdparty/ocornut-imgui/widgets/gizmo.inl +++ b/3rdparty/ocornut-imgui/widgets/gizmo.inl @@ -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);