Skip to main content
GameDev.net gamedev.net
🔒 Locked

Highlighting objects based on 3d click

Started by Endar Mar 21, 2005 at 6:36 AM 4 replies 1.1k views
Original Post
Endar
Endar
I'm working on a little 3d editor(win + opengl), and I got this little piece of code from one of the articles on NeHe.

CVector3d GetOGLPos(int x, int y)
{
	GLint viewport[4];
	GLdouble modelview[16];
	GLdouble projection[16];
	GLfloat winX, winY, winZ;
	GLdouble posX, posY, posZ;

	glGetDoublev( GL_MODELVIEW_MATRIX, modelview );
	glGetDoublev( GL_PROJECTION_MATRIX, projection );
	glGetIntegerv( GL_VIEWPORT, viewport );

	winX = (float)x;
	winY = (float)viewport[3] - (float)y;
	glReadPixels( x, int(winY), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ );

	gluUnProject( winX, winY, winZ, modelview, projection, viewport, &posX, &posY, &posZ);

	return CVector3d(posX, posY, posZ);
}

Now, this returns 3d coords for a 2d window click. But I'm having a little bit of trouble when I think about how I'm going to be able to use this to highlight the object that was clicked on.

// The points that I'm drawing:
glVertex3f( 4.0f,  4.0f, -10.0f);
glVertex3f(-4.0f, -4.0f, -10.0f);

// coords that I recieved from function
3.99569, 4.08208, -10
-4.03888, -3.99569, -10

So, how would I go about finding exactly which object is being clicked on? Note: so far I haven't gone as far as choosing a data structure to keep my objects in, so for this exact problem, I'm basically starting from the start. I pretty much have 3d coords and need to find the object they belong to, or are closest to. Got any ideas that could help?
[size="2"][size=2]Mort, Duke of Sto Helit: NON TIMETIS MESSOR -- Don't Fear The Reaper
pim
pim
To find out which object was selected you can render the scene (to an offscreen buffer) with (flat) colors that represent the objects ID and the get the ID at the point where the mouse is. The ID will basically be a 24 bit integer...
lubby
lubby
Convert the 2d screen space position into a 3d world space position, Not sure is gluUnproject does this, as I dont code with this API. Use the result from gluUnproject as the destination position.

From there you can create a ray.

Vector3 ray = dest - source;
ray.Normalise();

now you can use this ray and test against objects in the scene.

for (int i=0;i if (ray intersects objects)
object = selected;

I personally would just test against bounding boxes or simpler bounding spheres, but you may require ray versus triangle tests. Do this though after a bounding box or sphere test returns a positive. Note that a ray test should return a distance to the collision point. If this value is negative then the collision is behind the near clip plane and should be discarded.
Endar
Endar
Quote:
Original post by lubby
From there you can create a ray.

Vector3 ray = dest - source;
ray.Normalise();


lubby: if the return from glUnProject is the destination, what is the source? The camera position?
[size="2"][size=2]Mort, Duke of Sto Helit: NON TIMETIS MESSOR -- Don't Fear The Reaper
lubby
lubby
gluUnProject with winZ as 0 will give you a source point. And following OrangyTang line of thought, winZ as 1.0 will give you a dest point.

However the source is the translation part from the inverse of the modelview * projection matrix.

// you can project your cursor pos into a screen space vector like this (assume float16 matrix)Vector3 v;v.x =  (((2.0f * cursor.x) / winsizex ) - 1) / projection[0];v.y = -(((2.0f * cursor.y) / winsizey ) - 1) / projection[5];v.z =  1.0f;// Inverse of projection & modelviewMatrix16 invMat = Inverse(modelview * projection);// now transform screen space ray into world space (assume float16 matrix)Vector3 rayDir;rayDir.x  = v.x*invMat[0] + v.y*invMat[1] + v.z*invMat[2];rayDir.y  = v.x*invMat[4] + v.y*invMat[5] + v.z*invMat[6];rayDir.z  = v.x*invMat[8] + v.y*invMat[9] + v.z*invMat[10];Vector3 rayOrigon;rayOrigon.x = invMat[3];rayOrigon.y = invMat[7];rayOrigon.z = invMat[11];


I am pretty sure the matrix indexes are correct but no guarantees there :) I am use to using row major matrices not column major. This is probably what gluUnproject is doing anyhow so go with whatever works for you.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.