PDA

View Full Version : Getting the depth image of a 3D object



Prendtout
03-01-2012, 08:22 AM
Hi all,

I'm currently trying to save the depth image (pixel values = depth ) of 3D models. The aim is to simulate a kinect sensor taking depth pictures of a 3D object.
After looking at some websites, I read there are three ways to achieve this: using the zbuffer, using the wbuffer or using ray casting.
Which would you advice ? What are the pros and cons ?

For now, the only thing I barely managed to do is get information from the zbuffer. But I guess I'm doing something wrong as the values I get are really strange.

glEnable(GL_DEPTH_TEST);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGBA);

GLfloat *zData = new GLfloat[window_width*window_height];
glReadPixels(0, window_height, window_width, window_height, GL_DEPTH_COMPONENT32, GL_FLOAT, zData);


If you have better ideas, or know of a project already doing this, I would be glad to ear about.

Thanks for your advice.

Alfonse Reinheart
03-01-2012, 10:19 AM
What is "really strange" about the values?

Also, you should read your depth buffer back in the format that it's stored in. Which means that unless you did something special when creating it, it is likely stored in 24_8 format (where the 8 bits are stencil bits). You should read them back as unsigned integers.

Prendtout
03-02-2012, 07:50 AM
Well, the values are all zeros while there should be a huge teapot in the middle of the scene.
According to your comment I modified the code :

GLuint *zData = new GLuint[window_width*window_height];
glReadPixels(0, window_height, window_width, window_height, GL_DEPTH_COMPONENT24, GL_UNSIGNED_INT, zData);

But I get the same result.

Here is my display function, in case the problem is there :

readDepth();
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Clear the background of our window to red
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //Clear the colour buffer (more buffers later on)
glLoadIdentity(); // Load the Identity Matrix to reset our drawing locations
glTranslatef(0.0f, 0.0f, -3.0f);
glutSolidTeapot(1.0f); // Render a teapot
glutSwapBuffers();

Where the readDepth() function read the zbuffer and write it to a file.

Alfonse Reinheart
03-02-2012, 12:13 PM
glReadPixels(0, window_height, window_width, window_height, GL_DEPTH_COMPONENT24, GL_UNSIGNED_INT, zData);

This reads from outside of the screen. If you want to read the entire screen, the first two values should be 0, 0. You're starting at the height of the screen, and then reading another screen height on top of that. That's not going to work.

Prendtout
03-03-2012, 11:26 AM
I read the origin of the image is the bottom left corner ? Am I mistaken ?
Anyway, I changed it to

glReadPixels(0, 0, window_width, window_height, GL_DEPTH_COMPONENT24, GL_UNSIGNED_INT, zData);

Still, I get only zeros. Any idea ?

V-man
03-03-2012, 12:00 PM
I think that GL_DEPTH_COMPONENT24 would raise an error.
You probably want

glReadPixels(0, 0, window_width, window_height, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, zData);

http://www.opengl.org/wiki/Common_Mistakes#Depth_Buffer_Precision

Prendtout
03-03-2012, 07:30 PM
Using GL_DEPTH_COMPONENT24 did not raise any exception.
With V-man's solution, the zeros are replace by a full load of 4294967295.
But it is still as if my teapot doesn't exist.

Prendtout
03-05-2012, 04:19 AM
After some testing I get results. I think the problem is because I want to save the depth buffer to a file at the beginning of the program.
I suppose the object is not rendered when I try to read the zbuffer so it is empty.
The question now is, when should I attempt to read the z buffer in order to be sure there will be usefull information in it ?

Here is my display function :

glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();

glTranslatef(0.0f, 0.0f, -3.0f);

glutSolidTeapot(1.0f); // Render a teapot

glutSwapBuffers();

readDepth();

Thank you in advance.

Prendtout
03-06-2012, 01:51 AM
I kept advancing, and now I can read the zbuffer data.

However, I must read it as GL_FLOAT, adversely to all that as been said in this thread. How is that ?

Moreover, I linearize the values with the following formula :
zDataLin = (2.0 * zNear) / (zFar + zNear - zData * (zFar-zNear));

But this gives me very little numbers, I have to multiply them by 50000 to get something the order of unity.

ZbuffeR
03-06-2012, 06:37 AM
Assuming defaults, you should reverse the order, like this :

glutSolidTeapot(1.0f); // Render a teapot

readDepth();

glutSwapBuffers();

Prendtout
03-06-2012, 08:34 AM
Thank you Zbuffer, I figured this out eventually.

Now, my main problem is linearization of the z buffer data.

I need to transform z buffer data into distances from camera to object. As I said before, the only formula I came across performs poorly.