Как "сгладить" или "индексировать" 3D-массив в массиве 1D?
Я пытаюсь сгладить 3D-массив в 1D-массив для "chunk" -системы в моей игре. Это игра в 3D-блок, и в основном я хочу, чтобы система кусков была почти идентична системе Minecraft (однако это не клон Minecraft по какой-либо мере). В моих предыдущих 2D-играх я получил доступ к сплющенному массиву со следующим алгоритмом:
Tiles[x + y * WIDTH]
Однако это, очевидно, не работает с 3D, так как отсутствует ось Z. Я понятия не имею, как реализовать этот алгоритм в 3D-пространстве. Ширина, высота и глубина - это все константы (а ширина равна высоте).
Это просто x + y*WIDTH + Z*DEPTH
? Я довольно плохо с математикой, и я только начинаю 3D-программирование, поэтому я довольно потерян: |
PS. Причина этого в том, что я зацикливаюсь и получаю материал по индексу от него довольно много. Я знаю, что 1D-массивы быстрее, чем многомерные массивы (по причинам, которые я не могу вспомнить: P). Хотя это может и не быть необходимым, я хочу как можно более высокую производительность:)
Ответы
Ответ 1
Алгоритм в основном тот же. Если у вас есть 3D-массив Original[HEIGHT, WIDTH, DEPTH]
, вы можете превратить его в Flat[HEIGHT * WIDTH * DEPTH]
на
Flat[x + WIDTH * (y + DEPTH * z)] = Original[x, y, z]
В стороне, вы должны предпочесть массивы массивов над многомерными массивами в .NET. Различия в производительности значительны.
Ответ 2
Вот решение на Java, которое дает вам оба:
Ниже представлена графическая иллюстрация пути, который я выбрал для перемещения 3D-матрицы, ячейки пронумерованы в порядке прохождения:
![2 Примеры 3D-матриц]()
Функции преобразования:
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 };
}
Ответ 3
Я думаю, что вышеизложенное нуждается в небольшой коррекции. Допустим, что у вас ВЫСОТА 10, а размер WIDTH 90, одномерный массив будет равен 900. По логике выше, если вы находитесь в последнем элементе массива 9 + 89 * 89, очевидно, это больше 900. Правильный алгоритм:
Flat[x + HEIGHT* (y + WIDTH* z)] = Original[x, y, z], assuming Original[HEIGHT,WIDTH,DEPTH]
По иронии судьбы, если вы ВЫСОТа > ШИРИНА, у вас не будет переполнения, просто выполните результаты bonkers;)
Ответ 4
x + y*WIDTH + Z*WIDTH*DEPTH
. Визуализируйте его как прямоугольное твердое тело: сначала вы проходите вдоль x
, тогда каждый y
является шагом "width
", а каждый z
является "плоскостью" WIDTH*DEPTH
шагов в области.
Ответ 5
Ты почти там. Вам нужно умножить Z на WIDTH
и DEPTH
:
Tiles[x + y*WIDTH + Z*WIDTH*DEPTH] = elements[x][y][z]; // or elements[x,y,z]
Ответ 6
Чтобы лучше понять описание 3D-массива в массиве 1D, было бы (думаю, глубина в лучшем ответе подразумевается размером Y)
IndexArray = x + y * InSizeX + z * InSizeX * InSizeY;
IndexArray = x + InSizeX * (y + z * InSizeY);