Create the cube

Now that we're all set up, it's time to get started writing some code. Creating and coloring in cubes really consists of two tasks: creating the cube and then coloring in it's faces (just like the title says).

We'll start with the code that describes the geometry of the cube. So grab a piece of 3-D graph paper and sketch a cube. You'll notice that it has six sides and eight vertices:

Diagram showing a 3-D cube.

In main.c we start by declaring an array to store the cube's vertices to look like this (if the array already exists from the template, you can replace it, keeping in mind to remove any array initialization code as well):

static const GLfloat vertices[] =
{
      // front
      -0.5f, 0.5f, 0.5f, 
      -0.5f, -0.5f, 0.5f, 
      0.5f, 0.5f, 0.5f,
      0.5f, 0.5f, 0.5f, 
      -0.5f, -0.5f, 0.5f, 
      0.5f, -0.5f, 0.5f,

      // right
      0.5f, 0.5f, 0.5f, 
      0.5f, -0.5f, 0.5f, 
      0.5f, 0.5f, -0.5f,
      0.5f, 0.5f, -0.5f, 
      0.5f, -0.5f, 0.5f, 
      0.5f, -0.5f, -0.5f,

      // back
      0.5f, 0.5f, -0.5f, 
      0.5f, -0.5f, -0.5f, 
      -0.5f, 0.5f, -0.5f,
      -0.5f, 0.5f, -0.5f, 
      0.5f, -0.5f, -0.5f, 
      -0.5f, -0.5f, -0.5f,

      // left
      -0.5f, 0.5f, -0.5f, 
      -0.5f, -0.5f, -0.5f, 
      -0.5f, 0.5f, 0.5f,
      -0.5f, 0.5f, 0.5f, 
      -0.5f, -0.5f, -0.5f, 
      -0.5f, -0.5f, 0.5f,

      // top
      -0.5f, 0.5f, -0.5f, 
      -0.5f, 0.5f, 0.5f, 
      0.5f, 0.5f, -0.5f,
      0.5f, 0.5f, -0.5f, 
      -0.5f, 0.5f, 0.5f, 
      0.5f, 0.5f, 0.5f,

      // bottom
      -0.5f, -0.5f, 0.5f, 
      -0.5f, -0.5f, -0.5f, 
      0.5f, -0.5f, 0.5f,
      0.5f, -0.5f, 0.5f, 
      -0.5f, -0.5f, -0.5f, 
      0.5f, -0.5f, -0.5f
 };

Notice that there are more than eight vertices there. OpenGL ES is designed to work with triangles. So we are specifying each side of our cube as a pair of triangles, like this:

Diagram showing that each side of the cube has a pair of triangles.

Each triangle is defined by three vertices. So we need 3 vertices/triangle x 2 triangles/side x 6 sides = 36 vertices.

Next, we specify a color for each side of the cube. These colors are defined per vertex and are in RGBA format. The A in RGBA refers to the alpha channel, which represents the transparency of the color. All of our colors are opaque, so each value ends with a 1.0. Here, we're using different shades of blue (for example, R=16, G=147, B=237 becomes 0.0625, 0.57421875, and 0.92578125, since these values are normalized to 256). If this array already exists from the template, you can replace it, keeping in mind to remove any array initialization code as well.

static const GLfloat colors[] =
{
      /* front */
      0.0625f,0.57421875f,0.92578125f,1.0f,
      0.0625f,0.57421875f,0.92578125f,1.0f,
      0.0625f,0.57421875f,0.92578125f,1.0f,
      0.0625f,0.57421875f,0.92578125f,1.0f,
      0.0625f,0.57421875f,0.92578125f,1.0f,
      0.0625f,0.57421875f,0.92578125f,1.0f,
      /* right */
      0.29296875f,0.66796875f,0.92578125f,1.0f,
      0.29296875f,0.66796875f,0.92578125f,1.0f,
      0.29296875f,0.66796875f,0.92578125f,1.0f,
      0.29296875f,0.66796875f,0.92578125f,1.0f,
      0.29296875f,0.66796875f,0.92578125f,1.0f,
      0.29296875f,0.66796875f,0.92578125f,1.0f,
      /* back */
      0.52734375f,0.76171875f,0.92578125f,1.0f,
      0.52734375f,0.76171875f,0.92578125f,1.0f,
      0.52734375f,0.76171875f,0.92578125f,1.0f,
      0.52734375f,0.76171875f,0.92578125f,1.0f,
      0.52734375f,0.76171875f,0.92578125f,1.0f,
      0.52734375f,0.76171875f,0.92578125f,1.0f,
      /* left */
      0.0625f,0.57421875f,0.92578125f,1.0f,
      0.0625f,0.57421875f,0.92578125f,1.0f,
      0.0625f,0.57421875f,0.92578125f,1.0f,
      0.0625f,0.57421875f,0.92578125f,1.0f,
      0.0625f,0.57421875f,0.92578125f,1.0f,
      0.0625f,0.57421875f,0.92578125f,1.0f,
      /* top */
      0.29296875f,0.66796875f,0.92578125f,1.0f,
      0.29296875f,0.66796875f,0.92578125f,1.0f,
      0.29296875f,0.66796875f,0.92578125f,1.0f,
      0.29296875f,0.66796875f,0.92578125f,1.0f,
      0.29296875f,0.66796875f,0.92578125f,1.0f,
      0.29296875f,0.66796875f,0.92578125f,1.0f,
      /* bottom */
      0.52734375f,0.76171875f,0.92578125f,1.0f,
      0.52734375f,0.76171875f,0.92578125f,1.0f,
      0.52734375f,0.76171875f,0.92578125f,1.0f,
      0.52734375f,0.76171875f,0.92578125f,1.0f,
      0.52734375f,0.76171875f,0.92578125f,1.0f,
      0.52734375f,0.76171875f,0.92578125f,1.0f
};

