Quale struttura di dati dovrebbe essere utilizzata per rappresentare il terreno voxel?


18

Secondo la pagina Wikipedia sui voxel, "[...] la posizione di un voxel viene dedotta in base alla sua posizione rispetto ad altri voxel (cioè, la sua posizione nella struttura dei dati che costituisce una singola immagine volumetrica)."

Come si dovrebbe implementare una tale struttura di dati? Stavo pensando a un ottetto ma mi chiedo se c'è qualcos'altro di cui non ho mai sentito parlare.


1
Questa è una domanda un po 'difficile da porre perché dipende molto da quali dati saranno necessari i tuoi dati voxel. Cose come quanto è pieno il voxel, che aspetto ha, ecc. Dipenderanno abbastanza da quello che stai facendo. In secondo luogo, la struttura dei dati deve prestarsi all'accesso ad alta velocità per la manipolazione in tempo reale dei dati e il successivo aggiornamento di essi. Come mantenere bassa la struttura della memoria per voxel e un accesso / manipolazione rapidi dei dati sono praticamente le principali sfide tecniche che sono abbastanza intento specifico quando si lavora con i motori voxel. Non una risposta, quindi un commento.
James,

Risposte:


14

Primo. Scriviamo cosa sappiamo di ogni voxel:

voxel = (x, y, z, color) // or some other information

Archiviazione generale

Il modo generale è semplicemente questo:

set of voxels = set of (x,y,z, color)

Nota che quella tripletta (x, y, z) identifica ogni voxel in modo univoco, poiché voxel è punto nello spazio e non c'è modo che due punti occupino un posto (credo che stiamo parlando di dati voxel statici).

Dovrebbe andare bene per dati semplici. Ma non è affatto una struttura di dati veloce.

Il rendering è AFAIK fatto dall'algoritmo scanline. L'articolo di Tom sull'hardware su voxels ha un'immagine dell'algoritmo scanline .

Ricerca veloce

Se è necessaria una ricerca rapida, la struttura dati più veloce per la ricerca è l'hash (aka array, map ...). Quindi devi fare hash da esso. Quindi, ingenuamente vogliamo il modo più veloce per ottenere elementi arbitrari:

array [x][y][z] of (color)
  • Questo ha O (1) per cercare voxel con le coordinate x, y, z.

  • Il problema è che i suoi requisiti di spazio sono O (D ^ 3), dove D è un intervallo di ogni numero x, y e z (dimentica il numero reale, poiché se fossero Char, che hanno un intervallo di 256 valori, ci sarebbero 256 ^ 3 = 2 ^ 24 == 16 777 216 elementi nella matrice).

Ma dipende da cosa vuoi fare con i voxel. Se il rendering è quello che vuoi, allora è probabilmente questo array quello che vuoi. Ma il problema di archiviazione rimane ancora ...

Se l'archiviazione è il problema

