public void OnMouseMove(object sender, MouseEventArgs e) { if (Hidden) { return; } if (selectedAxis != SelectedAxis.None) { Vector3 intersection; var registrationOrigin = ProjectPoint(worldRegistrationPosition); var registrationMouse = ProjectScreenPoint(new Vector3(e.ScreenCoordinates)); var mouseRay = new Ray( Maths.Project(viewMatrix, projectionMatrix, registrationMouse.Xy, depth: -1, viewport: viewport).Xyz, Maths.Project(viewMatrix, projectionMatrix, registrationMouse.Xy, depth: 1, viewport: viewport).Xyz ); var registrationRay = new Ray( Maths.Project(viewMatrix, projectionMatrix, registrationOrigin.Xy, depth: -1, viewport: viewport).Xyz, Maths.Project(viewMatrix, projectionMatrix, registrationOrigin.Xy, depth: 1, viewport: viewport).Xyz ); var viewerAxis = (mouseRay.Origin - origin).Normalized( ); viewerAxis.Normalize( ); // Setup and select the collision plane var planeUNormal = new Vector3(0, 0, 0); var planeVNormal = new Vector3(0, 0, 0); var translationNormal = new Vector3(0, 0, 0); if (selectedAxis.HasFlag(SelectedAxis.U)) { planeUNormal = up; planeVNormal = forward; translationNormal = right; } else if (selectedAxis.HasFlag(SelectedAxis.V)) { planeUNormal = right; planeVNormal = up; translationNormal = forward; } else if (selectedAxis.HasFlag(SelectedAxis.W)) { planeUNormal = right; planeVNormal = forward; translationNormal = up; } else { return; } Vector3.Normalize(ref planeUNormal, out planeUNormal); Vector3.Normalize(ref planeVNormal, out planeVNormal); Vector3.Normalize(ref translationNormal, out translationNormal); // Calculate the perpendicularness values var cosineToPlaneU = Vector3.Cross(viewerAxis, planeUNormal).LengthFast; var cosineToPlaneV = Vector3.Cross(viewerAxis, planeVNormal).LengthFast; // Select the most perpendicular plane var translationPlaneNormal = planeUNormal; if (cosineToPlaneU > cosineToPlaneV) { translationPlaneNormal = planeVNormal; } // Produce the plane-distance from origin from this obejcts position vector var planeOffset = Vector3.Dot(translationPlaneNormal, origin); var translationPlane = new Plane(translationPlaneNormal, -planeOffset); float?hit, registrationHit; if (translationPlane.Intersects(mouseRay, out hit) && translationPlane.Intersects(registrationRay, out registrationHit)) { //// Debug drawing code //GL.VertexAttrib3(1, new[] { 230f / 255f, 128f / 255f, 0f / 255f }); //DebugDrawer.DrawPlane(translationPlane); //using (Form1.ScreenProgram.Use()) //{ // GL.VertexAttrib3(1, new[] { 225f / 255f, 128f / 255f, 255f / 255f }); // DebugDrawer.DrawPoint(mouseRay.Origin + mouseRay.Direction * hit.Value, pointSize: 7); // GL.VertexAttrib3(1, new[] { 15f / 255f, 128f / 255f, 255f / 255f }); // DebugDrawer.DrawPoint(registrationRay.Origin + registrationRay.Direction * registrationHit.Value, pointSize: 9); //} var componentU = Vector3.Dot(planeUNormal, this.position) * planeUNormal; var componentV = Vector3.Dot(planeVNormal, this.position) * planeVNormal; var dot = Vector3.Dot(translationNormal, mouseRay.Origin + mouseRay.Direction * hit.Value); var translation = translationNormal * Vector3.Dot(translationNormal, mouseRay.Origin + mouseRay.Direction * hit.Value); var registrationOffset = translationNormal * Vector3.Dot(translationNormal, worldRegistrationPosition); var actualtranslation = mouseRay.Origin + mouseRay.Direction * hit.Value; this.Position = translation - registrationOffset + componentU + componentV; } } }