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

这篇具有很好参考价值的文章主要介绍了空间数据结构(四叉树、八叉树、BVH树、BSP树、k-d树)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一. 前言

在游戏程序中,利用空间数据结构加速计算往往是非常重要的优化思想,空间数据结构可以应用于场景管理、渲染、物理、游戏逻辑等方面。

二、多叉树

空间数据结构(四叉树、八叉树、BVH树、BSP树、k-d树),游戏物理学,数据结构

2.1 四叉树

四叉树是很常见的一种 2D 碰撞检测方法,实现手段也五花八门。不过在具体实现中要注意优化细节,控制建树时间消耗与建树空间大小,特别是在 JS 语言环境下。但四叉树的射线检测、区域检测效率比较高,树更新很快,会产生物体多次划分,空间占用大。

空间数据结构(四叉树、八叉树、BVH树、BSP树、k-d树),游戏物理学,数据结构
四叉树的结构在空间数据对象分布比较均匀时,具有比较高的空间数据插入和查询效率(复杂度O(logN))。

//示例:一个四叉树节点的简单结构
struct QuadtreeNode {
  Data data;
  QuadtreeNode* children[2][2];
  int divide;  //表示这个区域的划分长度
};

//示例:找到x,y位置对应的四叉树节点
QuadTreeNode* findNode(int x,int y,QuadtreeNode * root){
  if(!root)return;

  QuadtreeNode* node = root;
  
  for(int i = 0; i < N && n; ++i){
  	//通过diliver来将x,y归纳为0或1的值,从而索引到对应的子节点。
  	int divide = node->divide;
    int divideX = x / divide;
    int divideY = y / divide;
    
    QuadtreeNode* temp = node->children[divideX][divideY];
    if(!temp){break;}
  	node = temp;
    
  	//如果归纳为1的值,还需要减去该划分长度,以便进一步划分
    x -= (divideX == 1 ? divide : 0);
  	y -= (divideY == 1 ? divide : 0);
  }
  
  return node;
}

2.2 八叉树
空间数据结构(四叉树、八叉树、BVH树、BSP树、k-d树),游戏物理学,数据结构

八叉树虽然包围精确性没 BVH 高(可用状态压缩改善)、占用空间较大(过度划分),但是建树和增删非常快,很适合用作物体的筛选。目前 98K 使用了八叉树对模型包围盒进行空间划分,简单高效的建树比精确计算建树(比如 BVH 建树会有大量计算消耗)更加划算。缺点和四叉树一样,射线检测、区域检测较快,树更新很快, 会产生物体多次划分,空间占用大。

2.3 应用

相比网格,四叉树/八叉树主要是多了层次,它们可以进行区域较大的划分,然后可以对各种检测算法进行分区域的剪枝/过滤。
下面提几个应用(实际应用面很广):

  • 场景管理
    特别适合大规模的广阔室外场景管理。一般来说如果游戏场景是基于地形的(甚至没有高度)(如城市、平原、2D场景),那么适合用四叉树来管理。而如果游戏场景在高度轴上也有大量物体需要管理(如太空、高山),那么适合用八叉树来管理。
  • 碰撞检测
    类似上面感知检测。不同划分区域保证不会碰撞的情况下,就能快速过滤与本物体不同区域的其他潜在物体碰撞。
  • 光线追踪(Ray Tracing)过滤
    光线追踪渲染,可使用八叉树来划分3D空间区域,从而过滤掉大量不必要的区域。

三、二叉树

空间数据结构(四叉树、八叉树、BVH树、BSP树、k-d树),游戏物理学,数据结构
3.1 BVH树

四叉树和八叉树是以平均空间来划分物体,划分算法简单,而 BVH 是对当前物体集合进行空间的划分,追求左右空间大小相对均衡且无相交。BVH 构建的一般是二叉树,划分算法复杂。

主流物理引擎都有采用 BVH(层次包围盒树 (Bounding Volume Hierarchy Based On Tree)),因为其功能支持完备、查找精确性高、性能不俗。但是其在建树和增删改时要维护平衡树,消耗很大。针对这个问题,有一些时序性的空间优化方法,通过减少增删改达到优化目的,感兴趣的朋友可以参考各大物理引擎中的实现方法。

