.3DO File Format - General 3DOs by P.A.Flack 1999
last revised 7/June/1999

Most 3DOs, that is, 3DOs that aren't tracks or cars, have the following structure, where some of the sections are optional (and can probably be in any order):

      Header;   Normals;   Vertices;   Planes;   Strings;   Primitive Tree(s);   Handles

This page will hopefully explain the way in which these work together to create the objects used in GPL.  Hopefully.  If you are new to 3DOs, I recommend you take your time and read all of the pages here several times over before doing anything.  Unless you think it's all too easy ;-)


As you'll find out (if you haven't already), 3DOs are complicated.  Especially the cars and tracks.  I will be using an example 3DO familiar to many, the hay bales at Watkins Glen.  This is a good choice because it has relatively few polygons, and has a collision detection volume built in.  Once you've mastered this, the other features that 3DOs have will be childsplay (sort of).
The 3DO is a cuboid shape, with 8 polygons (no base, 2 per long side/top).  Here is the same object as shown by GPLEditor (by Paul Hoad).  Note the positions of the axes, Z is up (completely wrong in my opinion, as Z should be depth and Y should be up, but that's Papyrus' choice and enough of that debate).

I'll assume an understanding of 3D vertices and the fact that polygons can be constructed from those vertices.  In the hay bale (bale?, bail?), only rectangles are used.


Texture Mapping
To make everything look lovely, nearly every polygon in GPL is texture mapped.  Those that aren't are coloured with single colours (every polygon is, but usually the texture mapping is chosen above flat shading).  For each polygon, the appropriate texture needs to be chosen, and texture coordinates are needed to specify where the texture is placed on the polygon.
Lets say that this is the texture to be applied to a polygon.  Texture coordinates usually range from 0.0 to 1.0, where 0 is top/left and 1 is bottom/right.  (Either or both of them might be the other way around, I can't remember :-).  If a texture is to be repeated, values greater than 1.0 are used.  If only a small piece of the texture is to be used, values smaller than 1.0 are used.  Negative values are never used.  If the values used are the wrong way round, the texture will be mapped back-to-front.


Hidden Surface Removal
Drawing the polygons aside, this is the most time consuming task.  It is necessary to remove the hidden surfaces because if they weren't, the number of polygons to draw each frame would be too large in comparison to the number seen, and performance would be badly affected.

Take a wall that has two sides (forget the thickness for now).  When you are standing on one side, unless you have some really cool vision, you can't see the other side (also forget mirrors and such).  If you move around to the other side, you can't see the side you were on.  Thus, to reduce the number of polygons drawn by half, all that is needed is a way to determine which side of the wall you are on.  The same goes for objects which are on opposite sides of a surface.  If you have an apple behind a wall, it is fairly safe to say that it won't be visible from in front of the wall (unless the wall has lots of holes, in which case it is pointless to use visibility determination like Hidden Surface Removal - a depth buffer is much more useful - but forget this little side point if you're confused already).

To determine which side of a plane (an infinitely thin surface, extending to infinity in all other directions), a point (i.e. an observer) is on, maths is used.  The equation of the plane (Ax + By + Cz + D = 0) is jiggled about a bit with the location of the viewer and a number results.  If negative, the viewer is one side, positive the other, zero and the viewer is actually on the plane (and thus in a bizarre infinity reality Star Trek situation and can't see anything (or can they?)).

Back to the hay bale, and you'll see 5 numbers from 0 to 4.  These reference the red squares/lines, which are the planes for the hay bale.  Most planes you'll encounter will be in the same plane as a polygon, like those in the example.  It is not necessary for this to be the case, but it usually helps.  The numbers are the same as used by GPL.

Now we need to see the 3DO as a tree:

Yes, it looks scary.  Basically, everything beginning with a T- is a node in the tree.  The T-81f leaves are the polygons.  The T-5 nodes choose the appropriate texture.  T-4's act as a branch and can have any number of children.  The important nodes for this tutorial are the T-9's and the T-6.  These are the nodes which reference the planes (numbers shown).

When GPL comes to render the hay bale (or any other object), it starts at the top of the tree (T-9,2) and sees which side of plane number 2 the viewer is on.  Looking at the diagram, it can be seen that if the viewer is above the plane (in the direction of the line), they can see the contents of the left hand branch (which is actually the middle branch, because no left branches are defined for this particular object).  Presumably, if they are below the plane they would be shown the contents of the left hand branch.  The rendering then continues by following the right hand branch, where similar checks are made.
The T-6 node is a bit different in that it does not contain anything other than a single branch which is followed if the viewer is in front of the plane, otherwise is isn't.


Collision Volumes
The planes are not used exclusively for visibility determination.  They are used for detecting whether collisions have occured.

Remember that planes are infinite, and divide space into two.  If you take several planes, it is possible to define a region of space which is behind all of the planes, i.e. enclosed.  GPL uses this (not enclosed top and bottom, though), to define volumes where collisions occur.  This is achieved by using a tree of a particular structure:

This tree is contained within the hay bale's 3DO as a separate tree.  A Handle is used to point to the tree, under the name 'collision'.  (see the Handles section for more information).  The number of children in the first T-4 defines how many volumes make up the collision detection, for there can be more than one.  For each volume, a T-4 has n children, one per plane, that consist of a T-6 (with the appropriate plane id), and a T-10, which lists numbers.  For collision volumes, there is only ever 1 number, for this example it is 0xB, or 11decimal, which presumably means hay, or more accurately, a solid collision.  I haven't yet researched the different types of collision available.  Needless to say there are types with different rebound characteristics, and types like hedges, that 'catch' the car.


- probably not finished, I haven't read through it yet...
- now I've read it and I'm sure there's stuff to add...

last revised 7/June/1999