(gedeeltelijk vertaald)

Over dit document

Dit document beschrijft de bestandsformaten die door Ultimate Stunts gebruikt worden. De informatie die hier beschreven wordt is van toepassing op de meest recente versie, dat is 0.7.5 op het moment van schrijven, maar veel dingen gelden ook voor oudere en nieuwere versies. Dit document beschrijft NIET de configuratiebestanden (*.conf); voor deze bestanden kunt u de documentatie van de corresponderende programma's lezen, of het commentaar in de bestanden zelf.

Dit bestand bevat de volgende secties:

General information about tracks

An UltimateStunts track is similar to an old stunts track in one important aspect: it consists of tiles. Each tile contains a 3D model of a piece of the track, e.g. a road, a piece of water, a bridge, or a tunnel. Tile-information is stored in files, each file containing just one tile.

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.

Het track-bestand (*.track) formaat

The track file is an implementation of the information described above. Track files are text files, so you should be able to edit them with a text editor. A track file has the following sections (in this order): Except for the header, each section begins with a line containing "BEGIN", and ends with a line "END". Inside a section, no comments should be placed. Outside a section, all data is ignored, but to make clear that it is a comment, each comment line should begin with a "#".

The header

The header, consisting of four lines, has the following syntax:
TRACKFILE
length
width
height
The 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.

De texture-sectie

De texture-sectie kan gebruikt worden om bepaalde textures als eerste te laden. Vanaf versie 0.7.5 is het niet meer nodig om alle textures op deze manier te laden, dus het zal meestal leeg zijn. Echter, zelfs als het leeg is, dan moeten de "BEGIN" en "END" tags nog steeds aanwezig zijn.

Elke regel in de texture-sectie bevat een bestandsnaam van een texture-afbeelding. Deze bestandsnamen worden geïnterpreteerd als relatief ten opzichte van de datafiles directory. De meest gebruikte bestandsformaten (JPEG, PNG etc.) worden ondersteund via de SDL_image bibliotheek. Texture-afbeeldingen moeten een breedte en hoogte hebben die machten van 2 zijn (8, 16, 32, 128 enz.).

Na de bestandsnaam kunnen enkele optionele parameters gegeven worden, in de vorm van naam=waarde paren, gescheiden door spaties. De volgende parameters kunnen ingesteld worden:

Als de schaal-parameter (die een macht van 2 moet zijn) groter is dan 1, dan wordt een kleinere texture-resolutie gebruikt. De resolutie wordt op de volgende manier berekend:
resolution_used = texture_maxsize / (scalehint * lod)
De gebruikte lod (Level Of Detail) hangt af van de afstand tussen de tile en de camera; een texture wordt geladen met lod = 1, 2, 4 en 8.
Als de grootte van de texture in het bestand kleiner is dan resolution_used, dan wordt de bestands-resolutie gebruikt. Als resolution_used kleiner is dan 8, dan wordt geen texture gebruikt. In plaats daarvan worden texture-loze oppervlaktes met de gemiddelde kleur van de texture gebruikt.

De achtergrond-sectie

Deze sectie bevat een beschrijving van de omgeving. Deze sectie moet een aantal "naam = waarde" paren bevatten, met de volgende betekenissen:
naambetekenisformaat
skyDe lucht/wolken texture bestandsnaamstring
horizonDe horizon texture bestandsnaamstring
envmapDe reflectie-map bestandsnaamstring
lightdirDe richting waar het licht naartoe gaatdrie coordinaten gescheiden door komma's, vector lengte moet 1 zijn
lightcolDe lichtkleur ("diffuse light")rood, groen, blauw componenten tussen 0.0 en 1.0
ambientcolDe schaduwkleur ("ambient light")rood, groen, blauw componenten tussen 0.0 en 1.0
skycolDe luchtkleur in het zenitrood, groen, blauw componenten tussen 0.0 en 1.0
horizonskycolDe luchtkleur aan de horizonrood, groen, blauw componenten tussen 0.0 en 1.0
fogcolDe mistkleurrood, groen, blauw componenten tussen 0.0 en 1.0
envcolDe modulatiekleur van wolken- en horizontexturerood, groen, blauw componenten tussen 0.0 en 1.0
Zie de onderstaande afbeelding:

