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.