空间数据结构(四叉树、八叉树、BVH树、BSP树、k-d树),游戏物理学,数据结构
3.2 BSP树

BSP(Binary Space Partitioning Tree),二维空间分割树,非常经典,1993年在知名游戏 DOOM 里第一次被应用,早期 CS 也是用 BSP 来做地形碰撞。BSP 通常通过计算得到一个合理的任意角度片面或者法线,然后对空间进行划分。标准的 BSP 虽然高效,但树构建非常消耗时间,通常都是编辑器预处理,比较适合静态模型或者静态场景使用。

空间数据结构(四叉树、八叉树、BVH树、BSP树、k-d树),游戏物理学,数据结构

3D空间下要构造一棵较平衡的BSP树,则需要尽可能每次划分出一个节点时,让其左子树节点数和右子树节点数相差不多:

  • 在一个平面形状集合里,用其中一个平面构造一个BSP树节点时,需满足它前方的平面形状数和后方的平面形状数之差 小于
    一定阈值;若超过阈值则尝试用下一个形状来构造。
  • 一个麻烦的问题是当2个平面形状是相交时,即出现平面形状既可以在前方也可以在后方的情况。这时候就需要一个将该形状切割成两个子形状,从而可以一个添加在前方,一个添加在后方,避免冲突。
  • 构造完一个节点则移除对应的平面,该节点前面的平面形状和后面的平面形状则作为两个子平面形状集合。
  • 对这两个子集合以重复步骤1、2继续构造出两个子节点,并作为本节点的左右儿子。
  • 最后所有平面形状都被用于构造节点,组成了一棵BSP树。
//BSP tree节点结构示例
class BSPTreeNode {
	Plane plane;				  //平面
	BSPTreeNode* front;           //前向的节点
	BSPTreeNode* back;            //后向的节点
	//Data data;                  //数据
};

由于需要进行N次划分,每次划分后,要在子集合里一个个挑选合适的平面(需要logN次遍历),为了评定合适又需要与子集合里所有其它形状比较前后位置(需要logN次比较),因此可以知道BSP树构造的平均时间复杂度为 O(Nlog²N)

判断点在平面前后的算法:平面的法向量(A,B,C),则平面的方程为:Ax + By + Cz + D = 0;
将点(x0,y0,z0)代入方程得到 distance = Ax0 + By0 + Cz0 + D;
若 distance < 0 则在平面背后
若 distance = 0 则在平面中
若 distance > 0 则在平面前方

3.3 k-d树

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

树的每层都是对应一个划分维度(取决于你定义第i层是哪个维度)
树的每个节点代表一个超平面,该超平面垂直于当前划分维度的坐标轴,并在该维度上将空间划分为两部分,一部分在其左子树,另一部分在其右子树
实际上,k-d树就是一种特殊形式的BSP树(轴对齐的BSP树)。

//一种实现方式示例:二维k-d树节点
class KdTreeNode{
  Vector2 position;         //位置
  int dimension;            //当前所属层的维度
  KdTreeNode* children[2];  //两个子树
  //Data data;              //数据
};

k-d 树是一种特殊的 BSP 树,它基于动态计算的三个轴进行划分。k-d 树相比 BSP 可能精确性没那么高,但是建树时间大大减少,因为对轴划分算法简单,所以很适合使用

举例,一棵k-d树(k=2)的结构如图:
空间数据结构(四叉树、八叉树、BVH树、BSP树、k-d树),游戏物理学,数据结构

根据第一层划分维度为X,第二层为Y,第三层为X,
所以该k-d树(k=2)对应代表划分的空间,看起来应该是这样的:
空间数据结构(四叉树、八叉树、BVH树、BSP树、k-d树),游戏物理学,数据结构文章来源地址https://www.toymoban.com/news/detail-805231.html