De tiles-sectie

Elke regel in de tile-sectie heeft de volgende syntax:
bestandsnaam[:flags] [texture_id_0 [... [texture_id_n]]]
De bestandsnaam, relatief ten opzichte van de datafile dir, verwijst naar het gebruikte 3D-model. Dit kan ofwel een .glb bestand zijn, ofwel (vanaf versie 0.7.5) een .conf-bestand van een tile. In het geval van een .conf-bestand zijn de flags en texture_id waarden niet nodig, en zouden niet moeten worden gebruikt. Het wordt aangeraden om altijd .conf-bestanden te gebruiken in deze sectie als dat mogelijk is. Bij het gebruik van .glb bestanden kan het nodig zijn om de flags en texture_id waarden op te geven:

De flags geven wat extra informatie aan Ultimate Stunts. Op dit moment worden de volgende flags herkend:

De texture_id parameters zijn indices naar de textures sectie. (De eerste texture heeft id=0, de tweede id=1 enz.) Deze parameters beschrijven welke textures worden gebruikt door de tile. Op deze manier is het zelfs mogelijk om de zelfde tile met verschillende textures te gebruiken:
BEGIN
...
de_zelfde_bestandsnaam.glb 1 2 3
de_zelfde_bestandsnaam.glb 4 5 6
...
END
De volgorde waarin de indices worden gegeven is belangrijk: bijv. voor een weg-tile zou de eerste index kunnen verwijzen naar een weg-texture en de tweede naar een gras-texture. Bij het verwisselen krijg je effecten die je niet wilt. :-)

The grid sections

Every grid section contains the data of one grid. The first grid section in the file contains layer 0, which should contain the lowest tiles of the track. Every higher layer should contain the tiles placed above the tiles of the lower layer.

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/height
tile_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 * rotation
height is an integer describing the vertical position, via
y_offset = vertical_tilesize * height

The checkpoint section

This section defines the routes that can be followed by players in order to finish the track. When a player does not follow one of the alternatives, he/she gets penalty time.

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 3D-editor texture file (textures.dat)

In order to use the right texture when editing a 3D-model file, the 3D editor needs a file which describes the textures to be loaded. This file is called textures.dat, and it should be located in the current directory.

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:

The old 3D-model (*.gl / *.glt) format

In previous version (0.5.2 and before), all 3D models in UltimateStunts were stored in a text format. OpenGL programmers will recognise its syntax, because it's very similar to the commands in the openGL library. This section describes this old *.gl format. The new *.glt format is an extension to the *.gl format, and it allows vertex array models. It will be described here in the future. An important thing to know is that *.glt files are only used for editing: they cannot be loaded by Ultimate Stunts. Instead of that, version 0.5.3 and later use *.glb files.

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.

Primitives

3D models in *.gl files are described with the same 3D primitives that are supported by openGL. Every primitive describes a certain kind of 3D polygon, with the verticed defined counterclockwise as seen from the side where the polygon should be visible. As an additional requirement, the order in which the primitives are defined in the *.gl file should be a "back to front" order as much as possible. This is necessary for users who disable Z-buffering.

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

Vertex x,y,z

The most important command for describing primitives is the Vertex command. It describes one threedimensional point in the primitive, and should only be used within primitive code. The following example describes one square:
Quads
Vertex -5,0,-5
Vertex -5,0,5
Vertex 5,0,5
Vertex 5,0,-5
End
In 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.

Color red,green,blue

The color command is used to change the drawing color. This can be done both before and within a primitive definition (like in openGL). The parameters red,green and blue should be within the range [0,1]. Usage of Color is described by the following examples:

A red triangle:

Color 1,0,0
Triangles
Vertex -1,0,0
Vertex 0,1,0
Vertex 1,0,0
End
A 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
End
A 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

Opacity level

Defines how opaque the next primitives will be. 1.0 is fully opaque, 0.0 is fully transparent.

Reflectance level

