Как «сгладить» или «индексировать» 3D-массив в 1D-массиве? - PullRequest
21 голосов
/ 10 сентября 2011

Я пытаюсь объединить 3D-массив в 1D-массив для системы "chunk" в моей игре.Это трехмерная блочная игра, и я хочу, чтобы система чанков была практически идентична системе Minecraft (однако, это ни в коем случае не клон Minecraft).В моих предыдущих 2D-играх я обращался к сглаженному массиву по следующему алгоритму:

Tiles[x + y * WIDTH]

Однако это, очевидно, не работает с 3D, поскольку в нем отсутствует ось Z.Я понятия не имею, как реализовать этот алгоритм в 3D-пространстве.Ширина, высота и глубина - все постоянные (а ширина равна высоте).

Это просто x + y*WIDTH + Z*DEPTH?Я довольно плохо разбираюсь в математике, и я только начинаю 3D-программирование, поэтому я довольно растерялся: |

PS.Причиной этого является то, что я довольно много зацикливаюсь и получаю данные по индексу.Я знаю, что одномерные массивы быстрее многомерных (по причинам, которые я не могу вспомнить: P).Даже если в этом нет необходимости, я хочу максимально возможной производительности:)

Ответы [ 8 ]

32 голосов
/ 10 сентября 2011

Алгоритм в основном тот же. Если у вас есть 3D-массив Original[HEIGHT, WIDTH, DEPTH], вы можете превратить его в Flat[HEIGHT * WIDTH * DEPTH] на

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

Кроме того, вы должны предпочесть массивы массивов многомерным массивам в .NET. Различия в производительности значительны

24 голосов
/ 18 декабря 2015

Вот решение на Java, которое дает вам оба:

  • от 3D до 1D
  • от 1D до 3D

Ниже приведена графическая иллюстрация пути, который я выбрал для прохождения 3D-матрицы, ячейки пронумерованы в порядке их обхода:

2 Examples of 3D matrices

Функции преобразования:

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 };
}
21 голосов
/ 17 мая 2013

Я думаю, что вышесказанное нуждается в небольшой коррекции.Допустим, у вас есть ВЫСОТА 10, а ШИРИНА 90, одномерный массив будет 900. По приведенной выше логике, если вы находитесь на последнем элементе массива 9 + 89 * 89, очевидно, что это больше, чем 900.Правильный алгоритм:

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

По иронии судьбы, если у вас ВЫСОТА> ШИРИНА, вы не будете испытывать переполнение, просто завершите помешанные результаты;)

11 голосов
/ 10 сентября 2011

x + y*WIDTH + Z*WIDTH*DEPTH. Визуализируйте его как прямоугольное тело: сначала вы перемещаетесь вдоль x, затем каждый y представляет собой «линию» width шагов в длину, а каждый z представляет собой «плоскость» WIDTH*DEPTH шагов в области.

5 голосов
/ 10 сентября 2011

Ты почти у цели.Вам нужно умножить Z на WIDTH и DEPTH:

Tiles[x + y*WIDTH + Z*WIDTH*DEPTH] = elements[x][y][z]; // or elements[x,y,z]
2 голосов
/ 09 июля 2018

TL; DR

Правильный ответ может быть написан различными способами, но мне больше всего нравится, когда его можно написать так, чтобы его было легко понять и визуализировать.Вот точный ответ:

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

TS; DR

Визуализируйте его:

someNumberToRepresentZ + someNumberToRepresentY + someNumberToRepresentX

someNumberToRepresentZ указывает, на какой матрице мы находимся (depth),Чтобы знать, на какой матрице мы находимся, мы должны знать, насколько велика каждая матрица.Матрица имеет размер width * height, простой.Вопрос, который нужно задать: " сколько матриц перед матрицей, на которой я работаю?"Ответ: z:

someNumberToRepresentZ = width * height * z

someNumberToRepresentY указывает, в какой строке мы находимся (height).Чтобы узнать, в какой строке мы находимся, мы должны знать, насколько велика каждая строка: каждая строка имеет размер 1 * и имеет размер width.Вопрос, который нужно задать: « сколько строк перед строкой, в которой я нахожусь?».Ответ: y:

someNumberToRepresentY = width * y

someNumberToRepresentX указывает, в каком столбце мы находимся (width).Чтобы узнать, в каком столбце мы находимся, мы просто используем x:

someNumberToRepresentX = x

Тогда наша визуализация

someNumberToRepresentZ + someNumberToRepresentY + someNumberToRepresentX

становится

(width * height * z) + (width * y) + x
2 голосов
/ 13 марта 2018

Правильный алгоритм:

Flat[ x * height * depth + y * depth + z ] = elements[x][y][z] 
where [WIDTH][HEIGHT][DEPTH]
1 голос
/ 07 февраля 2014

Чтобы лучше понять описание трехмерного массива в одномерном массиве (я думаю, Глубина в лучшем ответе означает размер Y)

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

IndexArray = x + InSizeX * (y + z * InSizeY);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...