Quelle structure de données doit être utilisée pour représenter le terrain des voxels?


18

Selon la page Wikipedia sur les voxels, "[...] la position d'un voxel est déduite en fonction de sa position par rapport aux autres voxels (c'est-à-dire sa position dans la structure de données qui constitue une seule image volumétrique)".

Comment mettre en œuvre une telle structure de données? Je pensais à un octree mais je me demande s'il y a autre chose dont je n'ai jamais entendu parler.


1
C'est une question quelque peu difficile à poser car elle dépend très de quelles données vos données de voxel vont avoir besoin. Des choses comme le niveau de remplissage du voxel, à quoi il ressemble, etc., dépendront assez de ce que vous faites. Deuxièmement, la structure des données doit se prêter à un accès à grande vitesse pour une manipulation en temps réel des données et une mise à jour ultérieure de celles-ci. assez spécifique à l'intention lorsque vous travaillez avec des moteurs voxel. Pas une réponse, donc un commentaire.
James

Réponses:


14

Premier. Permet d'écrire ce que nous savons sur chaque voxel:

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

Stockage général

La manière générale est simplement la suivante:

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

Notez que ce triplet (x, y, z) identifie chaque voxel de manière unique, car le voxel est un point dans l'espace et il n'y a aucun moyen que deux points occupent une place (je pense que nous parlons de données statiques de voxel).

Cela devrait convenir aux données simples. Mais ce n'est en aucun cas une structure de données rapide.

Le rendu est AFAIK effectué par l'algorithme scanline. L'article de Tom's Hardware sur les voxels contient une image de l'algorithme scanline .

Recherche rapide

Si une recherche rapide est nécessaire, la structure de données la plus rapide pour la recherche est le hachage (aka tableau, carte ...). Vous devez donc en faire du hachage. Donc, naïvement, nous voulons juste le moyen le plus rapide d'obtenir un élément arbitraire:

array [x][y][z] of (color)
  • Cela a O (1) pour rechercher le voxel par les coordonnées x, y, z.

  • Le problème est que l'espace requis est O (D ^ 3), où D est la plage de chaque nombre x, y et z (oubliez le nombre réel, car s'il s'agissait de caractères, qui ont une plage de 256 valeurs, il y aurait 256 ^ 3 = 2 ^ 24 == 16 777 216 éléments dans le tableau).

Mais cela dépend de ce que vous voulez faire avec les voxels. Si le rendu est ce que vous voulez, c'est probablement ce tableau que vous voulez. Mais le problème de stockage reste toujours ...

Si le stockage est le problème

Une méthode consiste à utiliser la compression RLE dans le tableau. Imaginez une tranche de voxels (ensemble de voxels, où les voxels ont une valeur constante de coordonnées ... comme un plan où z = 13 par exemple). Une telle tranche de voxels ressemblerait à un simple dessin dans MSPaint . Le modèle de voxel, je dirais, occupe généralement une fraction de tous les endroits possibles (espace D ^ 3 de tous les voxels possibles). Je crois que "prendre une paire dans un triplet de coordonnées et compresser l'axe restant" ferait l'affaire (par exemple prendre [x] [y] et pour chaque élément compresser tous les voxels sur l'axe z à x, y .. . il devrait y avoir 0 à peu d'éléments, RLE ferait bien ici):

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

Une autre méthode pour résoudre le problème de stockage serait au lieu d'un tableau utilisant une structure de données arborescente:

tree data structure  = recursively classified voxels
for octrees: recursively classified by which octant does voxel at (x,y,z) belong to
  • Octree, comme mentionné par Nick. Il devrait comprimer les voxels. Octree a même une vitesse décente pour la recherche, je suppose que c'est un certain O (log N), où N est le nombre de voxels.
  • Octree devrait pouvoir stocker des données de voxels arbitrairement décentes.

Si les voxels sont une carte de hauteur simpliste, vous pouvez stocker exactement cela. Ou vous pouvez stocker les paramètres de la fonction qui génère la carte de hauteur, alias la générer de manière procédurale ...

Et bien sûr, vous pouvez combiner toutes les approches possibles. Mais n'en faites pas trop, sauf si vous testez que votre code fonctionne et mesurez qu'il est VRAIMENT plus rapide (il vaut donc la peine d'être optimisé).

TL; DR

Autre qu'Octrees, la compression RLE avec voxels, google "voxlap", "ken silverman" ...

Ressources

Il y a une liste de ressources et une discussion sur la façon de faire un rendu rapide de voxel, comprend des articles et du code source .


1
"Si le stockage est le problème": vous pouvez également utiliser la compression VTC ( oss.sgi.com/projects/ogl-sample/registry/NV/… ) ou DXT
KindDragon

@KindDragon Merci pour ces informations. :) C'est une très bonne idée.
user712092

Le lien de ressource est en panne.
Ezequiel

4

Il peut y avoir deux aspects différents de la structure des données.

Structures de tableau

Lorsque vous référencez un élément d'un tableau de n'importe quel nombre de dimensions, considérez que le tableau lui-même, une fois que vous avez passé les indices (par exemple. myArray[4][6][15]) Sait ce qui se trouve à cet emplacement. Si ce qui se trouve à cet emplacement est un voxel, ce voxel n'a pas besoin d'enregistrer en plus ses propres coordonnées x, y et z - le tableau contenant le voxel spécifie son emplacement mondial implicitement en fonction de son emplacement indexé sur le tableau.

