Contents

Introduction / Disclaimer
Basic informations
Level .w file
Instance .prm file
.ncp file
.por file
.rim file
Data structures
structure World
structure Mesh
structure Polygon
structure Vertex
structure Vector
structure UV
structure FunnyBall
structure WorldNCP
structure Polyhedron
structure Plane
structure LookupGrid
structure LookupList
structure UnknownList
structure EnvList
structure Bounding Box
structure RIM_Entry
structure POR_Entry

Introduction / Disclaimer

This document describes the contents of some data files "Re-Volt" uses. It is intended for those who are interested in creating Re-Volt levels of their own.

Re-Volt is a game by Acclaim (www.acclaim.com). This is no publication from Acclaim, so don't expect them to answer to questions.

If you have questions, corrections or additions, feel free to write an e-mail to ali. Updated versions of this document can be found here. If you are willing to correct my bad english, please do so.

Data structures are given in C++-stylish pseudo-syntax, and some explanations are given as POV-Ray source.

(Back to top)


Basic informations

Files
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).
Coordinate System
The underlying coordinate system is right-handed: The positive X-Axis goes to the right, Y downwards and Z forwards.
Basic data types
rvfloat is a 32-bit floating point number,
rvshort a 16-bit integer, and
rvlong a 32-bit integer. (Both rvshort and rvlong are signed unless explicit marked as unsigned)

(Back to top)


Level .w file

The .w file contains the look of your level. It is basically a sequence of

(Back to top)


Instance .prm file

A .prm consists of one mesh and nothing more. It has a slightly different header:
struct PRM_Mesh
{
  /*
   * These members are only present in .w files:
   *  Vector   bound_ball_center;
   *  rvfloat  bound_ball_radius;
   *  Vector   bound_box[2];
   */

  rvshort  polygon_count;
  rvshort  vertex_count;
   
  Polygon  polygons[polygon_count];
  Vertex   vertices[vertex_count];
};

(Back to top)


.ncp file

.ncp files contain the "feel" of levels or instances. They start with a sequence of Polyhedra, which describe flat polygons. The .ncp of a level also consists of a LookupTable, where the game looks which polyhedra have to be tested for a given car position.

(Back to top)


Data structures

World (.w)

struct World
{
  rvlong      mesh_count;
  Mesh        mesh[mesh_count];
  
  rvlong      funnyball_count;
  FunnyBall   fball[funnyball_count];

  UnknownList unkn_list;

  EnvList     env_list;
};

(Back to top)


