如何在一维数组中“变平”或“索引”3d数组?

时间:2023-02-08 00:14:53

I am trying to flatten 3D array into 1D array for "chunk" system in my game. It's a 3D-block game and basically I want the chunk system to be almost identical to Minecraft's system (however, this isn't Minecraft clone by any measure). In my previous 2D-games I have accessed the flattened array with following algorithm:

我正在尝试将3D数组压缩到1D数组中,用于我的游戏中的“块”系统。这是一个3d块游戏,基本上我希望块系统与《我的世界》的系统几乎相同(然而,无论如何,这不是《我的世界》的克隆)。在我之前的2d游戏中,我使用以下算法访问了扁平阵列:

Tiles[x + y * WIDTH]

However, this obviously doesn't work with 3D since it's missing the Z-axis. I have no idea how to implement this sort of algorithm in 3D-space. Width, height and depth are all constants (and width is just as large as height).

然而,这显然不适用于3D,因为它缺少z轴。我不知道如何在三维空间中实现这种算法。宽度、高度和深度都是常数(宽度和高度一样大)。

Is it just x + y*WIDTH + Z*DEPTH ? I am pretty bad with math and I am just beginning 3D-programming so I am pretty lost :|

是x + y*宽度+ Z*深度吗?我的数学很差,而且我刚刚开始3d编程,所以我很迷茫:|

PS. The reason for this is that I am looping and getting stuff by index from it quite a lot. I know that 1D arrays are faster than multi-dimensional arrays (for reasons I cant remember :P ). Even though this may not be necessary, I want as good performance as possible :)

这样做的原因是我对它进行了循环,并从它中获得了很多索引。我知道一维数组比多维数组快(因为我记不清了:P)。虽然这可能不是必须的,但我想要尽可能好的表现:

7 个解决方案

#1


28  

The algorithm is mostly the same. If you have a 3D array Original[HEIGHT, WIDTH, DEPTH] then you could turn it into Flat[HEIGHT * WIDTH * DEPTH] by

算法基本上是一样的。如果你有一个三维数组原始的[高度,宽度,深度],那么你可以把它变成平的[高度*宽度*深度]by

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

As an aside, you should prefer arrays of arrays over multi-dimensional arrays in .NET. The performance differences are significant

顺便说一句,在。net中,您应该更喜欢数组而不是多维数组。性能差异是显著的。

#2


21  

Here is a solution in Java that gives you both:

下面是Java中的一个解决方案:

  • from 3D to 1D
  • 从三维到1 d
  • from 1D to 3D
  • 从一维到三维

Below is a graphical illustration of the path I chose to traverse the 3D matrix, the cells are numbered in their traversal order:

下面是我选择遍历3D矩阵的路径的图示,单元格按其遍历顺序编号:

如何在一维数组中“变平”或“索引”3d数组?

Conversion functions:

转换函数:

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


16  

I think the above needs a little correction. Lets say you have a HEIGHT of 10, and a WIDTH of 90, single dimensional array will be 900. By the above logic, if you are at the last element on the array 9 + 89*89, obviously this is greater than 900. The correct algorithm is:

我认为上述情况需要做一些修正。假设高度是10,宽度是90,单维数组是900。根据上面的逻辑,如果您在数组9 + 89*89的最后一个元素,显然这个元素大于900。正确的算法是:

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

Ironically if you the HEIGHT>WIDTH you will not experience an overflow, just complete bonkers results ;)

讽刺的是,如果你的高度>宽度你将不会经历一个溢出,只是完全疯狂的结果;)

#4


12  

x + y*WIDTH + Z*WIDTH*DEPTH. Visualize it as a rectangular solid: first you traverse along x, then each y is a "line" width steps long, and each z is a "plane" WIDTH*DEPTH steps in area.

x + y*宽度+ Z*宽度*深度。把它想象成一个长方形的实体:首先你沿着x走,然后每一个y都是一个“线”宽的台阶,每一个z都是一个“平面”宽的台阶。

#5


6  

You're almost there. You need to multiply Z by WIDTH and DEPTH:

你差不多了。你需要用Z乘以宽度和深度:

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

#6


1  

To better understand description of 3D array in 1D array would be ( I guess Depth in best answer is meant Y size)

为了更好地理解一维数组中三维数组的描述(我猜最好的答案是Y的大小)

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

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

#7


1  

The correct Algorithm is:

正确的算法是:

Flat[ x * height * depth + y * depth + z ] = elements[x][y][z] 
where [WIDTH][HEIGHT][DEPTH]

#1


28  

The algorithm is mostly the same. If you have a 3D array Original[HEIGHT, WIDTH, DEPTH] then you could turn it into Flat[HEIGHT * WIDTH * DEPTH] by

算法基本上是一样的。如果你有一个三维数组原始的[高度,宽度,深度],那么你可以把它变成平的[高度*宽度*深度]by

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

As an aside, you should prefer arrays of arrays over multi-dimensional arrays in .NET. The performance differences are significant

顺便说一句,在。net中,您应该更喜欢数组而不是多维数组。性能差异是显著的。

#2


21  

Here is a solution in Java that gives you both:

下面是Java中的一个解决方案:

  • from 3D to 1D
  • 从三维到1 d
  • from 1D to 3D
  • 从一维到三维

Below is a graphical illustration of the path I chose to traverse the 3D matrix, the cells are numbered in their traversal order:

下面是我选择遍历3D矩阵的路径的图示,单元格按其遍历顺序编号:

如何在一维数组中“变平”或“索引”3d数组?

Conversion functions:

转换函数:

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


16  

I think the above needs a little correction. Lets say you have a HEIGHT of 10, and a WIDTH of 90, single dimensional array will be 900. By the above logic, if you are at the last element on the array 9 + 89*89, obviously this is greater than 900. The correct algorithm is:

我认为上述情况需要做一些修正。假设高度是10,宽度是90,单维数组是900。根据上面的逻辑,如果您在数组9 + 89*89的最后一个元素,显然这个元素大于900。正确的算法是:

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

Ironically if you the HEIGHT>WIDTH you will not experience an overflow, just complete bonkers results ;)

讽刺的是,如果你的高度>宽度你将不会经历一个溢出,只是完全疯狂的结果;)

#4


12  

x + y*WIDTH + Z*WIDTH*DEPTH. Visualize it as a rectangular solid: first you traverse along x, then each y is a "line" width steps long, and each z is a "plane" WIDTH*DEPTH steps in area.

x + y*宽度+ Z*宽度*深度。把它想象成一个长方形的实体:首先你沿着x走,然后每一个y都是一个“线”宽的台阶,每一个z都是一个“平面”宽的台阶。

#5


6  

You're almost there. You need to multiply Z by WIDTH and DEPTH:

你差不多了。你需要用Z乘以宽度和深度:

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

#6


1  

To better understand description of 3D array in 1D array would be ( I guess Depth in best answer is meant Y size)

为了更好地理解一维数组中三维数组的描述(我猜最好的答案是Y的大小)

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

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

#7


1  

The correct Algorithm is:

正确的算法是:

Flat[ x * height * depth + y * depth + z ] = elements[x][y][z] 
where [WIDTH][HEIGHT][DEPTH]