Jak "spłaszczyć " lub" indeks " tablicę 3D w tablicy 1D?
Próbuję spłaszczyć tablicę 3D do tablicy 1D dla systemu "chunk" w mojej grze. Jest to gra 3D-block i w zasadzie chcę, aby system chunk był prawie identyczny z systemem Minecraft (jednak nie jest to klon Minecraft w żadnym stopniu). W moich poprzednich grach 2D uzyskałem dostęp do spłaszczonej tablicy z następującym algorytmem:
Tiles[x + y * WIDTH]
To oczywiście nie działa z 3D, ponieważ brakuje w nim osi Z. Nie mam pojęcia jak zaimplementować tego typu algorytm w przestrzeni 3D. Szerokość, wysokość i głębokość są stałymi (a szerokość jest tak samo duża jak wysokość).
Czy to tylko x + y*WIDTH + Z*DEPTH
? Jestem dość kiepski z matematyką i dopiero zaczynam programowanie 3D, więc jestem dość zagubiony : /
PS. Powodem tego jest to, że często zapętlam i otrzymuję rzeczy według indeksu. Wiem, że tablice 1D są szybsze niż tablice wielowymiarowe (z powodów, których nie pamiętam :P). Mimo, że to może nie być konieczne, chcę jak najlepszego wykonania:)
8 answers
Algorytm jest w większości taki sam. Jeśli masz tablicę 3D Original[HEIGHT, WIDTH, DEPTH]
, możesz przekształcić ją w Flat[HEIGHT * WIDTH * DEPTH]
przez
Flat[x + WIDTH * (y + DEPTH * z)] = Original[x, y, z]
Na marginesie powinieneś preferować tablice tablic zamiast wielowymiarowych tablic w .NET. różnice w wydajności są znaczące
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-09 21:46:49
Oto rozwiązanie w Javie, które daje Ci oba:
- od 3D do 1D
- od 1D do 3D
Poniżej znajduje się graficzna ilustracja ścieżki, którą wybrałem do przemierzania macierzy 3D, komórki są ponumerowane w kolejności ich przemierzania:
Funkcje konwersji:
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 };
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-18 20:08:43
Myślę, że powyższe wymaga małej korekty. Powiedzmy, że masz wysokość 10, a szerokość 90, tablica jednowymiarowa będzie 900. Według powyższej logiki, jeśli jesteś na ostatnim elemencie tablicy 9 + 89*89, oczywiście jest to ponad 900. Prawidłowy algorytm to:
Flat[x + HEIGHT* (y + WIDTH* z)] = Original[x, y, z], assuming Original[HEIGHT,WIDTH,DEPTH]
Jak na ironię jeśli masz wysokość > szerokość nie doświadczysz przepełnienia, po prostu wypełnij bonkers wyniki;)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-17 13:41:44
x + y*WIDTH + Z*WIDTH*DEPTH
. Wizualizuj go jako prostokątną bryłę: najpierw przemierzasz wzdłuż x
, Następnie każdy y
jest "linią" width
, a każdy z
jest "płaszczyzną" WIDTH*DEPTH
w obszarze.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-09 21:46:30
Już prawie jesteś. Musisz pomnożyć Z przez WIDTH
oraz DEPTH
:
Tiles[x + y*WIDTH + Z*WIDTH*DEPTH] = elements[x][y][z]; // or elements[x,y,z]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-09 21:46:02
Aby lepiej zrozumieć opis tablicy 3D w tablicy 1D byłoby (myślę, że głębokość w najlepszej odpowiedzi oznacza rozmiar Y)
IndexArray = x + y * InSizeX + z * InSizeX * InSizeY;
IndexArray = x + InSizeX * (y + z * InSizeY);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-07 15:45:12
Prawidłowy algorytm to:
Flat[ x * height * depth + y * depth + z ] = elements[x][y][z]
where [WIDTH][HEIGHT][DEPTH]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-13 10:20:23
TL;DR
Poprawną odpowiedź można napisać na różne sposoby, ale najbardziej lubię, gdy można ją napisać w sposób bardzo łatwy do zrozumienia i wizualizacji. Oto dokładna odpowiedź:
(width * height * z) + (width * y) + x
TS; DR
Visualize it:
someNumberToRepresentZ + someNumberToRepresentY + someNumberToRepresentX
someNumberToRepresentZ
wskazuje, na której macierzy jesteśmy (depth
). Aby wiedzieć, na której macierzy jesteśmy, musimy wiedzieć, jak duża jest każda macierz. Macierz ma rozmiar 2d width * height
, prosty. Pytanie brzmi: "ile macierzy jest przed matrix, na którym jestem?"Odpowiedź brzmi z
:
someNumberToRepresentZ = width * height * z
someNumberToRepresentY
wskazuje, w którym wierszu jesteśmy (height
). Aby wiedzieć, w którym rzędzie jesteśmy, musimy wiedzieć, jak duży jest każdy wiersz: każdy wiersz to 1D, wielkości width
. Pytanie brzmi: "ile wierszy jest przed rzędem, w którym jestem?". Odpowiedź brzmi y
:
someNumberToRepresentY = width * y
someNumberToRepresentX
wskazuje, na której kolumnie jesteśmy (width
). Aby dowiedzieć się, na której kolumnie jesteśmy, wystarczy użyć x
:
someNumberToRepresentX = x
Nasza wizualizacja wtedy z
someNumberToRepresentZ + someNumberToRepresentY + someNumberToRepresentX
Staje się
(width * height * z) + (width * y) + x
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-09 19:02:01