Autore originale: N/A
Link originale: N/A
Tradotto da: TheFactor82
Questo Manuale descrive i contenuti di alcuni file di dati che Re-Volt utilizza. 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++).
Le informazioni contenute in questo manuale sono state tradotte dall'inglese e non sono state testate. Risalgono inoltre al 1999-2000, quindi particolarmente vecchie. Le informazioni sulla struttura dei file PRM sono state estrapolate dall'utente Maximvs e sono più recenti.
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:
Codice: Seleziona tutto
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];
}
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)
Codice: Seleziona tutto
struct World
{
rvlong mesh_count;
Mesh mesh[mesh_count];
rvlong funnyball_count;
FunnyBall fball[funnyball_count];
Unknownlost unkn_list;
EnvList env_list;
}
Codice: Seleziona tutto
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)
Codice: Seleziona tutto
struct Polygon
{
rvshort type;
rvshort texture;
rvshort vertex_indices[4];
unsigned rvlong colors[4];
UV texcoord[4];
}
MAPPA BIT
Bit-# | Valore | Effetto in .w | Effetto in .prm |
---|---|---|---|
bit 0 | 0x001 | Il poligono è quadrato | Il poligono è quadrato |
bit 1 | 0x002 | Il poligono è a doppia faccia | Il poligono è a doppia faccia |
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 |
"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)
Codice: Seleziona tutto
struct Vertex
{
Vector position;
Vector normal;
}
Vector (.w / .prm / .ncp-w / .ncp-i)
Codice: Seleziona tutto
struct Vector
{
rvfloat x;
rvfloat y;
rvfloat z;
}
Codice: Seleziona tutto
struct UV
{
rvfloat u;
rvfloat v;
}
Codice: Seleziona tutto
struct FunnyBall
{
Vector center;
rvfloat radius;
rvlong mesh_count;
rvlong mesh_indices[mesh_count];
}
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)
Codice: Seleziona tutto
struct WorldNCP
{
rvshort polyhedron_count;
Polyhedron polyhedra[polyhedron_count];
LookupGrid lookup;
}
Polyhedron (.ncp-w / .ncp-i)
Codice: Seleziona tutto
struct Polyhedron
{
rvlong type;
rvlong surface;
Plane plane[5];
BoundingBox bbox;
}
Codice: Seleziona tutto
object {
intersection {
plane { plane[0] }
plane { plane[1] }
plane { plane[2] }
...
}
}
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)
Codice: Seleziona tutto
struct Plane
{
Vector normal;
rvfloat distance;
}
Normal ha come lunghezza 1.0.
LookupGrid (.ncp-w)
Codice: Seleziona tutto
struct LookupGrid
{
rvfloat x0;
rvfloat z0;
rvfloat x_size;
rvfloat z_size;
rvfloat raster_size;
LookupList lists[z_size] [x_size];
}
La griglia definisce una lista di Polyhedra che si trovano sopra o sotto la griglia stessa. La lista è data agli indici WorldNCP.polyhedra[WorldNCP.polyhedron_count].
LookupList (.ncp-w)
Codice: Seleziona tutto
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.
Codice: Seleziona tutto
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.
Codice: Seleziona tutto
struct EnvList
{
unsigned rvlong env_color[number of bit-11-polys in file];
}
Bounding Box
I Bounding Box sono solo alcuni valori che descrivono le variabili delle coordinate più alte o più basse contenute in esso.
Codice: Seleziona tutto
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:
Codice: Seleziona tutto
struct_POR_File
{
rvlong entry_count;
POR_Entry entries[entry_count];
}
Portals entry_structure (.por)
Codice: Seleziona tutto
struct POR_Entry
{
rvulong type;
rvulong id[2];
Vector center;
rvfloat rotation_matrix[3] [3];
Vector size;
rvfloat zeroes[4];
}
zeroes sembra avere sempre valore 0.
.rim file (Mirrors)
Codice: Seleziona tutto
struct RIM_File
{
rvshort entry_count;
RIM_Entry entries[entry_count];
}
Codice: Seleziona tutto
struct RIM_Entry
{
rvulong flags;
Vector plane_normal;
rvfloat plane_distance;
BoundingBox bbox;
Vector vertices[4];
}
Hull.hul file
Codice: Seleziona tutto
struct HullFile
{
rvshort chull_count;
ConvexHull chulls[chull_count];
Interior interior;
}
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 è il file Hull di Mouse:
Convex Hull
Codice: Seleziona tutto
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];
}
Edge & Face
Codice: Seleziona tutto
struct Edge
{
rvshort verts[2];
}
struct Face
{
Vector normal;
rvfloat distance;
}
Interior
Codice: Seleziona tutto
struct Interior
{
rvshort sphere_count;
Sphere spheres[sphere_count];
}
Codice: Seleziona tutto
struct Sphere
{
Vector center;
rvfloat radius;
}
.prm file
Maximvs ha analizzato e scoperto come viene strutturato il file Body.prm delle auto di Re-Volt. Il file è codificato in esadecimale, quindi si mostrerà come un elenco di byte. Ogni byte è formato da due caratteri (cifre o numeri). La prima parte del file si presenta così:
Codice: Seleziona tutto
08000F00000000000200000001000000
FFFFFF00FFFFFF00FFFFFF00FFFFFF00
E5A6DF3E940EBFBF000EE0B8940EBFBF
001AE0B8582187BF0000000000000000
000000000500030004000000FFFFFF00
FFFFFF00FFFFFF00FFFFFF005F7EF6BF
D253603F5F7EF6BF00E91E3B2691BEBF
D253603F000000000000000000000000
0100000006000000FFFFFF00FFFFFF00
FFFFFF00FFFFFF00001AE0B8582187BF
000EE0B8940EBFBFEEC2DFBE940EBFBF
00000000000000000000000007000300
05000000FFFFFF00FFFFFF00FFFFFF00
FFFFFF00CE3517C0D253603F5F7EF6BF
00E91E3B5F7EF6BFD253603F00000000
00000000000000000600000008000000
FFFFFF00FFFFFF00FFFFFF00FFFFFF00
EEC2DFBE940EBFBF000EE0B8940EBFBF
000AE0B8CEFBF6BF0000000000000000
000000000B0009000A000000FFFFFF00
FFFFFF00FFFFFF00FFFFFF00E07B863E
C586033FE07B863E2871753F3086203D
2871753F000000000000000000000000
0800000002000000FFFFFF00FFFFFF00
FFFFFF00FFFFFF00000AE0B8CEFBF6BF
000EE0B8940EBFBFE5A6DF3E940EBFBF
0000000000000000000000000E000C00
0D000000FFFFFF00FFFFFF00FFFFFF00
FFFFFF00F4E6F83EC5B7753FE07B863E
AE4C033FE07B863EC5B7753F00000000
00000000
I successivi 4 byte sono e dovrebbero essere sempre lasciati a 0.
Il gruppetto composto da 0200;0000;0100 indica il numero di vertici che compongono il poligono 0 (V2,V0,V1), mentre il gruppo di 12 byte (FF;FF;FF;00 ripetuto 3 volte) indica il colore dei vertici (V2,V0 e V1) informato RGB più il canale alfa (B=FF=255:G=FF=255:R=FF=255 Alfa=0).
I 4 byte identici ai precedenti (FF;FF;FF;00) indicano il colore del poligono ma non vengono utilizzati da Revolt).
Il successivo gruppo di 24 byte indicano invece le coordinate UV della mappatura del poligono 0, composto dai 3 vertici V2,V0,V1. Quindi nel caso dell'esempio troviamo V2 coordinata U=E5A6DF3E=0.43682018 (essendo un valore di tipo float con virgola), poi troviamo V2 V=940EBFBF=-1.4926324 e così via sia per V0.U,V0.V,V1.U,V1.V. In coda a questi ci sono 8 byte a zero e poi si ricomincia per per i rimanenti 7 poligoni.
Codice: Seleziona tutto
F00A2F3B68F94FBB00B664BD
0FF5D0C49706B044FF499B4250142F3B
68F94FBBA1E02D41AFEBD0C49706B044
5E1FD2BE63BA2EC168F94FBB00B664BD
9C45D13E9706B044FF499B42F00A2F3B
D6CBAEC100B664BD0FF5D0C42934513E
FF499B4263BA2EC168F94FBB00B664BD
9C45D13E9706B044FF499B4250142F3B
68F94FBBA1E02D41AFEBD0C49706B044
5E1FD2BE4AD02E4168F94FBBC8B664BD
B52FD1BE9706B04437499B424AD02E41
68F94FBBC8B664BDB52FD1BE9706B044
37499B42D0072F3B68F94FBB0CAA2FC1
2FF8D0C49706B044F355D03EF00A2F3B
D6CBAEC100B664BD0FF5D0C42934513E
FF499B424AD02E4168F94FBBC8B664BD
B52FD1BE9706B04437499B42D0072F3B
68F94FBB0CAA2FC12FF8D0C49706B044
F355D03EF00A2F3BD6CBAEC100B664BD
0FF5D0C42934513EFF499B42D0072F3B
68F94FBB0CAA2FC12FF8D0C49706B044
F355D03E63BA2EC168F94FBB00B664BD
9C45D13E9706B044FF499B4263