您的位置:首页 > 其它

碰撞检测之Sphere-Box检测

2016-03-06 02:22 417 查看

检测思路

首先要做的是将Box转为AABB,然后判断圆心是否在Box内,用的就是之前的SAT
如果圆心在Box内,肯定相交,
如果不在圆心内,则有四种情况,与顶点相交,与楞相交,与面相交,这里的确定也是通过SAT来确定。
在二维中,如果圆心不box内,有两种情况





只要对比红色线段的长度和圆的半径就可以了。

代码

public static bool IntersectSphereBox(Sphere sphere, Box box)
{
Vector3 delta = sphere.center - box.center;
Matrix4x4 boxRotMatrix = Matrix4x4.TRS(Vector3.zero, box.rotation, Vector3.one);
Vector3 dRot = boxRotMatrix.inverse.MultiplyVector(delta);

bool outside = false;
if (dRot.x < -box.extents.x)
{
outside = true;
dRot.x = -box.extents.x;
}
else if (dRot.x > box.extents.x)
{
outside = true;
dRot.x = box.extents.x;
}

if (dRot.y < -box.extents.y)
{
outside = true;
dRot.y = -box.extents.y;
}
else if (dRot.y > box.extents.y)
{
outside = true;
dRot.y = box.extents.y;
}

if (dRot.z < -box.extents.z)
{
outside = true;
dRot.z = -box.extents.z;
}
else if (dRot.z > box.extents.z)
{
outside = true;
dRot.z = box.extents.z;
}

if (outside) //if clipping was done, sphere center is outside of box.
{
Vector3 clippedDelta = boxRotMatrix.MultiplyVector(dRot); //get clipped delta back in world coords.
Vector3 clippedVec = delta - clippedDelta; //what we clipped away.

float lenSquared = clippedVec.sqrMagnitude;
float radius = sphere.radius;
if (lenSquared > radius * radius) // PT: objects are defined as closed, so we return 'true' in case of equality
return false; //disjoint
}
return true;
}

测试代码

public class SphereBoxTester : MonoBehaviour {
public GameObject sphere;
public GameObject box;
Box _box;
Sphere _sphere;
// Use this for initialization
void Start () {
_box = new Box();

_sphere = new Sphere();
}

// Update is called once per frame
void Update () {
_box.center = box.transform.position;
_box.rotation = box.transform.rotation;
_box.extents = 0.5f * box.transform.localScale;

_sphere.center = sphere.transform.position;
_sphere.radius = 0.5f * sphere.transform.localScale.x;

if (NIntersectTests.IntersectSphereBox(_sphere, _box))
{
sphere.GetComponent<MeshRenderer>().materials[0].SetColor("_Color", new Color(1, 0, 0));
}
else
{
sphere.GetComponent<MeshRenderer>().materials[0].SetColor("_Color", new Color(1, 1, 1));
}
}
}


运行结果





内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  三维 图形 游戏开发