# Mesh Picking

## Recommended Posts

homer_3    173
I'm attempting to implement a picking function and having some trouble. No matter where my mouse is, the center of the screen is always picked. I got my code from a tutorial that I had to modify slightly. What I'm trying to do is place an object where the mouse is when the function is called. So I'm trying:
void setObjPos(UnitBase obj)
{
Point mouseLoc = Cursor.Position;

Vector3 rayStart, rayDirection;
Matrix proj = _camera.Projection;

Vector3 v;
v.X = (((2.0f * mouseLoc.X) / _device.PresentationParameters.BackBufferWidth) - 1) / proj.M11;
v.Y = -(((2.0f * mouseLoc.Y) / _device.PresentationParameters.BackBufferHeight) - 1) / proj.M22;
v.Z = 1.0f;

// Get the inverse of the composite view and world matrix

Matrix m = Matrix.Identity * _camera.View;
m.Invert();

// Transform the screen space pick ray into 3D space
rayDirection.X = v.X * m.M11 + v.Y * m.M21 + v.Z * m.M31;
rayDirection.Y = v.X * m.M12 + v.Y * m.M22 + v.Z * m.M32;
rayDirection.Z = v.X * m.M13 + v.Y * m.M23 + v.Z * m.M33;

rayStart.X = m.M41;
rayStart.Y = m.M42;
rayStart.Z = m.M43;

obj.Position = rayStart;
}


This seems to follow the general algorithm I've found in several places online.

##### Share on other sites
MJP    19755
D3DX has a function for exactly this purpose: D3DXVec3Unproject.

##### Share on other sites
homer_3    173
After looking at that I'm trying
Vector3 screenv = new Vector3(mouseLoc.X, mouseLoc.Y, 0);            screenv.Unproject(_device.Viewport, _camera.Projection, _camera.View, Matrix.Identity);            screenv.Z += 5;            obj.Position = screenv;

Which sort of works but not really. It's very inaccurate. But If I mouse the mouse left, it will put the object farther to the left and the same for all other directions. It's just not placed anywhere near the cursor.

##### Share on other sites
Buckeye    10747
Is your mouse location in screen coordinates or window coordinates?

##### Share on other sites
Endurion    5408
Since you start out with a 2d position you have to make up for the lost information (depth). A pixel on the screen can be made up from a whole ray in 3d space.

The usual way is to unproject two 2d points and use the resulting ray for intersection tests.

Call Unproject with two vectors:

Vector3 screenv1 = new Vector3( mouseLoc.X, mouseLoc.Y, 0 );
Vector3 screenv2 = new Vector3( mouseLoc.X, mouseLoc.Y, 1 );

You will get two points in 3d space which lie on a line. Now calculate the intersection with the resulting line (from the two points) and the plane the object lies on.

##### Share on other sites
homer_3    173
Quote:
 Original post by BuckeyeIs your mouse location in screen coordinates or window coordinates?

Screen coords.

##### Share on other sites
Buckeye    10747
Just to clarify as my terminology may not have been exact enough. By screen coordinates, I meant coordinates relative to the screen of your monitor, not "screen-space" in the DirectX sense.

Hopefully, window coordinates and screen-space coordinates are the same.

In any case, Unproject needs window (or screen-space) coordinates. I should just have said that. If you use GetCursorPos to get the mouse coordinates and your app is not full-screen, you need to use ScreenToClient to translate the mouse position to window coordinates before you call Unproject.

I'm not familiar with Cursor.position and didn't know if that returned screen or window coordinates.