6

我正在制作一个 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;
}

它实际上速度惊人,并在第一个找到的立方体后停止。

替代文字

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

4

3 回答 3

5

使用盒子作为原语在内存需求和处理能力方面是多余的。立方体非常适合渲染,即使在那里,您也可以找到更高级的算法,为您提供更好的最终图像(行进立方体)。Minecraft 的图形在这个意义上是非常原始的,因为体素渲染已经存在了很长时间并且已经取得了重大进展。

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

于 2011-01-03T00:12:16.237 回答
0

您不需要内存中的任何显式八叉树结构。所需要的只是字节[,,]。只需在搜索期间懒惰地生成一个盒子的 8 个孩子(就像国际象棋引擎生成孩子游戏状态)。

于 2011-01-22T02:41:00.417 回答
0

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

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

但是使用八叉树和相机定位 + 相机距离/边界,您基本上知道用户正在看到什么,而不必求助于光线跟踪来精确?如果您可以将三角形合并为更大的三角形以进行渲染,然后使用纹理将大的可见性破坏为立方体形式(轻微手感),则可以显着减少顶点数。然后它只是渲染船体的问题,并通过跟踪你的相机方向是什么以及它位于 xyz 的位置,你可以避免让一些不应该显示的面孔,因为它对性能的影响最小(尤其是如果你的着色器自己也做一些工作)

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

于 2013-08-03T02:01:51.587 回答