La raison pour laquelle cela est bon est que l'arithmétique du pointeur utilisée pour ce type d'accès aux tableaux est intrinsèquement rapide et, en règle générale, fournit la base de la plupart des tableaux rapides (souvent appelés "natifs") trouvés dans toutes les langues. L'inconvénient de ces tableaux est qu'ils doivent avoir des éléments de taille égale en octets, pour que ladite arithmétique de pointeur soit applicable.

Octrees

(Je note cette seconde, car c'est probablement ce à quoi Wikipédia fait référence, et les implémentations de voxel ne nécessitent pas l'utilisation d'octrees bien que presque tous les modernes utilisent des octrees.)

Le nœud racine d'un octree est un cube unique et non divisé. Créons un exemple. Supposons que la racine de votre octree, le centre même du cube, se trouve {0, 0, 0}dans l'espace 3D. Une fois que vous commencez à placer des objets dans cet espace (lire: plus d'un objet), il est temps de subdiviser l'octree plus loin. C'est là que vous divisez en 8 ( oct- ), en le découpant en utilisant 3 plans, ces plans étant les plans xy, xz et yz. Votre cube d'origine contient désormais exactement 8 cubes plus petits. Chacun de ces sous-nœuds est positionné comme un décalage par rapport au cube parent central . Autrement dit, par exemple, le cube situé dans l'octant xyz positif aurait un décalage par rapport au centre du cube parent / contenant exactement{root.width / 4, root.height / 4, root.depth / 4}. Plutôt que de spécifier une position absolue pour chaque sous-nœud, il est plus logique de considérer le nœud parent comme l'origine de son espace pour enfants. Il en va de même pour les graphiques de scène.

Il est assez simple de voir cela dans un dessin 2D, où vous dessinez un carré et le subdivisez en 4 régions égales. Si, comme notre nœud racine octree, le centre du carré parent était considéré comme étant {0, 0}, alors les 4 centres des carrés enfants seraient

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

... Par rapport à leur parent - le même principe qu'en 3D.


Merci pour votre réponse. Dans mon cas, certaines grandes parties du terrain seraient faites du même type de voxel, c'est pourquoi je pensais aux octrees (un gros morceau n'aurait pas à être subdivisé). Cependant, je vais essayer le tableau 3D car il semble plus simple à mettre en œuvre. Je suis sûr que je peux réussir à résumer suffisamment les détails d'implémentation de ma classe de terrain pour qu'il ne soit pas si difficile de changer d'implémentation si le besoin s'en faisait sentir.
pwny

Je vous en prie. Je suggérerais certainement de regarder dans les octrees, vraiment ils ne sont pas difficiles à saisir. Mais oui, votre approche est logique pour le moment, il vaut certainement la peine de faire le prototypage initial à l'aide d'une matrice 3D.
Ingénieur

En tant que lecture supplémentaire, une bonne discussion sur la mise en œuvre d'octrees, y compris plusieurs références utiles, peut être trouvée dans l'article Intel sur l' extension de la STL pour les jeux .
Martin Foot

1

Vous pouvez utiliser RLE. Mais vous pouvez utiliser SVO (Sparse Voxel Octree), id Tech 6 utilise SVO. Un SVO est une technique de rendu graphique 3D utilisant une diffusion de rayons ou parfois une approche de lancer de rayons dans une représentation de données octree.

La technique varie quelque peu, mais repose généralement sur la génération et le traitement de la coque de points (voxels clairsemés) qui sont visibles ou peuvent être visibles, compte tenu de la résolution et de la taille de l'écran.

Utilisez le raycasting, car c'est plus rapide.


0

En règle générale, vous pouvez éviter une structure de données 3D pour le terrain. Vous pouvez utiliser une carte de hauteur à la place. Cela peut être voxélisé très bon marché et efficacement au moment de l'exécution. Il est généralement avantageux (selon mon expérience) de suivre la hauteur minimale que vous devez rendre dans chaque colonne et également parfois les angles de début et de fin afin que vous puissiez également supprimer les colonnes de face arrière.

En voici une que j'ai faite il y a longtemps: http://sites.google.com/site/williamedwardscoder/spinning-voxels-in-flash

Si votre terrain a un petit nombre de surplombs ou de grottes ou d'autres entités qui ne peuvent pas être représentées par une carte de hauteur, vous pouvez avoir des trous dans votre carte de hauteur et avoir une représentation alternative, par exemple de véritables objets de voxel 3D qui remplissent uniquement les endroits localisés où les dépenses d'exécution est garanti.

Des représentations clairsemées de voxels en valent la peine lorsque vous avez de grands mondes de voxels réels. John Carmack en parle depuis quelques années maintenant ...


J'ai aussi pensé aux cartes d'altitude, mais deux choses m'ont éloigné d'eux. Le truc c'est que dans mon cas, le terrain n'est pas vraiment grand du tout ou très compliqué (pensez à un terrain de type labyrinthe, très cartésien). J'aimerais également qu'une partie du terrain soit destructible ou permette à l'utilisateur d'affecter le terrain à travers la construction. Cela peut amener le joueur à créer des "tunnels" sur le terrain qui semblent plus compliqués à représenter avec une carte de hauteur.
pwny
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.