Next, in initialize(), we do a bit of setup work. We set the depth value and color that the screen will be cleared to using glClearDepthf() and glClearColor(). Then we specify the size of the window or viewport through which we view the scene. We use glViewport() to set the viewport to the same size as the screen (some of this may differ from the template, so verify that the code is as shown here).

EGLint surface_width, surface_height;

eglQuerySurface(egl_disp, egl_surf, EGL_WIDTH, &surface_width);
eglQuerySurface(egl_disp, egl_surf, EGL_HEIGHT, &surface_height);

EGLint err = eglGetError();
if (err != 0x3000) {
    fprintf(stderr, "Unable to query EGL surface dimensions\n");
    return EXIT_FAILURE;
}

glClearDepthf(1.0f);
glEnable(GL_CULL_FACE);
glShadeModel(GL_SMOOTH);

//set clear color to black
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

glViewport(0, 0, surface_width, surface_height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

Give the cube a home and show it off

Now that you have a cube to show off, you have to give it a home so that the world can see it!

Continuing with initialize(), we specify the projection matrix by doing a bit of trigonometry and using glFrustumf(). We specify the near and far clipping planes, the vertical field of view, and the aspect ratio. Then we calculate minimum and maximum horizontal and vertical values.

float nearClip = -2.0f;
float farClip  = 2.0f;
float yFOV  = 75.0f;
float yMax = nearClip * tan(yFOV*M_PI/360.0f);
float aspect = surface_width/surface_height;
float xMin = -yMax * aspect;
float xMax = yMax *aspect;

glFrustumf(xMin, xMax, -yMax, yMax, nearClip, farClip);
glScalef((float)surface_height/(float)surface_width, 1.0f, 1.0f);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

For the M_PI constant, you'll need to verify that math.h is included:

#include <math.h>

Within our render() function in main.c, use glClear() to clear the color and depth buffers.

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

Next, we let OpenGL know that we want to specify a vertex array to describe the geometry of our cube and a color array to specify the colors used on the sides of the cube.

glEnableClientState(GL_VERTEX_ARRAY);

glEnableClientState(GL_COLOR_ARRAY);

After setting up how we want things to look, we should probably have something to look at. We tell OpenGL to use those matrices of vertices and color values that we defined at the beginning of the tutorial.

glVertexPointer(3, GL_FLOAT, 0, vertices);

glColorPointer(4, GL_FLOAT, 0, colors);

The 3 in the glVertexPointer() call indicates that each group of three values in the vertices array specifies a single vertex. Similarly, the 4 in the glColorPointer() call indicates that each group of four values in the colors array indicates a single color value. If you don't know what the 0 means in the calls, don't worry about it yet. Just think of it as the default value.

Next, we call glRotatef() to rotate the cube, then call glDrawArrays() to tell OpenGL to draw the triangles. Remember that our representation required 36 vertices and that was because we specified the geometry as a set of triangles. This leaves us with a complete render() function (some of this may differ from the template, so verify that the code is as shown here):

void render()
{
    //Typical render pass
	   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glEnableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(3, GL_FLOAT, 0, vertices);

    glEnableClientState(GL_COLOR_ARRAY);
    glColorPointer(4, GL_FLOAT, 0, colors);

    glRotatef(1.0f, 1.0f, 1.0f, 0.0f);

    glDrawArrays(GL_TRIANGLES, 0 , 36);

    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_COLOR_ARRAY);

    //Use utility code to update the screen
    bbutil_swap();
}

Finally, in main, we create the application loop. This will cause the angle of our cube to change during every frame update.

while (!exit_application) {
    //Request and process all available BPS events
    bps_event_t *event = NULL;

    for(;;) {
        rc = bps_get_event(&event, 0);
        assert(rc == BPS_SUCCESS);

        if (event) {
            int domain = bps_event_get_domain(event);

            if (domain == screen_get_domain()) {
                handleScreenEvent(event);
            } else if ((domain == navigator_get_domain())
                    && (NAVIGATOR_EXIT == bps_event_get_code(event))) {
                exit_application = 1;
            }
        } else {
            break;
        }
    }
    render();
}

After all of that, you are now the proud owner of your very own multicolored rotating cube! Of course, we aren't exactly making the GPU sweat with this masterpiece, but it's a start.

Device image showing the finished3-D app.