• Advertisement
Sign in to follow this  

Constant speed for dragging of 3D objects by mouse

This topic is 989 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I am implementing dragging 3D object by mouse in my engine.

 

I have the following formulas:

1. I get length of the vector from camera to object

2. Calculate angles like FOV/width (for X axis) * mouseDelta.X

3. Find triangle side length like var x = Math.Tan(angleX)*distance;

4. multiply X *= frame time;

 

So, I receive the length in the 3D world space on which I must move the model.

Then I multiply my camera relative X and Y axis on those final values (X and Y) and add to the current position.

And it seems working for fps 300.

 

But when I set 60 fps, my gametime increases and object become moving much faster.

 

My goal is to make my dragging algorithm fps independent and move all objects with constant speed.

 

Does anyone know how to reach that?

Share this post


Link to post
Share on other sites
Advertisement

My frame time is correct. I am sure. for 220 fps its - 0.004, for 60 fps - 0.016. Si, its logic that multiply the same value on different frametime will give me different results and in the second case result will be bigger.

Share this post


Link to post
Share on other sites

Frame time shouldn't be used here at all?

 

Unless you want to push the object which would then be going on its way all by itself the object should simply be placed under the current location of the mouse.

Share this post


Link to post
Share on other sites

Here is my calculations:

//Distance - distance to object (length of the vector (offset - absolute position))
               var distance = SelectedEntity.GetDistanceToCamera(cameraController.UserControlledCamera.Offset).Length();
               //angle of the triangle = (FOVx / width of the screen) * mouse offset for X axis
               var angleX = (cameraController.UserControlledCamera.Fov/cameraController.UserControlledCamera.Width)*
                           (totalDelta.X* (float)GameTime.FrameTime);
               //angle of the triangle = (FOVy / width of the screen) * mouse offset for Y axis
               var angleY = (cameraController.UserControlledCamera.Fov / cameraController.UserControlledCamera.Height) *
                           (totalDelta.Y * (float)GameTime.FrameTime);
               //find shift for X axis
               var x = Math.Tan(angleX)*distance;
               //find shift for Y axis
               var y = Math.Tan(angleY)*distance;
               
               SelectedEntity.MoveRelX(right, (decimal)x  );
               SelectedEntity.MoveRelY(up, (decimal)-y);

My question is how to keep object exactly under the cursor? Because In my case they have big shift.

 

Maybe my calculations incorrect?

Edited by BlackJoker

Share this post


Link to post
Share on other sites

Try this:

 

Calc the ray from under the mouse pointer towards the object at the old position.

Define a plane parallel to the screen surface at the exact distance from screen to object.

Calc the ray from under the mouse pointer at the new position.

Place the object at the intersection between new ray and the plane.

 

 

With that method the object is always moved parallel to the current camera angle. You may want to define the plane differently to confine the object to some level specific area.

Share this post


Link to post
Share on other sites

But result of intersection is in the screen coordinates. How I will translate them to my 3d world coordinates?

Edited by BlackJoker

Share this post


Link to post
Share on other sites
The actual result should be in 3d coordinates already. The key word is unproject, e.g. take the mouse screen coordinates and get the ray that one pixel represents in 3d space.
 
For SharpDX use this method: http://sharpdx.org/documentation/api/m-sharpdx-vector3-unproject
 
Unproject the screen coordinates twice, with z set to 0 and 1 respectively. This nets you two points in 3d space, defining a line/ray. Edited by Endurion

Share this post


Link to post
Share on other sites

Ok, seems I implement this, but I see a serious issue regarding intersection point.

I dont know why, but in some places (mostly near the edges of directX window) plane intersection check gives floating results for the same coordinates.

And this causing objects jump from one position to another.

 

Maybe My implementation is not correct. Could you just take a look on it?

var ray2 = CalculateRay(MouseManager.RelativeCoordinates, cameraController.UserControlledCamera,
                   SelectedEntity.GetActualMatrix());
               Plane p = new Plane(cameraController.UserControlledCamera.ViewMatrix.Backward, Vector3.UnitZ);
               Vector3 position;
               var res = ray2.Intersects(ref p, out position);
               RenderSystem.D2DText += "Distance to plane = " + SelectedEntity.GetRelativePosition() + "\n";
               RenderSystem.D2DText += "Intersection with plane = " +res+"\n";
               RenderSystem.D2DText += "Point = " + position + "\n";
               if (res)
               {
                  startPoint.X += (decimal)position.X;
                  startPoint.Y += (decimal)position.Y;
                  SelectedEntity.SetPosition(startPoint);

               }

I not set plane to the distance to the object bacuse in that case object not synced with the mouse cursor. And jump are much more bigger at that case.

 

When plane at the same distance as the object, it also give me diferent (in most cases opposite) results from frame to frame. For ex, X = 4000 and at the next frame it will be -4000. This leads to visual effect when seems that object is in 2 different places at the same time.

 

I suspect that I do something wrong with plane.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement