Andre Bandarra's Blog

OpenGL Superbible in Java, the MatrixStack

On the last example, we learned how to rotate/translate a triangle manipulating the matrices. There was a lot of code for such a small feature. Imagine if you hat to rotate various objects in different places of the screen. Thats where the MatrixStack class comes to help. It encapsulates the feature of the old OpenGL 1.1 where you could push, pop and manipulate the matrix state, demanding much less code if you want to draw various objects.

As the first example, lets modify our RotatingTriangle to use the MatrixStack, on Example3.java. The first step is creating an instance variable to hold our MatrixStack. Let's also move our FloatBuffer from inside the update method to an instance variable;

private MatrixStack matrixStack = new MatrixStack();
private FloatBuffer buff = BufferUtils.createFloatBuffer(16);
public void render() {
angle += 1f;
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
shader.useShader();
shader.setUniform4("vColor", 1.0f, 0.0f, 0.0f, 1.0f);

matrixStack.push();
matrixStack.rotate(angle, 0.0f, 0.0f, 1.0f);
matrixStack.fillBuffer(buff);

shader.setUniformMatrix4("mvpMatrix", false, buff);
triangleBatch.draw(shader.getAttributeLocations());
matrixStack.pop();
Display.update();
}

Now, lets see what happens on the render method. Instead of declaring and multipying the matrices by hand, we just push the matrix, manipulate it as we want by calling the matrix.translate() and matrix.rotate() methods, then we call the fillBuffer() method to put the result matrix in the buff variable and draw(). The last important thing is to call the pop() method so that we end up with the same matrix that we started.

Again, the code is available at http://code.google.com/p/opengl-superbible-java/. Just look for Example3.java.

Now, to show how simple it is to draw various objects on the screen, each one at its own place and rotation, let's check what happens on Example4.java. The first change is on the initGL() method. We are now using a smaller triangle.

triangleBatch = new SimpleGLBatch(GL11.GL_TRIANGLES,
new float[]{ 0.0f, 0.3f, 0.0f, 1.0f,
-0.3f, -0.3f, 0.0f, 1.0f,
0.3f, -0.3f, 0.0f, 1.0f},
new short[]{0, 1, 2});

Now, lets see what happens on the render() method.

public void render() {
angle += 1f;
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
shader.useShader();

matrixStack.push();
shader.setUniform4("vColor", 1.0f, 0.0f, 0.0f, 1.0f);
matrixStack.translate(-0.5f, 0, 0);
matrixStack.rotate(angle, 0.0f, 0.0f, 1.0f);
matrixStack.fillBuffer(buff);
shader.setUniformMatrix4("mvpMatrix", false, buff);
triangleBatch.draw(shader.getAttributeLocations());
matrixStack.pop();

matrixStack.push();
shader.setUniform4("vColor", 0.0f, 0.0f, 1.0f, 1.0f);
matrixStack.translate(0.5f, 0, 0);
matrixStack.rotate(angle, 0.0f, 1.0f, 0.0f);
matrixStack.fillBuffer(buff);
shader.setUniformMatrix4("mvpMatrix", false, buff);
triangleBatch.draw(shader.getAttributeLocations());
matrixStack.pop();

Display.update();
}

For each triangle we want to draw, we call matrix.push() before translating and rotating, fill the buffer, draw the triangle and call pop. You could easily have a loop in your code to draw hundreds of objects this way!!

← Home