空间划分算法优化碰撞检测研究(网格划分、四叉树\八叉树、层次包围盒树BVH)Unity C#实现

这篇具有很好参考价值的文章主要介绍了空间划分算法优化碰撞检测研究(网格划分、四叉树\八叉树、层次包围盒树BVH)Unity C#实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

前言

一、Demo说明

二、暴力法

 三、网格划分

实测

分析

四、四叉树

四叉树的构建细节

 实测

五、松散四叉树

实测

八叉树

六、层次包围盒树(BVH)

包围盒

AABB树

AABB树构建细节

实测

总结

 


前言

碰撞检测是一个非常经典的问题。虽然现在我们都有物理引擎提供的便捷接口,很多时候不需要我们手动实现,但是了解其中的算法思想有助于拓展我们的思维。而且很多问题其实都可以转化为碰撞检测问题,如:视锥体裁剪、LOD(视野范围与显示对象的碰撞)、RTS游戏中单位自动攻击警戒范围内的敌方单位(警戒范围与敌方单位的碰撞)、光线追踪等。 本次分享的不是碰撞检测中的检测算法(分离轴、GJK等),而是用于过滤检测对象的空间划分算法。我将通过实现一个碰撞检测的小demo来介绍碰撞检测中如何使用空间划分做优化以及他们的实现原理。


一、Demo说明

在一个100*100的空间内,随机生成2000个1*1的小方块,小方块生成后会随机赋予一个初速度,小方块将沿速度方向匀速运动,碰到空间边界会反弹。小方块之间不会反弹。现在需要检查方块是否与其他方块发生了碰撞(相交),是的话将方块标记为红色,否则为白色。 每种方法的测试中都将列出以下数据做为对比:帧率(FPS)、维护空间数据结构耗时(rebuild time)、碰撞检测耗时(check time)、碰撞检测函数调用次数(intersectsCheckCount)。

空间划分算法优化碰撞检测研究(网格划分、四叉树\八叉树、层次包围盒树BVH)Unity C#实现

使用trigger

空间划分算法优化碰撞检测研究(网格划分、四叉树\八叉树、层次包围盒树BVH)Unity C#实现

使用Physics.OverlapBoxNonAlloc


二、暴力法

如果我们直接对所有的方块两两检测是否发生碰撞,那么算法的时间复杂度将是N平方。在测试中的2000个方块已经卡成PPT,不足1帧。

空间划分算法优化碰撞检测研究(网格划分、四叉树\八叉树、层次包围盒树BVH)Unity C#实现

暴力法效果图


 三、网格划分

可以发现在暴力法中做了太多多余的检查,如果能提前过滤掉一些明显不可能发生碰撞的方块就好了。 思路:将空间按网格分块,只对有可能发生碰撞的网格内的方块进行碰撞检测。具体做法就开启一个网格的数组,然后根据方块的坐标计算出应该属于哪些格子,最后只需要对每个格子内的方块进行碰撞检测即可。

实测

下面是将使用32*32的网格来划分空间,这里可以通过对方块的左下角和右上角坐标取模快速得到方块属于哪些网格。经过网格划分之后性能得到了大幅提升。

空间划分算法优化碰撞检测研究(网格划分、四叉树\八叉树、层次包围盒树BVH)Unity C#实现空间划分算法优化碰撞检测研究(网格划分、四叉树\八叉树、层次包围盒树BVH)Unity C#实现 

网格划分效果图

分析

网格划分在大部分时候都是简单又有效的。但是缺点也很明显,如果我们的空间再大点,方块分布也不是这么均匀的话。我们的网格大小就不好定了。网格太大的话碰撞检测的候选项就会增多,降低优化效果。网格太小的话就需要开辟更多的网格节点,而且可能很多节点都不会包含方块造成内存的浪费。下面是将空间扩大到1000*1000,方块初始位置设为左下角后的测试。

空间划分算法优化碰撞检测研究(网格划分、四叉树\八叉树、层次包围盒树BVH)Unity C#实现

