Struttura files

Area riservata alle guide e gli how-to relativi a Re-Volt

Moderatori: Michelangelo, Vas0sky

Rispondi
Avatar utente
AngelS93
Utente
Messaggi: 1951
Iscritto il: lun 5 ott 2015, 20:47
Località: Modugno (BA)

Struttura files

Messaggio da AngelS93 » lun 12 ott 2020, 17:25

STRUTTURA DEI FILES

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];
 }
.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)

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;
 }
Mesh (.w)

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];
 }
"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:


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
(*): 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)

Codice: Seleziona tutto

struct Vertex
 {
    Vector position;
    Vector normal;
 }
Il "vector normal" deve avere lunghezza normalizzata (1.0).

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

Codice: Seleziona tutto

 struct Vector
 {
    rvfloat x;
    rvfloat y;
    rvfloat z;
 }
UV (.w / .prm)

Codice: Seleziona tutto

struct UV
 {
    rvfloat u;
    rvfloat v;
 }
FunnyBall (.w)

Codice: Seleziona tutto

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)

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;
 }
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:

Codice: Seleziona tutto

 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)

Codice: Seleziona tutto

 struct Plane
 {
    Vector normal;
    rvfloat distance;
 }
In linguaggio Pov-Ray è plane { normal, 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];
 }
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 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];
 }
type ha valore 0 se la struttura descrive un portale, 1 se descrive una regione
zeroes sembra avere sempre valore 0.


.rim file (Mirrors)

Codice: Seleziona tutto

struct RIM_File
 {
    rvshort entry_count;

    RIM_Entry entries[entry_count];
 }
Mirrors entry_structure (.rim)

Codice: Seleziona tutto

 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

Codice: Seleziona tutto

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 è il file Hull di Mouse:


967


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];
 }
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 & Face

Codice: Seleziona tutto

 struct Edge
 {
    rvshort verts[2];
 }

 struct Face
 {
    Vector normal;
    rvfloat distance;
 }
Questo rappresenta unicamente un piano (le parti principali di un file Hull sono convesse).

Interior

Codice: Seleziona tutto

 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.

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 primi 2 byte (0800) indica il numero di poligoni o di facce presenti nel file, mentre il terzo e il quarto byte (0F00) indicano il numero di vertici. Con la calcolatrice possiamo quindi ottenere che all'interno di questo file sono presenti 8 poligoni e 15 vertici.
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
Questo ultimo blocco di byte, raccolti 12 per volta in gruppi da 4 (F00A2F3B,68F94FBB,00B664BD) sono le coordinate X,Y,Z dei vertici, elencati in sequenza dal vertice 0 al vertice 15, seguiti da altri 12 byte per le coordinate per i riflessi della macchina.
Classe '93, in cerca di un posto nel mondo vagando con Humma per il Toytanic.


1078 "Spectare o non spectare? Questo è il dilemma"
autore immagine: WheelSmith18

Rispondi

Chi c’è in linea

Visitano il forum: Nessuno e 2 ospiti