Author:
bugall
Wechat:bugallF
Email:769088641@qq.com
Github: https://github.com/bugallgit
碰撞检测是游戏开发中经常使用到的基础功能,一般的物理引擎中都会包含碰撞引擎.咱们今天主要介绍
的就是Dynamic AABB Tree的实现原理,AABB Tree是个二叉树,从名字上看,像是个动态平衡树的变种。
确实在构造AABB树的时候是须要balance逻辑的。可是AABB的平衡不是基于数的深度的而是"面积",后面
会详细介绍。github
为了方便介绍,后文里的将用ABT来表明AABB Tree算法
这个游戏想必你们都玩过,这里面就牵扯到一个碰撞检测的问题,须要实时检测用户控制的小车是否spa
碰到了障碍物,最简单的方法就是枚举每个障碍物,判断障碍物是否跟用户控制的小车有交集。code
当障碍物少的时候,好比障碍物有100~10000个的时候枚举是能够解决的,可是在一些加有物理引对象
擎的场景里,枚举就显然行不通了,由于须要判断每个物体是否被其它n-1个物体碰撞。若是咱们仍是用排序
枚举的形式来作碰撞检测那么时间复杂度就是n!,若是有100个物体,那么作一次检测的时间复杂度就已经递归
难以接受。游戏
在枚举算法作碰撞检测的时候有存在一个很大的问题,那就是若是两个物体距离很远,远到它们不可能
接触,可是检测中仍是会枚举这对组合。图片
ABT是基于二叉树实现的,这时候咱们能大概感受到,它的时间复杂度将会从枚举的n*n变成nlog(n)
接下来咱们看下具体原理
为何预处理?咱们看下面的两个图。若是咱们须要对这两张图片作碰撞检测,该如何处理?
咱们能够基于像素的对比,判断青蛙的像素坐标有没有出如今钥匙的像素坐标里,若是有重叠的部分
那说明,两个物体碰撞里,可是仔细想一下这并非很好的办法,假如咱们两个照片都是600*600像素,那么
单单这两个物体的碰撞检测的时间复杂度就是600^4。
很显然不能这么作,我么接下来对图片进行"描边"。咱们就会获得两个矩形。那么接下来就好处理了。
假设上图中的A,B,C是咱们要作碰撞检测的物体,外面的蓝色框体就是咱们对物体描边之后得到的矩形
接下来就是构建树的过程,上面说过ABT树中的每个节点是AABB Tree结构。咱们从左至右建树,就像构建
二叉排序树同样。
step-1: 把A加入到树结构中,做为根节点 step-2: 把B加入到数结构中,这时须要和根节点作比较,判断根节点的区域是否跟B有交集,若是有的话 就判断子节点是否跟B有交集,若是都没有就判断B分别加入子节点区域后的面积,找到面节差最 小的,组合。若是B与根节点没有交集,就把A和B看成一个总体从新构建轮廓(橘黄色的矩形),并 生成A,B的父节点(上图中橘黄色的圆圈), step-3: 把C加入到树中,判断是否有交集,方法与step-2中同样,最终获得上图中的树 最终全部的物体将会在树的叶节点上。 树中除叶节点外,全部的节点存的都是本身的面积,或是说是本身的轮廓矩形的四个点的坐标。这样的话,一旦
判断一个对象是否与树中物体碰撞,咱们只需判断是否与物体所在区域有交集,若是有就说明"有可能"会碰撞,而后
接着递归向下,直到找到与目标物体碰撞的叶节点。
整个过程当中,很想是一个二叉排序树,给一个数字,判断这个数字在不在二叉排序树中。
不管是二叉排序树也好仍是ABT算法也好,最重要的仍是它们都巧妙的使用里二分法,不要ABT算法的二分法是将
面积进行二分,尽量的避免搜索错误区域。
因此ABT算法在检测一个物体是否与其它物体碰撞的时候时间负责度是log(n)的(n为碰撞物体的数量)。