gluUnProj

Hi,

I use gluUnProj to get a ray:

gluUnProject(lMousePos.x,lMousePos.y,depth[0],modelm,projm,(GLint*)view,&pos[0],&pos[1],&pos[2]);

So the direction (for selection) is (0,0,-1), isn’t it ?

So can I check for an intersection with a triangle by ignore the z-Coord ?

I don’t know what you mean by get a ray. I assume that for an (x,y) position on your screen like (312,522) you want a ray in 3D space?

gluUnProject maps the specified window coordinates into object coordinates using modelMatrix, projMatrix, and viewport. The result is stored in objx, objy, and objz. A return value of GL_TRUE indicates success, and GL_FALSE indicates failure. 

What I’ve used in the past is (winx,winy,.3) and (winx,winy,.6). This will give me two points in 3D space. Construct a vector from the first one to the second one, normalize it, and you’ve got a ray that goes out through that pixel. Is that what you want?

I don’t know what you mean by get a ray. I assume that for an (x,y) position on your screen like (312,522) you want a ray in 3D space?

Yes.

Construct a vector from the first one to the second one, normalize it, and you’ve got a ray that goes out through that pixel. Is that what you want?

Yes. But how can I construct this vector ? And what does normalize mean ?
I need that for intersections with triangles, how could I test that the quickest way ?

To construct a vector that pass from two point you have to substract the second to the first… that’s the definition of vector. :-S
A normalied vector is a vector of unit length


void normalize(vec3f &v)
{
  float sqLength = v.x*vx+v.y*v.y+v.z*v.z;
  if(sqLength != 0.0){
    float l = static_cast<float>(sqrt(sqLength));
    v.x/= l;
    v.y/= l;
    v.z/= l;
  }else
    throw std::runtime_error("Zero length vector normalization");
}

For the triangle/ray intersection try to google you will find the right algorithm.

It seems that one of the most often asked questions is ray triangle intersections. Keep in mind that calculating triangle intersections is slow especially if you’re doing it for a large scene. Make sure you really need that power. If you need a simpler method that involves getting whatever triangle is rendered at a given pixel (what most games need for picking) you can use OpenGL selection or something. Look up OpenGL picking for the various methods, but I’d read up on them before deciding to do a bunch of triangle intersections and starting to build an acceleration structure until you know why OpenGL picking techniques aren’t robust enough for you.

@Rosario Leonardi

Thanks, I will try that tommorow :wink:

@strattonbrazil

OpenGL selection (GL_SELECT) is limited to a fix numer of objects (128/256/…)
I used another method, selection by depth-testing, but there I have to get the depth from every object, and 60 times glReadPixels() is very slow…

So I hope the ray-triangle intersection is (much) faster than transfering the depth-values from the graphic card to main RAM…

What would you recommend for selection of many objects ?

Yeah, if you’re doing a huge number of objects, GL_SELECT isn’t an option. It depends on how many objects you really need to handle. I wish it were higher, but I think OpenGL 3 is getting rid of it anyway…

I’m not sure the exact number, but a lot of people have had good success using the color buffer. You can actually render the color buffer out in the same pass to a separate color buffer and do a glReadPixel on that. This may be naive, but if you’re using 32-bit color, you should be able to get that 32-bits of unique integers.

http://www.opengl.org/resources/faq/technical/color.htm#0050

Either way, you don’t have to waste any CPU time building acceleration structures and dealing with numerical errors doing triangle intersections.

What I’ve used in the past is (winx,winy,.3) and (winx,winy,.6). This will give me two points in 3D space. Construct a vector from the first one to the second one, normalize it, and you’ve got a ray that goes out through that pixel. Is that what you want?

But:

(winx,winy,.6) - (winx,winy,.3) = (0,0,.3)

That must be always (0,0,.3), or am I wrong ?

Sorry for the confusion. Your math is correct. You were using gluUnproject, so I thought my response was in context. You use (winx, winy, .3) and (winx, winy, .6) with gluUnproject to get the two points in 3D space as I said. You construct a vector from those two points. Not the two window coordinates as that would indeed always be (0,0,.3).

(winx, winy, .3) --> (worldX1, worldY1, worldZ1)
(winy, winy, .6) --> (worldX2, worldY2, worldZ2)

vec = normalize((worldX2, worldY2, worldZ2) - (worldX1, worldY1, worldZ1))

and that’s your vector in world space (assuming you give gluUnproject the basic modelview matrix).

You mean “.3” and “.6” as depth ?

Sure, depth or winZ as the docs call it.

Then I have ONE vector. But I need two points for a ray.
Shall I choose arbitrary points ? :sick:
Then I’d get the second point by adding the vector to the first point…

Solved.
I just used only the first triangle…
I forgot to increase the variable :o