Last time we looked at drawing triangles with the GLES2Sample project (you can get this from here). Let’s modify this project a little so we can do interesting things.
First problem is that the ‘model’ is spinning. This is done using:
glRotatef(3.0f, 0.0f, 0.0f, 1.0f);
You can change 3.0f to 0.0f or comment out this line of code to test. Here’s the code fragment, still within ES1Renderer:
// from ES1Renderer.m in GLES2Sample glMatrixMode(GL_PROJECTION); glLoadIdentity(); // left, right, bottom, top glOrthof(-10.0f, 10.0f, -15.0f, 15.0f, -1.0f, 1.0f); glMatrixMode(GL_MODELVIEW); // this causes the square to rotate glRotatef(3.0f, 0.0f, 0.0f, 1.0f);
This code is puzzling. How does it work? What’s a matrix anyway? Can we use it to setup an isometric view? Yes! We want to tilt the ‘model’ 45 degrees left and 60 degrees right. tilt=rotate, so let’s uncomment
angle is the angle we rotate by.
x,y,z is a vector to rotate around.
glRotatef(60,1,0,0) rotates your model around the X axis – like holding a skewer in both hands and making it spin.
glRotatef(45,0,1,0) rotates your model around the Y axis – like a horse on a carrousel.
// updated to try creating an isometric view glMatrixMode(GL_PROJECTION); glLoadIdentity(); // left, right, bottom, top glOrthof(-10.0f, 10.0f, -15.0f, 15.0f, -1.0f, 1.0f); glMatrixMode(GL_MODELVIEW); // this is trying to setup the isometric view. glRotatef(60,1,0,0); glRotatef(45,0,1,0);
This should give us an isometric view – tilted so we look from up and from the side. Run this code.
Well… actually this gives me headache. What we really want is rotate just once, then stop. There are several ways to do this:
1 – Since it’s animating there’s probably a time-loop running somewhere, s o we could stop the time-loop. Since we’re making a game, we probably want to leave the time-loop running.
2 – We could use a latch to rotate only once within (void)render:, so that the first time the function rotates, then stops rotating forever. That’s pretty dumb. Not elegant.
3 – Is there a way we can just specify the angle at every frame, rather than rotate again at every frame? Yes.
glLoadIdentity() happens to be used to clear the rotation of the ‘model’.
Given the fact, it seems that we are already clearing the rotation at every frame
glLoadIdentity is already there! Let’s call this function again anyway, just before we call
glMatrixMode(GL_PROJECTION); glLoadIdentity(); // this call was already there. // left, right, bottom, top glOrthof(-10.0f, 10.0f, -15.0f, 15.0f, -1.0f, 1.0f); glMatrixMode(GL_MODELVIEW); // this causes the square to rotate glLoadIdentity(); // hard headed: calling glLoadIdentity again. glRotatef(60,1,0,0); glRotatef(45,0,0,1);
Run this. Yes – now that works. Notice that i swapped the y for the z coordinate to make it look right. This is easy to get wrong at the beginning.
*Why* does it work?
1 – GL doesn’t know about your ‘model’. It just draws stuff. That would be the first answer to the question ‘how does it know how to rotate that particular model’. It doesn’t. We’re not rotating the model, we’re rotating the view. So we rotate the view first, and draw next, and it seems like we have rotate the model.
2 – GL retains all state assigned to it.
glLoadIdentity() actually affects a target defined by
glMatrixMode(). Notice that there are two calls to
glMatrixMode(GL_PROJECTION) – set the so called projection matrix as target to transformations such as glRotatef, glOrthof etc…
glMatrixMode(GL_MODELVIEW) – set the so called model view matrix as target to transformations.
The first call to
glLoadIdentity() actually resets the projection. This implies that before adding a second call to
glMatrixMode(GL_MODELVIEW), the model view matrix was not reset between two invocations of render: that explains the animated rotation.
The projection matrix defines the ’3D style’ such as isometric (no distortion) and perspective (further objects are smaller).
The model view matrix defines the rotation of the camera or ‘the whole world’.