Draw the cube with OpenGL ES 1.1
Initialize the model
Next, in initialize(), we do a bit of setup work. We obtain the EGL surface width and height. We set the image depth value by calling glClearDepthf(). We also enable smooth shading of the model and enable polygons to be culled based on their window coordinates. We call glClearColor() to set the clear color to black, so that when we call glClear(GL_COLOR_BUFFER_BIT), the screen is cleared to this color. Then, we specify the size of the viewport through which we view the scene. We use glViewport() to set the viewport to the same size as the EGL surface. Some of this may differ from the template, so verify that the code is as shown here.
void initialize(){
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();
Continuing with initialize(), we specify the projection matrix by doing a bit of trigonometry. 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. We call glFrustumf() to perform a perspective projection. Next, we scale the model, but adjust the X and Y axes for scaling depending on the surface width and height. Last, we set the current matrix to modelview, and load the identity matrix.
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);
if (surface_width > surface_height)
{
glScalef((float)surface_height/(float)surface_width, 1.0, 1.0f);
}
else
{
glScalef(1.0, (float)surface_width/(float)surface_height, 1.0f);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
return EXIT_SUCCESS;
}
For the M_PI constant, you'll need to verify that math.h is included:
#include <math.h>
Rotate the model
Within our render() function in main.c, use glClear() to clear the color and depth buffers.
void render(){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Next, enable the passing of 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 specify the arrays of vertices and color values that we defined at the beginning of the tutorial to be used to render the model.
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.
We disable vertex and color array states, then call bbutil_swap() which swaps the window buffers. 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):
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 BPS next available event
bps_event_t *event = NULL;
if (BPS_SUCCESS != bps_get_event(&event, 0)) {
fprintf(stderr, "bps_get_event() failed\n");
}
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;
}
}
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.