XYZ 到线性值,反之亦然
XYZ to a linear value and vice-versa
我有我的3D世界x, y, z
。我可以使用我的宏 XYZ
:
轻松地将给定坐标 x
、y
、z
转换为整数
const ulong WORLD_SIZE_X = 60;
const ulong WORLD_SIZE_Y = 60;
const ulong WORLD_SIZE_Z = 60;
const ulong WORLD_SIZE = WORLD_SIZE_X * WORLD_SIZE_Y * WORLD_SIZE_Z;
#define XYZ(_x, _y, _z) \
((_x) + ((_y)*WORLD_SIZE_X) + ((_z)*WORLD_SIZE_X*WORLD_SIZE_Y))
因此我可以通过 calloc(WORLD_SIZE, sizeof(Cube))
分配一个大的“线性”数组,并且我可以像这样访问任何多维数据集(只是一个例子):
for (int z=0; z<=WORLD_SIZE_Z; ++z) {
for (int y=0; y<=WORLD_SIZE_Y; ++y) {
for (int x=0; x<=WORLD_SIZE_X; ++x) {
printf("blabla\n", myWorld(XYZ(x, y, z));
}
}
}
所以:
- 我可以分配一个“线性”数组(=对我来说比数组的数组简单得多)
- 给定
x
、y
和z
,我可以轻松找到我想要的元素
而且我找不到执行相反操作的正确宏:给定一个 long long pos
,找到 x
、y
和 z
.
对于二维数组来说很简单,就是x = pos % SIZE_X;
和y = (int)(pos / SIZE_X);
。但是对于 3D 世界你怎么做?
如果你重写你的等式,也许会更容易:
u = (z * WORLD_SIZE_Y + y) * WORLD_SIZE_X + x;
您可以通过以下方式获取个人坐标:
x = u % WORLD_SIZE_X;
y = (u / WORLD_SIZE_X) % WORLD_SIZE_Y;
z = (u / WORLD_SIZE_X) / WORLD_SIZE_Y;
表达式 'extract' 来自组合 pos
的 X、Y 和 Z 坐标需要反转用于形成该位置的操作。
- 对于 X,它将与 2D 情况相同(只是取值模 X_SIZE):
x = pos % X_SIZE
.
- 对于 Y,我们可以先除以 X_SIZE(到 shift-out X 分量),然后取模 Y_SIZE:
y = (pos / X_SIZE) % Y_SIZE
.
- 对于 Z,我们扩展了您对 2D Y 的原始操作,但除以 X_SIZE 和 Y_SIZE 的乘积:
z = pos / (X_SIZE * Y_SIZE)
但是,通过为位置定义 struct
,您的系统可能会更有效率(避免任何数学运算);假设三个“世界维度”不大于 255,我们可以为每个元素使用单个字节。然后,您可以拥有此类结构的数组 (1D),并且可以在一条语句中分配所有三个(x、y 和 z)值 – 无需使用宏 – 通过 compound literal.
这是一个简短的演示:
#include <stdio.h>
#include <stdint.h>
typedef struct {
uint8_t x;
uint8_t y;
uint8_t z;
} pos_type;
int main()
{
uint8_t x = 37;
uint8_t y = 42;
uint8_t z = 123;
pos_type pos[100];
pos[3] = (pos_type){ x, y, z }; // Can assign elements using a compound literal
uint8_t ax = pos[3].x;
uint8_t ay = pos[3].y;
uint8_t az = pos[3].z;
printf("%hhu %hhu %hhu\n", ax, ay, az);
return 0;
}
我有我的3D世界x, y, z
。我可以使用我的宏 XYZ
:
x
、y
、z
转换为整数
const ulong WORLD_SIZE_X = 60;
const ulong WORLD_SIZE_Y = 60;
const ulong WORLD_SIZE_Z = 60;
const ulong WORLD_SIZE = WORLD_SIZE_X * WORLD_SIZE_Y * WORLD_SIZE_Z;
#define XYZ(_x, _y, _z) \
((_x) + ((_y)*WORLD_SIZE_X) + ((_z)*WORLD_SIZE_X*WORLD_SIZE_Y))
因此我可以通过 calloc(WORLD_SIZE, sizeof(Cube))
分配一个大的“线性”数组,并且我可以像这样访问任何多维数据集(只是一个例子):
for (int z=0; z<=WORLD_SIZE_Z; ++z) {
for (int y=0; y<=WORLD_SIZE_Y; ++y) {
for (int x=0; x<=WORLD_SIZE_X; ++x) {
printf("blabla\n", myWorld(XYZ(x, y, z));
}
}
}
所以:
- 我可以分配一个“线性”数组(=对我来说比数组的数组简单得多)
- 给定
x
、y
和z
,我可以轻松找到我想要的元素
而且我找不到执行相反操作的正确宏:给定一个 long long pos
,找到 x
、y
和 z
.
对于二维数组来说很简单,就是x = pos % SIZE_X;
和y = (int)(pos / SIZE_X);
。但是对于 3D 世界你怎么做?
如果你重写你的等式,也许会更容易:
u = (z * WORLD_SIZE_Y + y) * WORLD_SIZE_X + x;
您可以通过以下方式获取个人坐标:
x = u % WORLD_SIZE_X;
y = (u / WORLD_SIZE_X) % WORLD_SIZE_Y;
z = (u / WORLD_SIZE_X) / WORLD_SIZE_Y;
表达式 'extract' 来自组合 pos
的 X、Y 和 Z 坐标需要反转用于形成该位置的操作。
- 对于 X,它将与 2D 情况相同(只是取值模 X_SIZE):
x = pos % X_SIZE
. - 对于 Y,我们可以先除以 X_SIZE(到 shift-out X 分量),然后取模 Y_SIZE:
y = (pos / X_SIZE) % Y_SIZE
. - 对于 Z,我们扩展了您对 2D Y 的原始操作,但除以 X_SIZE 和 Y_SIZE 的乘积:
z = pos / (X_SIZE * Y_SIZE)
但是,通过为位置定义 struct
,您的系统可能会更有效率(避免任何数学运算);假设三个“世界维度”不大于 255,我们可以为每个元素使用单个字节。然后,您可以拥有此类结构的数组 (1D),并且可以在一条语句中分配所有三个(x、y 和 z)值 – 无需使用宏 – 通过 compound literal.
这是一个简短的演示:
#include <stdio.h>
#include <stdint.h>
typedef struct {
uint8_t x;
uint8_t y;
uint8_t z;
} pos_type;
int main()
{
uint8_t x = 37;
uint8_t y = 42;
uint8_t z = 123;
pos_type pos[100];
pos[3] = (pos_type){ x, y, z }; // Can assign elements using a compound literal
uint8_t ax = pos[3].x;
uint8_t ay = pos[3].y;
uint8_t az = pos[3].z;
printf("%hhu %hhu %hhu\n", ax, ay, az);
return 0;
}