¿Cómo “aplanar” o “indexar” 3D-array en 1D array?

Estoy tratando de aplanar matriz 3D en matriz 1D para el sistema “trozo” en mi juego. Es un juego de bloques en 3D y, básicamente, quiero que el sistema de fragmentos sea casi idéntico al sistema de Minecraft (sin embargo, esto no es un clon de Minecraft por ninguna medida). En mis juegos 2D anteriores, he accedido a la matriz aplanada con el siguiente algoritmo:

Tiles[x + y * WIDTH] 

Sin embargo, esto obviamente no funciona con 3D ya que falta el eje Z. No tengo idea de cómo implementar este tipo de algoritmo en el espacio 3D. El ancho, la altura y la profundidad son todas constantes (y el ancho es tan grande como la altura).

¿Es solo x + y*WIDTH + Z*DEPTH ? Soy bastante malo con las matemáticas y recién comienzo la progtwigción en 3D, así que estoy bastante perdido: |

PD. La razón de esto es que estoy haciendo bucles y obteniendo cosas por índice bastante. Sé que las matrices 1D son más rápidas que las matrices multidimensionales (por razones que no puedo recordar: P). Aunque esto puede no ser necesario, quiero el mejor rendimiento posible 🙂

El algoritmo es casi el mismo. Si tiene una matriz 3D Original[HEIGHT, WIDTH, DEPTH] entonces puede convertirla en Flat[HEIGHT * WIDTH * DEPTH]

 Flat[x + WIDTH * (y + DEPTH * z)] = Original[x, y, z] 

Como un lado, deberías preferir matrices de matrices sobre matrices multidimensionales en .NET. Las diferencias de rendimiento son significativas

Aquí hay una solución en Java que le da a ambos:

  • de 3D a 1D
  • de 1D a 3D

A continuación se muestra una ilustración gráfica de la ruta que elegí para atravesar la matriz 3D, las celdas están numeradas en su orden transversal:

2 Ejemplos de matrices 3D

Funciones de conversión:

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

Creo que lo anterior necesita una pequeña corrección. Digamos que tienes una ALTURA de 10, y un ANCHO de 90, una matriz dimensional única será de 900. Por la lógica anterior, si estás en el último elemento de la matriz 9 + 89 * 89, obviamente esto es mayor que 900. El algoritmo correcto es:

 Flat[x + HEIGHT* (y + WIDTH* z)] = Original[x, y, z], assuming Original[HEIGHT,WIDTH,DEPTH] 

Irónicamente, si la ALTURA> ANCHURA no experimentará un desbordamiento, solo complete los resultados absurdos;)

x + y*WIDTH + Z*WIDTH*DEPTH . Visualícelo como un sólido rectangular: primero recorre x , luego cada y tiene un width “línea” de largo, y cada z es un WIDTH*DEPTH “plano” WIDTH*DEPTH pasos en el área.

Ya casi estás ahí. Necesitas multiplicar Z por WIDTH y DEPTH :

 Tiles[x + y*WIDTH + Z*WIDTH*DEPTH] = elements[x][y][z]; // or elements[x,y,z] 

Para comprender mejor la descripción de la matriz 3D en matriz 1D sería (creo que la profundidad en la mejor respuesta se refiere al tamaño Y)

 IndexArray = x + y * InSizeX + z * InSizeX * InSizeY; IndexArray = x + InSizeX * (y + z * InSizeY); 

El algoritmo correcto es:

 Flat[ x * height * depth + y * depth + z ] = elements[x][y][z] where [WIDTH][HEIGHT][DEPTH] 

TL; DR

La respuesta correcta se puede escribir de varias maneras, pero me gusta más cuando se puede escribir de una manera que sea muy fácil de entender y visualizar. Aquí está la respuesta exacta:

 (width * height * z) + (width * y) + x 

TS; DR

Visualízalo:

 someNumberToRepresentZ + someNumberToRepresentY + someNumberToRepresentX 

someNumberToRepresentZ indica en qué matriz estamos ( depth ). Para saber en qué matriz estamos, debemos saber qué tan grande es cada matriz. Una matriz tiene un tamaño 2d como width * height , simple. La pregunta es: ” ¿Cuántas matrices hay antes de la matriz en la que estoy?” La respuesta es z :

 someNumberToRepresentZ = width * height * z 

someNumberToRepresentY indica en qué fila estamos ( height ). Para saber en qué fila estamos, debemos saber qué tan grande es cada fila: cada fila es 1d, del mismo tamaño que el width . La pregunta que debe hacerse es ” ¿cuántas filas hay antes de la fila en la que estoy?”. La respuesta es y :

 someNumberToRepresentY = width * y 

someNumberToRepresentX indica en qué columna estamos ( width ). Para saber en qué columna estamos simplemente utilizamos x :

 someNumberToRepresentX = x 

Nuestra visualización entonces de

 someNumberToRepresentZ + someNumberToRepresentY + someNumberToRepresentX 

Se convierte

 (width * height * z) + (width * y) + x