object loading object loading object loading object loading object loading objec
ding object loading object loading object loading object loading object loading 
ct loading
object loading object loading object loading object loading object lo

borland c & glut      source      loading .lwo objects      texture coordinates      mail      links

ing object loading object loading object loading object loading object loading o

introduction It's no use writing 3D applications if we limit ourselves by constructing objects solely from opengl primitives.  It's better to design objects using a dedicated modeler.  These provide the proper tools we need for such a task.  Of course, after we've designed and built our object we need to load it into opengl.  Initially to keep things simple, we'll design a limited 'object language' that will allow us to load objects and colour properties.

ing object loading object loading object loading object loading object loading o

issues  So how do 'real' object formats store their data? Below is an example of a simple, easy to parse file format that contains the type of data necessary to record the shape and properties of an object.  To the right is an explanation of the file format.

 
VERTEX: 8
-1 1 0
1 1 0
1 -1 0
-1 -1 0
-1 1 1
1 1 1
1 -1 1
-1 -1 1

MATERIAL: 2
R: 0.3 G: 0.3 B: 0.6
R: 0.4 G: 0.4 B: 0.1

FACE: 6
0 1 2 3 1
0 4 5 1 1
3 7 6 2 1
4 5 6 7 0
0 4 7 3 1
1 5 6 2 1
 
  • You'll notice that the file is divided into three main parts, the first deals with vertices.  The total number of vertices in the object is given at the top - we need this number to allocate the required amount of memory.
    The following lines (eight lines in this case) show where the vertices are placed in 3D space. Each number will be represented as a GLfloat in an array.
  • 'Material' tells the parser that a collection of red, green, blue triples are coming next.
    Their values are expressed here as GLfloats. In the future these will probably be changed to GLubytes - they take up less space.
  • Next is the face component. The keyword will direct the parser to enter 'face mode'. A check can done here to test whether the correct number of vertices has been read.
    Again the single number is to allocate memory for the object.  The number of polygons (or faces) is indicated.
    The following numbers are indices to elements in the vertex array.  Each line represents a polygon.  The fifth number on each line is an index to the material that this polygon will have.

So there you have it. A commented, clear (IE no pointer passing) version of the simple parser is here.

[mesh loader]

It works okay as long as you don't throw any dodgy files its way.  Remember we're trying to keep it simple, so there is no error checking.  Notice how it creates the display list and optimises the material properties to minimise colour state changes...

ing object loading object loading object loading object loading object loading o

lightwave  Just to make it clear, I have nothing against lightwave for modeling and rendering.  [texture tools extortion] explains why lightwave models aren't the best choice for objects in games.  

milkshape  Okay, so we're smug in the knowledge that this kind of thing actually isn't that difficult. Lets try something a little more challenging.

Firstly read a copy of [milkshape's file format]. Now breathe and relax! 
Like the program before, we want our function to return a pointer to a display list. This time however we'll be loading textures, mapping them onto surfaces and making normals for smooth shading.

If we stick to good software engineering principles all of this is not as horrific as it sounds. For starters, a single function like in the previous program wouldn't be any use. We'll need a number of smaller functions collected together to form a library. This helps us reason about the problem in small pieces and ensures that we get each part working properly on its own without the rest of the project to worry about.
If you're new to programming then you should buy a good software engineering book with plenty of examples - the simpler the language the better (IE stay away from C/C++ for as long as is humanly possible!)

We're splitting our main task into a few 'subtasks'. These will the basis for our .c functions that will make up the library. If we're careful about how we separate our functions, adding extra functionality (like normal and texture coordinate generation) is much easier

ing object loading object loading object loading object loading object loading o

story so far...  The binary filespec. in the SDK appears to be incorrect - either it's wrong or I'm being incredibly stoopid.  So we'll be loading the ascii version of the files.  This isn't what I'd hoped, but its not a total disaster.

Now this picture is the indie fighter from i-war (no, I've never seen it this close either).  You can see that the ship fully textured, we've generated our own normals - lots of people ask how to do this, so we'll ignore the normals calculated by milkshape.

The textures for the Indie Fighter were collected together into one 256x256 image, the benefits of milkshape's interactive texturecoord editing become clear - as we said in [texture tools extortion], you save on texture memory and on opengl state changes.

first release  The two zip files below contain everything necessary to load milkshape ascii files.  The code for both libraries is heavily commented but quite a few new opengl functions are introduced.  

You'll want an object with textures to try it out too.  The [starship enterprise] has always been a favourite of mine.  The screenshots below were grabbed from the displaylist version of the program.  Press '1' to see the model untextured, you can see more clearly that we generate vertex normals and use glMaterial to set emission properties for the deflector dish and running lights.

"to do" checklist  There's a few things wrong with this that need fixing:

[done]

Smoothed normals would be nice.

[pending]

EVERY surface needs a texture or you get garbage mapped on to it.  I'm really lazy, a simple if statement would fix this.

[pending]

Textures need flipping after you've mapped them in milkshape.  I'm at a loss with this one.  Once you've mapped your object in milkshape and you run it through the loader the textures appear upside down.  Just flip them in your art package and you'll be fine.  You could flip them in the tgaloader (make a bit field argument like TGA_FLIP_VERTICAL).  It's probably something to do with the way milkshape assigns UV coords...

[pending]

Texture names can't have a full path.  The tgaloader goes funny if the textures you're loading aren't in the same directory.

the future...  
I'd like to add support for multipass texturing - lightmaps or damage maps.  This is where the vertex arrays will realy come into their own because the geometry isn't static we can still play about with it.  Keep checking back for more updates.

ion compilation compilation compilation compilation compilation compilation co

Website and content, Paul Groves.
Indie Fighter model taken from [Independence War] Copyright (c) 1999, 2000 [Particle Systems] and Infogrames.  Used with permission.