1

所以,我可能应该先解释一下我想如何实现它。我的想法很简单,我想创建每个块并通过利用每个块本地的浮点网格来确定每个顶点的位置,然后我想将体素放置在一个大的 64 位整数网格中(每个块的位置由它具有的整数值,0,0,0 将是中间,20,20,20 将在 x、y 和 z 轴上 20 个块)进一步创建一个巨大的世界我会进行一些检查以确定如何将根据它们在整数网格中的位置推断出块,这是我尚未弄清楚的。(不如让它运行重要)

我遇到的问题:

  1. 弄清楚如何使用 libnoise 生成 3D perlin 噪声,据我所知,该文档没有涉及这个主题,而且我从谷歌那里得到了没有像样的结果。
  2. 不知何故将块放在整数网格中
  3. 弄清楚一个人将如何确定从网格中的位置推断出该块的坚固程度(我认为这很简单,例如检查周围的块是什么以及您在网格中的位置并根据该数据确定它)
  4. 根据从整数网格推断出的位置,将各种稀有矿石散布在周围,这相当容易,但在解决其他问题之前无法完成。
  5. 找出区间树。

那么,有什么想法吗?到目前为止的相关代码(删除了光、遮挡、UV 和正常计算代码,因为它与问题无关)

#define get(x, y, z)\
data[\
        clamp(x, size)+\
        clamp(y, size)*size+\
        clamp(z, size)*size*size\
    ]
#define put(x,y,z, value)\
    data[\
            (x)+\
            (y)*size+\
            (z)*size*size\
        ] = value
#define index(x, y, x) clamp (x, size)+clamp(y, size)*size+clamp(z, size)*size*size

