// see description of function by same name in Editing3dPos public void InteractiveHandleEdit(Axis axis, int mousex, int mousey) { Entity entity = selectionmodel.GetFirstSelectedEntity(); if (entity == null) { return; } Vector3 ourpos = null; Rot ourrot = null; if (camera.bRoamingCameraEnabled) { ourpos = camera.RoamingCameraPos; ourrot = camera.RoamingCameraRot; } else { Avatar ouravatar = MetaverseClient.GetInstance().myavatar; if (ouravatar != null) { ourpos = ouravatar.pos; ourrot = ouravatar.rot; } else { return; } } // what is the scaling from screen pixels to world pixels, at the distance of the object from us // obviously this is only approximate for nearish objects, which is most objects... double fDistanceFromUsToObject = (entity.pos - ourpos).Det(); double fScalingFromPosToScreen = graphics.GetScalingFrom3DToScreen(fDistanceFromUsToObject); // Create a 3d vector represeting our mouse drag, in avatar coordinates, in screen pixels Vector3 mousemovescreenaxes = new Vector3(0, -(double)(mousex - editing3d.iDragStartX), -(double)(mousey - editing3d.iDragStartY)); // transform into a 3d vector, in avatar coordinates, in "world units" Vector3 mousemoveavaxes = mousemovescreenaxes * (1 / fScalingFromPosToScreen); // Get handleaxis in avatar axes: Vector3 handleaxisentityaxes = axis.ToVector(); handleaxisentityaxes.x = Math.Abs(handleaxisentityaxes.x); handleaxisentityaxes.y = Math.Abs(handleaxisentityaxes.y); handleaxisentityaxes.z = Math.Abs(handleaxisentityaxes.z); Vector3 handleaxisworldaxes = handleaxisentityaxes * entity.rot.Inverse(); Vector3 handleaxisavaxes = handleaxisworldaxes * ourrot; // we project our handleaxis onto the screen, then project our mousemove onto this // to get mousemove2 (see function description for more info) Vector3 handleaxisprojectedtoscreen = new Vector3(0, handleaxisavaxes.y, handleaxisavaxes.z); Vector3 mousemove2 = handleaxisprojectedtoscreen.Unit() * Vector3.DotProduct(mousemoveavaxes, handleaxisprojectedtoscreen.Unit()); // now we are going to find the ratio between our mousemovement size and how far we need to move along the handleaxis double entitymovetomousemoveratio = Vector3.DotProduct(handleaxisavaxes.Unit(), mousemove2.Unit()); // This gives us the ratio between mouse move distance and entity move distance, now we can calculate the change in entity scale: if (Math.Abs(entitymovetomousemoveratio) < 0.05) // prevent infinite scaling.. { return; } Vector3 scalechange = (mousemove2.Det() / entitymovetomousemoveratio) * handleaxisentityaxes; Vector3 newscale = null; if (axis.IsPositiveAxis) { newscale = editing3d.startscale + scalechange; } else { newscale = editing3d.startscale - scalechange; } newscale.x = Math.Max(0.05, newscale.x); newscale.y = Math.Max(0.05, newscale.y); newscale.z = Math.Max(0.05, newscale.z); Vector3 finalscalechange = newscale - editing3d.startscale; Vector3 finalscalechangeworldaxes = finalscalechange * entity.rot.Inverse(); if (axis.IsPositiveAxis) { entity.pos = editing3d.startpos + (finalscalechangeworldaxes) / 2; } else { entity.pos = editing3d.startpos - (finalscalechangeworldaxes) / 2; } // scale is defined in entity local axes, so no need to transform into world axes entity.scale = newscale; MetaverseClient.GetInstance().worldstorage.OnModifyEntity(entity); }
double GetRotationAngleForEntityAndMouse(Vector3 EntityVector3, Rot EntityRot, Axis axis, int mousex, int mousey) { double fRotationAngle = 0; bool bRotAngleGot = false; Vector3 OurPos; Rot OurRot; if (camera.bRoamingCameraEnabled) { OurPos = camera.RoamingCameraPos; OurRot = camera.RoamingCameraRot; } else { Avatar ouravatar = MetaverseClient.GetInstance().myavatar; if (ouravatar != null) { OurPos = ouravatar.pos; OurRot = ouravatar.rot; } else { return(0); } } Rot rInverseOurRot = OurRot.Inverse(); double fDistanceFromUsToEntity = (EntityVector3 - OurPos).Det(); double fScalingFromPosToScreen = graphics.GetScalingFrom3DToScreen(fDistanceFromUsToEntity); Vector3 ScreenEntityPos = graphics.GetScreenPos(OurPos, OurRot, EntityVector3); Vector3 ScreenMousePos = new Vector3( 0, RendererFactory.GetInstance().WindowWidth - mousex, RendererFactory.GetInstance().WindowHeight - mousey); // mousepoint is a point on the mouseray into the screen, with x = entity.pos.x Vector3 ScreenVectorEntityToMousePoint = ScreenMousePos - ScreenEntityPos; Vector3 VectorEntityToMousePointObserverAxes = ScreenVectorEntityToMousePoint * (1.0f / fScalingFromPosToScreen); //Test.Debug( " screenobjectpos: " + ScreenEntityPos + " screenmousepos: " + ScreenMousePos + " objecttomouse: " + ScreenVectorEntityToMouse ); // Test.Debug Vector3 RotationAxisEntityAxes = axis.ToVector(); Rot rInverseEntityRot = EntityRot.Inverse(); Vector3 RotationAxisWorldAxes = RotationAxisEntityAxes * rInverseEntityRot; // Test.Debug( " RotationAxisWorldAxes " + RotationAxisWorldAxes ); // Test.Debug Vector3 RotationAxisObserverAxes = RotationAxisWorldAxes * OurRot; RotationAxisObserverAxes.Normalize(); double DistanceOfRotationPlaneFromOrigin = 0; // Lets move right up to the object // we're going to imagine a ray from the MousePoint going down the XAXIS, away from us // we'll intersect this ray with the rotation plane to get the point on the rotation plane // where we can consider the mouse to be. double fVectorDotRotationAxisObserverAxesWithXAxis = Vector3.DotProduct(RotationAxisObserverAxes, mvMath.XAxis); if (Math.Abs(fVectorDotRotationAxisObserverAxesWithXAxis) > 0.0005) { double fDistanceFromMousePointToRotationPlane = (DistanceOfRotationPlaneFromOrigin - Vector3.DotProduct(RotationAxisObserverAxes, VectorEntityToMousePointObserverAxes)) / fVectorDotRotationAxisObserverAxesWithXAxis; // Test.Debug( " fDistanceFromMousePointToRotationPlane " + fDistanceFromMousePointToRotationPlane ); // Test.Debug Vector3 VectorMouseClickOnRotationPlaneObserverAxes = new Vector3( fDistanceFromMousePointToRotationPlane, VectorEntityToMousePointObserverAxes.y, VectorEntityToMousePointObserverAxes.z); // Test.Debug( " VectorMouseClickOnRotationPlaneObserverAxes " + VectorMouseClickOnRotationPlaneObserverAxes ); // Test.Debug // We'll rotate this vector into object axes Vector3 VectorMouseClickOnRotationPlaneWorldAxes = VectorMouseClickOnRotationPlaneObserverAxes * rInverseOurRot; Vector3 VectorMouseClickOnRotationPlaneEntityAxes = VectorMouseClickOnRotationPlaneWorldAxes * EntityRot; // Test.Debug( " VectorMouseClickOnRotationPlaneEntityAxes " + VectorMouseClickOnRotationPlaneEntityAxes ); // Test.Debug // now we work out rotation angle double fDistanceOfPointFromOrigin; if (axis.IsXAxis) { fDistanceOfPointFromOrigin = Math.Sqrt(VectorMouseClickOnRotationPlaneEntityAxes.z * VectorMouseClickOnRotationPlaneEntityAxes.z + VectorMouseClickOnRotationPlaneEntityAxes.y * VectorMouseClickOnRotationPlaneEntityAxes.y); // Test.Debug( "Z axis distnace of point from origin: " + fDistanceOfPointFromOrigin ); // Test.Debug if (Math.Abs(fDistanceOfPointFromOrigin) > 0.0005) { fRotationAngle = -Math.Asin(VectorMouseClickOnRotationPlaneEntityAxes.y / fDistanceOfPointFromOrigin); if (VectorMouseClickOnRotationPlaneEntityAxes.z < 0) { fRotationAngle = mvMath.Pi - fRotationAngle; } // Test.Debug( "************RotANGLE: " + fRotationAngle ); // Test.Debug bRotAngleGot = true; } } else if (axis.IsYAxis) { fDistanceOfPointFromOrigin = Math.Sqrt(VectorMouseClickOnRotationPlaneEntityAxes.z * VectorMouseClickOnRotationPlaneEntityAxes.z + VectorMouseClickOnRotationPlaneEntityAxes.x * VectorMouseClickOnRotationPlaneEntityAxes.x); // Test.Debug( "Z axis distnace of point from origin: " + fDistanceOfPointFromOrigin ); // Test.Debug if (Math.Abs(fDistanceOfPointFromOrigin) > 0.0005) { fRotationAngle = Math.Asin(VectorMouseClickOnRotationPlaneEntityAxes.x / fDistanceOfPointFromOrigin); if (VectorMouseClickOnRotationPlaneEntityAxes.z < 0) { fRotationAngle = mvMath.Pi - fRotationAngle; } // Test.Debug( "************RotANGLE: " + fRotationAngle ); // Test.Debug bRotAngleGot = true; } } else { fDistanceOfPointFromOrigin = Math.Sqrt(VectorMouseClickOnRotationPlaneEntityAxes.x * VectorMouseClickOnRotationPlaneEntityAxes.x + VectorMouseClickOnRotationPlaneEntityAxes.y * VectorMouseClickOnRotationPlaneEntityAxes.y); // Test.Debug( "Z axis distnace of point from origin: " + fDistanceOfPointFromOrigin ); // Test.Debug if (Math.Abs(fDistanceOfPointFromOrigin) > 0.0005) { fRotationAngle = Math.Asin(VectorMouseClickOnRotationPlaneEntityAxes.y / fDistanceOfPointFromOrigin); if (VectorMouseClickOnRotationPlaneEntityAxes.x < 0) { fRotationAngle = mvMath.Pi - fRotationAngle; } // Test.Debug( "************RotANGLE: " + fRotationAngle ); // Test.Debug bRotAngleGot = true; } } } if (bRotAngleGot) { //fRotationAngle = fRotAngle; return(fRotationAngle); } else { return(0); } }