1
\$\begingroup\$

I'm making a networked game which has a birds-eye view and I'm trying to convert the 2D mouse coordinates into 3D space. Right now I have a perfectly flat grid and it intends to remain perfectly flat, all I really want is the mouse coordinates to translate onto this grid.

I had a solution figured out that worked fine if the camera was perfectly straight looking down which I thought was going to be enough for what I wanted, but now I've found that it would be nicer if the camera had a slight tilt to it which completely messes with what I have. Could someone help me out in what I'm missing?

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

mouseCoordinatesIn3D = Vector3.Normalize(farsourceV - nearsourceV);

zoomMultiplier = -mouseCoordinatesIn3D.Y;
zoomMultiplier = camera.CameraOffset.Y / zoomMultiplier;

mouseCoordinatesIn3D = mouseCoordinatesIn3D * zoomMultiplier;

mouseCoordinatesIn3D.X = mouseCoordinatesIn3D.X + camera.CameraOffset.X;
mouseCoordinatesIn3D.Z = mouseCoordinatesIn3D.Z + camera.CameraOffset.Z;


//Sends data and moves character

I figured I needed to include the camera rotation into it somehow, but I'm not really sure how or where.

Thanks!

\$\endgroup\$
1
\$\begingroup\$
  1. The grid has a plane associated. It should be Y=0, if you want to get 2D coords easily, the normal will be Vector3.UnitY
  2. If you want to do zoom you should do it by modifying the camera view
  3. The Camera.World has not sense, it should be the plane world... or the transformations that you apply to the grid... if you don't apply it should be Matrix.Identity

This way the plane coords can be calculated this way:

var plane = new Plane(Vector3.UnitY, 0); // At (0,0,0)
nearsourceV = GD.Viewport.Unproject(new Vector3(mouse.X, mouse.Y, 0f), camera.Projection, camera.View, PlaneWorld); 
farsourceV = GD.Viewport.Unproject(new Vector3(mouse.X, mouse.Y, 1f), camera.Projection, camera.View, PlaneWorld);

var ray = new Ray( nearsourceV , Vector3.Normalize(farsourceV - nearsourceV));

var distance = ray.Intersects(plane);

if (distance.HasValue) {    
        coords3D = ray.Position + ray.Direction * distance;    
        // if your plane is Y=0, the 2D grid coords are x,z 
}
\$\endgroup\$
  • \$\begingroup\$ Ah thanks. Sorry for the super late response, that helped a lot. Before I didn't understand rays at all but I read through some tutorials and now the code makes perfect sense. \$\endgroup\$ – user1157885 Aug 15 '13 at 14:42
0
\$\begingroup\$

Right now I have a perfectly flat grid and it intends to remain perfectly flat, all I really want is the mouse coordinates to translate onto this grid.

[...]

I figured I needed to include the camera rotation into it somehow, but I'm not really sure how or where.

The Unproject call takes all the camera information it needs, so you're probably just missing the ray/grid intersect calculation.

mouseCoordinatesIn3D.X = mouseCoordinatesIn3D.X + camera.CameraOffset.X;
mouseCoordinatesIn3D.Z = mouseCoordinatesIn3D.Z + camera.CameraOffset.Z;

So you no longer need to do that - the plane intersect would calculate the appropriate (x,z) using your ray.

XNA gives you a handy function: Ray.Intersects.

Your mouseCoordinatesIn3D variable is probably better being called the rayDirection, and your nearsourceV is the starting Position of the ray.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.