Track file format
(Version 3.0)

Introduction

A track specification is a directory containing the various assets that define a particular course. One of the files in this directory is the track file, which is an ASCII file that specifies the geometry and AI meta-data for a particular track using the the JSON syntax extended with C-style comments (most JSON parsers accept such comments).

This specification is meant to be a baseline specification that you can extend with information that is specific to your game. For example, you might add acceleration/breaking hints to sectors.

The file format

File

A track file consists of a JSON object with the following fields:

"version" : string
This field specifies the version of the track-file format (currently "3.0").
"name" : string
The name of the track.
"revision" : string
A revision number for the track itself. This field is optional.
"track" : a track object
Information about the track geometry
"racing-lines" : a racing-lines object
Information about racing lines around the track

Track

A track is a JSON object that describes the geometry of the track. The track is represented as a list of polygonal sectors. Note that while the track geometry can be used for simple rendering, it is not meant to be a substitute for the actual 3D mesh representation of the world.

"num-vertices" : integer
The number of elements in the vertices array.
"vertices" : array of 3D-vertex
These are the vertices used in the sector. They are referenced by index (starting at zero).
"num-sectors" : integer
The number of elements in the sectors array.
"sectors" : array of line
The array of sectors that define the boundaries of the track.

3D-Vertex

A vertex is a location in 3D space. Each track description has an array of vertices, which are then referenced by index (zero-based). The representation of a vertex is an array of three numbers representing the X, Y, and Z coordinates of the vertex. The Y coordinate is used to represent the altitude of the vertex.

Sector

A sector is a convex polygon that defines a region of the track. Its edges are classified into walls, entry edges, and exit edges. The entry/exit distinction defines the direction that vehicles are expected to travel. A sector has the following fields:

"num-edges" : int
The number of edges in the edges array.
"edges" : array of edge
The edges of the sector in CCW order.
"attributes" : object
This optional field is used to associate name-value pairs with a sector.

Sector edge

Edges have the following common fields:

"kind" : string
The kind of edge. This field will be either the string "wall", "entry", or "exit"
"start" : int
The vertex index of the start of this edge. The endpoint of the edge will be the start vertex of the next edge.
Wall edge

A wall edge represents the boundary of the track and has no additional fields.

Entry and exit edges

Entry and exit edges connect sectors connect two sectors, with the exit edge in one sector having a corresponding entry edge in the neighbor sector. These edges have the following additional fields:

"neighbor" : integer
specifies the sector that this edge connects to.
"neighbor-edge" : integer
specifies the edge-index of this edge in the neighboring sector's edge array.

Racing Lines

"num-vertices" : integer
The number of elements in the vertices array.
"vertices" : array of 2D-vertex
These are the vertices used in the racing-line descriptions. They are referenced by index (starting at zero).
"num-lines" : integer
The number of elements in the lines array.
"lines" : array of line
The array of racing lines in left-to-right order.

2D-Vertex

A 2D vertex is a location on the XZ plane (recall that the Y-axis is elevation). Each racing line description has an array of vertices, which are then referenced by index (zero-based). The representation of a 2D vertex is an array of three numbers representing the X and Z coordinates of the vertex.

Line

A racing line specifies a path around the track that the AI can follow. Currently lines are expected to define a loop. It has the following fields:

"num-segments" : integer
The number of elements in the segments array.
"segments" : array of segment
The array of segments that define the racing line; these will be in path order

Segment

A segment is a piece of a line. There are two kinds of segments: lines and arcs. They share the following common fields:

"kind" : string
The kind of segment. This field will be either the string "line" or the string "arc".
"start" : integer
The vertex index of the start of the segment. This will be the same vertex as the end of the previous segment.
"end" : integer
The vertex index of the end of the segment. This will be the same vertex as the start of the next segment.
"length" : number
The length of the segment.
Line segments

Line segments do not have any additional fields.

Arc segments

Arc segments have the following additional fields:

"center" : int
The vertex index of the center of the arc. The radius of the arc is the distance from the center to the start vertex, which should be equal to the distance from the center to the end vertex.
"angle" : number
The angle of the arc from start to end in degrees. This number will be negative for CCW arcs (left turns) and positive for CW arcs (right turns).

An example

Here is an example of a minimal track with a single racing line. The track geometry is in blue and the racing lines are in caynne.

simple track
The source for this file can be found
HERE.

Extending the file format

This file format can be extended by adding additional fields to the various objects. To improve interoperability between groups, we adopt the following convention for extensions. Suppose that group gpr-123 wants to add two fields (bar and baz) to an object. It does so by adding a object-valued field "gpr-123" to the object; this object contains the bar and baz fields.

Possible enhancements

We could extend the racing line specifications to use Catmull-Rom splines.

Currently racing lines form closed loops; we could introduce split and join points to generalize lines to multiple circular paths.


Last revised: April 5, 2017.