PDA

View Full Version : Ray picking with glPushMatrix() and glPopMatrix()



increator
07-21-2012, 08:35 AM
Hello
Im trying to do a ray picking for quads drawn like this:




bool bCollided = IntersectedPolygon(vCube, vLine, 4);


float scval=1.1f;

for (int x = 0; x <= 1; x++) {
for (int y= 0; y <= 1; y++) {
glPushMatrix();
glTranslatef(scval * x, 0.0f, scval * y);

for (int z=1; z <= 1; z++) {

glPushMatrix();

glBegin(GL_QUADS); // Draw A Quad

if(bCollided) {
glColor3f(1.0f, 0.0f, 0.0f);
}else
{
glColor3f(0.5f, 0.5f, 0.5f);
}

glVertex3f(0.00, 1.00, 1); // Top Left
glVertex3f( 1.00, 1.00, 1); // Top Right
glVertex3f( 1.00, 1.00, 0); // Bottom Right
glVertex3f(0.00, 1.00, 0); // Bottom Left
glEnd(); // Done Drawing The Quad

glPopMatrix();
glTranslatef(0.0f, scval, 0.0f);
}// z
glPopMatrix();
}// y
}// x


Here is image:
http://i.minus.com/iMeDc6d83hjDg.JPG

As you see, picking only works for first quad, not for the rest of them.
For the rest, ray picking just doesn't do anything.

Im very poor at 3D math and advanced openGL, but maybe here are experts who know what the problem is and how to solve it?
I googled alot, even tried to find some open source codes, with similar problem, but there isn't anything.

Maybe it's possible to get rid of the glPushMatrix() and glTranslatef() at all and still draw quads like so?
If somebody knows how to do that also, i would be very thankful.

This could fix the ray problem i have. I believe.


Thank you in advance.

V-man
07-22-2012, 07:10 AM
Maybe it's possible to get rid of the glPushMatrix() and glTranslatef() at all and still draw quads like so?
If somebody knows how to do that also, i would be very thankful.


Yes, you can get rid of those functions and do the vertex transforms yourself. All you have to do is build a translation matrix and multiply it by your vertices, which is pretty easy to do.
http://en.wikipedia.org/wiki/Translation_matrix

If you don't want to write your own math library, there is my glhlib.

increator
07-22-2012, 04:37 PM
Yes, now it i can draw without glPushMatrix(), glTranslatef(). Very nice.
Now the multiple cube picking, im drawing cubes now. Basically i got it to work. I can select any of the blocks i want, i even have the coordinates and face nr, where user clicked. But there is one problem.

The picking is too good. Really. It does too much work. I mean, it does picking of every cube on the scene. Although i ask him to do that but... For example i have 2 cubes, One in front and another behind it. Let's say i click on the cube that's on the front.
Ray goes through first cube and through second cube that's behind the first cube. It goes through first cube faces then inside second cube and detects the back side of it, even if user does not see it.

But it should not do that, if it detects the first cube face, the ray should "stop" and not go through cube faces to the far other sides.
I hope somebody understand what i mean.

But i have no idea how to do that. I have one loop, that goes thru all the blocks in the scene. Doesn't matter if it's visible or not, then it goes thru all the cube faces (5 faces for me), and then i just test the ray for each cube vertices. If i find it, then i just getting it's coords or face id, where user clicked.

I have no culling or something like that. Except face culling.

Any ideas how i should rewrite my rendering? How to make the ray stop on first detected side (face) of cube?
Break from loop?

V-man
07-23-2012, 10:19 AM
You can use GL to render each cube with a different color, as described here
http://www.opengl.org/wiki/Common_Mistakes#Selection_and_Picking_and_Feedback _Mode

GPUs tend to be fast so maybe it will be faster than your own ray-collision algorithm.

increator
07-23-2012, 11:32 AM
Yes, i have working implementation of my cube picking with unique colors.
You see, im also coding / using Borland Delphi. Because it's easier to create GUI with.
So this implementation was coded in Delphi and using additional C++ DLL, to make it faster.


My trick in Delphi was to render each cube and each cube face with color, according to it's position X,Y,Z. Ie color was derived from current cube X,Y,Z position + color for identifying current cube face. So main color + face color + some unique ID added to it. I don't even remember all the tricks i used.

In that helper DLL, i was using std::map, because it's so fast and Delphi doesn't have it.
In my case everything in picking must be as fast as possible. Because in my editor, user can hold down left mouse btn and at the same time drag over cubes and my code should know exactly the X,Y,Z position of current cube and the specific face of cube. Always, when dragging or just clicking on some cube.

It worked with my tricks, but i also remember that it had some weird problems sometimes.
Sometimes it was fast enough and some other day, it was too slow or refused to work correctly.
My source was getting very big, and it was hard to debug, why it fails sometimes or slows down.


So i have plan to rewrite it in pure C++, with minimal stuff. Just white cubes with unique hidden colors and picking.


But at the moment,
i also have plan b with code from friend (http://www.youtube.com/user/thecplusplusguy), who made better cube and face picking for me in C++, but it had problems with the same thing i had: glTranslatef(), glPush(Pop)Matrix() and making ray work with them.

So he used just rand() function to glTranslatef() cubes at random positions and then doing a ray picking.

But his face picking was working very well, ray didn't go through the cubes, it was just detecting "front" faces and skipped the backside of cube. And it was amazingly fast. That's what i need exactly.

So...

I will try to render his cubes without glTranslatef(), glPush(Pop)Matrix() and if ray picking with his cubes still works after this. Then i guess i can be happy.
Will post the code here also.


I will let you know.

increator
07-25-2012, 05:24 AM
OK, rewrote in C++, set my rendering threaded timer to interval of 1ms and picking with unique colors is very fast and precise, and another important thing for me: it doesn't depend on cam rotation.
CPU usage stays in 70%. It could be lower but the speed of picking in my case slows down. Specially when dragging with mouse and doing a glReadPixels().

I guess i leave it to 1ms. Best for picking.