WebGL2.0从入门到精通-2、数据结构与算法(五、通用树的封装之理论篇)

五、通用树的封装

2、理论

对于游戏开发或计算机图形编程来说,树数据结构可能是应用最广泛的数据结构之一。可以使用树结构来表示场景图渲染系统、角色动画中的骨骼系统、具有层次性的空间分割系统或者是层次包围体系统等。

树是一类非线性数据结构。树的相关概念:

  • 节点: 每个元素称为节点
  • 树根:根节点
  • 度:一个节点含有的子节点的个数称为该节点的度
  • 叶子节点:度为 0 的节点
1、二叉树

在这里插入图片描述

2、四叉树

在这里插入图片描述
在这里插入图片描述

四叉树索引的基本思想是将地理空间递归划分为不同层次的树结构。
它将已知范围的空间等分成四个相等的子空间,如此递归下去,直至树的层次达到一定深度或者满足某种要求后停止分割。

四叉树的结构在空间数据对象分布比较均匀时,具有比较高的空间数据插入和查询效率

3、八叉树

八叉树的结构和四叉树基本类似,其拥有8个节点(三维2元素数组),其构建方法与查询方法也大同小异。

在这里插入图片描述

4、松散四叉树/八叉树

四叉树/八叉树的一个问题是,物体有可能在边界处来回,从而导致物体总是在切换节点,从而不得不更新四叉树/八叉树。

而松散四叉树/八叉树正是解决这种边界问题的一种方式:
首先它定义一个节点有入口边界(inner boundary),出口边界(outerboundary)。
那么如何判定一个物体现在在哪个节点呢?

  1. 若物体还没添加进四叉树/八叉树,则检测现在位于哪个节点的入口边界内;
  2. 若物体先前已经存在于某个节点,则先检测现在是否越出该节点的出口边界,若越出再检测位于哪个节点的入口边界内。
  3. 一篇关于松散四叉树/八叉树的论文里,实验表明出口边界长度为入口边界2倍时可以表现得很好

在这里插入图片描述

这里不详细赘述,感兴趣可以深入了解。

5、层次包围盒树(Bounding Volume Hierarchy Based On Tree)

层次包围盒树(BVH树)是一棵多叉树,用来存储包围盒形状。
它的根节点代表一个最大的包围盒,其多个子节点则代表多个子包围盒。

常用的层次包围盒树有AABB层次包围盒树和球体树。

AABB包围盒树

下图为层次AABB包围盒树。把不同形状粗略用AABB形状围起来看作一个AABB形状(为了统一化形状),然后才建立层次AABB包围盒树。

在这里插入图片描述

在物理引擎里,由于物理模拟,大部分形状都是会动态更新的,例如位移/旋转都会改变形状。于是就又有一种支持动态更新的层次包围盒树,称之为动态层次包围盒树。

球体包围盒树

球体是最容易计算的一类包围盒,而且球体树构造速度可以很快,因此球体树可被用作粗略松散但快速的空间划分结构。

快速构造松散球体树的步骤(以三角形物体为例):

  1. 计算出包围所有三角边顶点的最小球体包围盒,作为根节点
  2. 以球心为坐标系原点,其坐标系X轴划分出在该X轴左右的三角形,并将这些分别放入左子节点、右子节点中
  3. 重复步骤1、2,最后得到一棵球体树

在步骤2中,还可以按X轴,Y轴,Z轴的顺序轮流划分,即第一次步骤2划分用X轴,第二次步骤2划分用Y轴…

在这里插入图片描述

BSP树 (Binary Space Partitioning Tree)

BSP tree是一棵二叉树,中文译名为二维空间分割树。

BSP tree在3D空间下其每个节点表示一个平面,其代表的平面将当前空间划分为前向和背向两个子空间,分别对应左儿子和右儿子。

2D空间下,BSP树每个节点则表示一条边,也可以将2D空间划分成前后两部分。

在这里插入图片描述

k-d树 (k-dimensional tree)

k-d树是一棵二叉树,其每个节点都代表一个 k维坐标点:

  • 树的每层都是对应一个划分维度(取决于你定义第i层是哪个维度)
  • 树的每个节点代表一个超平面,该超平面垂直于当前划分维度的坐标轴,并在该维度上将空间划分为两部分,一部分在其左子树,另一部分在其右子树

举例,一棵k-d树(k=2)的结构如图:

在这里插入图片描述

根据第一层划分维度为X,第二层为Y,第三层为X,
所以该k-d树(k=2)对应代表划分的空间,看起来应该是这样的:

在这里插入图片描述

6、总结
数据结构 适用情形 n的数量级 构造所需时间 是否可以动态更新 占用空间
四叉树 场景管理(基于地形或不含高度)、渲染 物体数量 O(n*logn) 大(取决于区域大小和物体数量)
八叉树 场景管理、渲染 物体数量 O(n*logn) 大(取决于区域大小和物体数量)
BVH树 任何情形(包括物理、渲染) 物体数量 O(n*logn) 中(取决于物体数量)
BSP树 编辑器、复杂室内场景 平面数量 O(n*log²n) 大(取决于平面数量)
k-d树 - 物体数量 O(knlogn) 中(取决于物体数量)
7、通用树的封装及遍历

这里代码封装的树支持二叉树、四叉树、八叉树等,是一种非严格的通用树结构。

同时支持 8 种遍历方式

树的遍历这里分为 3 类 共计 8 种:

广度优先(层次)、深度优先

从上到下(先根/前序) 或 从下到上 (后根/后序)

从左到右 或 从右到左

在这里插入图片描述

拿上面的树数据结构为例,采用八种遍历方式得到的遍历结果分别为:

在这里插入图片描述

项目代码版本对应地址

在这里插入图片描述

本章参考如下:

《TypeScript 图形渲染实战——基于WebGL的3D架构与实现》

空间数据结构(四叉树/八叉树/BVH树/BSP树/k-d树)

猜你喜欢

转载自blog.csdn.net/yinweimumu/article/details/128810145
今日推荐