PDA

View Full Version : Beginner: Cube perspective messed up...



Richard Connamacher
01-15-2011, 09:15 PM
I'm teaching myself OpenGL programming and wrote a cube-drawing algorithm. Unfortunately, as I rotate it, the perspective ends up very weird. The back of the cube gets drawn, in part, over the front of the cube.

I have enabled GL_DEPTH_TEST and GL_CULL_FACE in my setup code.

I've banged away at this in my spare time for a few days, but still can't figure out what's going on or how to fix it. All I can guess is that cube faces are being drawn in the wrong order. But then again, I thought OpenGL is supposed to keep track of that?

(Another problem it's having, which may or may not be related, is that some faces are visible when viewed from one direction, but disappear when rotated in the other direction.)

I've attached the screen shot. And here's the C function I wrote to draw the cube. Any idea what I'm doing wrong?

Thanks!



void mygl_draw_cuboid(myglDimensions dimensions, GLfloat faceColors[6][3]) {
// Vertices (name key: Top/Bottom, Left/Right, Front/Back)
recVec vertTLF, vertTRF, vertBLF, vertBRF, vertTLB, vertTRB, vertBLB, vertBRB;
vertTLF = (recVec) { 0 - dimensions.width/2, 0 - dimensions.height/2, 0 - dimensions.depth/2};
vertTRF = (recVec) { dimensions.width/2, 0 - dimensions.height/2, 0 - dimensions.depth/2};
vertBLF = (recVec) { 0 - dimensions.width/2, dimensions.height/2, 0 - dimensions.depth/2};
vertBRF = (recVec) { dimensions.width/2, dimensions.height/2, 0 - dimensions.depth/2};
vertTLB = (recVec) { 0 - dimensions.width/2, 0 - dimensions.height/2, dimensions.depth/2};
vertTRB = (recVec) { dimensions.width/2, 0 - dimensions.height/2, dimensions.depth/2};
vertBLB = (recVec) { 0 - dimensions.width/2, dimensions.height/2, dimensions.depth/2};
vertBRB = (recVec) { dimensions.width/2, dimensions.height/2, dimensions.depth/2};

recVec cube_faces[6][4] = {
{vertTRB, vertTLB, vertBLB, vertBRB}, // Back
{vertTRF, vertTLF, vertBLF, vertBRF}, // Front
{vertBRF, vertBLF, vertBLB, vertBRB}, // Bottom
{vertTRF, vertTLF, vertTLB, vertTRB}, // Top
{vertTLF, vertTLB, vertBLB, vertBLF}, // Left
{vertTRF, vertTRB, vertBRB, vertBRF} // Right
};

GLint cube_start_face = 0;
GLint cube_num_faces = 6;

for (long f=cube_start_face; f<cube_start_face+cube_num_faces; f++) {

glColor3f(faceColors[f][0], faceColors[f][1], faceColors[f][2]);

glBegin(GL_POLYGON);
glVertex3d(cube_faces[f][0].x, cube_faces[f][0].y, cube_faces[f][0].z);
glVertex3d(cube_faces[f][1].x, cube_faces[f][1].y, cube_faces[f][1].z);
glVertex3d(cube_faces[f][2].x, cube_faces[f][2].y, cube_faces[f][2].z);
glVertex3d(cube_faces[f][3].x, cube_faces[f][3].y, cube_faces[f][3].z);
glEnd();
}
}


recVec and myglDimensions are just structs I made. recVec is {GLdouble x, GLdouble y, GLdouble z} and myglDimensions is {GLdouble width, GLdouble height, GLdouble depth}. The different name styles is because recVec was copied from some sample code.

Alfonse Reinheart
01-15-2011, 10:01 PM
All I can guess is that cube faces are being drawn in the wrong order. But then again, I thought OpenGL is supposed to keep track of that?

Read this. (http://www.arcsynthesis.org/gltut/Positioning/Tut05%20Overlap%20and%20Depth%20Buffering.html) You may not understand all of it (since the code it's talking about is shader-based code), but the basic act of turning on and using depth tests is fairly straightforward.


Another problem it's having, which may or may not be related, is that some faces are visible when viewed from one direction, but disappear when rotated in the other direction.

Read the part on face culling. (http://www.arcsynthesis.org/gltut/Positioning/Tutorial%2004.html) If you don't want face culling, turn it off.

Dan Bartlett
01-16-2011, 04:26 AM
In your example model, you need to make sure that all the triangles (or polygons) have the same winding order.

When you are looking at the side of the polygon that you want to appear visible, all the vertices should be in a counter-clockwise order by default. Whether on-screen polygons with a counter-clockwise or clockwise order appear visible can be altered with glFrontFace.

In your example model you don't have a consistent order for face winding, some are counter-clockwise, others are clockwise. So rather than the back face being rendered over the top of the back face (as can happen when depth buffer isn't set up), your front face isn't being rendered at all, which gives a similar effect.

http://www.opengl.org/sdk/docs/man4/xhtml/glFrontFace.xml

Once adjusted, your model should look something like this (not 100% sure I did it correctly, so you should visually check the model):



recVec cube_faces[6][4] = {
{vertTLB, vertTRB, vertBRB, vertBLB}, // Back
{vertTRF, vertTLF, vertBLF, vertBRF}, // Front
{vertBRF, vertBLF, vertBLB, vertBRB}, // Bottom
{vertTLF, vertTRF, vertTRB, vertTLB}, // Top
{vertTLF, vertTLB, vertBLB, vertBLF}, // Left
{vertTRB, vertTRF, vertBRF, vertBRB} // Right
};


With culling turned off, your original model should render correctly, but rendering without culling turned on is usually slower.

Richard Connamacher
01-16-2011, 05:22 AM
Dan,

Thanks! That fixed the problem, as long as culling is on. I'll have to remember to pay attention to winding direction.

(With culling off, all faces show up but the perspective problem is still there. For example, the right face is drawn over the left face no matter if viewed from the left or right. My problem was that the front was visible, but the sides were being drawn over it.)

Richard Connamacher
01-16-2011, 05:30 AM
Alfonse,

Thanks for the link, that's a good read. I had DEPTH_TEST enabled (and set a DepthFunc), but apparently the way I as using it must have been broken. I'll be looking over the article more to see if I can figure out what I did wrong.

theprof
04-25-2011, 01:12 AM
Hello, I had the same problem, it is likely that you did not clear your depth buffer:

In JOGL, the code is:

// Clear the color and depth buffers
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);