113 Three.js的obb (OrientedboundingBox)方向包围盒的使用
一、包围盒简介:
包围盒是一个简单的几何空间,里面包含着复杂形状的物体。为物体添加包围体的目的是快速的进行碰撞检测或者进行精确的碰撞检测之前进行过滤(即当包围体碰撞,才进行精确碰撞检测和处理)。包围体类型包括球体、轴对齐包围盒(AABB)、有向包围盒(OBB)、8-DOP以及凸壳。
包围盒广泛地应用于碰撞检测,比如射击、点击、相撞等,每一个物体都有自己的包围盒。因为包围盒一般为规则物体,因此用它来代替物体本身进行计算,会比直接用物体本身更加高效和简单。
目前广泛应用的是AABB和OBB包围盒,其中AABB包围盒更常见。因为它的生成方法很简单,因它与坐标轴是对齐的。但它也有不足,它不随物体旋转,可以看出当图中的老虎沿着Z轴方向站立时,AABB包围盒还和老虎比较贴合,但当老虎转了一个角度后,AABB包围盒便增加了较大的空隙,对于较精确的碰撞检测效果不太好。这时就需要OBB包围盒,它始终沿着物体的主成分方向生成最小的一个矩形包围盒,可以随物体旋转,可用于较精确的碰撞检测。
以上摘自:https://blog.csdn.net/qing101hua/article/details/53100112
二、 Three.js中的包围盒使用
在three.js中,获取一个模型的包围盒有很多种方法,下面我列一下,我个人经常使用的:
第一种方法,也是最无脑的方法:
实例化一个THREE.Box3,然后用.expandByObject 直接可以获取到此模型的包围盒,而且还能包含它的子对象,官方注释(扩展此包围盒的边界,使得对象及其子对象在包围盒内,包括对象和子对象的世界坐标的变换。)
第二种方法,获取单个几何体的模型的方法:
首先获取到模型的geometry的boundingbox,然后把这个boundingbox乘以模型的世界变换矩阵,就可以实现包围盒的获取。
以上两种,都是获取AABB类型的包围盒,使用简单,理解简单,也好用。
针对于OBB包围盒,今天发现three.js也有相应的封装,文件地址在/examples/jsm/math/OBB.js
。
官方有demo,可以在我网站上翻一翻,地址:http://wjceo.com/three.js/examples/?q=obb#webgl_math_obb
你也可以自己打开一个官方的demo搜一下OBB,来查看一下,demo效果就是,如果两个盒子发生了碰撞,就会变成红色,仅此而已。
针对于这个OBB包围盒对象使用,我们需要手动设置其初始的包围盒尺寸,官方的demo没有在初始化的时候直接传值,而是,实例化后,直接设置的尺寸,而且还需要设置包围盒子尺寸的一半,不知道为啥要这么设置:
var obb = new OBB();
obb.halfSize.copy(new THREE.Vector(x, y, z)).multiplyScalar(0.5);
我们可以直接复制一下size的值,然后让每个值乘以0.5,就是一半的盒子。
每个对象都设置了一个OBB对象,那么怎么实现的碰撞检测。官方demo里面是在每一帧的render里面,因为demo里面的模型的几何体都是用的一个默认的几何体盒子,所以,在每一帧里面,模型都先copy了一下几何体的OBB对象,然后再乘以模型的世界矩阵,获取到了模型的OBB包围盒。
我们查看这个OBB.js文件,会发现里面有很多的内置方法,什么和点检测的,面检测碰撞的,和球的,所以,我们只需要调用相应的api即可。
官方demo在render里面,显示更新每个模型的OBB包围盒,然后拿着其中的一个和其它所有的OBB包围盒,通过intersectsOBB
方法来检测是否碰撞,如果检测碰撞,直接设置颜色为红色。