Defines How well the reflection of the next primitives will be. 1.0 is fully reflecting, 0.0 is non-reflecting.

Normal x,y,z

The normal vector is used to calculate shadows. Its length should be 1, and it should be perpendicular to the surface. Normal can be used both before and within a primitive definition. The following example describes a quad with a correct normal vector:
Normal 0,0.96,0.29
Quads
Vertex 5,0,5
Vertex 5,3,-5
Vertex -5,3,-5
Vertex -5,0,5
End

Texture texture_id

This enables the usage of a texture. texture_id refers to one of the indices in the track file, called texture_id_n in the description above. The texture command can only be used outside primitive-definitions. The following listing, describing how to use the texture "texture_file.rgb", will make things clearer:
----------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.

Notex

Notex disables the usage of textures.

TexCoord u,v

Attaches texture coordinates to vertices, used in a similar way as Normal and Color. If u and/or v are given a range greater than [0,1], the texture is tiled. The following example, showing a square with texture 0 attached to is, should be clear now:
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

Lod levels

Defines in which LOD (Level Of Detail) levels the following objects should be visible. levels is a combination of the characters 1, 2, 3, 4 and c. 1 is the "high detail", "close-up" LOD, 4 is the "low detail", "far away" LOD, and c is the collision detection LOD. For example:
Object A
Lod 1c
Object B
Lod 1234c
Object C
Here, 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.

RotationAnimation origin;velocity

Enables the rotation animation for the most recently added primitive. This is not a state variable, so rotation animation is not enabled automatically for following primitives. Origin and velocity are settings for the rotation animation.

The new 3D model (*.glb) format

This fileformat has replaced the *.gl file format since version 0.5.3. It is a 3D geometry file format, designed to have the following advantages over the *.gl format: The general idea is that a model consists of objects (like the primitives in the *.gl format); objects have a name, a material definition, a set of vertices and an index array that defines the triangles. We will probably also want to add other kinds of data to the file, so there will be a possibility to add new types of objects to the file format.

Byte order

The byte order is defined in the file shared/binbuffer.cpp, as binbuffer objects are used to load and store data from *.glb files.

Top level format

magic number (4 byte)
objects
The 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 format

object type (4 byte)
object name size (4 byte)
object name (null-terminated, aligned to 4 byte size)
object data size (4 byte)
object data
The 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.

Geometry object data 0.5 (type 0x00000000)

material data size (4 byte)
number of vertices (4 byte)
number of indices (4 byte)
material data
vertex array
index array
This 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 data

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

vertex element data

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)

index element data

i (4 byte)
The index refers to an element in the vertex array of the object.

Geometry object data 0.7 (type 0x00000001)

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 array
This 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 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 data

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

vertex element data

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)

index element data

i (4 byte)
The index refers to an element in the vertex array of the object.

Replay (*.repl) formaat

Een replaybestand bevat een soort film van wat er tijdens een race is gebeurd. Voor elk momenr in de race zijn autoposities, oriëntaties en andere toestandsinformatie opgeslagen. Het *.repl formaat is een mix van binaire en UNIX-stijl tekst-elementen. Dus, wanneer er een "tekstregel" aanwezig is, dan is het een '\n'-terminated string. De binaire onderdelen gebruiken allemaal een formaat dat ook gebruikt wordt in de netwerkcommunicatie van Ultimate Stunts multiplayer spelsessies. Ze gebruiken allemaal de functies in shared/binbuffer.cpp voor het schrijven van high-level objecten zoals strings of vectoren.

header

