Box looks see through in wrong places

So I am trying to learn vertex arrays by writing a simple example for a cube. I noticed that when I rotate the cube I can see through some of the faces except the top. I thought maybe I just needed to specify normals, so I tried that and with no difference. Here is my code.


// Name: boxes.c
// Description: OpenGL program using GLUT...

// GLUT header safely includes any OS dependencies as well as GL and GLU...
#include <GL/glut.h>
#include <stdio.h>
#include <stdlib.h>

// Box interleaved data...
static GLfloat BoxData_c3f_v3f[] =
{
    0.2, 0.4, 1.0, -25.0, -25.0, -25.0, /* 0 rear bottom left */
    0.0, 0.5, 0.3, -25.0,  25.0, -25.0, /* 1 rear top left */
    0.0, 0.0, 1.0,  25.0,  25.0, -25.0, /* 2 rear top right */
    0.1, 0.2, 0.1,  25.0, -25.0, -25.0, /* 3 rear bottom right */
    0.7, 0.6, 0.6, -25.0, -25.0,  25.0, /* 4 front bottom left */
    1.0, 0.3, 0.8, -25.0,  25.0,  25.0, /* 5 front top left */
    0.0, 0.2, 0.5,  25.0,  25.0,  25.0, /* 6 front top right */
    1.0, 0.0, 0.1,  25.0, -25.0,  25.0  /* 7 front bottom right */
};

// Box indices...
static GLubyte BoxData_Indices[] =
{
    4, 7, 6, 5, /* front face */
    2, 6, 7, 3, /* right face */
    3, 7, 4, 0, /* bottom face */
    1, 2, 3, 0, /* back face */
    5, 1, 0, 4, /* left face */
    2, 1, 5, 6  /* top face */
};

// Box quad normals...
static GLfloat BoxData_QuadNormals[] =
{
    0.0,  0.0,  1.0, /* front face */
    1.0,  0.0,  0.0, /* right face */
    0.0, -1.0,  0.0, /* bottom face */
    0.0,  0.0, -1.0, /* back face */
   -1.0,  0.0,  0.0, /* left face */
    0.0,  1.0,  0.0 /* top face */    
};

// X and Y rotation...
static GLfloat fRotateX = 0.0;
static GLfloat fRotateY = 0.0;

// OpenGL state initializer...
void InitializeOpenGL()
{
    // Set the clear colour...
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

    // Let's draw everything wire frame, because we are cool...
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

    // Set the shade model to smooth to interpolate colours between vertices...
    glShadeModel(GL_SMOOTH);
    
    // Enable colour array and specify data...
    glEnableClientState(GL_COLOR_ARRAY);
    glColorPointer(3, GL_FLOAT, 6 * sizeof(GL_FLOAT), &BoxData_c3f_v3f[0]);

    // Enable vertex array and specify data...
    glEnableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(3, GL_FLOAT, 6 * sizeof(GL_FLOAT), &BoxData_c3f_v3f[3]);

    // Enable vertex normal array and specify data...
    glEnableClientState(GL_NORMAL_ARRAY);
    glNormalPointer(GL_FLOAT, 0, &BoxData_QuadNormals);
}

