Archived

This topic is now archived and is closed to further replies.

Landsknecht

3D object selection

Recommended Posts

Anyone have any idea how to pick out an object in 3D space based on mouse clicks? I am making a board game and need to pick a grid square on the board. I want to use the mouse to click the grid square and have NO idea how to go about it. Any help is welcome. Landsknecht "For gold or glory, but never for free!"

Share this post


Link to post
Share on other sites
If you are using a 2D mouse cursor on top of a 3D world then the first thing you need to do is find out what 3D objects are underneath the current 2D position of the mouse. This process is sometimes called picking, and your 3D api might support this, e.g. Direct3D Retained Mode has a function Direct3DRMViewport.Pick which takes a 2D pixel coordinate and returns a list of 3D objects underneath it. There''s a similar function for picking faces on a mesh.

If you are using a 3D virtual reality pointer instead of 2D mouse (e.g. a hand) which is moved to physically touch things, then you know what your pointer has touched via standard 3D collision detection techniques.

Unfortunately, since I only know Direct3D Retained Mode, I cannot help you with other 3D APIs, but looking up terms like picking, transform, inversetransform might help.

Share this post


Link to post
Share on other sites
I am using DX8. Standard mouse stuff (2D pointer). I looked throught the SDK and couldn''t find anything similar to what you are describing. I may just be overlooking the obvious though. I did find a sample in the SDK that allows you to pick polys - but the sample seems to be concerned with getting the texture coords and not the object.

I thought about using a color map on an offscreen surface and mapping mouse points to that surface and retrieving a color to map to the board... Overly complicated?

Still looking for advice,
Landsknecht
"For gold or glory, but never for free!"

Share this post


Link to post
Share on other sites
You could project a ray from camera cordinates (X_Mouse,YMouse,0), direction (X_Mouse,YMouse,1). Then check intersection on this ray with the faces of objects near of the ray, excluding the objects far from the ray via BSP, OCT Tree, etc.

Hope it helps!

Share this post


Link to post
Share on other sites
If you are using the D3DX Utility library have a look at D3DXVec3Unproject which will project a vector from 2D screen space to 3D object space. Then have a look at D3DXIntersectMesh which takes care of ray intersections with triangles.

As I explained before, I haven''t used D3DX myself so I cannot vouch that these will work, but after looking at the documentation I think they''re a good starting point.

Perhaps one of these days I will progress from Retained Mode to D3DX.

Share this post


Link to post
Share on other sites
I DID check the forums and you are right, it is a bi-weekly topic. However, it is a topic that has NEVER been answered with anything resembling a decent or knowledgeable answer.

Thanks for the reference to the DX util functions. I had not found them yet. I will give it a shot and post back with results.

Landsknecht,
"For gold or glory, but never for free!"

Share this post


Link to post
Share on other sites
You mentioned that you saw the example in DX8. Indeed this is what you need. You are right, the example also calculates the texture coordinates, but it also calculates the polygons that were picked. You may simply throw away the texture coordinates that were calculated. Just have a look at the sample again. Run it and click on any poly. You will see that it is highlighted. Now make your board, where every square is two triangles, let the algorithm run and test which polygons on the board are hit, and tada, you are ready.
What the example indeed does is casting a ray from the center of your camera through the mouse position by doing an inverse projection (unproject) of the mouse point. Then it calculates the intersection point of this ray with all planes within which triangles lie (except if the ray is parallel to the plane). Now your "texture" coordinates are calculated. It is indeed not the real texture coordinates, but the 2D coordinates of the intersection point in the coordinate system that is spanned by the border vectors of the triangle. If those two coordinates are larger than 0 and their sum is smaller than 1, the ray hits the plane inside the triangle, otherwise outside. That those two coordinates are also returned, is just a bonus, you may throw them away.
The math behind this is rather simple. You only need the cross product (which calculates the normal on two vectors) and the dot product. Where a.b = length(a) * length(b) * sin(angle between a and b). And thus calculates somewhat the length of a in the direction of b. I think nothing more is needed, but it is quite some time, I looked at it.
I hope you are now able to understand the pick example or you can even code it yourself. The thing is much simpler if you calculate this for a board anyways, because you only need to calculate the intersection point with one plane, and then decide on the coordinates you get which field was clicked.
Pictures would help a lot, but I am no good at ascii art.

Share this post


Link to post
Share on other sites