J'essaye d'aplatir un tableau 3D en tableau 1D pour le système "chunk" dans mon jeu. Il s’agit d’un jeu de blocs en 3D et, fondamentalement, je souhaite que le système de blocs soit presque identique au système de Minecraft (toutefois, ce n’est en aucun cas un clone de Minecraft). Dans mes précédents jeux 2D, j'ai accédé au tableau aplati avec l'algorithme suivant:
Tiles[x + y * WIDTH]
Cependant, cela ne fonctionne évidemment pas avec la 3D car il manque l'axe Z. Je ne sais pas comment implémenter ce type d'algorithme dans l'espace 3D. La largeur, la hauteur et la profondeur sont toutes des constantes (et la largeur est aussi grande que la hauteur).
Est-ce juste x + y*WIDTH + Z*DEPTH
? Je suis assez mauvais en maths et je commence juste à programmer en 3D, alors je suis assez perdu: |
PS. La raison en est que je boucle et que je tire pas mal de choses par index. Je sais que les tableaux 1D sont plus rapides que les tableaux multidimensionnels (pour des raisons que je ne me souviens plus: P). Même si cela peut ne pas être nécessaire, je veux la meilleure performance possible :)
L'algorithme est essentiellement le même. Si vous avez un tableau 3D Original[HEIGHT, WIDTH, DEPTH]
, vous pouvez le transformer en Flat[HEIGHT * WIDTH * DEPTH]
par
Flat[x + WIDTH * (y + DEPTH * z)] = Original[x, y, z]
En passant, vous devriez préférer les tableaux de tableaux aux tableaux multidimensionnels dans .NET. Les différences de performance sont significatives
Voici une solution en Java qui vous donne les deux:
Ci-dessous, une illustration graphique du chemin que j'ai choisi pour parcourir la matrice 3D. Les cellules sont numérotées dans leur ordre de parcours:
Fonctions de conversion:
public int to1D( int x, int y, int z ) {
return (z * xMax * yMax) + (y * xMax) + x;
}
public int[] to3D( int idx ) {
final int z = idx / (xMax * yMax);
idx -= (z * xMax * yMax);
final int y = idx / xMax;
final int x = idx % xMax;
return new int[]{ x, y, z };
}
Je pense que ce qui précède nécessite une petite correction. Disons que vous avez une hauteur de 10, et une largeur de 90, un tableau à une dimension sera 900. Selon la logique ci-dessus, si vous êtes au dernier élément du tableau 9 + 89 * 89, il est évident qu'il est supérieur à 900. L'algorithme correct est:
Flat[x + HEIGHT* (y + WIDTH* z)] = Original[x, y, z], assuming Original[HEIGHT,WIDTH,DEPTH]
Ironiquement, si vous avez la HAUTEUR> LARGEUR, vous ne rencontrerez pas de débordement, complétez simplement les résultats douteux;)
x + y*WIDTH + Z*WIDTH*DEPTH
. Visualisez-le sous la forme d'un solide rectangulaire: vous parcourez d'abord x
, puis chaque y
est une "ligne" width
longue, et chaque z
est un "avion" WIDTH*DEPTH
croissant.
Tu y es presque. Vous devez multiplier Z par WIDTH
et DEPTH
:
Tiles[x + y*WIDTH + Z*WIDTH*DEPTH] = elements[x][y][z]; // or elements[x,y,z]
L'algorithme correct est:
Flat[ x * height * depth + y * depth + z ] = elements[x][y][z]
where [WIDTH][HEIGHT][DEPTH]
TL; DR
La bonne réponse peut être écrite de différentes manières, mais je l’aime mieux quand elle peut être écrite d’une manière très facile à comprendre et à visualiser. Voici la réponse exacte:
(width * height * z) + (width * y) + x
TS; DR
Visualisez le:
someNumberToRepresentZ + someNumberToRepresentY + someNumberToRepresentX
someNumberToRepresentZ
indique la matrice sur laquelle nous sommes (depth
). Pour savoir sur quelle matrice nous sommes, nous devons savoir quelle est la taille de chaque matrice. Une matrice est de taille 2D en tant que width * height
, simple. La question à poser est " combien de matrices sont avant la matrice sur laquelle je suis?" La réponse est z
:
someNumberToRepresentZ = width * height * z
someNumberToRepresentY
indique la rangée sur laquelle nous nous trouvons (height
). Pour savoir à quelle rangée nous nous trouvons, nous devons savoir quelle est la taille de chaque rangée: Chaque rangée vaut 1d, de taille width
. La question à poser est " combien de lignes sont avant la ligne sur laquelle je suis?". La réponse est y
:
someNumberToRepresentY = width * y
someNumberToRepresentX
indique la colonne sur laquelle nous sommes (width
). Pour savoir sur quelle colonne nous nous trouvons, nous utilisons simplement x
:
someNumberToRepresentX = x
Notre visualisation alors de
someNumberToRepresentZ + someNumberToRepresentY + someNumberToRepresentX
Devient
(width * height * z) + (width * y) + x
Pour mieux comprendre la description d'un tableau 3D dans un tableau 1D, je suppose que (la meilleure réponse est Profondeur, taille Y)
IndexArray = x + y * InSizeX + z * InSizeX * InSizeY;
IndexArray = x + InSizeX * (y + z * InSizeY);