diff --git a/Assets/Scripts/SelectionManager.cs b/Assets/Scripts/SelectionManager.cs index 1034fd6646..53d0231fae 100644 --- a/Assets/Scripts/SelectionManager.cs +++ b/Assets/Scripts/SelectionManager.cs @@ -977,6 +977,39 @@ public void SetSnappingGridSize(int snapIndex) } } + public Quaternion QuantizeAngle(Quaternion rotation) + { + // Currently a snapping angle of "0" means "no-snapping". It might in future mean "snap to whole rotations only" + if (SnappingAngle == 0) return Quaternion.identity; + + float round(float val) { return Mathf.Round(val / SnappingAngle) * SnappingAngle; } + + Vector3 euler = rotation.eulerAngles; + float y = euler.y; + + // First snap to x and z to get a rotation around the origin + euler = new Vector3(round(euler.x), 0, round(euler.z)); + rotation = Quaternion.Euler(euler); + + // Snap to the local y last to handle snapping around the x/z axis + // (Snapping x/y/z all at once results in counter-intuitive results) + rotation *= Quaternion.Euler(0, round(y), 0); + + return rotation; + } + + public Vector3 SnapToGrid(Vector3 position) + { + if (SnappingGridSize == 0) return position; + Vector3 localCanvasPos = App.ActiveCanvas.transform.worldToLocalMatrix.MultiplyPoint3x4(position); + float round(float val) { return Mathf.Round(val / SnappingGridSize) * SnappingGridSize; } + Vector3 roundedCanvasPos = new Vector3( + round(localCanvasPos.x), + round(localCanvasPos.y), + round(localCanvasPos.z) + ); + return App.ActiveCanvas.transform.localToWorldMatrix.MultiplyPoint3x4(roundedCanvasPos); + } } diff --git a/Assets/Scripts/Widgets/GrabWidget.cs b/Assets/Scripts/Widgets/GrabWidget.cs index 16689db073..24d12bb415 100644 --- a/Assets/Scripts/Widgets/GrabWidget.cs +++ b/Assets/Scripts/Widgets/GrabWidget.cs @@ -1211,7 +1211,7 @@ virtual protected TrTransform GetSnappedTransform(TrTransform xf_GS) if (SelectionManager.m_Instance.CurrentSnapAngleIndex != 0) { var rot_CS = xf_GS.rotation * App.Scene.Pose.rotation.TrueInverse(); - Quaternion nearestSnapRotation_CS = QuantizeAngle(rot_CS); + Quaternion nearestSnapRotation_CS = SelectionManager.m_Instance.QuantizeAngle(rot_CS); float snapAngle = SelectionManager.m_Instance.SnappingAngle; float stickiness = m_ValidSnapRotationStickyAngle / 90f; @@ -1236,36 +1236,12 @@ virtual protected TrTransform GetSnappedTransform(TrTransform xf_GS) if (SelectionManager.m_Instance.CurrentSnapGridIndex != 0) { - outXf_GS.translation = SnapToGrid(outXf_GS.translation); + outXf_GS.translation = SelectionManager.m_Instance.SnapToGrid(outXf_GS.translation); } return outXf_GS; } - private Quaternion QuantizeAngle(Quaternion rotation) - { - var snapAngle = SelectionManager.m_Instance.SnappingAngle; - float round(float val) { return Mathf.Round(val / snapAngle) * snapAngle; } - - Vector3 euler = rotation.eulerAngles; - euler = new Vector3(round(euler.x), round(euler.y), round(euler.z)); - return Quaternion.Euler(euler); - } - - public static Vector3 SnapToGrid(Vector3 position) - { - float gridSize = SelectionManager.m_Instance.SnappingGridSize; - Vector3 localCanvasPos = App.ActiveCanvas.transform.worldToLocalMatrix.MultiplyPoint3x4(position); - float round(float val) { return Mathf.Round(val / gridSize) * gridSize; } - Vector3 roundedCanvasPos = new Vector3( - round(localCanvasPos.x), - round(localCanvasPos.y), - round(localCanvasPos.z) - ); - return App.ActiveCanvas.transform.localToWorldMatrix.MultiplyPoint3x4(roundedCanvasPos); - } - - protected int GetBestSnapRotationIndex(Quaternion rot) { float fNearestDot = 0.0f;