按32*32的网格划分

空间划分算法优化碰撞检测研究(网格划分、四叉树\八叉树、层次包围盒树BVH)Unity C#实现

按128*128的网格划分

 为了保证网格划分的效果,在更大的空间里就必须使用更多的网格去划分空间。


四、四叉树

网格划分的缺点是空间划分太过死板,因此我们需要一个更灵活的空间划分方案。四叉树就其中之一,四叉树是一种类似二叉树的数据结构,树中的子节点数只能是4或0(叶子节点)。我们将用树中的每个节点对应到空间中的一片区域,并包含这个区域中的对象。

空间划分算法优化碰撞检测研究(网格划分、四叉树\八叉树、层次包围盒树BVH)Unity C#实现

从图中我们可以清晰的看到树节点到空间的对应关系。根节点代表整个空间的大小,然后将父节点的空间均等地划分为4份,并由4个子节点来表示,然后层层递归下去。

因为不可能无限制的划分下去,一般我们会设置两个阈值来控制一个节点是不是应该继续划分:最大对象数和最大划分层级。当一个节点代表的区域中包含的对象数超过最大对象数,且当前层级小于最大划分层级时,我们才对当前节点进行划分,并将当前节点包含的对象分配到子节点中去。这样就能将对象分布密集的区域划分的更细,实现灵活的空间划分。

利用四叉树将空间划分完毕后,我们就能根据树结构快速查询可能与检测区域发生碰撞的候选项了。具体做法就是从根节点开始检查当前节点代表的区域是否与待检测节点相交,是的话将当前节点包含的对象添加到候选项列表中,然后递归检测子节点即可。

四叉树的构建细节

上面提到的四叉树模型是个理想概念。实际问题中是不会有完美的点,对象都是有一定大小的,比如我们的方块。当方块与多个节点区域相交时怎么办?这里就有两种方案来处理这种情况。下面例子中最大对象数设置为2。

空间划分算法优化碰撞检测研究(网格划分、四叉树\八叉树、层次包围盒树BVH)Unity C#实现

例子

 方案一:只在四叉树的叶子节点包含对象。无法完美划分的对象将分配到每个相交的子区域中。

空间划分算法优化碰撞检测研究(网格划分、四叉树\八叉树、层次包围盒树BVH)Unity C#实现

使用方案一划分后的树结构

方案二:不只在叶子节点包含对象。无法完美划分的对象留在当前节点中。

 空间划分算法优化碰撞检测研究(网格划分、四叉树\八叉树、层次包围盒树BVH)Unity C#实现

使用方案二划分后的树结构

 实测

接下来分别使用两种方案测试一下看看实际表现如何。

空间划分算法优化碰撞检测研究(网格划分、四叉树\八叉树、层次包围盒树BVH)Unity C#实现

空间划分算法优化碰撞检测研究(网格划分、四叉树\八叉树、层次包围盒树BVH)Unity C#实现

方案一效果图

 空间划分算法优化碰撞检测研究(网格划分、四叉树\八叉树、层次包围盒树BVH)Unity C#实现

 空间划分算法优化碰撞检测研究(网格划分、四叉树\八叉树、层次包围盒树BVH)Unity C#实现

方案二效果图

两种方案帧数都不如网格划分,但是带来了更灵活的空间利用和更稳定的表现(针对之前的更大空间更不均匀的分布),后面会用之前网格最后的例子做对比,我们现在先来分析四叉树两种方案的优劣。四叉树在对象移动后需要重新调整树的结构,这里会产生的额外的开销。

方案一中由于一个对象会同时存在于多个节点中,每一个节点中的对象都要检测是否还在当前节点的区域内,所以在调整树结构的时候开销更大。

方案二中因为存在存在大量“压线”的不能继续往下划分的对象,导致在查询候选项的时候加入了很多明显不可能发生碰撞的对象。比如在之前四叉树中的构建细节中举的例子,当我们要查询方块1所在的区域可能发生碰撞的候选项时,我们会获取到[1,4,5,7],而按方案一只会获取到[1]。这一点也可以从实测中两种方案的碰撞检测函数的调用次数看出来。

