1
votes

I've been looking into OpenGL and diving into the 3D world. This question relates to OpenGL in general but I've been using WebGL (which is OpenGL ES if I believe). I've had a problem understanding how cubes are drawn. I know that to draw a quad, you create two triangles in (default) CCW order like

1       0 
|‾ ‾ ‾ ‾|
|       |    Indices = 0,1,2, 0,2,3 (2 triangles one face)
|       |
|_ _ _ _|
2       3  

However, I'm having a bit of trouble understanding the best way to draw a cube. Is there a specific way I should be drawing the cube? For example, is drawing the faces in front->right->bottom->left->top->back the best order or is it some other way. Do I draw the cube faces counter-clockwise too or something? I just need to understand the different ways I could represent a model/cube and why.

1

1 Answers

2
votes

It can be done with 2 triangle strips, but strips are usually replaced with indexed triangles for more complex geometry because they become more efficient when you need multiple strips. I think it can also be done with a single strip if you use a degenerate triangle to connect the two, but indexed is usually better for larger geometry. Quads just get converted into triangles.

The winding direction is important only when backface culling is enabled. Also, things get more complicated when you add texture coordinates and surface normals for lighting. The normals can be used to make the cube look faceted or smooth shaded, which is really for larger models, like spheres. Here is a tutorial I wrote years ago for OpenGL ES 2.0:

/******************************************************************************

  Function      DrawCubeSmooth

  Return        None

  Description   Draw a cube using Vertex and NormalsPerVertex Arrays and
                glDrawArrays with two triangle strips.  Because normals are
                supplied per vertex, all the triangles will be smooth shaded.
                Triangle strips are used instead of an index array.  The first
                strip is texture mapped but the second strip is not.

******************************************************************************/

void Cube2::DrawCubeSmooth(void)
{
    static GLfloat Vertices[16][3] =
    {   // x     y     z
        {-1.0, -1.0,  1.0}, // 1  left    First Strip
        {-1.0,  1.0,  1.0}, // 3
        {-1.0, -1.0, -1.0}, // 0
        {-1.0,  1.0, -1.0}, // 2
        { 1.0, -1.0, -1.0}, // 4  back
        { 1.0,  1.0, -1.0}, // 6
        { 1.0, -1.0,  1.0}, // 5  right
        { 1.0,  1.0,  1.0}, // 7
        { 1.0,  1.0, -1.0}, // 6  top     Second Strip
        {-1.0,  1.0, -1.0}, // 2
        { 1.0,  1.0,  1.0}, // 7
        {-1.0,  1.0,  1.0}, // 3
        { 1.0, -1.0,  1.0}, // 5  front
        {-1.0, -1.0,  1.0}, // 1
        { 1.0, -1.0, -1.0}, // 4  bottom
        {-1.0, -1.0, -1.0}  // 0
    };
    static GLfloat NormalsPerVertex[16][3] =    // One normal per vertex.
    {   // x     y     z
        {-0.5, -0.5,  0.5}, // 1  left          First Strip
        {-0.5,  0.5,  0.5}, // 3
        {-0.5, -0.5, -0.5}, // 0
        {-0.5,  0.5, -0.5}, // 2
        { 0.5, -0.5, -0.5}, // 4  back
        { 0.5,  0.5, -0.5}, // 6
        { 0.5, -0.5,  0.5}, // 5  right
        { 0.5,  0.5,  0.5}, // 7
        { 0.5,  0.5, -0.5}, // 6  top           Second Strip
        {-0.5,  0.5, -0.5}, // 2
        { 0.5,  0.5,  0.5}, // 7
        {-0.5,  0.5,  0.5}, // 3
        { 0.5, -0.5,  0.5}, // 5  front
        {-0.5, -0.5,  0.5}, // 1
        { 0.5, -0.5, -0.5}, // 4  bottom
        {-0.5, -0.5, -0.5}  // 0
    };
    static GLfloat TexCoords[8][2] =
    {   // x   y
        {0.0, 1.0}, // 1  left                  First Strip
        {1.0, 1.0}, // 3
        {0.0, 0.0}, // 0
        {1.0, 0.0}, // 2
        {0.0, 1.0}, // 4  back
        {1.0, 1.0}, // 6
        {0.0, 0.0}, // 5  right
        {1.0, 0.0}  // 7
    };

    glEnableVertexAttribArray(VERTEX_ARRAY);
    glEnableVertexAttribArray(NORMAL_ARRAY);
    glEnableVertexAttribArray(TEXCOORD_ARRAY);

    // Set pointers to the arrays
    glVertexAttribPointer(VERTEX_ARRAY, 3, GL_FLOAT, GL_FALSE, 0, Vertices);
    glVertexAttribPointer(NORMAL_ARRAY, 3, GL_FLOAT, GL_FALSE, 0, NormalsPerVertex);
    glVertexAttribPointer(TEXCOORD_ARRAY, 2, GL_FLOAT, GL_FALSE, 0, TexCoords);

    // Draw first triangle strip with texture map
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 8);

    // Draw second triangle strip without texture map
    glDisableVertexAttribArray(TEXCOORD_ARRAY);
    glDrawArrays(GL_TRIANGLE_STRIP, 8, 8);

    glDisableVertexAttribArray(VERTEX_ARRAY);
    glDisableVertexAttribArray(NORMAL_ARRAY);
};

I hope this helps.