Как "сгладить" или "индексировать" 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 до 1D
  • от 1D до 3D

Ниже представлена ​​графическая иллюстрация пути, который я выбрал для перемещения 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);