下面我们实际对比一下两种方案获取到的候选项的差异。取左下角区域的候选项,将候选项标记为绿色。

空间划分算法优化碰撞检测研究(网格划分、四叉树\八叉树、层次包围盒树BVH)Unity C#实现

方案一左下角候选项

空间划分算法优化碰撞检测研究(网格划分、四叉树\八叉树、层次包围盒树BVH)Unity C#实现

方案二左下角候选项

 如果能将方块抽象成点就能避免方案二中的问题了,于是就有了松散四叉树。


五、松散四叉树

基于“使用更大的候选区域,检测结果总不会错”的事实。我们可以让四叉树节点实际包含的区域(下图b中的outer boundary)比它代表的区域(下图b中的inner boundary)略大一点。所以这里“松散”对应的是“紧凑”。如下图(c)我们的四叉树节点实际包含是的区域的会有部分重叠的。而实际区域大多少合适呢?综合考虑是边长扩大到原来的2倍泛用性最广,这种情况下只要判断对象的大小是否大于当前节点的子节点所代表的区域大小,如果的大于节点代表区域就留在当前节点。否则只需要判断对象的中心点属于哪个子节点即可分配到对应子节点中。

空间划分算法优化碰撞检测研究(网格划分、四叉树\八叉树、层次包围盒树BVH)Unity C#实现

松散四叉树 

如果设置合理的松散范围,我们就能通过对象的中心点来判断应该属于哪个区域了。在我们的例子中,因为最大的对象就是1*1的方块,所以我们将松散范围设为0.5可以带来最佳的优化效果。

在查询时对比的是松散后的区域,因为区域产生了重叠,所以候选项会根据设定的松散范围而增加。

实测

空间划分算法优化碰撞检测研究(网格划分、四叉树\八叉树、层次包围盒树BVH)Unity C#实现 空间划分算法优化碰撞检测研究(网格划分、四叉树\八叉树、层次包围盒树BVH)Unity C#实现

松散四叉树效果图

 性能已经十分接近网格划分了。

我们再看看四叉树在大空间中的表现,和网格划分中的一样将空间扩大到1000*1000并且方块初始化位置设置左下角。

空间划分算法优化碰撞检测研究(网格划分、四叉树\八叉树、层次包围盒树BVH)Unity C#实现

 在这种情况,可以更明显的体现出四叉树更稳定的帧率和空间利用率。

八叉树

如果是在3D环境中做空间划分,就是将立方体均等分为8个小立方体,对应的我们的节点变为8个,也就成了八叉树。

空间划分算法优化碰撞检测研究(网格划分、四叉树\八叉树、层次包围盒树BVH)Unity C#实现

空间划分算法优化碰撞检测研究(网格划分、四叉树\八叉树、层次包围盒树BVH)Unity C#实现

八叉树效果图


六、层次包围盒树(BVH)

前面介绍的两种方法都是对固定空间的一个划分,下面将介绍的层次包围盒树是一种不被空间所限制的划分方案。

包围盒

包围盒是一种求解离散点集最优包围空间的算法,基本思想是用体积稍大且特性简单的几何体(称为包围盒)来近似地代替复杂的几何对象。

常见的包围盒算法有AABB包围盒、包围球、方向包围盒OBB

空间划分算法优化碰撞检测研究(网格划分、四叉树\八叉树、层次包围盒树BVH)Unity C#实现

 几种包围盒示意图

AABB树

这里选用AABB包围盒实现层次包围盒树,因此也可以称为AABB树。AABB树是一棵二叉树。其中每个叶子节点都表示一个对象的包围盒,父节点表示为刚好能包住两个子节点的包围盒。

空间划分算法优化碰撞检测研究(网格划分、四叉树\八叉树、层次包围盒树BVH)Unity C#实现

 AABB树

