RE-VOLT FILES STRUCTURE

Questo Tutorial descrive i contenuti di qualche file di dati che Re-Volt usa. E' destinato quindi solo a chi ha intenzione di creare i propri livelli e soprattutto a chi ha già sufficienti esperienze di programmazione (in C++).
La Acclaim non ha pubblicato nulla riguardo a queste strutture, quindi non aspettatevi risposte da loro per eventuali domande. E' comunque consentito modificare questi file a patto che non vengano distribuiti a scopo di lucro e che rimanga una nota di copyright per la Acclaim nel readme di quello che modificate.
Le strutture dei dati vengono date in uno stile pseudo-C++, e qualche spiegazione viene data in linguaggio sorgente Pov-Ray.

Informazioni di Base

Files:
    I Levels sono simili alle Instances, e consistono in due files:
    level.w, che è simile a instance.prm, contiene la vista generale del livello.
    level.ncp, che è simile a instance.ncp (ma non uguale), contiene l'essenza del livello, quello che non puoi
    vedere ma dentro il quale puoi guidare.
Sistema delle coordinate:
    Le coordinate che verranno successivamente usate seguono la regola della mano destra (in fisica si dice così):
    L'asse X va verso destra
    L'asse Y va verso il basso
    L'asse Z va in avanti.
Tipi base di dati:
    rvfloat è un numero in floating point a 32 bit
    rvshort è un numero intero a 16 bit
    rvlong è un numero intero a 32 bit (sia rvshort che rvlong hanno il segno + o - a meno che non siano
    esplicitamente indicati come unsigned, cioè senza segno).

Level.w file

I file.w contengono la vista generale del livello. E' principalmente una sequenza di:
    Poligoni in stile .prm con struttura Mesh
    una sequenza di FunnyBalls, il cui scopo ci è ancora sconosciuto
    alcune liste completamente sconosciute
    una env mapping list.

Instance.prm file

