30
MAR
2010

Matrix Stack

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 D3D class, but there was no implementation to peek at, so I had to figure out the implementation of the methods on my own. If anyone is interested in the code, I am willing to share.

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++.

#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); 
};


30
MAR
2010

Racing Restart

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!

First Render


30
JUL
2009

iPhone Racer, Part 6

Making the wheels spin is actually a bit more complicated than one might think. The 3D model of the car is divided in five different geometric objects. Four of these objects represent the wheels and the fifth object is the rest of the car.

Each object is defined by a number of vertices (points) in 3D space. If you want to spin a wheel, you have to rotate its vertices around its center axis. The problem is that when you rotate vertices using OpenGL, they are rotated around the origin of the coordinate system. Consequently, if you apply a rotation transform to a wheel, it will not spin around its center axis. So what you have to do is move the wheel to the origin, rotate it, and then move it back to its original position.

Transforms

I extended my OBJ converter script to calculate the center point for each object in the 3D model and then save it along with the geometric data. Then in the car rendering code, I added a translation transform to move the wheel to the origin by subtracting the center point, followed by a rotation, and another translation to move it back by adding the center point again.

The order of the OpenGL transformation calls may look like they're in the wrong order, but this is due to the order in which the transformation matrices are multiplied.

Currently, it takes one separate call to the drawing function for each object in the 3D model, because different transforms have to be applied to the objects. This can be optimized by using the matrix palette OpenGL extension.

Instead of pushing matrices on the OpenGL matrix stack, you precalculate the entire transformation matrix for each object and place them in a matrix palette, which is really an array of matrices. Then each vertex struct is extended with a field that contains an index into the matrix palette, indicating which matrix should be used to transform that particular vertex.

This way you only need one call to the OpenGL draw function to draw the entire model, because no state changes need to occur in between the rendering of the different objects in the model.


30
JUL
2009

iPhone Racer, Part 5

I have added lateral movement of the car. Whenever your finger touches the screen, the "requested" lateral position of the car is updated. The car then moves towards the requested position at a preset rate. If the car moved to the new position immediately, it would look like it was teleporting.

I think I'll probably add spinning wheels next.


28
JUL
2009

iPhone Racer, Part 4

I created a fairly ugly Formula 1-type car in 3D and exported it as an OBJ file. The OBJ format is a very simple and fairly common plain text format for 3D objects. However, it is not a very compact format, so it takes up a lot of space.

The usual approach is to create an importer in the game engine that can parse and load the OBJ file, but I created a converter in REBOL instead. The converter reads the OBJ file, optimizes the geometric data for use with vertex buffer objects in OpenGL, and finally saves the data in a binary file.

I then wrote a corresponding file loader in C++ in the game framework. It basically loads the binary file straight into the vertex buffer object, since the converter has already organized the data in the same way it is stored in memory.

A lot of things can be improved, but at least now I have a 3D car to play with in my game code. I guess the road may be next!


27
JUL
2009

iPhone Racer, Part 3

The time has come to start thinking about the technical details of the iPhone racing game. I like to attack my projects on multiple fronts from the get-go, as it gives me a sense of the overall architecture and requirements quickly.

Placeholders

This is probably not the right place to start, but I've created placeholders for the app icon and the loading screen. I would rather look at placeholders than the default white icon and black loading screen, given how many times you see the icon and loading screen during the development of an iPhone app. More importantly, I had fun doing it.

Game Framework

My iPhone game framework interface is heavily inspired by XNA and the game state XNA sample. Obviously, the implementation of the interface is completely different, but anyone who has ever used XNA would feel at home using my framework. However, I have not implemented anything similar to the content pipeline... yet.

The framework was/is implemented in a hybrid of Objective-C and C++, where Objective-C is really only used for Cocoa specific functionality and the fundamental app skeleton. The main reason for this decision is that I am hoping to be able to reuse some C++ code that I have written in the past for other platforms.

Graphics

I've decided to use 3D graphics and OpenGL is the obvious, not to mention only, choice for that purpose. Fortunately, I have previous experience with OpenGL, both from work and my own projects. The first time I used OpenGL was in 1998, on a 3Dfx Voodoo 2 GPU. Since then, OpenGL has come a long way. Still, I prefer Direct3D over OpenGL, but OpenGL will have to do.