查询的时候就是沿根节点开始遍历树,如果与当前节点的包围盒相交就递归检查子节点,否则跳出,遇到叶子几点就将叶子节点对应的对象加入候选项列表。

AABB树构建细节

每个对象都是一个节点,对象节点将从根节点开始插入。

插入的过程中,对于非叶子节点,就判断应该插入到哪个子节点下面,这里的做法是分别计算将对象节点插入两个子节点后引起子节点包围盒面积的变化值,然后取变化小的那个节点插入。这种做法能尽量避免出现父节点包围盒的区域过大导致查询时候选项增多。插入子节点的同时更新当前节点的包围盒大小。

对于叶子节点,生成一个能刚好包住当前叶子节点和插入节点的新节点,用新节点替换掉当前叶子节点的位置,然后将当前叶子节点和插入节点作为新节点的子节点。

下面看一个插入的例子:

空间划分算法优化碰撞检测研究(网格划分、四叉树\八叉树、层次包围盒树BVH)Unity C#实现 空间划分算法优化碰撞检测研究(网格划分、四叉树\八叉树、层次包围盒树BVH)Unity C#实现

空间划分算法优化碰撞检测研究(网格划分、四叉树\八叉树、层次包围盒树BVH)Unity C#实现空间划分算法优化碰撞检测研究(网格划分、四叉树\八叉树、层次包围盒树BVH)Unity C#实现

插入D后的节点变化

 插入D后根节点的绿色包围盒和黄色包围盒的跟着变大了。

实测

由于我们每个节点都代表一个包围盒,而且节点的数量与空间中对象的数量相关,所以2000个对象时包围盒已经看不清了,这里给个100个对象的包围盒效果图。

 空间划分算法优化碰撞检测研究(网格划分、四叉树\八叉树、层次包围盒树BVH)Unity C#实现

100个对象的层次包围盒效果图

下面是2000个对象的实测。

空间划分算法优化碰撞检测研究(网格划分、四叉树\八叉树、层次包围盒树BVH)Unity C#实现

空间划分算法优化碰撞检测研究(网格划分、四叉树\八叉树、层次包围盒树BVH)Unity C#实现

AABB树效果图

性能与网格划分相当,重建树结构的开销比较大,因为要对比面积变化,更新父节点包围盒等操作。因为每个方块都在频繁的移动,在我的测试中比起调整每一个方块在树中的位置,还不如全部重新构建整课树效果高。不过一直重建树肯定不是个好办法这里应该还有优化空间。

看看3D的效果。

空间划分算法优化碰撞检测研究(网格划分、四叉树\八叉树、层次包围盒树BVH)Unity C#实现

 AABB树3D效果图


总结

空间划分的数据结构还有KD树、R树、BSP树等。这些算法都没有绝对的优劣,都有各自的优缺点,实际应用中要根据情况选择合适的算法才能起到最大的优化效果。文章来源地址https://www.toymoban.com/news/detail-410143.html

