XYZ 到线性值,反之亦然

XYZ to a linear value and vice-versa

我有我的3D世界x, y, z。我可以使用我的宏 XYZ:

轻松地将给定坐标 xyz 转换为整数
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));
        }
    }
}

所以:

而且我找不到执行相反操作的正确宏:给定一个 long long pos,找到 xyz.

对于二维数组来说很简单,就是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;
}