zoukankan      html  css  js  c++  java
  • 碰撞检測之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));
            }
        }
    }
    



    执行结果





  • 相关阅读:
    java8 parallel并行处理实战
    java相关技术问答(二)
    [安卓基础] 007.管理Activity的生命周期
    [Python基础]009.os模块(1)
    [Objective-C] 012_数据持久化_XML属性列表,NSUserDefaults
    SD.Team团队人物形象
    读Pyqt4教程,带你入门Pyqt4 _013
    [Objective-C] 011_数据持久化_NSKeyedArchiver
    [Objective-C] 010_Foundation框架之NSSet与NSMutableSet
    [JavaWeb基础] 007.Struts2的配置和简单使用
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/7307971.html
Copyright © 2011-2022 走看看