Minecraft克隆的最佳盒子选择方法

时间:2011-01-02 22:22:56

标签: c++ opengl picking

我正在制作一个Minecraft克隆作为我的第一个OpenGL项目,我被困在盒子选择部分。选择可靠的盒子的最佳方法是什么?

我一直在研究一些AABB算法,但是没有一个能够很好地解释它们到底做了什么(尤其是超级调整的算法),而且我不想使用我不理解的东西。

由于世界是由立方体组成的,我使用八叉树来消除光线投射计算的一些压力,基本上我唯一需要的是这个函数:

float cube_intersect(Vector ray, Vector origin, Vector min, Vector max)
{
    //???
}

使用

轻松获得光线和原点
Vector ray, origin, point_far;
double mx, my, mz;

gluUnProject(viewport[2]/2, viewport[3]/2, 1.0, (double*)modelview, (double*)projection, viewport, &mx, &my, &mz);
point_far = Vector(mx, my, mz);
gluUnProject(viewport[2]/2, viewport[3]/2, 0.0, (double*)modelview, (double*)projection, viewport, &mx, &my, &mz);
origin = Vector(mx, my, mz);
ray = point_far-origin;

min和max是立方体的对角。

我甚至不确定这是否是正确的方法,考虑到我必须检查的多维数据集的数量,即使是八叉树。

我也试过gluProject,它有效,但非常不可靠,并没有给我选中的立方体。


修改

所以这就是我所做的:用光线计算空间位置:

float t = 0;
for(int i=0; i<10; i++)
{
    Vector p = ray*t+origin;
    while(visible octree)
    {
        if(p inside octree)
        {
            // then call recursive function until a cube is found
            break;
        }
        octree = octree->next;
    }
    if(found a cube)
    {
        break;
    }
    t += .5;
}

它实际上非常快,并在第一个找到的立方体后停止。

alt text

正如您所看到的,在找到一个立方体(实际上是空间中的位置)之前,光线必须经过多个八叉树 - 屏幕中间有一个十字准线。增量步长越低,选择越精确,但也越慢。

3 个答案:

答案 0 :(得分:5)

使用框作为基元对内存要求和处理能力来说过分。 立方体可以很好地渲染,甚至在那里你可以找到更高级的算法,为你提供更好的最终图像(Marching cubes)。从这个意义上讲,Minecraft的图形是非常原始的,因为体素渲染已经存在了很长时间并且已经取得了重大进展。

基本上你应该利用这样一个事实,即你所有的盒子都是等距的,大小相同。这些被称为体素。 与您所拥有的相比,网格中的光线投射是微不足道的 - 宽相位八叉树和窄相位AABB测试。我建议你研究一下体素和体素集碰撞检测/光线投射,因为你会发现两种算法都更容易实现并且运行速度更快。

答案 1 :(得分:0)

内存中不需要任何明确的八叉树结构。所需要的只是byte [,,]。在搜索过程中懒洋洋地生成8个盒子的孩子(就像国际象棋引擎生成儿童游戏状态一样)。

答案 2 :(得分:0)

我还认为你不必依赖实际的光线投射来确定要渲染的内容。鉴于您处于预定义的网格形式中,您实际上不会受到“确切可见”要求的制约。如果您可以跟踪摄像机的位置并分配某些类型的NSWE指南针,您也可以使用它来确定GPU缓冲区是否应该考虑渲染顶点数组。

我在这里详细介绍了这个理论https://stackoverflow.com/a/18028366/94167

但是使用八叉树和相机定位+相机距离/边界你基本上知道用户看到了什么而不必诉诸光线跟踪精确度?如果您可以将三角形合并为较大的三角形以进行渲染,然后使用纹理将大背面的可见性打破为立方体(轻微的手),则可以显着减少顶点数。然后它只是渲染船体并跟踪你的摄像机方向和xyz的位置,你可以放弃一些不应该显示的面,因为它对性能的影响很小(特别是如果你的着色器本身也做了一些工作)

我正在通过跟踪相机的中心点来进一步试验,以确定它的水平焦点,然后你可以确定角度,从而确定你可能在它面对的方向上看到的块的深度。