// Display callback...
void OnDisplay()
{
    // Variables...
    GLenum nError;

    // Clear the screen...
    glClear(GL_COLOR_BUFFER_BIT);
    
    // Reset the model and view transformation matrices...
    glLoadIdentity();
    
    // Initialize view matrix transformation...
    gluLookAt(0.0, 0.0, 70.0, 
              0.0, 0.0, 0.0, 
              0.0, 1.0, 0.0);
    
    // Rotate along X...
    glRotatef(fRotateX, 1.0, 0.0, 0.0);
    
    // Rotate along Y...
    glRotatef(fRotateY, 0.0, 1.0, 0.0);
    
    // Dereference vertex array, upload to server, and down pipeline...
    glDrawElements(
        GL_QUADS, sizeof(BoxData_Indices) / sizeof(BoxData_Indices[0]), 
        GL_UNSIGNED_BYTE, &BoxData_Indices);

    // Check for error...
    if((nError = glGetError()) != GL_NO_ERROR)
    {
        // Print it and then exit...
        printf("glGetError() reported 0x%.4x
", nError);
        exit(1);
    }

    // Flush the command queue and swap the back buffer...
    glutSwapBuffers();
}

// Special keyboard callback...
void OnSpecialKeyboard(int nKey, GLsizei nX, GLsizei nY)
{
    // The angular displacement delta to add on each key press...
    GLfloat const fAngleDelta = 5.0;

    // Which key?
    switch(nKey)
    {
        // Left button...
        case GLUT_KEY_LEFT:
            fRotateY -= fAngleDelta;
            break;
        
        // Right button...
        case GLUT_KEY_RIGHT:
            fRotateY += fAngleDelta;
            break;
        
        // Up button...
        case GLUT_KEY_UP:
            fRotateX -= fAngleDelta;
            break;
        
        // Down button...
        case GLUT_KEY_DOWN:
            fRotateX += fAngleDelta;
            break;
    }
    
    // Clamp angles...
    
        // X rotation...
        if(fRotateX > 360.0 || fRotateX < 0.0)
            fRotateX = abs(abs(fRotateX) - 360.0);

        // Y rotation...
        if(fRotateY > 360.0 || fRotateY < 0.0)
            fRotateY = abs(abs(fRotateY) - 360.0);

    // Post a redisplay...
    glutPostRedisplay();
}

// Reshape callback...
void OnReshape(GLsizei nWidth, GLsizei nHeight)
{
    // Initialize viewport transformation matrix to new dimensions...
    glViewport((GLsizei) 0, (GLsizei) 0, (GLsizei) nWidth, (GLsizei) nHeight);
    
    // Initialize projection transformation matrix...
    
        // Select...
        glMatrixMode(GL_PROJECTION);
        
        // Set to something a little more human...
        glLoadIdentity();
        glFrustum(-25.0, 25.0, -25.0, 25.0, 20, 600.0);

    // Initialize the model and view transformations...
    glMatrixMode(GL_MODELVIEW);
}

// Entry point...
int main(int nArguments, char *ppszArguments[])
{
    // Initialize GLUT...
    glutInit(&nArguments, ppszArguments);
    
    // Initialize window display mode...
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
    
    // Initialize window size...
    glutInitWindowSize(500, 500);
    
    // Initialize window position...
    glutInitWindowPosition(400, 200);
    
    // Allocate a window...
    glutCreateWindow("Boxes");
    
    // Initialize OpenGL state...
    InitializeOpenGL();
    
    // Register our callbacks with GLUT...
    glutReshapeFunc(OnReshape);
    glutSpecialFunc(OnSpecialKeyboard);
    glutDisplayFunc(OnDisplay);

    // Begin main message loop which opens window, displays, et cetera...
    glutMainLoop();

    // Appease compiler with ISO C behaviour... (never actually executed)
    return 0;
}


Use the arrow keys on keyboard to rotate. Help is appreciated.

Kip

The problem is that you draw some faces clockwise, some counter-clockwise.

Try disabling backface culling or change glPolygonMode(GL_FRONT_AND_BACK, GL_FILL) into 2 separate calls, where you set front faces to GL_FILL and back facing to GL_LINE. Especially the second option should help you fix the problem.

I’ve tried the two separate calls to glPolygonMode and it doesn’t seem to help. I can still see through most of the faces.

As I understand it, faces that are plotted with the vertices arriving in counterclockwise direction have their normal pointing outwards. I’ve looked over my BoxData_Indices and BoxData_c3f_v3f, but can’t see any problems? One thing I did notice though is that the last quad rendered always seems to be rendered correctly with the normal facing the right way. If I move the first group of indices to the end, same thing again.

Also, BoxData_QuadNormals seems to be totally ignored even though I enabled GL_NORMAL_ARRAY and fed it in with glNormalPointer. I am pretty certain the array is not even being read since passing a bad pointer to it when I try still doesn’t make it segfault. Neither passing NULL or a pointer to some dummy variable makes a difference.

Kip

Do you have lighting enabled, or anything else that needs the normals?

I think the problem is that you haven’t enabled depth testing. Simply add glEnable(GL_DEPTH_TEST); to your initializations and clear the depth buffer too when rendering the scene (glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT):wink:

Also make sure you tell GLUT to give you a depth buffer. I don’t use GLUT so I don’t know how to do that however.

Hope that helps!
Greetings
Tom

Yes, it seems that you don’t have depth-testing enabled, like tom wrote. just create your rendering context with a depth buffer (the docs should give you a hint), IMHO I think it was adding GLUT_DEPTH to the bitmask in glutInitDisplay and then use glEnable(GL_DEPTH_TEST) and set a glDepthFunc. glDepthFunc(GL_LEQUAL) should be fine.
Normals are only needed for lighting calculations in the fixed function pipeline. the front- and backside of a polygone is determined by evaluating the vertices. default is counter clockwise is front side. but you can change this. if you disable backface culling and don’t set different material properties for front and backside, you won’t see a difference between front- and backsides.

greetings
Sebastian

glFrustum(-25.0, 25.0, -25.0, 25.0, 20, 600.0);

The near plane is quite far away, thus the object is partially clipped.

Thanks guys. The combination depth testing and adjusting the clipping distances fixed it. =)

Kip