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.
Réponses:
Premier. Permet d'écrire ce que nous savons sur chaque voxel:
Stockage général
La manière générale est simplement la suivante:
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:
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):
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:
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 .
la source
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.
la source
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.
la source
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 ...
la source