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

发布于 2024-10-10 05:12:10 字数 1490 浏览 0 评论 0原文

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

通过最小值和最大值是立方体的对角,

。考虑到我必须检查的立方体数量,即使使用八叉树,我什至不确定这是正确的方法。

我也尝试过 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

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

I'm making a Minecraft clone as my very first OpenGL project and am stuck at the box selection part. What would be the best method to make a reliable box selection?

I've been going through some AABB algorithms, but none of them explain well enough what they exactly do (especially the super tweaked ones) and I don't want to use stuff I don't understand.

Since the world is composed of cubes I used octrees to remove some strain on ray cast calculations, basically the only thing I need is this function:

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

The ray and origin are easily obtained with

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 and max are the opposite corners of a cube.

I'm not even sure this is the right way to do this, considering the number of cubes I'd have to check, even with octrees.

I've also tried gluProject, it works, but is very unreliable and doesn't give me the selected face of the cube.


EDIT

So this is what I've done: calculate a position in space with the ray:

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;
}

It's actually surprisingly fast and stops after the first found cube.

alt text

As you can see the ray has to go trough multiple octrees before it finds a cube (actually a position in space) - there is a crosshair in the middle of the screen. The lower the increment step the more precise the selection, but also slower.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

以酷 2024-10-17 05:12:10

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

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

Working with boxes as primitives is overkill in memory requirements and processing power.
Cubes are fine for rendering and even there you can find more advanced algorithms that give you a better final image (Marching cubes). Minecraft's graphics are very primitive in this sense as voxel rendering has been around for a long time and significant progress has been made.

Basically you should exploit the fact that all your boxes are equally spaced and of the same size. These are called voxels.
Raycasting in a grid is trivial in comparison to what you have - a broad-phase oct-tree and a narrow phase AABB test. I suggest you research a bit on voxels and voxel set collision detection/raycasting as you will find both algorithms that are easier to implement and that would run faster.

无人问我粥可暖 2024-10-17 05:12:10

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

You don't need any explicit octree structure in memory. All that is needed is byte[,,]. Just generate 8 children of a box lazily during search (like a chess engine generates children game states).

记忆で 2024-10-17 05:12:10

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

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

但是使用八叉树和相机定位+相机距离/边界,你基本上就知道用户看到了什么必须求助于光线追踪来获取精确信息吗?如果您可以将三角形合并为更大的三角形以进行渲染,然后使用纹理将大三角形的可见性分解回立方体形式(稍微手工一下),则可以显着减少顶点数。然后,只需渲染出船体,并通过跟踪相机方向以及它位于 xyz 的位置,您就可以避免让一些不应该显示的面孔出现,因为这对性能的影响最小(尤其是如果你的着色器本身也做了一些工作)

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

I'd also argue you don't have to rely on actual raycasts to determine what to render. Given you are in a predefined grid formation you really aren't held hostage to "exact visible" requirements. If you can track your camera's position and allocate a NSWE compass of some sorts you can also use that to determine if the GPU buffer should even consider array of vertex's for rendering..

I cover this theory in detail here https://stackoverflow.com/a/18028366/94167

But using Octree and Camera positioning + camera distance/bounds you basically know what the user is seeing without having to resort to raytrace(s) for exacts? If you can consolidate your triangles into larger ones for rendering purposes and then use a texture to break the visibility of large back to a cubic form (slight of hand) you reduce your vertex count significantly. Then its a matter of just rendering out the hull and by keeping track of what your camera direction is and where it sits xyz you can get away with letting some faces that shouldn't be displayed in as it will have minimal impact on performance (especially if your shaders themselves also do some of the work)

I'm experimenting further by tracking the centre point of the camera to determine it's horizontal focal point and from that you can determine the angle which in turn determines the depth of the chunk you're likely to see in the direction it faces.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文