Sign in to follow this  
ktuluorion

Picking: Finding out if/where a mouse click lies on a 3d plane

Recommended Posts

That about says it.. I want to take a mouse click, and figure out what coords the mouse is over on a 2d plane located in 3d space. Anybody have any ideas?

Share this post


Link to post
Share on other sites
hi there ktuluorion,
How are you doing?

The Problem
Transforming mouse coordinates from screen space to 3d space.

The Solution
Buddy, you might want to look into the following areas.
D3DXVec3Unproject Function
"Projects a vector from screen space into object space."
So just give it the screen coordinates of the mouse in your window. Remember that the angle at which your camera is, is also a factor and might complicate matter.

I hope this helps. Take care buddy.

Share this post


Link to post
Share on other sites
Hi, I am doing well, thank you.

I believe this function you have given me will help me. However, what I am unsure of is what I need to put into the D3DXVECTOR3 that I pass to it. I would imagine it would be X and Y coords of the mouse, but what would the third value be, since the screen is only 2d?

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
look at gluUnProject:
http://www.ugrad.cs.ubc.ca/~cs414/opengl/gluUnProject.html

You may have to modify the y value from gl y (bottom) to window y (top)

From the link you will see that you also need to pass GL_MODELVIEW_MATRIX, GL_PROJECTION_MATRIX, and GL_VIEWPORT values.

Share this post


Link to post
Share on other sites
If you want a ray you will have to have 2 vectors.. one for the near plane and one for the far plane.
You would then have
[source lang = "cpp"]
D3DXVECTOR3 near;
near.x = mouse.X;
near.y = mouse.Y;
near.z = 0;
D3DXVECTOR3 far;
near.x = mouse.X;
near.y = mouse.Y;
near.z = 1;


You can then just subtract the one vector from the other. This should work
D3DXVECTOR3 ray = far - near; which would give you a ray.

You can then use the D3DXIntersect Function to check if the ray intersects with a given mesh.

Share this post


Link to post
Share on other sites
This isn't quite working out right:


D3DXVECTOR3 v,vf,vn;
POINT lp;
D3DVIEWPORT9 vp;

GetCursorPos(&lp);
D3DXMATRIX matproj;
D3DXMATRIX matview;
D3DXMATRIX matworld;
d3ddevice->GetViewport(&vp);
d3ddevice->GetTransform(D3DTS_VIEW,&matview);
d3ddevice->GetTransform(D3DTS_WORLD,&matworld);
d3ddevice->GetTransform(D3DTS_PROJECTION,&matproj);

D3DXVec3Unproject(&vn,&D3DXVECTOR3(lp.x,lp.y,0),&vp,&matproj,&matview,&matworld);

D3DXVec3Unproject(&vf,&D3DXVECTOR3(lp.x,lp.y,1),&vp,&matproj,&matview,&matworld);
v=vf-vn;




This is coming out with all kinds of weird stuff, like values changing without the mouse even moving.

Share this post


Link to post
Share on other sites
Does anyone see an error in my code? I can't find anything wrong with it... I zeroed out the world matrix (I realized that is why it wasn't coming out as a static number without moving) now I get the number 1 all the time as the ray's x value (or any value)

Share this post


Link to post
Share on other sites
Hi,
I am currently working on the same issue. Take a look at the tutorial pointed by Scotto1001 (toymaker), it might help.

Share this post


Link to post
Share on other sites
Your sample code looks ok so far, but:

If you've got a pure device the GetTransform functions will fail. Check with the SUCCEEDED or FAILED macro.

A D3DXPlane can be constructed from three random points with the function D3DXPlaneFromPoints.

Then use D3DXPlaneIntersectLine function with the plane and the two points you got from the D3DXVec3Unproject calls.

Share this post


Link to post
Share on other sites

Here you go. This is how I have done it in my 3D Mesh Builder:


/////////////////////////////////////////////////////////////
// get a line from the mouse cursor projected into the world
/////////////////////////////////////////////////////////////

POINT m1;
GetCursorPos( &m1 );
pActiveView->ConvertMouseToLocal( m1 );

D3DXVECTOR3 result;
D3DXVECTOR3 result2;
D3DXMATRIX world;
D3DXMatrixIdentity( &world );

D3DVIEWPORT9 viewport;
pActiveView->GetDXDevice()->GetViewport( &viewport );

D3DXVec3Unproject( &result, &D3DXVECTOR3( m1.x, m1.y, 0 ), &viewport, &pActiveView->GetCamera()->GetProjection(), &pActiveView->GetCamera()->GetView(), &world );

D3DXVec3Unproject( &result2, &D3DXVECTOR3( m1.x, m1.y, 0.5f ), &viewport, &pActiveView->GetCamera()->GetProjection(), &pActiveView->GetCamera()->GetView(), &world );

IntersectLine line;
if( pActiveView->GetCamera()->IsViewProjected() )
{
line.start = pActiveView->GetCamera()->GetPos();
line.end = line.start + (10 * (result2-result));
}
else
{
line.start = result;
line.end = result2;
}

///////////////////////////////////////////////
// this code is to test my poly select methods
///////////////////////////////////////////////

int index = appData.pActiveMesh->GetPolyIndexOnLine( line );


Hope that helps. : )

Share this post


Link to post
Share on other sites
Quote:
Original post by Endurion
Your sample code looks ok so far, but:

If you've got a pure device the GetTransform functions will fail. Check with the SUCCEEDED or FAILED macro.

A D3DXPlane can be constructed from three random points with the function D3DXPlaneFromPoints.

Then use D3DXPlaneIntersectLine function with the plane and the two points you got from the D3DXVec3Unproject calls.


Pure device? What does that mean?

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