#define foreach_xyz(start, end) \
    int x, y, z; \
    float xf, yf, zf;\
    for(x=(start); x<(end); x++\
    {\
        for(y=(start); y<(end); y++)\
            {\
                for (z=(start); z<(end); z++)\
                {\
                    xf=(float)x/(float)size;\
                    xy=(float)y/(float)size;\
                    xz=(float)z/(float)size;

#define endfor }}}

//removed pointless code from here

typedef struct //vertices
{
    float xVertex, yVertex, zVertex, wVertex;
} vertex;

//removed pointless code from here

typedef struct //cell
{
    float leftCell, rightCell, topCell, bottomCell, frontCell, backCell;
} cell;

//removed pointless code from here

int primitiveCount_CUBE (int size, byte* data)
{
    int value, count = 0;
    foreach_xyz(0, size)
        value = get(x,y,z)ĵ;
        if(!value)
        {
            if(get(x+1, y, z)) count++;
            if(get(x-1, y, z)) count++;
            if(get(x, y+1, z)) count++;
            if(get(x, y-1, z)) count++;
            if(get(x, y, z+1)) count++;
            if(get(x, y, z-1)) count++;
        }
        endfor
        return count;
}

//removed pointless code from here

void setPos(vertex** posPtr, float x0, float y0, float z0,
                         float x1, float y1, float z1,
                         float x2, float y2, float z2,
                         float x3, float y3, float z3)

//removed pointless code from here

void setData(vertex posPtr,
         float x0, float y0, float z0,
         float x1, float y1, float z1,
         float x2, float y2, float z2
         float x3, float y3, float z3,
         normal** normalPtr, float nx, float ny, float nz,
         normal** sPtr, float sx, float sy, float sz,
         normal** tPtr, float tx, float ty, float tz,
         UV** UVPtr, int value,
         color** lightPtr, color** gather,
         float** occlusionPtr, float occlusion)
{
    setPos(posPtr,
           x0, y0, z0
           x1, y1, z1,
           x2, y2, y3,
           x3, y3, z3);

    setNormal(normalPtr, nx, ny, nz
              sPtr, sx, sy, sz
              tPtr, tx, ty, tz);

    setUV(value, UVPtr);
    setLight(gather, lightPtr);
    setOcclusion(occlusion, occlusionPtr);
}

void tesselate(int size, unsigned char* data, cell* occlusion, color** gather,
               vertex pos, normal* Normal, normal* s, normal* t, float outOcc,
               UV* uv, color* light)
{
    float n = 0.5;
    int idx, value;
    cell* Cell;
    color* cellGather;

    foreach_xyz(0, size)
        idx = index(x,y,z);
        cell = occlusion + idx;
        cellGather = gather + idx;
        if(get(x, y, z) == 0)
        {
            value = get(x-1, y, z)
                if(value > 0)
                    setData(&pos, x-n, y-n, z-n,
                            x-n, y+n, z-n,
                            x-n, y+n, z+n,
                            x-n, y-n, z+n

                            &normal, 1, 0, 0,
                            &s, 0, 1, 0
                            &t, 0, 0, 1,
                            &UV, value,
                            &light, cellGather,
                            &outOcc, cell->leftCell);

            value¨= get(x, y-1, z);
            if(value== materials_cube.dirt)
            {
                value=materials_cube.grass;
            }
            if( value > 0 )
                setData(&pos, x-n, y-n, z-n,
                        x-n, y-n, z+n,
                        x+n, y-n, z+n,
                        x+n, y-n, z-n
                        &normal, 0, 1, 0,
                        &s, 0, 0, 1,
                        &t, 1, 0, 0,
                        &UV, value,
                        &light, cellGather
                        &outOcc, cell->bottomCell);

            value = get(x, y+1, z);
            if(value > 0)
                setData(&pos, x-n, y+n, z-n,
                        x+n, y+n, z-n,
                        x+n, y+n, z+n,
                        x-n, y+n, z+n,
                        &normal, 0, -1, 0,
                        &s, 1, 0, 0,
                        &t, 0, 0, 1,
                        &UV, value,
                        &light, cellGather
                        &outOcc, cell->topCell);

            value = get(x, y, z-1);
            if(value > 0)
                setData((&pos, x-n, y-n, z-n
                         x+n, y-n, z-n,
                         x+n, y+n, z-n,
                         x-n, y+n, z-n,
                         &normal, 0, 0, 1,
                         &s, 1, 0, 0,
                         &t, 0, 1, 0,
                         &UV, value,
                         &light, cellGather,
                         &outOcc, cell->backCell);

            value = get(x, y, z+1);
            if(value > 0)
                setData(&pos, x-n, y-n, z+n,
                         x-n, y+n, z+n,
                         x+n, y+n, z+n,
                         x+n, y-n, x+n,
                         &normal, 0, 0, -1,
                         &s, 0, 1, 0,
                         &t, 1, 0, 0,
                         &UV, value,
                         &light, cellGather,
                         &outOcc, cell->frontCell);
        }
    endfor
}

bool neighbors(int size, byte* data, int x, int y, int z)
{
    if(get(x-1, y, z)){return true;}
    if(get(x+1, y, z)){return true;}
    if(get(x, y-1, z)){return true;}
    if(get(x, y+1, z)){return true;}
    if(get(x, y, z-1)){return true;}
    if(get(x, y, z+1)){return true;}
    return false;
}

据我所知,你可能会注意到这段代码与用 C 和 python 编写的某个演示非常相似,这是因为很多代码是在阅读后编写的,对我来说有点影响

问题是它似乎没有涵盖我的问题,它让我对体素的工作方式有了更好的理解,就是这样。

那么,关于我应该如何解决我的这个项目的任何指示?

PS,这和战地 3 是 DOOM 克隆一样多是我的世界克隆,我想我会让你决定如何解释。

哦,我已经完成了我的研究,我发现:关于 0fps 的帖子,我相信你们中的大多数人都熟悉博客 https://sites.google.com/site/letsmakeavoxelengine 和其他一些,包括 GPU gems 3,行进立方体和其他一些东西,没有一个能解决我的问题。

4

1 回答 1

0

我不确定我是否从您的问题中得到了正确的答案,但是:

  • 您想基于区域而不是完整地图来实现体素世界
  • 我在您的代码中没有看到任何地图(但可以忽略它)

我会这样做(在伪代码中):

class cell
 {
public:
 // physical properties
 float m,Q; // unit mass ,charge, ... 
 float c0,c1,c2; // friction indexes (could determine if it is liquid,gas or solid
 float p[3],v[3],a[3]; // position,velocity,acceleration 3D
 };

class object // or region
 {
public:
 int x0,y0,z0; // obj origin (center preferably)
 int xs,ys,zs; // obj size in cells
 cell *map;     // *map[xs*ys*za] or ***map[xs][ys][zs] do not forget to write dynamic allocation/free resize ...
 };

List<object> world; // list of all objects/regions
  • 您必须添加您需要或不需要的删除属性
  • 编写函数:
    • 解析世界
    • 加入区域分割
    • 更新位置(动态)
    • 碰撞、过热、爆炸等事件...

如果您的对象是,您还可以节省大量内存:

1.同质

// instead of cell *map;
cell properties; // single property class for whole object
bool *map;         // just a bit map if voxel is empty or occupied by cell

2.稀疏人口

// instead of int xs,ys,zs;
// instead of cell *map;
List<cell> map; 
List<int[3]> pos; // position inside object

3.或者你可以有 3 种对象类类型来组合这些方法

  • 为每个对象使用最适合的类
  • 并拥有 3 张独立的世界地图(每个类别对应)

此外,如果您的单元格属性是恒定的,那么您可以创建一个元素表(单元格)

  • 并记住每个体素的元素 ID 而不是单元格

希望它至少有一点帮助。

于 2014-02-14T07:46:54.507 回答