Sign in to follow this  
homer_3

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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this