空间数据结构我这个是项目中用来解决一些问题,包括在引擎中的场景管理!做了一个ppt来演讲,所以地下有的直接就用ppt的内容或者截图~
二维下使用四叉树、Kd-tree等等在三维下使用八叉树、bvh-tree、BSP-tree
BVH-tree在动态场景下使用(游戏使用的最多);Oc-tree八叉树是对于室外大场景来说的;BSP-tree是对于室内场景;
用途:场景管理、碰撞检测、LOD、光线追踪、 视椎体面剔除、几何加速;
KD-tree(以光追为例)
其每次将空间划分为两部分,且划分依次沿着x-axis,y-axis,z-axis,即如图中所示,第一次横着将2维空间分为上下,第二次再竖着将上下两个子空间分别划分为左右部分,依次递归划分,终止条件与八叉树类似,但是是以空间划分为依据;
循环以下步骤:
1 依次沿着x-axis,y-axis,z-axis划分,使得空间被划分的更加平衡
2 划分的位置由空间中三角面的分布决定,具体细节不展开
3 叶子节点存储对应空间的所有物体或三角面信息,中间节点仅存储指针指向两个子空间
4 当划分空间太小或是子空间内只有少量三角形则停止划分
区别:直接对空间进行划分,都是二分空间!比如先左右划分当前场景,再对子场景进行上下的划分
优点:
利用KD-Tree的结构来构建AABB的好处是倘若光线与哪一部分空间不相交,那么则可以省略该部分空间所有子空间的判断过程,在原始的纯粹的AABB之上更进一步提升了加速效率。
缺点:
缺点是判断包围盒与三角面的是否相交较难,因此划分的过程不是那么想象的简单,其次同一个三角面可能被不同的包围盒同时占有,这两个不同包围盒内的叶节点会同时存储这一个三角形面
近十年来 用的比较少;
层次包围盒树 (Bounding Volume Hierarchy Based On Tree)
不再以空间作为划分依据,而是从对象的角度考虑,即三角形面(主要是应用于动态场景)
层次包围盒树(BVH树)是一棵多叉树,用来存储包围盒形状。它的根节点代表一个最大的包围盒,其多个子节点则代表多个子包围盒。此外为了统一化层次包围盒树的形状,它只能存储同一种包围盒形状。 算法核心大概:形状的位移/旋转/伸缩更新对应的叶节点,然后一级一级更新上面的节点,使它们的包围体包住子节点, 构造时间复杂度只有O(NlogN)。
区别:利用了Bounding box(AABB)从物体来开始划分
**优点:**现代用的最多
1、每次划分一般选择最长的那一轴划分,假设是x轴,那么划分点选择所有三角面的重心坐标在x坐标上的中位数进行划分,如此便能保证划分的三角形左右两边三角形数量尽可能差不多,当然也就使得树形结构建立的更加平衡,深度更小,平均搜索次数更少,提高了效率,这些都是数据结构的知识,相信大家掌握的都不错,就不多赘述了。
2、与KD-Tree一样,中间节点不存储物体三角面信息,只在叶节点中存储,终止条件可设定为当前包围盒内三角形数量足够少 (e.g. 5个)
四叉树与八叉树:
二维使用四叉树、
三维是使用的八叉树(室外大场景)为了防止满树,优化需要线性八叉树(tree本质上就是数组)
递归分割立方体
- F: 子立方体被场景内容填充满内容标记为F(full)该子立方体不再被分割;
- E:子立方体没有场景内容标记为E(empty)该子立方体不再被分割;
- 叶子节点是F或E;(缺点)
松散四叉树/八叉树:减少边界问题
解决四叉树/八叉树一个问题,物体有可能在边界处来回(即在A象限也在B象限),从而导致物体总是在切换节点,从而不得不断更新四叉树/八叉树。除此之外较小的物体可能因为其特殊位置被存储到一个具有非常大的包围盒体积的八叉树节点中。
在《Game Programming
Gems》中该问题被描述为层次划分过程中产生的“粘性(Sticky)”区域,较小的物体却保持在树的较高层次,降低了划分的效率
而松散四叉树/八叉树正是解决这种边界问题的一种方式:
- 首先它定义一个节点有入口边界(inner boundary),出口边界(outerboundary)。
- 判定一个物体现在在哪个节点
- 若物体还没添加进四叉树/八叉树,则检测现在位于哪个节点的入口边界内;
- 若物体先前已经存在于某个节点,则先检测现在是否越出该节点的出口边界,若越出再检测位于哪个节点的入口边界内。
在非松散的四叉树/八叉树中,入口边界和出口边界是一样的。而松散四叉树/八叉树的松散,是指出口边界比入口边界要稍微宽些(各节点的出口边界也会发生部分重叠,松散比较符合这种描述),从而使节点不容易越过出口边界,减少了物体切换节点的次数。
随之而来一个问题就是,如何定义出口边界的长度。因为太短会退化成正常四叉树/八叉树,太长又可能会导致节点存储冗余的物体。而在一篇关于松散四叉树/八叉树的论文里,实验表明出口边界长度为入口边界2倍时可以表现得很好。
线性八叉树:
BSP树(Binary Space Partitioning Tree):二叉空间分割
在游戏工业算是老功臣了,第一次被应用用是在1993年的商业游戏《DOOM》上,可是随时渲染硬件的进步,基于BSP树的渲染慢慢淘汰。但是即使在今天,BSP仍是在其他分支(引擎编辑器)不可或缺的一个重要数据结构。
(用在室内场景)用空间超平面,递归的将空间分割为凸多面体,用二叉树表示被分割的的空间(AVL树),场景中的平面都有前平面与后平面(平面法向量的为前平面)