2011-09-09 13 views
15

Sto cercando di appiattire l'array 3D in un array 1D per il sistema "chunk" nel mio gioco. È un gioco a blocchi 3D e in pratica voglio che il sistema a blocchi sia quasi identico al sistema di Minecraft (tuttavia, questo non è un clone di Minecraft di nessuna misura). Nei miei precedenti 2D-giochi che ho letta la matrice appiattito con seguente algoritmo:Come "appiattire" o "indicizzare" l'array 3D nell'array 1D?

Tiles[x + y * WIDTH] 

Tuttavia, questo ovviamente non funziona con il 3D in quanto manca l'asse Z. Non ho idea di come implementare questo tipo di algoritmo nello spazio 3D. Larghezza, altezza e profondità sono tutte costanti (e la larghezza è grande quanto l'altezza).

È solo x + y*WIDTH + Z*DEPTH? Sono piuttosto cattivo con la matematica e sto solo iniziando la programmazione 3D, quindi sono piuttosto perso: |

PS. La ragione di ciò è che sto eseguendo un ciclo e ricevendo roba per indice da parecchio. So che gli array 1D sono più veloci degli array multidimensionali (per ragioni che non ricordo: P). Anche se questo potrebbe non essere necessario, voglio le migliori prestazioni possibili :)

+0

ho ragione nel dire che si desidera una matrice 3D per essere in forma in un arr 1D Ay? – DMan

+1

Perché non usi solo array 3D? – svick

+0

@DMan Sì, lo sei :) Spiego sempre tutto nel modo più duro e lungo, quindi nessuna sorpresa che non capisci: P – flai

risposta

24

L'algoritmo è principalmente lo stesso. Se si dispone di un array 3D Original[HEIGHT, WIDTH, DEPTH] allora si potrebbe trasformarlo in Flat[HEIGHT * WIDTH * DEPTH] da

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

Per inciso, si dovrebbe preferire array di array su array multidimensionali in .NET. Le differenze di prestazioni sono significative

+3

Puoi indicare qualche fonte discutendo le differenze di rendimento? Inoltre, non dovresti basare le tue decisioni solo sul rendimento. – svick

+0

http://stackoverflow.com/questions/597720/what-is-differences-between-multidimensional-array-and-array-of-arrays-in-c e http://stackoverflow.com/questions/468832/why -se-multidimensionale-array-in-net-lento-rispetto-normale-array- – hatchet

+0

@svick: alcune fonti possono essere viste nell'hooket dei collegamenti fornito. La mia nota sul rendimento era solo un accenno e non il suggerimento principale. Gli array frastagliati hanno una sintassi quasi identica (originale [x] [y] [z]), ma richiedono più lavoro per inizializzarsi. Tuttavia, i vantaggi in termini di prestazioni possono diventare abbastanza evidenti (2-5x speedup) a seconda dell'utilizzo. –

5

Sei quasi arrivato. È necessario moltiplicare Z da WIDTHeDEPTH:

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

x + y*WIDTH + Z*WIDTH*DEPTH. Visualizzalo come un solido rettangolare: per prima cosa percorri x, quindi ogni è un passo "linea" width lungo e ogni z è un "piano" WIDTH*DEPTH passaggi nell'area.

13

Penso che quanto sopra richiede una piccola correzione. Diciamo che avete un'ALTEZZA di 10, e una LARGHEZZA di 90, l'array monodimensionale sarà 900. Dalla logica sopra, se siete all'ultimo elemento dell'array 9 + 89 * 89, ovviamente questo è maggiore di 900.L'algoritmo corretto è:

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

Ironia della sorte se l'altezza> WIDTH non sperimenterà un overflow, basta completare risultati Bonkers;)

+3

Non riesco a fare un preventivo o commentare vera risposta corretta, ma Martin ha corretto, la risposta selezionata corrente è sbagliata. In sostanza: dati [x] [y] [z] = dati [x + y * maxX + z * maxX * maxY] – jking

+0

sì la risposta corrente è errata, dovrebbe essere altezza non profondità. mi ci è voluto troppo tempo per capirlo perché è la prima volta che ho usato una risposta SO sbagliata per codificare qualcosa>. < – chilleo

0

Per comprendere meglio descrizione della gamma 3D in 1D serie sarebbe (I dimensione Y indovinate profondità nel migliore risposta si intende)

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

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

Ecco una soluzione in Java che ti da entrambi:

  • da 3D a 1D
  • da 1D a 3D

segue è un'illustrazione grafica del percorso ho scelto di attraversare la matrice 3D, le cellule sono numerati nel loro ordine di attraversamento:

2 Examples of 3D matrices

funzioni di conversione:

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