Het begin van de header heeft het volgende formaat:
Magische headertekst (tekstregel)
Track-bestandsnaam (tekstregel)
Aantal objecten (tekstregel die een decimaal nummer bevat)
De eerste regel in een .repl-bestand bevat een magische headertekst. Deze tekst is er om te zien of we te maken hebben met een echt .repl-bestand, en of het formaat ervan overeenkomt met de replat-loader versie. Op het moment van schrijven (Ultimate Stunts 0.7.4) is de headertekst:
Ultimate Stunts replay format 0.7.4; network version ULTIMATESTUNTS 0.7.4
De volgende lijn bevat de bestandsnaam van het trackbestand. Dus, de track zelf is niet ingevoegd in het replay-bestand, alleen de bestandsnaam. Na de track-bestandsnaam is het aantal objecten (bijv. auto's) geschreven in het bestand.

Objecten

Vervolgens wordt, voor elk object, de volgende data geschreven:
Aantal bytes in beschrijving (tekstregel die een decimaal nummer bevat)
Objectbeschrijving (binaire buffer)
Het exacte formaat van de objectbeschrijving is gedefinieerd in simulation/objectchoice.cpp. Op dit moment heeft het het volgende formaat:
object type (8-bit unsigned integer, waared = 5 voor auto's)
.conf bestandsnaam van object(string)
naam van de speler (string)

Frame data

Tot slot wordt voor elke frame in de "animatie" de object-toestand-data geschreven in het bestand. Een toestand-data frame heeft het volgende formaat:
lengte van eerste object's toestandsdata (16-bit unsigned integer)
eerste object's toestandsdata
[lengte van tweede object's toestandsdata (16-bit unsigned integer)
tweede object's toestandsdata]
enz...
De lengte van de toestandsdata van een object wordt in elke frame opnieuw geschreven omdat het verschillend kan zijn voor elke frame. De toestandsdata van een enkel object is een binaire buffer, gedefinieerd door zijn afgeleide implementaties van de getData en setData methods. Meestal (zoals in auto's) wordt de basisimplementatie van CMovingObject gebruikt als startpunt. Op dit moment is het formaat als volgt:

Het eerste deel is het zelfde voor alle soorten moving objects (auto's en andere soorten voertuigen):

Object ID (8-bit unsigned integer)
Frame tijdstip (32-bit float, resolutie 0.005)
Positie (vector van 32-bit floats, resolutie 0.001)
Orientatie (vector van 16-bit floats, resolutie 0.0002)
Snelheid (vector van 16-bit floats, resolutie 0.01)
Hoeksnelheid (vector van 16-bit floats, resolutie 0.001)
Het volgende is een type-specifiek deel. Voor auto's (op dit moment het enige soort moving objects) is dit op dit moment:
Stuurhoek (8-bit float, resolutie 0.008)

Versnellingsnummer (8-bit unsigned integer)
Aandrijfas hoeksnelheid (16-bit float, resolutie 0.4)
Motor gas-deel (8-bit float, resolutie 0.008)

Wiel 0 hoeksnelheid (16-bit float, resolutie 0.4)
Wiel 0 hoek (8-bit float, resolutie 0.025)
Wiel 0 stuurhoek (8-bit, resolutie 0.008)
Wiel 0 slipvolume (8-bit, resolutie 0.008)

Wiel 1 hoeksnelheid (16-bit float, resolutie 0.4)
Wiel 1 hoek (8-bit float, resolutie 0.025)
..etc.

flags (8-bit unsigned integer, gebruikt als bitmasker)

[
botsing radiale snelheid (8-bit float, resolutie 0.40)
botsing tangentiale snelheid (8-bit float, resolutie 0.40)
botsing is fataal (8-bit unsigned integer, gebruikt als boolean)
]
Het botsingsdeel is niet altijd aanwezig: de 0x1 positie in de flags variabele staat aan als botsingsdata aanwezig is. Bitpositie 0x2 in flags staat aan wanneer de auto gecrasht is.

Toekomstige ontwikkelingen

Nieuwe bestandsformaten

Als nieuwe functionaliteit wordt toegevoegd, zullen nieuwe bestandsformaten nodig zijn. De botsingsdetectie-informatie zal uit de *.glb formaten gehaald worden, maar het zal bijv. ook materiaal-informatie nodig hebben, zoals wrijvings-coëfficiënten. Natuurlijk zal dat mooie Stunts zink-effect niet mogelijk zijn als we niet weten welke oppervlaktes water voorstellen.

Veranderingen in bestaande bestandsformaten

De grenzen die voorkómen dat auto's de track verlaten zouden in het track-bestand gedefinieerd moeten worden.