到了这里,关于空间划分算法优化碰撞检测研究(网格划分、四叉树\八叉树、层次包围盒树BVH)Unity C#实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 几何算法:矩形碰撞和包含检测算法

    大家好,我是前端西瓜哥。今天来讲讲几何算法中,比较经典的算法:矩形碰撞和包含检测算法。 矩形碰撞检测是被广泛使用的算法。 比如在游戏中,为了优化图形碰撞判断效率(复杂不规则图形之间的碰撞算法很复杂),经常会使用到包围盒。 所谓包围盒子是一个矩形,

    2024年02月07日
    浏览(41)
  • 碰撞检测——GJK算法

    目录 碰撞检测——GJK算法 1.GJK算法的原理及思想 1.1 Minkowski Sum(明可夫斯基和) 1.2 Simplex 1.3 support函数 1.4 构建Simplex 2. GJK算法步骤 3. GJK算法的优缺点分析 4. GJK算法与其他相关算法的比较分析 4.1 GJK算法和SAT算法的比较 4.2 GJK算法和EPA算法的比较 参考资料 GJK算法是由 Gilber

    2024年02月11日
    浏览(44)
  • 碰撞检测算法详述

    算法的分类 目录 一、基于空间域的碰撞检测算法分类 1. 基于图像空间的碰撞算法 2.基于几何空间的碰撞检测算法 (1)基于空间剖分算法 (2)裁剪扫掠法 (3)基于距离场的算法 (4)基于层次包围盒的算法 ① 轴向包围盒 ② 球包围盒 ③ 方向包围盒 ④ 离散方向多面体 从

    2024年02月07日
    浏览(49)
  • 常见的2D与3D碰撞检测算法

    分离轴定理(Separating Axis Theorem)是用于解决2D或3D物体碰撞检测问题的一种方法。其基本思想是,如果两个物体未发生碰撞,那么可以找到一条分离轴(即一条直线或平面),两个物体在该轴上的投影不会重叠。 具体实现时,我们需要确定所有可能作为分离轴的候选轴,并将

    2023年04月11日
    浏览(43)
  • 碰撞检测算法——分离轴算法在Unity中实现(二)

    一、介绍        分离轴算法(简称SAT)通常用于检查两个简单多边形(凸边形)之间或多边形与圆之间的碰撞。本质上,如果您能够绘制一条线来分隔两个多边形,则它们不会发生碰撞,如果找不到一条线来分割两个多边形,则它们发生碰撞。 如图:           具体做法

    2024年02月04日
    浏览(69)
  • GJK算法,碰撞检测(自学笔记,侵权删)

    学哔哩哔哩《看似简单的复杂问题,奇怪而优雅的解决方式(GJK算法) | Reducible》——来自博主“我最会爬惹”笔记   一、凸形和凹形的基础概念 所有图形可以分成两种:凸形和凹形,如图1.1所示。 图1.1 凸形和凹形  凸形的性质是: 该形状上任意两点的连线,必然在这个

    2024年02月07日
    浏览(44)
  • 深入分析物理引擎后,他写了一个轻量的 Cocos 3D 碰撞检测优化方案

    引言: 碰撞检测是游戏开发中一个非常重要的技术点,优化碰撞检测性能,是提升游戏体验不可或缺的一环。开发者「我叫98K」写了一个轻量碰撞系统,用以改善 3D 游戏在不同平台遇到的碰撞性能问题和包体问题。下载和在线体验地址见文末。 98K物理-轻量碰撞系统是一个高

    2024年02月03日
    浏览(40)
  • 机器人C++库(10)Robotics Library 之碰撞检测算法

    RL库中集成了以下开源含碰撞检测功能的库: 1.bullet3:https://pybullet.org/wordpress/ 2.FCL:https://github.com/flexible-collision-library/fcl 3.ODE:http://www.ode.org/ 4.PQP:http://gamma.cs.unc.edu/SSV/

    2023年04月08日
    浏览(42)
  • 智能交通系统-yolov5+deepsort车辆跟踪、计数、测速、碰撞检测、违规驶入检测(算法-毕业设计)

    本项目效果展示视频:https://www.bilibili.com/video/BV1E3411G7cP/ 1、本项目通过yolov8/yolov7/yolov5 5.0和deepsort实现了一个多功能智能交通监控系统,可为一些同学的课设、大作业等提供参考。分别实现了不同车辆的跟踪,统计不同车型“上行”和“下行”的数量,实时检测车辆速度,检

    2023年04月09日
    浏览(51)
  • 空间数据结构(四叉树、八叉树、BVH树、BSP树、k-d树)

    在游戏程序中,利用空间数据结构加速计算往往是非常重要的优化思想,空间数据结构可以应用于场景管理、渲染、物理、游戏逻辑等方面。 2.1 四叉树 四叉树是很常见的一种 2D 碰撞检测方法,实现手段也五花八门。不过在具体实现中要注意优化细节,控制建树时间消耗与建

    2024年01月19日
    浏览(55)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包