包围体的是什么_正垂面与圆球体表面相交

(58) 2024-08-10 18:01:01

包围体是啥?
我们直观觉得碰撞往往是两个多边形相交,但是在计算机中这么算是很复杂的,特别是边很多的物体时
为了减少计算,就需要把几何体用一个简单的体空间包围起来(简单体是指:长方体、球体)
PS:包围体的英文名叫:BV

如图所示:(来自百度图片)
包围体的是什么_正垂面与圆球体表面相交 (https://mushiming.com/)  第1张
注意:包围体具有低消耗的相交测试的好处同时,也会占用额外的内存(需要存储包围的数据),不过影响不大


在游戏开发中,一般都会对其进行简化

Unity里面也提供了集中包围体的Collider,比如BoxCollider、ShpereCollider等,同时官方也并不推荐你使用MeshCollider

那么详细说一下各种包围体,如图所示:
包围体的是什么_正垂面与圆球体表面相交 (https://mushiming.com/)  第2张
1.球体
球体是一种很常见的包围体,只需要存储圆心点以及半径
数据定义如下:

public struct Sphere { 
    public FPVector2 center; //圆心 public FP radius; //半径 } 

其优点就是计算相交速度非常之快,也不会受到旋转变换的影响
相交测试代码:

//圆心距离是否小于两者半径之和 public static bool TestSphereSphere(Sphere a, Sphere b) { 
    FPVector2 d = a.center - b.center; FP dist = FPVector2.Dot(d, d); FP radiusSum = a.radius + b.radius; return dist <= radiusSum * radiusSum; } 

包围盒如何计算呢?
简单可以通过所有顶点的AABB获取一个逼近的包围球,将AABB的中心点作为球心,球体的半径是计算最远顶点与圆心的距离
但是这种方法并不好,可能计算出的中心和实际中心相差甚远,所以还有一种优化方法,开始时就计算一个近似完整的包围球,然后通过后续步骤完善该球体,直至包围全部定点


但是都涉及到AABB(轴对齐包围盒)的计算,所以先说一下它
轴对齐包围盒是应用最最最广泛的包围体,其特点就是:面法线都平行于给定坐标轴
这样就可以快速的进行相交测试,只需比较坐标值就可以了
AABB的数据定义有好几种表达方式,分别是

public struct AABB1 { 
    public FPVector3 min; //左下角的坐标 public FPVector3 max; //右上角坐标 } public struct AABB2 { 
    public FPVector3 min; //左下角 public FP[] distance; //三个边的长度 } public struct AABB3 { 
    public FPVector3 center; //中心点 public FP[] radius; //三个边的长度的一半 } 

具体使用哪种方式,看自己的需求
1.如果从存储角度考虑,肯定是AABB2或者AABB3(差不多,3更小点)
2.如果物体的运动方式只有平移,则使用AABB2或者AABB3更为方便(只需更新一个坐标)
3.如果还需要当做一个包围球检测的话,可以使用AABB3,方便取半径

AABB的相交测试怎么做呢?
如果AABB在三个轴上都相交,则AABB相交
在这里以AABB1举例子,代码如下:

public static bool TestAABBAABB(AABB1 a, AABB1 b) { 
    if (a.max.x < b.min.x || a.min.x > b.max.x) return false; if (a.max.y < b.min.y || a.min.y > b.max.y) return false; if (a.max.z < b.min.z || a.min.z > b.max.z) return false; return true; } 
THE END

发表回复