到了这里,关于空间数据结构(四叉树、八叉树、BVH树、BSP树、k-d树)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【数据结构与算法】图像——四叉树自适应模糊(ppm图像为例)

    源于大作业~~ 目录 前言 一、实现算法 二、结果展示  三、算法框架  (1) QuadTreeNode.h (2) 结点扩展、细化模糊层次  (3) 模糊化图像四叉树转为图像 (4) 主函数代码 四、说明 五、结语 六、震惊一百年  七、开源代码——but拒绝抄袭从你我做起 ----------------------------------QuadTre

    2024年02月06日
    浏览(92)
  • C#几何算法:空间索引——Quadtree四叉树及应用(一)

    目录 前言 什么是四叉树? 四叉树的原理 结语         最近在CAD中开发拓扑检查和空间分析功能时发现,传统的双层递归法会极大的降低程序运行速度,就比如:图上有1000个图形,我们要求图形之间的交点,传统的作法就是遍历两次图形,在两次循环中分别对图形求交处

    2024年02月06日
    浏览(54)
  • 【PCL自学:ocTree】八叉树(octree)的原理及应用案例(点云压缩,搜索,空间变化)

      上世纪80年代,八叉树结构被提出来,用来表示空间中的区域划分,简单来说,空间可以被分为8个象限,想象一下假设空间中存在一个笛卡尔坐标系,则该坐标系将空间分为了8个象限,每个象限又可以按照这种方式再建立一个笛卡尔坐标系,再划分为8个象限,以此类推

    2024年02月04日
    浏览(44)
  • 【数据结构-二叉树】二叉树

    💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学习,不断总结,共同进步,活到老学到老 导航 檀越剑指大厂系列:全面总

    2024年02月07日
    浏览(48)
  • 【数据结构】二叉树——链式结构

    目录  一、前置声明 二、二叉树的遍历 2.1 前序、中序以及后序遍历 2.2 层序遍历 三、节点个数以及高度 3.1 节点个数 3.2 叶子节点个数 3.3 第k层节点个数 3.4 二叉树的高度/深度 3.5 查找值为x的节点 四、二叉树的创建和销毁 4.1 构建二叉树 4.2 二叉树销毁 4.3 判断二叉树

    2024年02月16日
    浏览(47)
  • 【数据结构】二叉树——顺序结构

    由于每个节点都 只有一个父节点 ,所以我们可通过双亲来表示一棵树。具体方式通过 数组的形式 实现。 根节点的下标为0 按照层序从上到下排序 每层从左向右递增 表示形式: 二维数组 数据的列标为0 ,只需确定行标,即可锁定位置 根节点的父节点下标为 -1 列标为1存父节

    2024年02月02日
    浏览(56)
  • 【数据结构】二叉树链式结构

    🚀write in front🚀 📜所属专栏:初阶数据结构 🛰️博客主页:睿睿的博客主页 🛰️代码仓库:🎉VS2022_C语言仓库 🎡您的点赞、关注、收藏、评论,是对我最大的激励和支持!!! 关注我,关注我,关注我 , 你们将会看到更多的优质内容!!   在之前的二叉树的顺序结

    2024年02月03日
    浏览(41)
  • 【数据结构和算法】--- 二叉树(3)--二叉树链式结构的实现(1)

    在学习二叉树的基本操作前,需先要创建一棵二叉树,然后才能学习其相关的基本操作。由于现在大家对二叉树结构掌握还不够深入,且为了方便后面的介绍,此处手动快速创建一棵简单的二叉树,快速进入二叉树操作学习,等二叉树结构了解的差不多时,我们反过头再来研

    2024年01月25日
    浏览(63)
  • 【数据结构】二叉树之链式结构

    🔥 博客主页 : 小羊失眠啦. 🎥 系列专栏 : 《C语言》 《数据结构》 《Linux》 《Cpolar》 ❤️ 感谢大家点赞👍收藏⭐评论✍️ 在学习二叉树各种各样的操作前,我们先来回顾一下二叉树的概念: 二叉树是度不超过2的树,由根结点和左右2个子树组成,每个子树也可以看作

    2024年02月04日
    浏览(45)
  • 数据结构——二叉树的链式结构

      个人主页 : 日刷百题 系列专栏 : 〖C语言小游戏〗〖Linux〗〖数据结构〗  〖C语言〗 🌎 欢迎各位 → 点赞 👍+ 收藏 ⭐️+ 留言 📝  ​ 这里我们使用先序遍历的思想来创建二叉树,这里的内容对于刚接触二叉树的朋友可能有些难理解,不妨先看完下面的二叉树各种遍历

    2024年02月05日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包