Levels are similar to “Instances”. They consist of two files:
level.w
, which is similar to instance.prm
. It contains the “look” of the level.
level.ncp
, which is similar to instance.ncp
(but not equal). Contains the “feel” (What you cannot see but drive on).
The underlying coordinate system is right-handed: The positive X-Axis goes to the right, Y downwards and Z forwards.
rvfloat
is a 32-bit floating point number,
rvshort
a 16-bit integer and goes from -32768 to 32767, and
rvlong
a 32-bit floating point number. (Both rvshort
and rvlong
are signed unless explicit marked as unsigned)
struct PRM_Mesh {
test polygon_count;
rvshort vertex_count;
Polygon polygons[polygon_count];
Vertex vertices[vertex_count];
};
struct World {
rvlong mesh_count;
Mesh meshes[mesh_count];
rvlong bigcube_count;
BigCube bcube[bigcube_count];
rvlong animation_count;
TexAnimation anim[animation_count]
EnvList env_list;
};
struct Mesh {
Vector bound_ball_center;
rvfloat bound_ball_radius;
BoundingBox bbox;
rvshort polygon_count;
rvshort vertex_count;
Polygon polygons[polygon_count];
Vertex vertices[vertex_count];
};
struct TexAnimation {
rvlong frame_count; // the number of frames per animation
Frame frames[animation_count]
};
struct Frame {
rvlong texture;
rvfloat delay; // in microseconds
UV uv[4];
};
struct Polygon {
rvshort type;
rvshort texture;
rvshort vertex_indices[4];
unsigned rvlong colors[4];
UV texcoord[4];
};
type is a bit field with the following values:
Bit-# | Value | Purpose in .w | Purpose in .prm |
---|---|---|---|
bit 0 | 0x001 | Polygon is quadratic | Polygon is quadratic |
bit 1 | 0x002 | Polygon is double-sided | Polygon is double-sided |
bit 2 | 0x004 | is translucent | is translucent |
bit 8 | 0x100 | 0: Alpha, 1: Additive transmarency | 0: Alpha, 1: Additive transmarency |
bit 10 | 0x400 | unused | Disable EnvMapping |
bit 11 | 0x800 | Enable EnvMapping | unused |
texture is the number of the texture page (0=levela.bmp, 1=levelb.bmp, …). If set to -1, the object won't have any texture.
vertex_indices is a list of three or four indices for the list in the mesh structure. If the polygon is not double-sided, the vertices have to be given in clockwise order. (if you look at it from its “behind”, the points will be ordered ccw, and the poly is invisible)
struct Vertex {
Vector position;
Vector normal;
};
struct Vector {
rvfloat x;
rvfloat y;
rvfloat z;
};
struct UV {
rvfloat u;
rvfloat v;
};
struct BigCube {
Vector center;
rvfloat size;
rvlong mesh_count;
rvlong mesh_indices[mesh_count];
};
struct WorldNCP {
rvshort polyhedron_count;
Polyhedron polyhedra[polyhedron_count];
LookupGrid lookup;
};
struct Polyhedron {
rvlong type;
rvlong surface;
Plane plane[5];
BoundingBox bbox;
};
struct Plane {
Vector normal;
rvfloat distance;
};
struct LookupGrid {
rvfloat x0;
rvfloat z0;
rvfloat x_size;
rvfloat z_size;
rvfloat raster_size;
LookupList lists[z_size][x_size];
};
struct EnvList {
unsigned rvlong env_color[number of bit-11-polys in file];
};
struct BoundingBox {
rvfloat xlo, xhi;
rvfloat ylo, yhi;
rvfloat zlo, zhi;
};
struct RIM_File {
rvshort entry_count;
RIM_Entry entries[entry_count];
};
struct RIM_Entry {
rvulong flags;
Vector plane_normal;
rvfloat plane_distance;
BoundingBox bbox;
Vector vertices[4];
};
struct PAN {
rvlong number_nodes;
rvlong start_node;
float total_distance;
Node pos_nodes[number_nodes];
}
Position nodes don't consist of much. There is the number of nodes, the ID of the node the track starts with, the total length of the track and a list of Nodes. There is a maximum number of 1024 nodes (limit is hardcoded).
struct Node {
Vector position;
float distance;
long prev_node_ids[4];
long next_node_ids[4];
}
The nodes from the Pos. node file are very straightforward. There is a regular vector for its position, a float for the distance to the finish line and two lists of 4 longs that give you the IDs of the previous and next IDs of the nodes the current node is connected to. There is a maximum of 4 links (limit due to file definition). If there is no link, the value(s) are -1
.
struct Fin {
long instance_count;
Instance instaces[instance_count];
}
struct Instance {
char[9] name;
unsigned rvlong color[3];
unsigned rvlong env_rgb[4];
Byte priority;
Byte flag;
Vector position;
Matrix[3f][3f] transformation;
}