-1
\$\begingroup\$

Could somebody please tell me what I'm missing?

I have a scene where the camera is fixed in the sky looking down on a plane. On that plane is a 3D model. I want to move the 3D model in the direction of the mouse whenever the person clicks. I have accurately converted the mouse coordinates into 3D coordinates and then according to my understanding all I had to do was the following:

direction = new Vector3(mouseX - modelX, 0, mouseZ - modelZ);
direction = Vector3.Normalize(direction);

However this doesn't quite work. If I remove the normalize part and divide it by 100 it works as in it moves towards the mouse but the speed is constantly changing (as it should) since I'm just dividing by 100, so I sorta-kinda-know the rest is fine. But if I get rid of that and keep the normalize part the character goes crazy and moves towards the mouse but it moves very fast and is constantly flashing in different positions around the mouse. In 2D I had to use sin and cosine after subtracting the values from one another, is there something similar I have to do in 3D?

Thanks!

Edit - code for figuring out the mouse position:

nearsourceV = graphicsDevice.Viewport.Unproject(new Vector3(mouse.X, mouse.Y, 0f), camera.Projection, camera.View, camera.World);
farsourceV = graphicsDevice.Viewport.Unproject(new Vector3(mouse.X, mouse.Y, 1f), camera.Projection, camera.View, camera.World);

fullMouseCoord = Vector3.Normalize(farsourceV - nearsourceV);

mY = -fullMouseCoord.Y;
mY = zoomAmount / mY;
fullMouseCoord  = fullMouseCoord  * mY;

And then the code for updating the model position:

public void MoveVertices(float x2, float y2, float z2)
{            
    for (int i = 0; i < vertices.Length; i++)
    {
        vertices[i].Position.X += x2;
        vertices[i].Position.Z += z2;
    }
}
\$\endgroup\$
3
  • \$\begingroup\$ Sounds like you're moving in the right direction, but the speed is the only problem. The very fast flashing around is because the character overshoots the target and then moves towards the target again. Can you show us the snippet of code you use for updating the position of the character? You can also try normalizing it, then dividing that by some constant value. \$\endgroup\$
    – House
    Commented Jun 18, 2013 at 13:31
  • \$\begingroup\$ Is it possible that your movement code somehow expects a vector with values like: (0.38, 0, 0.004) ; as in, something even smaller than a unit vector? What happens if you try normalizing the vector, and THEN dividing it by something like 100? My suspicion, of course, is that there's something wrong with either your movement code, or the code determining the mouse/model position. \$\endgroup\$
    – Katana314
    Commented Jun 18, 2013 at 13:35
  • \$\begingroup\$ I tried normalizing it and then dividing it. It helped alot, it now has a sane constant speed, however the issue where it flashes from two different locations is still there, just in a lesser degree now. I'll update the original post with both bit of code. \$\endgroup\$ Commented Jun 18, 2013 at 17:03

2 Answers 2

1
\$\begingroup\$

I think you need to add a delta time, and movement speed into the equations in MoveVertices. Without these, you are moving one unit per update. Something like the following will make it N units per second:

public void MoveVertices(float x2, float y2, float z2, float movementSpeed, float deltaTime)
{            
    for (int i = 0; i < vertices.Length; i++)
    {
        vertices[i].Position.X += x2 * movementSpeed * deltaTime;
        vertices[i].Position.Z += z2 * movementSpeed * deltaTime;
    }
}

where movementSpeed is units/second and deltaTime is the number of fractional seconds that have passed since the last update. This will slow your character down.

You can read more about delta times here: When should I use a fixed or variable time step? and here: http://gafferongames.com/game-physics/fix-your-timestep/

\$\endgroup\$
0
\$\begingroup\$

1) Figuring out mouse position:

I think is easier using a Ray/Plane intersection. Seems that your plane is Y=0, then the code is:

  nearsourceV = graphicsDevice.Viewport.Unproject(new Vector3(mouse.X, mouse.Y, 0f), camera.Projection, camera.View, camera.World);
  farsourceV = graphicsDevice.Viewport.Unproject(new Vector3(mouse.X, mouse.Y, 1f), camera.Projection, camera.View, camera.World);

  direction = Vector3.Normalize(farsourceV - nearsourceV);
  ray = new Ray(nearSource, direction);
  var plane = new Plane(Vector3.UnitY,0);
  var distance = ray.Intersects(plane);
  if (distance.HasValue)
      fullMouseCoord = ray.Position + ray.Direction * distance.Value;

2) really you need to move the verticesd that way?

When you draw a model is usual to pass a model transform matrix as argument to the shader, use it to translate your model.

  // This is a good place to rotate and scale your model too
  var ModelTransform =  Matrix.CreateTranslation( model_position ); 

3) As pointed before if you want move with constant speed towards mouse point:

  model_movement_direction = Vector3.Normalize(fullMouseCoord-model_position);
  model_position += model_movement_direction * speed * elapsed_frame_time;

or doing some easing

  model_position +=  (fullMouseCoord-model_position) * 0.05f;
\$\endgroup\$
3
  • \$\begingroup\$ XNA actually includes methods for getting the cursor co-ordinates. If memory serves you create a MouseState object and query the position from that. \$\endgroup\$ Commented Sep 17, 2013 at 7:44
  • \$\begingroup\$ yep.. in 2D screen space.. but if you want to move a 3d object although the projection is top, the best is doing it right. \$\endgroup\$
    – Blau
    Commented Sep 17, 2013 at 13:01
  • \$\begingroup\$ ah I'd completely misread the question then! \$\endgroup\$ Commented Sep 17, 2013 at 18:22

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .