41

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

Tiles[x + y * WIDTH]

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

只是x + y*WIDTH + Z*DEPTH吗?我的数学很差,我刚刚开始 3D 编程,所以我很迷茫:|

PS。这样做的原因是我正在循环并通过索引从中获取很多东西。我知道一维数组比多维数组更快(出于我不记得的原因:P)。尽管这可能不是必需的,但我希望性能尽可能好:)

4

10 回答 10

57

这是 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 };
}
于 2015-12-18T20:08:43.617 回答
49

算法基本相同。如果你有一个 3D 数组,Original[HEIGHT, WIDTH, DEPTH]那么你可以把它变成Flat[HEIGHT * WIDTH * DEPTH]

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

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

于 2011-09-09T21:46:49.290 回答
38

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

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

具有讽刺意味的是,如果您的高度>宽度,您将不会遇到溢出,只是完成疯狂的结果;)

于 2013-05-17T13:16:50.960 回答
11

x + y*WIDTH + Z*WIDTH*DEPTH. 把它想象成一个长方体:首先你沿着 遍历x,然后每个y都是一个“线”width步长,每个z都是一个“平面”WIDTH*DEPTH步长。

于 2011-09-09T21:46:30.280 回答
7

您快到了。您需要将 Z 乘以WIDTH DEPTH

Tiles[x + y*WIDTH + Z*WIDTH*DEPTH] = elements[x][y][z]; // or elements[x,y,z]
于 2011-09-09T21:46:02.107 回答
4

正确的算法是:

Flat[ x * height * depth + y * depth + z ] = elements[x][y][z] 
where [WIDTH][HEIGHT][DEPTH]
于 2018-03-13T10:14:24.677 回答
4

TL;博士

正确答案可以用多种方式编写,但我最喜欢它可以以易于理解和可视化的方式编写。这是确切的答案:

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

TS;博士

可视化它:

someNumberToRepresentZ + someNumberToRepresentY + someNumberToRepresentX

someNumberToRepresentZ指示我们在哪个矩阵上 ( depth)。要知道我们在哪个矩阵上,我们必须知道每个矩阵有多大。一个矩阵是 2d 大小的width * height,简单。要问的问题是“在我所在的矩阵之前有多少个矩阵?” 答案是z

someNumberToRepresentZ = width * height * z

someNumberToRepresentY指示我们在哪一行 ( height)。要知道我们在哪一行,我们必须知道每行有多大:每行是 1d,大小为width. 要问的问题是“我所在的行之前有多少行?”。答案是y

someNumberToRepresentY = width * y

someNumberToRepresentX指示我们在哪一列 ( width)。要知道我们在哪一列,我们只需使用x

someNumberToRepresentX = x

我们的可视化然后

someNumberToRepresentZ + someNumberToRepresentY + someNumberToRepresentX

变成

(width * height * z) + (width * y) + x
于 2018-07-09T19:02:01.320 回答
4

上面 Samuel Kerrien 的正向和反向变换几乎是正确的。下面包含一个更简洁(基于 R)的转换图和一个示例(“a %% b”是模运算符,表示 a 除以 b 的余数):

dx=5; dy=6; dz=7  # dimensions
x1=1; y1=2; z1=3  # 3D point example
I = dx*dy*z1+dx*y1+x1; I  # corresponding 2D index
# [1] 101
x= I %% dx; x  # inverse transform recovering the x index
# [1] 1
y = ((I - x)/dx) %% dy; y  # inverse transform recovering the y index
# [1] 2
z= (I-x -dx*y)/(dx*dy); z  # inverse transform recovering the z index
# [1] 3

注意除法 (/) 和模块 (%%) 运算符。

于 2020-02-18T18:54:39.873 回答
3

为了更好地理解 1D 数组中 3D 数组的描述(我猜最佳答案中的深度是指 Y 大小)

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

IndexArray = x + InSizeX * (y + z * InSizeY);
于 2014-02-07T15:45:12.040 回答
1

m[x][y][z] = 数据[xYZ + yZ + z]

x-picture:
0-YZ
.
.
x-YZ

y-picture 

0-Z
.
.
.
y-Z


summing up, it should be : targetX*YZ + targetY*Z + targetZ  
于 2020-03-11T19:59:48.497 回答