diff --git a/src/ui/TransformManipulator.cpp b/src/ui/TransformManipulator.cpp index aa362f2..edc58be 100644 --- a/src/ui/TransformManipulator.cpp +++ b/src/ui/TransformManipulator.cpp @@ -581,10 +581,11 @@ bool TransformManipulator::HandleInput(const pxr::GfMatrix4d& viewProj, if (axLen > 1e-3f) { float screenDot = (delta.x*axDx + delta.y*axDy) / axLen; float worldDelta = screenDot * sf / axLen; - pxr::GfVec3d move( - m_dragAxis == 0 ? worldDelta : 0.f, - m_dragAxis == 1 ? worldDelta : 0.f, - m_dragAxis == 2 ? worldDelta : 0.f); + // Displace along the actual gizmo axis direction (world space). + // Using axes[m_dragAxis] is correct for both World and Object space; + // the old code used hardcoded world X/Y/Z components which broke + // Object-space translation. + pxr::GfVec3d move = axes[m_dragAxis] * static_cast(worldDelta); ApplyMoveDelta(move); } } @@ -606,6 +607,20 @@ bool TransformManipulator::HandleInput(const pxr::GfMatrix4d& viewProj, while (deltaAngle < -static_cast(M_PI)) deltaAngle += 2.f * static_cast(M_PI); float angleDeg = deltaAngle * (180.f / static_cast(M_PI)); + + // Correct sign: the screen-angle approach maps 2-D angular + // motion to 3-D rotation around axes[m_dragAxis]. When the + // ring normal faces the camera (dot < 0) the handedness flips, + // so negate the angle to keep rotation direction consistent. + pxr::GfVec3d ringNormal = axes[m_dragAxis]; + pxr::GfVec3d camToScene = pivot - cameraEye; + double camLen = camToScene.GetLength(); + if (camLen > 1e-9) camToScene /= camLen; + double axisDotView = ringNormal[0]*camToScene[0] + + ringNormal[1]*camToScene[1] + + ringNormal[2]*camToScene[2]; + if (axisDotView < 0.0) angleDeg = -angleDeg; + ApplyRotateDelta(m_dragAxis, angleDeg); m_dragRotateLastAngle = currentAngle; }