PDA

View Full Version : easy picking



{MSX}
04-04-2005, 05:28 PM
hi! I was reading some of the picking tecnique, to see where the mouse is pointing in a 3d game.
Now i've a very simple problem: to see in which tile the mouse is pointing.
The tiles are laid horizontally on the x,z plane, so the problem is simply to see where the mouse intersect the horizontal plane..
What's the easiest way to do this ? Thanks!

savage
04-04-2005, 09:41 PM
I have never tried working out how to do picking in OpenGL ( actually not done much at all in OpenGL ), but I found this article http://www.lighthouse3d.com/opengl/picking/ which seems to cover different techniques for doing it.

Paulius
05-04-2005, 06:00 AM
A more universal API independant way would be to shoot a ray from eye to mouse position and get the closest intersection with pickable objects
bounding spheres(or other primitives if you really need them)

Sly
05-04-2005, 06:13 AM
I'm not sure how much help this will be. It is a function that I wrote several years ago just after starting here at Krome that helped to work out which 3D object was selected with the mouse. Basically, it works out the world coordinate on the near clip plane, the world coordinate on the far clip plane, then casts a ray between those points from near to far. If the ray collides with an object, it returns the world position and normal of that collision point. It could also return the object that it collided with if it was extended a bit more.

BG was the name of our proprietary engine back then. BGU was my little utility library for common functions. Yes, it's in C. :)

vpRight and vpBottom were the right and bottom edges of the viewport, in this case, the width and height of the viewport.



//---------------------------------------------------------------------------
// Function: BGU_ProjectScreenToWorld
// Purpose: Projects a ray from the screen coordinate into the world and
// checks for a collision
// Input: sx, sy Screen coordinate
// world Pointer to a vector that will receive the world
// coordinate of the collision point
// normal Pointer to a vector that will receive the normal of
// the polygon that was involved in the collision. Can
// be NULL if no normal is required
// Output: int 0 if no collision, !0 if a collision

int BGU_ProjectScreenToWorld(int sx, int sy, Vector *world, Vector *normal)
{
Vector nearPoint, farPoint, farView;
float px, py;
float fovx, fovy;
BG_GetFOV(&fovx, &fovy);

// Get near point in worldspace
px = (((float)sx / (float)vpRight) * 2 - 1) * (nearPlane + 1.0f) / fovx;
py = (((float)sy / (float)vpBottom) * 2 - 1) * (nearPlane + 1.0f) / fovy;

BG_WorldPoint(px, py, (nearPlane + 1.0f), &nearPoint.x, &nearPoint.y, &nearPoint.z);

// Get far point in worldspace
px = (((float)sx / (float)vpRight) * 2 - 1) * (farPlane - 1.0f) / fovx;
py = (((float)sy / (float)vpBottom) * 2 - 1) * (farPlane - 1.0f) / fovy;

BG_WorldPoint(px, py, (farPlane - 1.0f), &farPoint.x, &farPoint.y, &farPoint.z);

// Now we have the near point and the far point, test for collision between them
if (BG_SurfaceHit(WORLD_OBJECT, nearPoint.x, nearPoint.y, nearPoint.z, farPoint.x, farPoint.y, farPoint.z))
{
if (world)
BG_GetLastPoint(&world->x, &world->y, &world->z);
if (normal)
BG_GetLastVector(&normal->x, &normal->y, &normal->z);
return 1;
}
else
{
return 0;
}
}

{MSX}
05-04-2005, 07:04 AM
Thanks everybody!
I only need some really basic picking, ie the intersection with the y panel.
I think Sly function may help.. if i have the line that's beneath the mouse, i can do a line/plane intersection.
The problem is that that function is not so clear without the called functions :P
For example the how the BG_GetFov work ? and the BG_WorldPoint ?
Also, where the nearPlane and farPlane came from ?

Thanks :P

Sly
05-04-2005, 07:13 AM
BG_GetFOV(): Returns the current field of view.
BG_WorldPoint(): Transforms the point from local (view) space back to world space. This is an inverse of the world-to-local transformation.
The near and far plane came from another function in my BGU library (BGU_SetClipPlanes).

As long as you know what you have set your fov, near and far planes to, you should be able to use those values in this function.

cragwolf
07-04-2005, 05:58 AM
I'm thinking of doing it this way:

1) Use gluUnproject to transform window coordinates (winx, winy, winz) to object coordinates (objx, objy, objz). Use it twice: once with winx = 0.0 for near plane; and once with winz = 1.0 for far plane. Subtract these two points from each other to retrieve a ray vector.

2) Use the ray vector to test for intersection with each selectable object in your frustum. There are plenty of sources for intersection algorithms on the net and in books. Use the nearest intersection (i.e. the closest object) for your selection.

I haven't tried it yet, though. Maybe I'll try it tomorrow and post some code here. It looks interesting enough to warrant the effort. 8)

Sly
07-04-2005, 06:06 AM
That's basically what my function does. :)

savage
07-04-2005, 11:51 AM
There's a new article on picking over @
http://www.bookofhook.com/Article/GameDevelopment/mousepick.pdf

Sly
07-04-2005, 09:35 PM
If you understand all your mathematical equations, that article may be of some assistance. It left me dumbfounded, primarily because I do not understand mathematical equations. There is no code at all, not even pseudo-code. Give me code in an article, then I'll understand it.

cragwolf
07-04-2005, 10:50 PM
That's basically what my function does. :)

Good, at least I know I'm on the right track. :) I should have my example done in a few hours. Unless there are bugs!

cragwolf
08-04-2005, 04:06 AM
Example is done. See the Tutorials and Links (http://www.pgd.netstarweb.com/viewforum.php?f=20) forum.