C++ 如何为块世界使用四叉树/oct树

C++ 如何为块世界使用四叉树/oct树,c++,octree,C++,Octree,过去几天我一直在摆弄八叉树和四叉树。我可以构建它们,迭代它们,并吐出我需要的信息。我还知道,它们在碰撞检测中非常有用,你可以将屏幕细分为更小的部分,以便能够在特定的部分检测屏幕上的运动,而不是一直浏览整个屏幕。然而,我无法理解如何使用八叉树或四叉树来生成立方体类型的世界 以下是我一直在思考的一些想法: 1) 使用四元/oct树细分一组立方体(10x10),并细分它,直到至少有一片叶子是均匀的;然后删除所有其他不一致的叶子,从而获得不同大小的立方体 2) 在空间(x、y、z)中细分一个点,直到得到

过去几天我一直在摆弄八叉树和四叉树。我可以构建它们,迭代它们,并吐出我需要的信息。我还知道,它们在碰撞检测中非常有用,你可以将屏幕细分为更小的部分,以便能够在特定的部分检测屏幕上的运动,而不是一直浏览整个屏幕。然而,我无法理解如何使用八叉树或四叉树来生成立方体类型的世界

以下是我一直在思考的一些想法:

1) 使用四元/oct树细分一组立方体(10x10),并细分它,直到至少有一片叶子是均匀的;然后删除所有其他不一致的叶子,从而获得不同大小的立方体

2) 在空间(x、y、z)中细分一个点,直到得到一个立方体,其中至少有一个叶大小相同,或达到节点的深度,然后使用所有这些位置(x、y、z)作为不同类型块的位置


有人能解释一下在构建这样一个3D环境时使用八叉树或四叉树背后的逻辑吗?它是基于x,y,z还是基于一个恒定的立方体测量?我很不确定如何继续。四叉树是二维的,所以用它们来表示三维空间是没有意义的


使用八叉树有多种方法。如果使用固定数量的恒定大小和相等大小的多维数据集,那么实现肯定会更简单。然而,这几乎不一定是最有效的实现,四元/八叉树都是关于效率的。

八叉树确实可以帮助您将多维数据集的数据块分成相等的部分。它们的诀窍是,当你不断地将立方体送入八叉树分支时,你会自动地将它们细分为片段,然后你可以在接近的基础上提取这些片段(即Chunk01(128,0,0)Chunk02(256,0,0)等)

当您将立方体存储到八叉树中时,您还可以定义它们的“类型”(材质或描述它们的某种枚举)。通过这样做,您还可以让八叉树将这些立方体分组在一起,如果它们成为邻居(即草、石头、沙子等)。这样,八叉树算法就可以为您处理一些关于如何将它们折叠/压缩成1x大的正方形/矩形原语的智能,从而减少立方体数量

在一天结束时,你有两种方法来处理立方体世界,第一种方法是你希望最终用户相信你一次制作了1个立方体,但实际上你正在合并网格/顶点计数,以产生错觉,因为一块曲面实际上只是1个大网格,而不是100个立方体。只有当用户与立方体交互(即删除/添加)时,您才重新计算网格,并将多个立方体的幻觉变为现实。但随后您立即将其交换回一个巨大的合并网格

一旦运行了八叉树并将块合并为单个网格形式(通过将顶点数组输入GPU缓冲区),那么还必须在八叉树之外执行一些关于剔除的额外工作。有很多方法可以做到这一点,体积剔除(光线跟踪)是我最推荐的方法,但我认为这可以做得更好

在我这里的例子中:我基本上是以不同的方式处理的,因为我知道摄像机中心点在哪里,并且我也跟踪摄像机面对的方向,然后我基本上将其用作近距离聚焦的剔除,如果有问题的块在摄像机后面,我会销毁它们,从而减少我的GPU负载


您还将注意到,每个“块”的表面在外部仍然可见,因为我从创建的块中剔除了每个块的内部,但鉴于每个块都在处理自己的工作负载,我仍然渲染摄影机下方的实际块“墙”。。。我后来还通过跟踪用户的Z深度和相机边界来修复这个问题

八叉树的大小和深度与叶节点的大小大致相同,它们是可逆的。一个大小为(x,y,z)的八叉树有10个分裂,其叶子大小为(x,y,z)/2^10。四叉树大多是二维的,它们可以是“2.5D”(同时存储高度)。我真的很想用一棵六角树,但很难把你的头绕在第四个维度上。你不能再想象它了,但它仍然有数学意义。