In OpenGL ES 2.0, there is no matrix stack. I really do miss the matrix stack, so I decided to take a cue from the Direct3D utility library, where there is a matrix stack class.
My class interface is heavily inspired by the ID3DXMATRIXStack class, but there was no implementation to peek at, so I had to figure out the implementation of the methods on my own.
I have ported most of my game engine to Objective-C, but since the open source GLGX math library I am using is in C++, I decided to write all my math related classes in C++.
As always, you can do whatever you want with code that I put on this blog, but I take no responsibility for it or what you do with it. :-)
MatrixStack.h:
#include "GLGXMath.h" #define MAX_MATRIX_STACK_LEVELS 32 class MatrixStack { private: GLGXMATRIX stack[MAX_MATRIX_STACK_LEVELS]; int currentLevel; public: MatrixStack(); void clear(); const GLGXMATRIX *getTop() const; void loadIdentity(); void loadMatrix(GLGXMATRIX *matrix); void multMatrix(GLGXMATRIX *matrix); void multMatrixLocal(GLGXMATRIX *matrix); void pop(); void push(); void rotateAxis(GLGXVECTOR3 *vector, float angle); void rotateAxisLocal(GLGXVECTOR3 *vector, float angle); void rotateYawPitchRoll(float yaw, float pitch, float roll); void rotateYawPitchRollLocal(float yaw, float pitch, float roll); void scale(float x, float y, float z); void scaleLocal(float x, float y, float z); void translate(float x, float y, float z); void translateLocal(float x, float y, float z); };
MatrixStack.cpp
#import <assert.h> #import "MatrixStack.cpp" // Constructs the matrix and loads the identity matrix. MatrixStack::MatrixStack() { clear(); } // Clears the stack and pops all matrices. void MatrixStack::clear() { currentLevel = 0; this->loadIdentity(); } // Retrieves the current matrix at the top of the stack. const GLGXMATRIX *MatrixStack::getTop() const { return &stack[currentLevel]; } // Loads identity in the current matrix. void MatrixStack::loadIdentity() { GLGXMatrixIdentity(&stack[currentLevel]); } // Loads the specified matrix in the current matrix. void MatrixStack::loadMatrix(const GLGXMATRIX *matrix) { stack[currentLevel] = *matrix; } // Multiplies the current matrix with the specified matrix. void MatrixStack::multMatrix(const GLGXMATRIX *matrix) { stack[currentLevel] = stack[currentLevel] * (*matrix); } // Multiplies the specified matrix with the current matrix. void MatrixStack::multMatrixLocal(const GLGXMATRIX *matrix) { stack[currentLevel] = (*(GLGXMATRIX *)matrix) * stack[currentLevel]; } // Removes the current matrix from the top of the stack. void MatrixStack::pop() { if (currentLevel > 0) { currentLevel--; } } // Adds a matrix level to the stack, by duplicating the current matrix. void MatrixStack::push() { assert(currentLevel + 1 < MAX_MATRIX_STACK_LEVELS); stack[currentLevel + 1] = stack[currentLevel]; currentLevel++; } // Rotates around an arbitrary vector axis. (world space) void MatrixStack::rotateAxis(const GLGXVECTOR3 *vector, float angle) { GLGXMATRIX tmp; GLGXMatrixRotationAxis(&tmp, (GLGXVECTOR3 *)vector, angle); stack[currentLevel] = stack[currentLevel] * tmp; } // Rotates around an arbitrary vector axis. (local space) void MatrixStack::rotateAxisLocal(const GLGXVECTOR3 *vector, float angle) { GLGXMATRIX tmp; GLGXMatrixRotationAxis(&tmp, (GLGXVECTOR3 *)vector, angle); stack[currentLevel] = tmp * stack[currentLevel]; } // Rotates around an arbitrary axis. (world space) void MatrixStack::rotateYawPitchRoll(float yaw, float pitch, float roll) { GLGXMATRIX tmp; GLGXQUATERNION quaternion; GLGXQuaternionRotationYawPitchRoll(&quaternion, yaw, pitch, roll); GLGXMatrixRotationQuaternion(&tmp, &quaternion); stack[currentLevel] = stack[currentLevel] * tmp; } // Rotates around an arbitrary axis. (local space) void MatrixStack::rotateYawPitchRollLocal(float yaw, float pitch, float roll) { GLGXMATRIX tmp; GLGXQUATERNION quaternion; GLGXQuaternionRotationYawPitchRoll(&quaternion, yaw, pitch, roll); GLGXMatrixRotationQuaternion(&tmp, &quaternion); stack[currentLevel] = tmp * stack[currentLevel]; } // Scale the current matrix. (world origin) void MatrixStack::scale(float x, float y, float z) { GLGXMATRIX tmp; GLGXMatrixScaling(&tmp, x, y, z); stack[currentLevel] = stack[currentLevel] * tmp; } // Scale the current matrix. (local origin) void MatrixStack::scaleLocal(float x, float y, float z) { GLGXMATRIX tmp; GLGXMatrixScaling(&tmp, x, y, z); stack[currentLevel] = tmp * stack[currentLevel]; } // Translate the current matrix. (world origin) void MatrixStack::translate(float x, float y, float z) { GLGXMATRIX tmp; GLGXMatrixTranslation(&tmp, x, y, z); stack[currentLevel] = stack[currentLevel] * tmp; } // Translate the current matrix. (local origin) void MatrixStack::translateLocal(float x, float y, float z) { GLGXMATRIX tmp; GLGXMatrixTranslation(&tmp, x, y, z); stack[currentLevel] = tmp * stack[currentLevel]; }
As is painfully obvious from the lack of posts on this blog, I pretty much abandoned my racing game for the iPhone. However, I still have the code and I am once again motivated to work on it. So here we go!
First of all, I have started to create my 3D content in Cheetah3D. The main reason for this is that Cheetah3D is very easy to use and it is scriptable using Javascript. So far I have created a script that generates a road mesh for me and I have imported meshes from a racing game I created for Windows in 2003.
Below is an image rendered by Cheetah3D, which might not look like much, but I am just getting started!

Hello, my name is Martin Johannesson and this is my home on the web. I live in Stockholm, Sweden, where I work as a software engineer at a software company.
Ever since I was a kid and discovered the art of programming on my
C64,
I've been tinkering with my own little software projects and experiments.
This site is one such experiment.
more...