Un file.prm consiste in una struttura Mesh e nient'altro. Questo potrebbe essere un esempio:

 struct PRM_Mesh
 {
    /*
     * le istruzioni seguenti sono presenti solo nel file.w:
     * 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];
 }

.ncp file

I files.ncp contengono l'atmosfera del livello o delle Instances. Iniziano con una sequenza di Poliedri, che descrivono i poligoni senza spessore. Questi file contengono anche una LookupTable, nella quale il gioco va a cercare i dati per sapere quali Poliedri testare per ottenere la posizione dell'auto.

Strutture dei dati

World (.w)

 struct World
 {
    rvlong mesh_count;
    Mesh mesh[mesh_count];

    rvlong funnyball_count;
    FunnyBall fball[funnyball_count];

    Unknownlost unkn_list;

    EnvList env_list;
 }

Mesh (.w)

 struct Mesh
 {
    Vector bound_ball_center;
    rvfloat bound_baòò_radius;

    BoundingBox bbox;

    rvshort polygon_count;
    rvshort vertex_count;

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

Un Mesh è una sequenza di poligoni (triangoli o quadrati) che sono sistemati uno vicino all'altro.

"bound_ball_center" e "bound_ball_radius" definiscono una sfera che circonda l'intero Mesh, e "bbox" è un parallelepipedo parallelo agli assi che circonda lo stesso Mesh. Funzionano così: "Se non puoi vedere la sfera (o il parallelepipedo), allora non puoi vedere il Mesh".

I poligoni contengono solo gli indici dei vertici, ma non le coordinate. Questi indici sono utilizzati nell'array (matrice) vertices[] (con indici da 0 a (vertex_count - 1)).

Polygon (.w / .prm)

 struct Polygon
 {
    rvshort type;

    rvshort texture;

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

    UV texcoord[4];
 }

"Type" è una mappa di bit. Il Bit 0 è il più importante, perchè determina la forma del poligono: 0 è un triangolo, 1 un quadrato. Altri casi conosciuti sono:

Bit-# Valore Effetto nei .w Effetto nei .prm
bit 0 0x001 Il poligono è quadrato Il poligono è quadrato
bit 1 0x002 Il poligono è grande il doppio Il poligono è grande il doppio
bit 2 0x004 Il poligono è traslucido o a specchio Il poligono è traslucido o a specchio
bit 8 0x100 Tipo di effetto traslucido (*) Tipo di effetto traslucido (*)
bit 10 0x400 Non usato Disabilita l'EnvMapping
bit 11 0x800 Abilita l'EnvMapping Non usato

(*): Impostalo a 0 per una trasparenza Alpha (usando il canale alpha in "colors[]"). Impostalo a 1 per sfumature aggiuntive.

"texture" imposta l'immagine grafica da applicare (0 = levela.bmp, 1 = levelb.bmp, ...). Se impostato a -1, il poligono non è texturato ma semplicemente colorato.

"vertex_indices" è una lista di 3 o 4 indici per la lista nella struttura Mesh. Se il poligono non è in dimensione doppia, i vertici vanno dati in ordine orario (se lo guardi "dal suo retro", i punti vengono ordinati in senso antiorario e il poligono diventa invisibile).

Non abbiamo nessuna idea su come funzionino le superfici a specchio. Tutti gli specchi che sono stati usati in realtà sono trasparenti (ad esempio in Museum 2, alla partenza: dovrebbe essere su marmo a specchio, ma in realtà quel pezzo è trasparente). Deve avere a che fare con le FunnyBalls (del tipo "Ogni texture trasparente tra una FunnyBall è a specchio e riflette tutto ciò che sta all'interno della palla").

Vertex (.w / .prm)

 struct Vertex
 {
    Vector position;
    Vector normal;
 }

Il "vector normal" deve avere lunghezza normalizzata (1.0).

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

 struct Vector
 {
    rvfloat x;
    rvfloat y;
    rvfloat z;
 }

UV (.w / .prm)

 struct UV
 {
    rvfloat u;
    rvfloat v;
 }

FunnyBall (.w)

 struct FunnyBall
 {
    Vector center;
    rvfloat radius;

    rvlong mesh_count;
    rvlong mesh_indices[mesh_count];
 }

Le FunnyBalls sono sfere che circondano qualche (o tutti) i Meshes del livello. Il loro scopo è sconosciuto. Se non si mette nulla nel file.w (e il parametro  fball_count è a 0) il gioco si blocca, ma averne una sola che circonda l'intero livello lo fa funzionare.
Possono essere usate per creare superfici a specchio (visto che gli specchi semplici sono poligoni trasparenti). Oppure per creare parti nascoste di un livello.

WorldNCP (.ncp / .w)

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

    LookupGrid lookup;
 }

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

 struct Polyhedron
 {
    rvlong type;
    rvlong surface;

    Plane plane[5];

    BoundingBox bbox;
 }

Un Polyhedron è una struttura infinita di spazi tridimensionali delimitati da 4 o 5 piani. Plane #0 definisce il pavimento, gli altri lo delimitano agli angoli. In linguaggio Pov-Ray:

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

Type è un campo di Bit. Bit 0 definisce se ha 4 o 5 piani (definisce anche se è triangolare o quadrato).
Bbox è una "scatola" che circonda il plane[0].
Surface definisce il tipo di pavimento. Può variare da 0 a 25, dando risultati diversi (terreno liscio, erba, terra...)

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

 struct Plane
 {
    Vector normal;
    rvfloat distance;
 }

In linguaggio Pov-Ray:

   plane { normal, distance }

Normal ha come lunghezza 1.0.

LookupGrid (.ncp-w)

 struct LookupGrid
 {
    rvfloat x0;
    rvfloat z0;

    rvfloat x_size;
    rvfloat z_size;

    rvfloat raster_size;

    LookupList lists[z_size] [x_size];
 }

Questa è una griglia che divide i piani X-Z (con origini in (x0, z0)) in aree di dimensione raster_size*raster_size, con area x_size in direzione +x e area z_size in direzione +z. x_size e z_size sono numeri interi salvati come float.

La griglia definisce una lista di Polyhedra che si trovano sopra o sotto la grigla stessa. La lista è data agli indici WorldNCP.polyhedra[WorldNCP.polyhedron_count].

LookupList (.ncp-w)

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

UnknownList (.w)

Questa parte del file.w è completamente sconosciuta. Anche la sua lunghezza non è certa. Per fortuna molti dei file.w non contengono nessun oggetto qui, per cui si può saltare senza problemi.

 struct UnknownList
 {
    rvlong item_count;

    rvlong something[];
 }

EnvList (.w)

Contiene una definizione di colori per tutti i poligoni con riflessi (bit #11 set). Definisce il colore riflesso.

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

Bounding Box

Un Bounding Box sono solo alcuni valori che descrivono le variabili delle coordinate più alte o più basse contenute in esso.

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

.por file (Portals)

I files Portal (in modalità edit "Erm - nothing to see here") non hanno effetto in Re-Volt (o meglio, non quello che dovrebbero avere). La struttura è la seguente:

 struct_POR_File
 {
    rvlong entry_count;

    POR_Entry entries[entry_count];
 }

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 ha valore 0 se la struttura descrive un portale, 1 se descrive una regione
zeroes sembra avere sempre valore 0.

.rim file (Mirrors)

 struct RIM_File
 {
    rvshort entry_count;

    RIM_Entry entries[entry_count];
 }

Mirrors entry_structure (.rim)

 struct RIM_Entry
 {
    rvulong flags;

    Vector plane_normal;
    rvfloat plane_distance;

    BoundingBox bbox;

    Vector vertices[4];
 }

flags sembra essere sempre 0 o 1, e sta a significare "3 vertici" o "4 vertici". I vertici devono essere su piano a specchio.

Hull.hul file

 struct HullFile
 {
    rvshort chull_count;
    ConvexHull chulls[chull_count];

    Interior interior;
 }

Una cosa strana è che il file Hull.hul di Candy Pebbles è vuoto, cioè occupa 0 bytes. O i programmatori si sono dimenticati qualcosa, oppure l'auto è strana.
Forse c'è più di una parte Interior. Tutte le auto eccetto Mouse ce l'hanno. Mouse invece ne ha tre. Anche questa stranezza non è ancora stata risolta.

Questo è quello che dovrebbe essere un file Hull:

Convex Hull

 struct ConvexHull
 {
    rvshort Vertex_count;
    rvshort edge_count;
    rvshort face_count;

    rvfloat bbox_xlo, bbox_xhi;
    rvfloat bbox_ylo, bbox_yhi;
    rvfloat bbox_zlo, bboz_zhi;

    Vector unknown_vector;

    Vector vertices[vertex_count];
    Edge edges[edge_count];
    Face faces[face_count];
 }

Non si capisce bene perchè le facce debbano essere di tre vertici, visto che altre forme sono possibili. Inoltre, il significato di unknown_vector è appunto sconosciuto.

Edge

 struct Edge
 {
    rvshort verts[2];
 }

Face

 struct Face
 {
    Vector normal;
    rvfloat distance;
 }

Questo rappresenta unicamente un piano (le parti principali di un file Hull sono convesse).

Interior

 struct Interior
 {
    rvshort sphere_count;

    Sphere spheres[sphere_count];
 }

Queste parti sembrano essere usate per determinare i punti di collisione della vettura. Imposta una serie di sfere che riempiono l'interno della vettura (lo sapevi di guidare un'auto piena di palloncini??? :) ).

Sphere

 struct Sphere
 {
    Vector center;
    rvfloat radius;
 }

L'ultimo aggiornamento di queste strutture da parte degli autori è stato effettuato agli inizi del 2000. Purtroppo non siamo autorizzati a darvi i contatti di queste persone. Inoltre noi non siamo a conoscenza dell'effettivo significato di quanto scritto sopra, ci siamo limitati a tradurne i contenuti dall'inglese, per coloro che hanno una notevole conoscenza di queste cose. Siete quindi pregati di non contattarci per eventuali domande.