碰撞检测之Sphere-Box检测

检测思路

首先要做的是将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));
        }
    }
}

运行结果

时间: 2024-10-04 20:51:54

碰撞检测之Sphere-Box检测的相关文章

碰撞检测之Ray-Sphere检测

提要 最近要开一个物理相关的系列,首先整理总结一下去年写的一些东西,然后看能不能撸一个物理引擎出来. 射线检测在之前写光线追踪的时候有写过一些,但当时写得都比较简单,恰好最近工作上又要用到这些,所以就好好来写写. 今天写Ray sphere 的碰撞检测. 环境: Unity5.2.3 Windows10 64bit 开工 定义一个类来记录相交的信息 public class RaycastHitInfo { public Vector3 point; public Vector3 normal;

Unity3d刚体Rigidbody与碰撞检测Collider

做了一个碰撞的小Demo,用一个球去撞击一堵墙,结果在球和墙都设置了刚体和碰撞体的情况下,球穿过了墙.移动球的位置,球有时能穿过墙,有时会被墙阻挡. 对于球穿过了墙,这个问题,在网上找了一下答案,基本可以确定原因是:球的速度过快,碰撞检测设置了离散检测,即相隔一段比较长的时间检测一次碰撞是否发生,而在这个比较长的时间内,球和墙确实发生了碰撞,只是没有检测到:移动球的位置时,球相对墙的距离改变,也就改变了检测的时间点,所以有时候能穿过墙,有时候会被阻挡. 解决方法:1.增大碰撞体积,即修改碰撞体C

(转)Unity3d中的碰撞检测

很多时候,当我们的主角与其他GameObject发生碰撞时, 我们需要做一些特殊的事情,比如:子弹击中敌人,敌人就得执行一系列的动作.这时,我们就需要检测到碰撞现象,即碰撞检测.这一篇,我来具体谈谈自己所了解的碰撞检测,希望高手不佞赐教. 首先,我们得明确一点:即产生碰撞信息所需要的条件.事实上,在unity3d中,能检测碰撞发生的方式有两种,一种是利用碰撞器,另一种则是利用触发器.这两种方式的应用非常广泛.为了完整的了解这两种方式,我们必须理解以下概念:    (一)碰撞器是一群组件,它包含了

Unity3d中的碰撞检测

很多时候,当我们的主角与其他GameObject发生碰撞时, 我们需要做一些特殊的事情,比如:子弹击中敌人,敌人就得执行一系列的动作.这时,我们就需要检测到碰撞现象,即碰撞检测.这一篇,我来具体谈谈自己所了解的碰撞检测,希望高手不佞赐教. 首先,我们得明确一点:即产生碰撞信息所需要的条件.事实上,在unity3d中,能检测碰撞发生的方式有两种,一种是利用碰撞器,另一种则是利用触发器.这两种方式的应用非常广泛.为了完整的了解这两种方式,我们必须理解以下概念:     (一)碰撞器是一群组件,它包含

2015/11/7用Python写游戏,pygame入门(7):碰撞检测

我们已经完成了飞机大战的大部分东西,但是游戏还是没有办法正式开玩,因为子弹并不能打掉飞机.只有完成了这一个工作,游戏才算基本成型. 今天的内容就非常简单了,就是做到这个碰撞检测,以及控制好子弹和飞机的消失.pygame里的sprite模块里有碰撞检测部分,但是,我们这里自己动手实现一个碰撞检测的函数. 检测碰撞的方法很简单,就是子弹的位置在飞机图片的内部.由于子弹和飞机的速度比较快,所以不需要非常精确地判别. 我们认为,如果子弹的坐标(b.x, b.y)在飞机的图片范围内,也就是(e.x, e,

个人关于存储不同类型对象进行碰撞检测的一些思路

(声明:以下面向对象思路是基于C++和2D图形的) 在代码量较小的程序中,我们可能会直接把所有需要的对象的碰撞检测封装在类当中,然后在 角色移动等动作的渲染过程中进行自动的碰撞检测,但这样的做法有个弊端,那就是我们已知了需求, 而我们如果需要扩展程序,则需要不断的在类内部进行添加,这样的做法显然破坏了程序的扩展性, 使得代码难以使用,因此我们需要该角色的类对外提供一个接口,利用这个接口,将那些需要进行 碰撞检测的对象进行检测,然后进行角色的移动等动作的渲染. 但是这里有一个问题,因为碰撞检测的对

Unity3D之碰撞体,刚体

一 概念介绍 刚体 Rigidbody(刚体)组件可使游戏对象在物理系统的控制下来运动,刚体可接受外力与扭矩力用来保证游戏对象像在真实世界中那样进行运动.任何游戏对象只有添加了刚体组件才能受到重力的影响,通过脚本为游戏对象添加的作用力以及通过NVIDIA物理引擎与其他的游戏对象发生互动的运算都需要游戏对象添加了刚体组件. 碰撞体 碰撞体是物理组件的一类,它要与刚体一起添加到游戏对象上才能触发碰撞.如果两个刚体相互撞在一起,除非两个对象有碰撞体时物理引擎才会计算碰撞,在物理模拟中,没有碰撞体的刚体

[算法][包围盒]球,AABB,OBB

参考地址请看图片水印:http://www.cnblogs.com/iamzhanglei/archive/2012/06/07/2539751.html http://blog.sina.com.cn/s/blog_6a1bf1310101g7zy.html 包围体是一个简单的几何空间,里面包含着复杂形状的物体.为物体添加包围体的目的是快速的进行碰撞检测或者进行精确的碰撞检测之前进行过滤(即当包围体碰撞,才进行精确碰撞检测和处理).包围体类型包括球体.轴对齐包围盒(AABB).有向包围盒(OB

Unity -- Collider(碰撞器与触发器)

(2d与3d的Collider可以相互存在,但是无法相互协作,如2d是无法检测3d的,反之,一样) 在目前掌握的情况分析,在Unity中参与碰撞的物体分2大块:1.发起碰撞的物体.2.接收碰撞的物体. 1. 发起碰撞物体有:Rigodbody , CharacterController . 2. 接收碰撞物体由:所有的Collider . 工作的原理为:发生碰撞的物体中必须要有“发起碰撞”的物体.否则,碰撞不响应. 比如:墙用BoxCollider ,所以墙与墙之间无反应. 比如:一个带有Rig