+2  A: 

Have you read OpenGL FAQ 12?

The one thing that looks suspicious about your code is the negative near plane. Negative Z values are behind the camera, which is usually a mistake when rendering a 3D scene. However, that in itself shouldn't cause the problem you're seeing, and the range [-6,6] for Z should provide plenty of precision for this kind of scene.

Are you calling glEnable(GL_DEPTH_TEST)? Are you passing GL_DEPTH_BUFFER_BIT to glClear each frame?

Update: you're calling glPolygonMode(GL_FRONT, GL_LINE). This means that front-facing triangles are drawn in outline only, which means that if front-facing triangle A overlaps another front-facing triangle B, you can see through A to the edges of B. With a convex body this can't happen, so you don't notice the problem.

If you want triangles to occlude the triangles behind them, then you are going to need to fill them in using mode GL_FILL. To get a wireframe figure, you need to draw the model with white fill, then draw the model again with black outline, like this:

glDepthFunc(GL_LEQUAL);
glPolygonMode(GL_FRONT, GL_FILL);
/* draw the model in white */
glDepthFunc(GL_EQUAL);
glPolygonMode(GL_FRONT, GL_LINE);
/* draw the model again in black */

The idea is that on the second pass over the model, we only want to draw the outlines that are not obscured by some triangle drawn in the first pass that is closer to the camera (that is, with lower Z).

Another idea: I think your camera may be pointing the wrong way. This would explain why the scene is being drawn wrongly with the glOrtho perspective, and not at all with the glFrustum perspective. In the glOrtho case, the entire scene is being drawn behind the camera; that's why it's being drawn with the Z order the wrong way round. When you set the near plane to a positive number, the entire scene is culled.

Gareth Rees
That link didn't helped me. I added more code in my question.
Dmitriy Matveev
It doesn't matter how I draw my polygons (GL_LINE or GL_FILL) the problem is still there. Is there any proofs that rendering with GL_LINE shouldn't use depth buffer?
Dmitriy Matveev
Can you take a screenshot of the model drawn as I recommend above?
Gareth Rees
Uploaded new rendered model with flat filled faces.
Dmitriy Matveev
You are using glOrtho which makes it a little hard to tell (see) which triangles is near/far. If you have a problem generating the meshes, triangles has to be generated in a certain order. See http://home.comcast.net/~fbui/glCullFace.html
epatel
See also http://home.comcast.net/~fbui/glFrontFace.html
epatel
I think it's clear that the culling is working correctly—we can see only front-facing triangles. It's the depth buffer that's not working. Are you sure you are calling glDepthFunc(GL_LEQUAL)?
Gareth Rees
The default for glDepthFunc is GL_LESS, which should be fine, so that's probably not the problem.
Gareth Rees
What does the scene look like if you try glFrustum instead of glOrtho? (make sure you use a positive near plane)
Gareth Rees
If I will use glFrustum(-maxDistance, maxDistance, -maxDistance, maxDistance, 0.1, 10) then the rendering area will be empty.
Dmitriy Matveev
I've found how to workaround this. But how can I set my camera properly? I need to ensure that I'm looking at the center of my model from some constant distance. What's wrong with my PolarView function?
Dmitriy Matveev
A: 

"8.070 How can I automatically calculate a view that displays my entire model? (I know the bounding sphere and up vector.)" entry at OpenGL FAQ 8 answers my question. However, my setup is slightly different, here is my rewritten PolarView and Reshape functions:

static void Reshape(int w, int h)
{
    float diameter = sqrt(3);
    glViewport(0, 0, (GLsizei)w, (GLsizei)h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    GLdouble zNear = 1;
    GLdouble zFar = zNear + diameter * 2;
    GLdouble left = -diameter;
    GLdouble right = diameter;
    GLdouble top = -diameter;
    GLdouble bottom = diameter;
    double aspect = (double)w / (double)h;
    if (aspect < 1)
    {
     bottom /= aspect;
     top /= aspect;
    }
    else
    {
     left *= aspect;
     right *= aspect;
    }
    glOrtho(left, right, bottom, top, zNear, zFar);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

static void PolarView(GLdouble twist, GLdouble elevation)
{
    float diameter = sqrt(3);
    double distance = diameter * 2;
    double centerx, centery, centerz;
    double eyex, eyey, eyez;

    eyex = distance * cos(twist) * cos(elevation);
    eyey = distance * sin(twist) * cos(elevation);
    eyez = distance * sin(elevation);
    centerx = centery = centerz = 0;
    gluLookAt(eyex, eyey, eyez, centerx, centery, centerz, 0, 0, 1);
}
Dmitriy Matveev