Un metodo consiste nell'utilizzare la compressione RLE nell'array. Immagina una fetta di voxel (insieme di voxel, in cui i voxel hanno un valore costante di coordinate .... come il piano dove z = 13 per esempio). Una tale fetta di voxel sembrerebbe un semplice disegno in MSPaint . Il modello di Voxel, direi, di solito occupa una frazione di tutti i posti possibili (D ^ 3 spazio di tutti i possibili voxel). Credo che "prendere una coppia da una tripletta di coordinate e comprimere l'asse rimanente" farebbe il trucco (ad esempio prendere [x] [y] e per ogni elemento comprimere tutti i voxel sull'asse z in corrispondenza di x, y .. ci dovrebbero essere da 0 a pochi elementi, RLE farebbe bene qui):

array [x][y] of RLE compressed z "lines" of voxel; each uncompressed voxel has color 

Un altro metodo per risolvere il problema di archiviazione sarebbe invece dell'array usando la struttura dei dati dell'albero:

tree data structure  = recursively classified voxels
for octrees: recursively classified by which octant does voxel at (x,y,z) belong to
  • Octree, come menzionato da Nick. Dovrebbe comprimere i voxel. Octree ha anche una velocità decente per la ricerca, immagino che sia un po '(log N), dove N è il numero di voxel.
  • Octree dovrebbe essere in grado di memorizzare dati voxel decentemente arbitrari.

Se i voxel sono un'altezza semplicistica, potresti archiviare proprio quello. Oppure è possibile memorizzare parametri per la funzione che genera la heightmap, ovvero generarla proceduralmente ...

E ovviamente puoi combinare tutti i possibili approcci. Ma non esagerare, a meno che tu non provi che il tuo codice funziona e misuri che è DAVVERO più veloce (quindi vale l'ottimizzazione).

TL; DR

Altro che Octrees è la compressione RLE con voxels, google "voxlap", "ken silverman" ...

risorse

C'è un elenco di risorse e discussioni su come rendere veloce il renderer voxel, include documenti e codice sorgente .


1
"Se l'archiviazione è il problema": è anche possibile utilizzare VTC ( oss.sgi.com/projects/ogl-sample/registry/NV/… ) o compressione
DXT

@KindDragon Grazie per queste informazioni. :) Questa è un'ottima idea.
user712092,

Il collegamento alla risorsa non è attivo.
Ezequiel,

4

Esistono due diversi aspetti della struttura dei dati di cui potrebbero parlare.

Strutture di array

Quando fai riferimento a un elemento di un array di qualsiasi numero di dimensioni, considera che l'array stesso, una volta passati gli indici (ad es. myArray[4][6][15]), Sa cosa c'è in quella posizione. Se ciò che si trova in quella posizione è un voxel, quel voxel non ha bisogno di registrare ulteriormente le proprie coordinate x, ye z - l'array che contiene il voxel specifica implicitamente la sua posizione mondiale in base alla sua posizione indicizzata da array.

Il motivo è che l'aritmetica del puntatore utilizzata per questo tipo di accesso all'array è intrinsecamente veloce e in generale fornisce le basi per la maggior parte degli array rapidi (spesso chiamati "nativi") presenti in tutte le lingue. Il rovescio della medaglia di questi array è che devono avere elementi della stessa dimensione in byte, affinché sia ​​applicabile detta aritmetica del puntatore.

octrees

(Noto questo secondo, perché è meno probabile che sia ciò a cui si riferisce Wikipedia, e le implementazioni di voxel non richiedono l'uso di ocre anche se quasi tutti quelli moderni usano ocre.)

Il nodo radice di un octree è un singolo cubo indiviso. Facciamo un esempio. Di 'che la radice del tuo octree, il centro del cubo, si trova {0, 0, 0}nello spazio 3D. Una volta che inizi a posizionare gli oggetti all'interno di quello spazio (leggi: più di un oggetto), è tempo di suddividere ulteriormente l'ottetto. Questo è dove dividi in 8 ( ott- ), tagliandolo usando 3 piani, questi piani sono i piani xy, xz e yz. Il cubo originale ora contiene esattamente 8 cubetti più piccoli. Ognuno di questi sottonodi è posizionato come offset dal cubo principale centrale . Cioè, ad esempio, il cubo che giace nell'ottante xyz positivo avrebbe un offset dal centro del cubo genitore / contenente esattamente{root.width / 4, root.height / 4, root.depth / 4}. Anziché specificare una posizione assoluta per ciascun nodo secondario, è più logico considerare il nodo padre come l'origine del suo spazio per bambini. Questo è lo stesso modo in cui funzionano i grafici delle scene.

È abbastanza semplice vederlo in un disegno 2D, dove si disegna un quadrato e lo si suddivide in 4 regioni uguali. Se, come il nostro nodo radice octree, il centro del quadrato principale fosse considerato {0, 0}, allora i 4 centri dei quadrati figli sarebbero

{root.width / 4, root.height / 4}, {-root.width / 4, root.height / 4}, {root.width / 4, -root.height / 4}, {-root.width / 4, -root.height / 4}

... Rispetto al genitore - lo stesso principio del 3D.


La ringrazio per la risposta. Nel mio caso, alcune grandi parti del terreno sarebbero state realizzate con lo stesso tipo di voxel ed è per questo che stavo pensando agli ocre (non sarebbe necessario suddividere un grosso pezzo). Tuttavia, darò una possibilità all'array 3D poiché sembra più semplice da implementare. Sono sicuro di riuscire a sottrarre abbastanza i dettagli dell'implementazione della mia classe di terreno in modo che non sia così difficile cambiare implementazione se fosse necessario.
pwny

Prego. Consiglio vivamente di guardare in ocre, in realtà non sono difficili da capire. Ma sì, il tuo approccio ha senso per ora, sicuramente vale la pena fare la prototipazione iniziale usando un array 3D.
Ingegnere

Come ulteriore lettura, una buona discussione sull'implementazione di octrees, inclusi numerosi riferimenti utili, è disponibile nell'articolo di Intel Extending the STL for Games .
Martin Foot,

1

Puoi usare RLE. Ma puoi usare SVO (Sparse Voxel Octree), id Tech 6 usa SVO. Un SVO è una tecnica di rendering di computer grafica 3D che utilizza un approccio di raycasting o talvolta ray tracing in una rappresentazione di dati a tre.

La tecnica varia leggermente, ma generalmente si basa sulla generazione e l'elaborazione dello scafo di punti (voxel sparsi) che sono visibili o possono essere visibili, data la risoluzione e le dimensioni dello schermo.

Usa il raycasting, perché è più veloce.


0

Generalmente è possibile evitare una struttura di dati 3D per il terreno. Puoi invece usare una heightmap . Questo può essere voxelised molto economico ed efficiente in fase di esecuzione. Di solito paga (secondo la mia esperienza) tenere traccia dell'altezza minima necessaria per il rendering in ogni colonna e talvolta anche degli angoli di inizio-arresto-superiore in modo da poter abbattere anche le colonne del backface.

Eccone uno che ho fatto molto tempo fa: http://sites.google.com/site/williamedwardscoder/spinning-voxels-in-flash

Se il tuo terreno ha un piccolo numero di sporgenze o grotte o altre caratteristiche che non possono essere rappresentate da una mappa di altezza, allora puoi avere buchi nella tua mappa di altezza e avere una rappresentazione alternativa, ad esempio veri oggetti voxel 3D che riempiono solo quei luoghi localizzati in cui le spese di runtime è garantito.

Le rappresentazioni di voxel sparse valgono la pena quando si hanno grandi mondi di voxel reali. John Carmack ne parla da alcuni anni ormai ...


Ho pensato anche alle mappe delle altezze, ma un paio di cose mi hanno allontanato da loro. Il fatto è che nel mio caso, il terreno non è veramente grande in alcun modo o molto complicato (pensa a un terreno di tipo labirinto, molto cartesiano). Vorrei anche che una parte del terreno fosse distruttibile o consentissi all'utente di influenzare il terreno attraverso la costruzione. Ciò può comportare che il giocatore crei "tunnel" nel terreno che sembrano più complicati da rappresentare con una mappa di altezza.
pwny
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.