Jump to content
  • Advertisement
Sign in to follow this  
pancomplex

[XNA] Making the mouse x and y coordinate into world space coordinates

This topic is 3753 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

Hello out there, After following the tutorial on the creators club's website, I figured out how to do the picking on my 3d models. However, when it comes to making the mouse x and y cordinates into world space, things start to get messy. I've tried to use the Unproject function, but it gives me weird numbers that make no sense :(. I want to make a method that returns a vector3 with the world coordinates based on the mouse x and y coordinate. Is this possible? /Christian

Share this post


Link to post
Share on other sites
Advertisement
Unproject is the type of function you need to use. If you're having trouble getting your routine to work correctly, post some code and, perhaps, someone can help you get it working correctly.

Share this post


Link to post
Share on other sites
Screen space looks like this:


0----------->
| screen width
|
|
|
|
v screen height


Point of origin is in the upper left corner, y-axis goes down, x,y coordinates are in the range of [0, width] and [0, height].


Post perspective space looks like this:


^ 1
|
|
|
|
|
----------0---------->
-1 | 1
|
|
|
| -1


Point of origin is the middle, y-axis goes up, x,y coordinates are in the range of [-1, 1]. You're using DirectX, so the z-values will be in the range [0, 1].


To transform your mouses x and y coordinates to pps, do this:

x' = (2 * x / screen_width) - 1;
y' = -(2 * y / screen_height) + 1;

Then you can make two 3D vectors, one on the far plane (z' = 1), one on the near plane (z' = 0) and transform them into world space by multiplying them with the inverse of the projection and view matrices.

Share this post


Link to post
Share on other sites
Okay, at the moment my method looks like this:


private Vector3 MousecordinatesToWorld()
{
Vector3 Coordinates =

this.graphics.GraphicsDevice.Viewport.Unproject(

new Vector3(Mouse.GetState().X, Mouse.GetState().Y, 0),

gameCamera.projectionMatrix, gameCamera.viewMatrix, Matrix.Identity);


return Coordinates;
}

The output of the vector3 should the return the world coordinates, but it doesn't :(

Share this post


Link to post
Share on other sites
Unproject cannot restore the full depth. After all you start out with 2d coordinates but want to end up with 3d coordinates.

But every pixel on the screen actually represents a line of possible coordinates in 3d space.

What you want to do is to get actual hit point of where this line and the object that created that pixel meet.

Therefor you call Unproject two times, both with x,y being the mouse pos, but with varying z values. Now you have two possible points in 3d space. These two points lie on that line.

Now you have to do collision detection and calculate where that line collides with something from your world. And there's your resulting hit point in 3d space.

Share this post


Link to post
Share on other sites
So how exactly would I need to modify my method to do that? I've been messing around with this for hours now, and it just doesn't work :S

Share this post


Link to post
Share on other sites
As Endurion mentioned, you need to unproject twice.

I suggest:

vec0 = Unproject(new Vector3(Mouse.GetState().X, Mouse.GetState().Y, 0)..)

and

vec1 = Unproject(new Vector3(Mouse.GetState().X, Mouse.GetState().Y, 1)..)

Then, the direction of the vector under the mouse position is:

mouseDirection = vec1 - vec0

Use mouseDirection to Pick() some mesh (pick point=vec0, pick direction = mouseDirection) in the world. That "pick" will return in coordinates of the mesh in the world under the mouse pointer.

Share this post


Link to post
Share on other sites
Buckeye explained in detail. You cannot modify your function because the hit detection will need some objects or a plane to do detection with.

You can return the two vectors (2 positions, or position plus direction) and have to modify the detection to your current scene.

Share this post


Link to post
Share on other sites
Quote:
Original post by Buckeye
As Endurion mentioned, you need to unproject twice.

I suggest:

vec0 = Unproject(new Vector3(Mouse.GetState().X, Mouse.GetState().Y, 0)..)

and

vec1 = Unproject(new Vector3(Mouse.GetState().X, Mouse.GetState().Y, 1)..)

Then, the direction of the vector under the mouse position is:

mouseDirection = vec1 - vec0

Use mouseDirection to Pick() some mesh (pick point=vec0, pick direction = mouseDirection) in the world. That "pick" will return in coordinates of the mesh in the world under the mouse pointer.


I really dont get it. I don't want to get the mesh coordinates, I want to get the mouse coordinates in the 3d world. Isn't this possible to do with one method?

I have a plane in the map which is loaded from a model called Map.

Sorry if I act like a n00b :(

Share this post


Link to post
Share on other sites
Quote:
I want to get the mouse coordinates in the 3d world.

The mouse location is not a point in the 3d world. It's like looking down an arrow. It appears to be a point from your view, but in the world, it's a vector or a line running from the front wall of the frustum to the back wall.

The two "unprojects" I outlined above give you the world point at the front wall of the frustum or screen (z=0), and the back wall of the frustum (z=1).

You can select any point along that line you want to represent the mouse. It's most usual function is to find the point on a mesh underneath the mouse by picking.

Think of the mouse position on the screen as some point in the 3d world projected onto the screen. That world point can be any distance away from the screen as long as it's "under" the mouse position. Any of the infinite number of world positions "under" the mouse will project onto the screen at the same point. That point can be as close to you as the screen itself (the world position given by Unproject((mousex,mousey,0)..), or as far away from you as the back wall of the frustum (the world position given by Unproject((mousex,mousey,1)..).

You can get a world position with just a single Unproject call, but you have to know what z-value (between 0 and 1) in projection space you want to use, where between the screen and the far plane you want it to be. That's pretty difficult to determine without some reference, like the surface of a mesh.

Maybe we can help you better if you can tell us what you want to do with that world position.


[Edited by - Buckeye on August 2, 2008 6:41:14 PM]

Share this post


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

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!