This document describes the file formats as used by Ultimate Stunts. The information described here applies to the most recent version, which is 0.7.5 at the time of writing, but many things also apply to older and newer versions. This document does NOT describe the configuration files (*.conf); for these files, please have a look at the documentation of the corresponding programs or at the comments in the files themselves.
This file contains the following sections:
The track-file, describing the track, contains references to the tile-files. Each tile can be used several times in one track, and in different orientations. So, if your track contains several straight roads in different directions, you'll only need one straight-road tile.
All tiles have the same sizes. Structures larger than the standard tile size, like wide corners, are built from smaller tiles. Tiles in a track are ordered in horizontal grids. Every point in the grid contains an id referring to the tile, an integer describing the orientation of the tile, and an integer describing the vertical position of the tile. Because of that last integer, it is possible to make tracks with very large height differences.
In one track, more than one of these grids can be used. This way, a threedimensional grid is created effectively, and tiles can be placed above each other. This results in the possibility of underground tunnels, viaducts crossing each other, etc. etc.
TRACKFILE length width heightThe word "TRACKFILE" is a magic word to make sure we are dealing with a track file. The length and width parameters give the sizes of the grids, and height is the number of grids used. Every number in the header must be consistent with the rest of the file, or else errors will occur while loading the track.
Each line in the texture section contains a filename of a texture
image. These filenames are interpreted as being relative to the
datafiles directory. The most common file formats (JPEG, PNG etc.) are
supported through the SDL_image library. Texture images must have a width
and height that are powers of 2 (8, 16, 32, 128 etc.).
After the filename, some optional parameters can be given, in the form
of name=value pairs, separated by spaces. The following
parameters can be set:
resolution_used = texture_maxsize / (scalehint * lod)The lod (Level Of Detail) used depends on the distance between tile and camera; a texture is loaded with lod = 1, 2, 4 and 8.
name | meaning | format |
sky | The sky/clouds texture filename | string |
horizon | The horizon texture filename | string |
envmap | The reflection map filename | string |
lightdir | The direction where the light goes to | three coordinates separated by commas, vector length should be 1 |
lightcol | The light color ("diffuse light") | red, green, blue components between 0.0 and 1.0 |
ambientcol | The shadow color ("ambient light") | red, green, blue components between 0.0 and 1.0 |
skycol | The sky color at the Zenith | red, green, blue components between 0.0 and 1.0 |
horizonskycol | The sky color at the Horizon | red, green, blue components between 0.0 and 1.0 |
fogcol | The fog color | red, green, blue components between 0.0 and 1.0 |
envcol | The modulation color of clouds and horizon texture | red, green, blue components between 0.0 and 1.0 |
filename[:flags] [texture_id_0 [... [texture_id_n]]]The filename, relative to the datafile dir, refers to the 3D-model to be used. This can either be a .glb file, or (version 0.7.5 or later) a tile's .conf file. In the case of a .conf file, the flags and texture_id values are not necessary, and should not be used. It is recommended to use .conf files whenever possible in this section. When using .glb files, you may need to specify the flags and texture_id values:
The flags give some additional information to Ultimate Stunts. Currently, these flags are recognised:
BEGIN ... the_same_filename.glb 1 2 3 the_same_filename.glb 4 5 6 ... ENDThe order in which the indices are given is important: e.g. for a road tile the first index could refer to a road texture, and the second to a grass texture. When swapping them, you get effects you don't want. :-)
Every line in a grid section contains the data of one line of tiles.
The number of lines in a section should equal length in the
header. The number of items in a line should equal width.
Every line begins with a tab, and items are separated with a tab.
(DON'T use spaces here!). Every item has the following syntax:
tile_id/rotation/heighttile_id is a reference to an item in the tiles section. rotation is an integer describing the orientation of the tile, via
degrees_clockwise = 90 * rotationheight is an integer describing the vertical position, via
y_offset = vertical_tilesize * height
Every checkpoint line in this section contains the tile coordinates of the checkpoint, followed by a ":" and a time value. The tile coordinates are integer numbers, that define a position in the grid: first the west-east position, then the north-south position and then the layer number (e.g. 0 for the lowest tile at that position). The time value is the time after starting when a fast car could be in the tile. The penalty time is calculated by taking the difference between the time of the last valid position and the new position, and multiplying this difference to make it bigger.
When a track has only one route, then the first checkpoint should be the start tile and the second checkpoint should be the tile directly after the start. After that, not every tile needs to be a checkpoint, but it is recommended to put checkpoints at strategic points like corners and the top of a looping. The last checkpoint should be the start/finish tile (when the start is also the finish), or, when the finish is at a diferent place, the last two checkpoints should be the finish and the tile directly behind the finish.
When there are multiple routes, the first route should be the fastest one. Then, the fastest alternative route should be defined, then all other alternatives, sorted on driving time, and as last the slowest alternative. The fastest route should be given in exactly the same way as described for single-route tracks. Alternative routes are slightly different from the first route:
The first checkpoint of an alternative route is not the start, but the last checkpoint that is shared with previously defined routes (Normally this is the tile where the two separate). The time of this tile is set to 0.0 seconds, and the time values of other checkpoints of this alternative should be given relative to this first point. The last checkpoint of the alternative should be the first checkpoint that is shared with previously defined routes. When Ultimate Stunts finds that there already is a checkpoint at that position, it knows that this alternative ends, and that following positions define new alternative routes.
Examples:
-finish-<-B-<--\ | | ^ ^ | | A->--/ | ^ | start gives: BEGIN {start pos} : 0.0 {checkpoints between start and A} {A pos} : {time of A} {checkpoints short path between A and B} {B pos} : {short time of B} {checkpoints between B and finish} {finish pos} : {short finish time} {pos after finish} : {time} {A pos} : 0.0 {checkpoints long path between A and B} {B pos} : {long time of B - time of A} END
The header section of this file only contains the line "TEDITFILE". The only other section in this file (beginning with the line "BEGIN" and ending with "END") contains the following lines:
Commands in *.gl files should be placed at the beginning of lines, so it's only possible to place one command per line, and no white space is allowed before the command.
The following 3D primitives are supported by the format: Quads, Triangles, Trianglestrip, Quadstrip and Polygon. A primitive is started with a line containing its name, and it is ended with "End". The following code describes two triangles:
Triangles [code describing the first triangle] [code describing the second triangle] End
Quads Vertex -5,0,-5 Vertex -5,0,5 Vertex 5,0,5 Vertex 5,0,-5 EndIn the same way, triangles, triangle strips, quad strips and polygons can be defined. The coordinates in Ultimate Stunts should be given in meters. For a tile, this means a range between -20 and 20 for x and z, and a range between 0 and 12 for y.
A red triangle:
Color 1,0,0 Triangles Vertex -1,0,0 Vertex 0,1,0 Vertex 1,0,0 EndA square with a red/yellow color gradient:
Color 1,0,0 Quads Vertex -5,0,-5 Vertex -5,0,5 Color 1,1,0 Vertex 5,0,5 Vertex 5,0,-5 EndA polygon with lots of colors:
Polygon Color 1,0,0 Vertex -3,0,-5 Color 0.5,0.5,0 Vertex -5,0,-3 Color 0,1,0 Vertex -5,0, 3 Color 0,0.5,0.5 Vertex -3,0, 5 Color 0,0,1 Vertex 3,0, 5 Color 0.5,0,0.5 Vertex 5,0, 3 Color 0,0,0 Vertex 5,0,-3 Vertex 3,0,-5 End
Normal 0,0.96,0.29 Quads Vertex 5,0,5 Vertex 5,3,-5 Vertex -5,3,-5 Vertex -5,0,5 End
----------tracks/default.track----------- TRACKFILE ... #Texture section BEGIN texture_one.rgb texture_two.rgb texture_file.rgb ... END ... #Tiles section BEGIN ... example_tile.gl 0 2 ... END ... ----------------------------------------- ------------example_tile.gl-------------- ... Texture 1 ... -----------------------------------------Here, texture_id = 1, and refers to texture_id_1. texture_id_1, being 2, refers to the third texture, which is "texture_file.rgb".
Note that directly using .gl files in a track is no longer possible, so this example is no longer completely correct. Instead, convert your .gl(t) file to a .glb file with the ustunts3dedit program, and use that .glb file in your track.
Texture 0 Normal 0,1,0 Quads TexCoord 1,1 Vertex 5,0,5 TexCoord 1,0 Vertex 5,0,-5 TexCoord 0,0 Vertex -5,0,-5 TexCoord 0,1 Vertex -5,0,5 End Notex
Object A Lod 1c Object B Lod 1234c Object CHere, in all LODs the objects A and C are visible, and object B is also visible in LOD 1 and it is used for collision detection. The default LOD is 1234c.
magic number (4 byte) objectsThe magic number is there to make sure that it really is an Ultimate Stunts geometry file. It must be "\0GLB". The order in which the objects are in the file does matter sometimes. For example, this order defines in which order the objects are displayed, so if the z-buffer is disabled, then a bad order can look bad.
object type (4 byte) object name size (4 byte) object name (null-terminated, aligned to 4 byte size) object data size (4 byte) object dataThe data size is the number of bytes in the object data (that excludes the object type and object data size). Depending on the object type, the object data can have the formats that are described below. For every format, the object type ID is placed within brackets.
material data size (4 byte) number of vertices (4 byte) number of indices (4 byte) material data vertex array index arrayThis object type is used in Ultimate Stunts prior to version 0.7.0. It is still supported, but its use is discouraged. Please use the Geometry object data 0.7 instead.
material modulation color r,g,b,a (4 byte) material replacement color r,g,b,a (4 byte) LODs (1 byte) material reflectance (1 byte) material emissivity (1 byte) static friction coefficient (1 byte, range 0..16) dynamic friction coefficient (1 byte, range ???) unused (3 byte) texture name (null-terminated, aligned to 4 byte size)LODs contains a set of flags that describe in which LODs the object should be visible. The texture name can be a filename (relative to the Ultimate Stunts datadir), or a number. The modulation color is used to modulate the texture, the replacement color is used if the texture is disabled.
If the texture name is a number, then it can be set in the track file as a parameter. Colors can also be set as a parameter: if a==0 and b==255, then r is the number of the parameter. (this does not reduce the number of colors that can be set: if a==0 then the values of r,g,b don't matter.)
x,y,z (3*4 byte, signed int, unit = millimeter) nx,ny,nz (3*4 byte, signed int, range -1..1) tx, ty (2*4 byte, signed int, range -128..128)
i (4 byte)The index refers to an element in the vertex array of the object.
animation data size (4 byte) material data size (4 byte) number of vertices (4 byte) number of indices (4 byte) animation data material data vertex array index arrayThis is the replacement of the Geometry object data 0.5 type. Animation data is added, and animation and material data is made extensible, so that later versions won't need a new object type too soon. Also, friction coefficients have been removed from the material data.
Animation flags (4 byte) Rotation origin x,y,z (3*4 byte, signed int, unit = millimeter) Rotation velocity x,y,z (3*4 byte, signed int, range -1000..1000) future additions (aligned to 4 byte size)The animation flags contain a number of flags to describe which animation types are enabled for this object. The rest of the animation data contains parameters for these animation types. The flags variable is an OR'ed combination of values that correspond to animation types in the following way:
The rotation animation has the rotation origin and velocity as parameters. The object is rotated around the axis that goes through the rotation origin point, and has the direction of the rotation velocity. The rotation speed (in rad/second) is equal to the size of the velocity vector.
material modulation color r,g,b,a (4 byte) material replacement color r,g,b,a (4 byte) LODs (1 byte) material reflectance (1 byte) material emissivity (1 byte) unused (1 byte) texture name (null-terminated, aligned to 4 byte size) future additions (aligned to 4 byte size)LODs contains a set of flags that describe in which LODs the object should be visible. The texture name can be a filename (relative to the Ultimate Stunts datadir), or a number. The modulation color is used to modulate the texture, the replacement color is used if the texture is disabled.
If the texture name is a number, then it can be set in the track file as a parameter. Colors can also be set as a parameter: if a==0 and b==255, then r is the number of the parameter. (this does not reduce the number of colors that can be set: if a==0 then the values of r,g,b don't matter.)
x,y,z (3*4 byte, signed int, unit = millimeter) nx,ny,nz (3*4 byte, signed int, range -1..1) tx, ty (2*4 byte, signed int, range -128..128)
i (4 byte)The index refers to an element in the vertex array of the object.
Magic header text (text line) Track filename (text line) Number of objects (text line containing decimal number)The first line in a .repl file contains a magic header text. This text is there to see whether we are dealing with a real .repl file, and whether its format version corresponds to the replay loader version. At the time of writing (Ultimate Stunts 0.7.4), the header text is:
Ultimate Stunts replay format 0.7.4; network version ULTIMATESTUNTS 0.7.4The next line contains the filename of the track file. So, the track itself is not included in the replay file, only its filename. After the track filename, the number of objects (e.g. cars) is written to the file.
Number of bytes in description (text line containing decimal number) Object description (binary buffer)The exact format of the object description is defined in simulation/objectchoice.cpp. Currently, this has the following format:
object type (8-bit unsigned integer, value = 5 for cars) object's .conf filename (string) player's name (string)
length of first object's state data (16-bit unsigned integer) first object's state data [length of second object's state data (16-bit unsigned integer) second object's state data] etc...The length of an object's state data is re-written in every frame, because it can be different for every frame. The state data of a single object is a binary buffer, defined by its derived implementations of the getData and setData methods. Usually (like in cars), the base implementation of CMovingObject is used as a starting point. Currently the format is as follows:
The first part is the same for all kinds of moving objects (cars and other kinds of vehicles):
Object ID (8-bit unsigned integer) Frame time (32-bit float, resolution 0.005) Position (vector of 32-bit floats, resolution 0.001) Orientation (vector of 16-bit floats, resolution 0.0002) Velocity (vector of 16-bit floats, resolution 0.01) Angular velocity (vector of 16-bit floats, resolution 0.001)Next is a type-specific part. For cars (currently the only kind of moving objects), this currently is:
Steering angle (8-bit float, resolution 0.008) Gear number (8-bit unsigned integer) Drive axis angular velocity (16-bit float, resolution 0.4) Engine gas fraction (8-bit float, resolution 0.008) Wheel 0 angular velocity (16-bit float, resolution 0.4) Wheel 0 angle (8-bit float, resolution 0.025) Wheel 0 steering angle (8-bit, resolution 0.008) Wheel 0 skid volume (8-bit, resolution 0.008) Wheel 1 angular velocity (16-bit float, resolution 0.4) Wheel 1 angle (8-bit float, resolution 0.025) ..etc. flags (8-bit unsigned integer, used as bitmask) [ collision radial velocity (8-bit float, resolution 0.40) collision tangential velocity (8-bit float, resolution 0.40) collision is fatal (8-bit unsigned integer, used as boolean) ]The collision part is not always present: the 0x1 position in the flags value is set when collision data is present. Bit position 0x2 in flags is set when the car has crashed.