When I did my master's thesis on terrain rendering, I started out in OpenGL, but I switched over to Direct3D very early on. Fortunately, my abstraction layer allowed me to completely replace the renderer in one single day. It would probably be a good idea to create a similar abstraction for this project, even if OpenGL is the only option on the iPhone.

Audio

When it comes to audio, I will go with OpenAL. I have already written a very, very basic implementation of an OpenAL audio engine. I will build on that to create something that is actually usable in a game.


25
JUL
2009

iPhone Racer, Part 2

Let's flesh out the game design for the iPhone racing game a little bit more. In the previous post I mentioned the fundamentals. This time I will go into more detail.

Obstacles

The player has to avoid obstacles on the road. There are obstacles that move, in the form of other cars. Bumping into a moving car will slow the player's car down. There are also static obstacles, such as:

  • Rocks
  • Brick walls
  • Trees
  • Oil patches
  • Water puddles
  • Pot holes

Bumping into large static obstacles will stop the car completely for a brief period of time. Oil patches will temporarily make the player unable to control the car. Water puddles will slow the car down.

Some obstacles are not really obstacles however. If the player runs into e.g. a fallen tree trunk, the car will jump. This can be used to jump over certain obstacles.

Obstacles are spawned randomly, but under controlled circumstances, to ensure that the track is not the same every time.

Levels

Each level consists of a stretch of road of a certain distance. At the end of every level, there is a checkpoint marker. The player has to reach the checkpoint within a certain time limit, or the game is over. Once the checkpoint marker has been passed, the timer is reset.

The levels get progressively more difficult. There are mainly three parameters for controlling the difficulty:

  1. The time limit.
  2. The number of obstacles.
  3. The speed of the car.

Racing in the Desert

Different environments will provide visual variety. Colors of the scenery and objects at the side of the road will change depending on what type of environment a particular level represents. It could be a desert, a winter landscape, a forest, a tropical island, or just about any other kind of setting.

Score

The objective of the game is to maximize the player's score. The player gets points for picking up flags along the way. The player also gets points for the amount of time left on the clock when a checkpoint is reached.

An optional feature would be to implement an online global high score table. This would hopefully add competitive value to the game.

Controls

The control scheme is easy: the player can only move the car sideways. The speed of the car is determined by the game. The player will move the car laterally by moving a finger, left and right, across the screen.

Game Over

The game ends when the player does not make it to a checkpoint on time. There is no set number of levels, but at some point, the game will get so ridiculously hard that the player will run out of time, no matter how skilled he (or she) is.


24
JUL
2009

iPhone Racer Mockup

OK, so I may as well kick off this blog with an entry about a new project. I've wanted to create a game for the iPhone for quite some time now and I have actually written parts of a game engine for the iPhone already. For some reason I just haven't been able to find the time to create an actual game. A lot of that probably has to do with the scope. I need to start with a very small project.

So, I have come up with an idea for a simple game that could still be entertaining. It's basically like the game Buggy Boy, but with a straight road. If I get that far, I can consider throwing some turns and curves in there as well, but let's not get ahead of ourselves here!

Here's a mockup picture I created in about 3 minutes:

Racer Mockup

The objective is simple. Avoid obstacles like other cars and the big grey thing (which is supposed to be a rock) and pickup flags for points. As you advance through the game, there will be more obstacles and the car will go faster. The objective is to get the highest score possible. An online high score list could possibly add motivation, but that is not crucial for the initial implementation.

Now that I'm blogging about it, it will haunt me for years if I don't finish it, because Google will cache this post for me for a long time. That should motivate me to keep going even when my dayjob makes me tired of coding, if ever so briefly.

Let's get this thing on the road! Pun intended.


About This Site

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...

Recent Entries RSS Feed

Tags

Amiga blog C game GLGX GLSL iPad iPhone Java jQuery OpenAL OpenGL Programming REBOL Shaders Vertex Shader web

Blog Archive

2010: 01 02 03 04 05 06 07 08 09 10 11 12
2009: 01 02 03 04 05 06 07 08 09 10 11 12

Random Images Load new images

loading
loading
loading
loading
loading
loading
loading
loading
loading
loading
loading
loading

People I Know