Mesh (.w)

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];
};
(Is equivalent, but not equal, to "struct MODEL_HEADER" from Balor Knight's .prm/.m-breakdown)

A mesh is a sequence of polygons (triangles or "quads") which are located close to each other.

bound_ball_center and bound_ball_radius define a sphere that surrounds the entire mesh, and bbox is an axis-parallel surrounding box. Both are likely used for "If you can't see the sphere, then you cannot see the mesh"-optimizations.

Polygons only contain vertex indices, and no coordinates. Those indices are for the vertices[] array (with indices 0 to (vertex_count - 1)).

(Back to top)


Polygon (.w/.prm)

struct Polygon
{
           rvshort  type;

           rvshort  texture;

           rvshort  vertex_indices[4];
  unsigned rvlong   colors[4];

           UV       texcoord[4];
};
(Is equal to "struct MODEL_POLY" from Balor Knight's .prm/.m-breakdown)

type is a bit-field. Bit 0 is the most important: If it is set to 1, then the Polygon is a "quad", otherwise it is a triangle. In the latter case vertex_indices[3], colors[3] and texcoord[3] are unused resp. filled with zeroes. Other known flags include:
bit-#valuepurpose in .wpurpose in .prm
bit 0 0x001 poly is quad poly is quad
bit 1 0x002 poly is double-sided poly is double-sided
bit 2 0x004 is translucent (or mirroring) is translucent (or mirroring)
bit 8 0x100 translucency type* translucency type*
bit 10 0x400 unused Disable EnvMapping
bit 11 0x800 Enable EnvMapping unused

(*) translucency type: Set to 0 for alpha transparency (using the alpha channel in colors[]. Set to 1 for additive blending.

texture gives the texture's graphic image (0=levela.bmp, 1=levelb.bmp, ...). If set to -1, the poly is not textured, but color-filled.

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)

A word about mirroring surfaces: I have no idea how they work. Every mirror I looked at turned out to be transparent. (Look at the second museum level: The starting position is on mirroring marble. If you look at it from above, you can see that it is transparent: You can see through it into another room) It may have something to do with FunnyBalls (Like "Every transparent texture within a FunnyBall is mirroring and mirrors everything else inside the ball").

(Back to top)


Vertex (.w/.prm)

struct Vertex
{
  Vector position;
  Vector normal;
};
(Is equal to "struct MODEL_VERTEX" from Balor Knight's .prm/.m-breakdown) The normal vector (or "UVW") has to be normalized (have length 1.0).

(Back to top)


Vector (.w/.prm/.ncp-w/.ncp-i)

struct Vector
{
  rvfloat x;
  rvfloat y;
  rvfloat z;
};
(Is equal to "struct VEC" from Balor Knight's .prm/.m-breakdown)

(Back to top)


UV (.w/.prm)

struct UV
{
  rvfloat u;
  rvfloat v;
};
(Is equal to "struct UV" from Balor Knight's .prm/.m-breakdown)

(Back to top)


FunnyBall (.w)

struct FunnyBall
{
  Vector  center;
  rvfloat radius;

  rvlong  mesh_count;
  rvlong  mesh_indices[mesh_count];
};

FunnyBalls are spheres that surround some (or all) meshes in the level. Their purpose is currently unknown. Having none in a .w file (and setting the fball_count to zero) crashes the game, but having one which surrounds the whole level works.

They may be used for mirroring surfaces (because mirrors are simply transparent polygons) and give the clue which meshes have to be mirrored, or they are used to define hidden parts of the level.

(Back to top)


WorldNCP (.ncp-w)

struct WorldNCP
{
  rvshort    polyhedron_count;
  Polyhedron polyhedra[polyhedron_count];

  LookupGrid lookup;
};

(Back to top)


Polyhedron (.ncp-w/.ncp-i)

struct Polyhedron
{
  rvlong      type;
  rvlong      surface;

  Plane       plane[5];

  BoundingBox bbox;
};

A polyhedron is a infinit subset of the three-dimensional space that is bordered by four or five planes. Plane #0 gives the surface itself, and the other ones cut it at its edges. This is equivalent to (POV-Ray):

object {
  intersection {
    plane { plane[0] }
    plane { plane[1] }
    plane { plane[2] }
    ...
  }
}

type is a bitfield. Bit 0 defines whether it has four or five planes (resp. is a triangle or quad). I've also seen bits 2 and 3 set, but haven't tested them yet.

bbox is a bounding box around the present part of plane[0].

surface gives the "feeling" of this surface. It may be a bit-field, but I cannot see regularities, and think that it is only a predefined list. Normal floor is value 0, most values between 1 and 25 lead to something useful. The documentation of rvglue lists their effects.

(Back to top)


Plane (.ncp-w/.ncp-i)

struct Plane
{
  Vector  normal;
  rvfloat distance;
};

Is equal to POV-Ray's

   plane { normal, distance }
object.

normal has a length of 1.0.

(Back to top)


LookupGrid (.ncp-w)

struct LookupGrid
{
  rvfloat    x0;
  rvfloat    z0;

  rvfloat    x_size;
  rvfloat    z_size;

  rvfloat    raster_size;

  LookupList lists[z_size][x_size];
};

This is a grid that spans the X-Z-Plane, with origin at (x0,z0), squares that are raster_size*raster_size sized, x_size squares in +X-direction and z_size squares in +Z-direction. Notice that x_size and z_size are integers saved to floats.

The grid provides a list of polyhedra that are above or below a given grid square. The list is given as indices for WorldNCP.polyhedra[WorldNCP.polyhedron_count].

(Back to top)


LookupList (.ncp-w)

struct LookupList
{
  rvlong length;
  rvlong polyhedron_indices[length];
};

(Back to top)


UnknownList (.w)

This part of .w files is completely unknown. Even it's length isn't know. Fortunately, most .w files contain zero items here, in which case overreading it is easy.

struct UnknownList
{
  rvlong item_count;

  rvlong something[];
};

(Back to top)


EnvList (.w)

Contains a color definition for every shiny polygon (bit #11 set) that defines the reflected color.

struct EnvList
{
  unsigned rvlong env_color[number of bit-11-polys in file];
};

(Back to top)


Bounding Box

A bounding box is just some values to describe the lowest resp. highest values of the coordinates inside it.

struct BoundingBox
{
  rvfloat xlo, xhi;
  rvfloat ylo, yhi;
  rvfloat zlo, zhi;
};

(Back to top)


Portals file (.por)

Portal files (Editing mode "Erm - nothing to see here") have no effect in Re-Volt. They look like follows:

struct POR_File
{
  rvlong    entry_count;

  POR_Entry entries[entry_count];
};

(Back to top)


Portals entry structure (.por)

struct POR_Entry
{
  rvulong  type;
  rvulong  id[2];
  Vector   center;
  rvfloat  rotation_matrix[3][3];
  Vector   size;

  rvfloat  zeroes[4];
};

type is: 0, if the structure describes a portal, and 1 for a region

zeroes seem to be always 0, but that's just a suggestion

(Back to top)


Mirrors file (.rim)

struct RIM_File
{
  rvshort   entry_count;

  RIM_Entry entries[entry_count];
};

(Back to top)


Mirrors entry structure (.rim)

struct RIM_Entry
{
  rvulong     flags;

  Vector      plane_normal;
  rvfloat     plane_distance;

  BoundingBox bbox;

  Vector      vertices[4];
};

flags seem to be 0 or 1, where 0 is "three vertices" and 1 is "four vertices".

The vertices have to be on the mirroring plane


ali, Last modified: Fri Sep 8 16:39:01 CEST 2000