这是我过去几个小时一直在考虑的事情。这是一个头脑练习。
所以我今天知道了八叉树是什么!很有意思!我一直在考虑如何实现一个解析为体素的八叉树。
我现在无法解决的最大问题是引用八叉树中的位置。
免责声明:首先,我将在二维平面中使用四叉树来可视化我的问题。其次,我在这里不理解正确的术语,我将假设八叉树中作为父级的任何细分都是“分支”,而任何只有子级的细分(在这种情况下它解析为体素)是一片树叶”。第三,我要对四叉树的一个分支中的每个空间进行编号,从左到右从上到下 {1,2,3,4}
假设我有一个定义 16x16 单位空间的四叉树。在位置 [16,16] 我存储了一个体素。
4->4->4->4
现在假设我们将一个体素添加到位置 [4,4]。(注意,我们从零开始)
1->4->1->1
4->4->4->4
现在假设我想检查 [16,8] 以查看是否存储了体素。使用前面的方法,我们将在技术上遍历这些分支:
4->1->1->1
但是 4->1 没有分配任何数据,所以它是空的。(它没有细分,因为它没有在使用中)。
我的问题变成了这个,我怎样才能快速遍历四叉树找到体素?
我的第一个也是最简单的方法是以我上面使用的格式沿着分支向下移动。
// Pseudo-code
Class Quadtree {
Quadtree Parent;
Quadtree c[4]; // children
};
Quadtree test1;
test1.c[4].c[4].c[4].c[4];
Quadtree test2;
test2.c[1].c[4].c[1].c[1];
这里的问题是 voxelArray[16][16]、voxelArray[4][4] 或 voxelArray[16][8] 要快得多。使用更大的四叉树 (256x256) 会增加深度(从 4 到 8)。嵌套数组仍然是 2 个内存操作。(注意,对于四叉树,实际上我们将使用访问器的东西并检查以确保孩子存在条件逻辑)
我的第二个想法是将四叉树本身存储为体素。例如,假设我们有一个 2x2 数组,空它看起来像
{0, 0, 0, 0}
在位置 [1,1] 我们将添加一个体素,它会变成
{0, 0, 0, 1}
如果我们要存储四叉树,它看起来像这样
{1/*q*/, 0, 0, 0, 1}
把它带到一个 4x4 和
{0/*q*/, 0, 0, 0,
0/*q*/, 0, 0, 0,
0/*q*/, 0, 0, 0,
1/*q*/, 0, 0, 1}
尽管现在您可以直接访问数据,但您已经失去了四叉树的内存紧凑性,您仍然可以执行许多逻辑操作。IMO 仅当您有大面积的 0 和小范围的 1 时,这才会有效。
通过将体素存储在四叉树/八叉树中,您可以在循环遍历所有体素时获得性能,但在直接访问它们时会损失性能。