ENUMs, User Preferences, and the MySQL SET Datatype
Changing Mailman Python Scripts for Virtual Host Support
JQuery Venetian Blinds Transition Effect
Visualising Website Performance with Flame Graphs
Installing Xdebug for use with Eclipse or Netbeans on Linux
Getting Set up with Ogre 3D on Ubuntu

First 3D Game

Saturday, 31 December 05, 12:00 am
I now feel I'm ready to have a go at creating my first simple OpenGL game. It's going to be pretty simple - there'll be no scene graph, just a simple array for storing objects in the world. I won't implement frustum culling either, at least not in the first instance.

My game will be based on space flight, so I will start with the player's ship. It should appear just in front and below of the camera, i.e. third person. It should turn and dive/climb in response to keyboard input, and have a speed that can be set.

I will start with the p51 IFS model that comes with G3D, as I don't have the means to create my own models as yet. The VC++ project is created as an empty Win32 Project. It needs as a minimum a main.cpp file containing the main() entry point.
2 

compton

7:00 am, Saturday, 31 December 05

Now main() creates a GAppSettings object, and uses it to set certain features of the application, such as window size. It is then passed to the constructor of my implementation of GApp, called App in keeping with the convention from the examples.

Calling run() on the App instance executes any code I have placed in App::main(), inside exception handlers. For this simple example, App::main() will simply instantiate my implementation of GApplet, and call run() on it. To begin with, I need to override GApplet::init() and GApplet::doGraphics(). I can then override GApplet::doLogic() and GApplet::doSimulation() later.

compton

7:00 am, Saturday, 31 December 05

I intend to load the IFS P51 Mustang model using G3D's IFSModel class.

This class has two static methods that appear to load an IFS model from disk, namely create() (two overloads) and load(). The former returns an IFSModelRef, the second populates three arrays, passed in as arguments, and named index, vertex, and texCoord. I think using the first is best for me. I need to pass in the filename as a minimum. Optional arguments set the scale, a transformation (as a CoordinateFrame), and whether to 'weld' together co-incident vertices.

For now, i'm going to attempt to load this in Game::init(), keeping hold of the IFSModelRef as a member variable.

compton

7:00 am, Saturday, 31 December 05

Hoh hoh haa! I've managed to load and position the P51! Currently it has no colour or shininess, and is placed at the origin, but I know why both of these are happening.

To load the model, you call IFSModel::create(), which returns an IFSModelRef. Calling pose() on this returns a PosedModelRef, which exposes a render() method (taking the render device as its argument) which in turn renders the model.

To change where it appears, I need to create an appropriate CoordinateFrame, and pass that in to pose(). Thus, I may need to move pose() out of init(), and into doGraphics().

compton

7:00 am, Wednesday, 4 January 06

Well with a CFrame created to position the P51, its position and orientation can be simply changed using the CoordinateFrame's translation and rotation attributes.

The CoordinateFrame's lookAt method returns a Vector3 indicating the direction the frame is facing w.r.t. world coordinates - in other words, its z-axis. It is a simple matter to use this to calculate how to change the plane's x, y and z coordinates so that it flies forward at its current set speed.

However, more of a problem is mapping control movements correctly. When the plane is flying level, sideways movements can be routed directly to a rotation about the z-axis, to create roll. Similarly, when it is level, up-down movements can be routed to a rotation about the x-axis, to change the airplane's pitch.

The problem arises when the plane is not level. For instance, say the plane is rolling at 90 degrees. Now we want up-down movements to be mapped to a rotation about the y-axis, and not about x.

In fact, as the plane rolls, changes in pitch should be mapped to some mix of x and y, according to the angle of roll. A roll of 90 degrees equates to zero x-rotation, and 100% y rotation, while a roll of 45 degrees corresponds to 50% of each. The first thing to do is change roll to radians. Then we can use sin (roll angle) to give us the rotation about y, and cos (roll angle) to give us the rotation about x. Not sure if that will work, but it's along the right lines!
2 

Please enter your comment in the box below. Comments will be moderated before going live. Thanks for your feedback!

Cancel Post

/xkcd/ Moon Armor Index