AABB与球的相交检测、AABB到一个点最近的点
如果一个AABB与球相交,则AABB内至少有一个点到球心的距离小于等于球的半径。
只需要找到AABB内到球心最近的一个点,判断点到球心的距离与半径长度关系。
如果球心在 AABB 内,则AABB到球心距离最近的点就是球心所在的点
如果球心在 AABB 外,则AABB到球心距离最近的点一定在AABB的一个表面上
我们假设,球心坐标(X, Y, Z) 就是 AABB内到球最近的一个点
因为AABB内所有的点都在(min, max)范围内
则
如果 X < AABB.min.x 令 X = AABB.min.x
如果 X > AABB.max.x 令 X = AABB.max.x
同理 Y、Z也这样处理,最终的 坐标 (X,Y,Z) 就是 AABB上的点到球心最近的点
代码如下
public class AABBSphereCollision
{
/// <summary>
/// AABB与球相交检测
/// </summary>
/// <param name="aabb">AABB数据</param>
/// <param name="spherePos">球中心坐标</param>
/// <param name="radius">球半径</param>
/// <returns></returns>
public static bool IsCollision(AABB aabb, Vector3 spherePos, float radius)
{
Vector3 nearestPoint = AABBNearestPointToPoint(aabb, spherePos);
float distance = Vector3.Distance(nearestPoint, spherePos);
return distance <= radius;
}
/// <summary>
/// AABB 内到所有点中到一个指定点最近的点坐标
/// </summary>
/// <param name="aabb"></param>
/// <param name="spherePos"></param>
/// <returns></returns>
public static Vector3 AABBNearestPointToPoint(AABB aabb, Vector3 spherePos)
{
float x = spherePos.x;
x = x > aabb.max.x ? aabb.max.x : x;
x = x < aabb.min.x ? aabb.min.x : x;
float y = spherePos.y;
y = y > aabb.max.y ? aabb.max.y : y;
y = y < aabb.min.y ? aabb.min.y : y;
float z = spherePos.z;
z = z > aabb.max.z ? aabb.max.z : z;
z = z < aabb.min.z ? aabb.min.z : z;
return new Vector3(x, y, z);
}
}
测试效果如下