/// <returns>true, if an iteraction with the gizmo is happening</returns> public bool MouseMoved(Matrix4x4 viewProjection, Ray ray) { if (!DrawGizmo || _mode == GizmoMode.None) { return(false); } bool upside = Orientation == GizmoOrientation.UpsideDown; bool flippedScale = false; // Flip sizing dimensions if object is rotateable on Y axis if ((_mode == GizmoMode.ScaleX || _mode == GizmoMode.ScaleZ) && SupportRotationY) { flippedScale = MathC.RadToDeg(RotationY) % 180.0f >= 45.0f; } // First get the ray in 3D space from X, Y mouse coordinates switch (_mode) { case GizmoMode.TranslateX: { Vector3 intersection; if (ConstructPlaneIntersection(Position, viewProjection, ray, Vector3.UnitY, Vector3.UnitZ, out intersection)) { GizmoMove(new Vector3(intersection.X - (upside ? -Size : Size) * _arrowHeadOffsetMultiplier, Position.Y, Position.Z)); GizmoMoveDelta(new Vector3(intersection.X - (upside ? -Size : Size) * _arrowHeadOffsetMultiplier - Position.X, 0.0f, 0.0f)); } } break; case GizmoMode.TranslateY: { Vector3 intersection; if (ConstructPlaneIntersection(Position, viewProjection, ray, Vector3.UnitX, Vector3.UnitZ, out intersection)) { GizmoMove(new Vector3(Position.X, intersection.Y - (upside ? -Size : Size) * _arrowHeadOffsetMultiplier, Position.Z)); GizmoMoveDelta(new Vector3(0.0f, intersection.Y - (upside ? -Size : Size) * _arrowHeadOffsetMultiplier - Position.Y, 0.0f)); } } break; case GizmoMode.TranslateZ: { Vector3 intersection; if (ConstructPlaneIntersection(Position, viewProjection, ray, Vector3.UnitX, Vector3.UnitY, out intersection)) { GizmoMove(new Vector3(Position.X, Position.Y, intersection.Z + (upside ? -Size : Size) * _arrowHeadOffsetMultiplier)); GizmoMoveDelta(new Vector3(0.0f, 0.0f, intersection.Z + (upside ? -Size : Size) * _arrowHeadOffsetMultiplier - Position.Z)); } } break; case GizmoMode.ScaleX: { Vector3 intersection; if (ConstructPlaneIntersection(Position, viewProjection, ray, Vector3.UnitY, Vector3.UnitZ, out intersection)) { if (flippedScale) { GizmoScaleZ(_scaleBase.Z * (float)Math.Exp(_scaleSpeed * (intersection.X - Position.X))); } else { GizmoScaleX(_scaleBase.X * (float)Math.Exp(_scaleSpeed * (intersection.X - Position.X))); } } } break; case GizmoMode.ScaleY: { Vector3 intersection; if (ConstructPlaneIntersection(Position, viewProjection, ray, Vector3.UnitX, Vector3.UnitZ, out intersection)) { GizmoScaleY(_scaleBase.Y * (float)Math.Exp(_scaleSpeed * (intersection.Y - Position.Y))); } } break; case GizmoMode.ScaleZ: { Vector3 intersection; if (ConstructPlaneIntersection(Position, viewProjection, ray, Vector3.UnitX, Vector3.UnitY, out intersection)) { if (flippedScale) { GizmoScaleX(_scaleBase.X * (float)Math.Exp(_scaleSpeed * -(intersection.Z - Position.Z))); } else { GizmoScaleZ(_scaleBase.Z * (float)Math.Exp(_scaleSpeed * -(intersection.Z - Position.Z))); } } } break; case GizmoMode.RotateY: { Plane rotationPlane = MathC.CreatePlaneAtPoint(Position, MathC.HomogenousTransform(Vector3.UnitY, RotateMatrixY)); Vector3 rotationIntersection; if (Collision.RayIntersectsPlane(ray, rotationPlane, out rotationIntersection)) { Vector3 direction = rotationIntersection - Position; _rotationLastMouseRadius = direction.Length(); direction = Vector3.Normalize(direction); float sin = Vector3.Dot(Vector3.UnitZ, direction); float cos = Vector3.Dot(rotationPlane.Normal, Vector3.Cross(Vector3.UnitZ, direction)); _rotationLastMouseAngle = (float)Math.Atan2(-sin, cos); GizmoRotateY(SimplifyAngle(_rotationPickAngleOffset + _rotationLastMouseAngle)); } } break; case GizmoMode.RotateX: { Plane rotationPlane = MathC.CreatePlaneAtPoint(Position, MathC.HomogenousTransform(Vector3.UnitX, RotateMatrixX)); Vector3 rotationIntersection; if (Collision.RayIntersectsPlane(ray, rotationPlane, out rotationIntersection)) { Vector3 direction = rotationIntersection - Position; _rotationLastMouseRadius = direction.Length(); direction = Vector3.Normalize(direction); float sin = Vector3.Dot(Vector3.UnitY, direction); float cos = Vector3.Dot(rotationPlane.Normal, Vector3.Cross(Vector3.UnitY, direction)); _rotationLastMouseAngle = (float)Math.Atan2(-sin, cos); GizmoRotateX(SimplifyAngle(_rotationPickAngleOffset + _rotationLastMouseAngle)); } } break; case GizmoMode.RotateZ: { Plane rotationPlane = MathC.CreatePlaneAtPoint(Position, MathC.HomogenousTransform(Vector3.UnitZ, RotateMatrixZ)); Vector3 rotationIntersection; if (Collision.RayIntersectsPlane(ray, rotationPlane, out rotationIntersection)) { Vector3 direction = rotationIntersection - Position; _rotationLastMouseRadius = direction.Length(); direction = Vector3.Normalize(direction); float sin = Vector3.Dot(Vector3.UnitY, direction); float cos = Vector3.Dot(rotationPlane.Normal, Vector3.Cross(Vector3.UnitY, direction)); _rotationLastMouseAngle = (float)Math.Atan2(-sin, cos); GizmoRotateZ(SimplifyAngle(_rotationPickAngleOffset + _rotationLastMouseAngle)); } } break; } return(true); }