创建一个体素系统并陷入困境,发现自己需要有关如何实现它的信息

时间:2013-08-29 07:19:28

标签: c++ algorithm voxel interval-tree

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

我遇到的问题:

  1. 弄清楚如何使用libnoise生成3D perlin噪音,文档没有触及我可以告诉的这个主题,我从谷歌得到的结果并不好。
  2. 以某种方式将块放在整数网格中
  3. 确切地确定如何确定从网格中的位置推断出块的稳固程度(我认为这很简单,因为检查周围的块是什么以及网格中的位置并根据它确定它那个数据)
  4. 根据从整数网格推断出的位置稀疏地分散各种矿石,这个很容易,但是在其他矿石解决之前无法完成。
  5. 计算间隔树。
  6. 那么,有什么想法吗? 到目前为止相关的代码(删除了光线,遮挡,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编写的某个演示,这是因为很多代码都是在读完之后编写的,并且有点被擦掉了关闭我

    问题在于它似乎没有解决我的问题,它让我对体素如何运作有了更好的理解,但就是这样。

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

    P.S,这是一个Minecraft克隆,因为Battlefield 3是一个DOOM克隆,我想我会让你决定如何解释它。

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

1 个答案:

答案 0 :(得分:0)

我不确定我是否从你的问题中做到了,但是:

  • 您希望基于非完整地图而不是区域来实现Voxel世界
  • 我的代码中没有看到任何地图(但可能会忽略它)

我会这样做(伪代码):

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.homogenous

// 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.sparse populated

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

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

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

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

  • 并且只记住每个Voxel
  • 的元素ID而不是单元格

希望它至少有一点帮助。