• 【OBB碰撞】


    <1>2D OBB碰撞算法(AABB算法对比最高 最低 最左 最右就完了)

    <2>思路

    构造OBB盒子的时候,设置角度,半宽,半高以及中心位置

    每次更改盒子旋转角度计算矩形2个单位检测轴(每条轴与矩形2条边平行2条边垂直,即2条轴把矩形划分成4个等大小矩形)

    方法提供:

    updateAngle函数:根据旋转角度计算单位检测轴

    dot函数:计算A在B上面的投影,并取绝对值

    isCollision函数:计算2个OBB盒子是否发生碰撞

    <3>代码

    isCollision函数解释:

    首先获得2个OBB中心点的向量:centerVec

    接下来分别在2个OBB的X,Y2条单位检测轴上做投影,一共4中情况,至多检测4次

    例如:有A和B2个OBB盒子,

               AW=A半宽,AH=A半高,AX=A检测轴X,AY=A检测轴Y

               BW=B半宽,BH=B半高,BX=B检测轴X,BY=B检测轴Y

               例:AX检测轴 centerVec在AX检测轴上的投影长度 > AW在AX上的投影 + AH在AX上的投影 + (BX在AX上的投影*BW)+ (BY在AX上的投影*BH)

               因为AW在AX上的投影 = AW ;AH在AX上的投影 = 0

               即:dot(centerVec,AX)> AW + (BX在AX上的投影*BW)+ (BY在AX上的投影*BH)

               即:dot(centerVec,AX)> AW + dot( BX*BW , AX )+ dot(BY*BH , AX)

               剩下3个轴同理

    其他:1.Vector2.x读取比Vector2[0]读取速度更快

               2.可以不用Vector2缓存,全部用float[]缓存

     新代码:

        public class OBB
        {
            //public Vector2 axisX = Vector2.zero;
            //public Vector2 axisY = Vector2.zero;
    
            public float[] axisX = new float[2];
            public float[] axisY = new float[2];
    
            public float halfWidth;
            public float halfHeight;
    
            public float[] center = new float[2];
    
            public OBB(float angle)
            {
                updateAngle(angle);
            }
    
            public void updateAngle(float angle)
            {
                //通过矩形旋转计算当前矩形的2个单位检测轴
                float radian = Mathf.PI / 180 * angle;
                axisX[0] = Mathf.Cos(radian); // Vector2.right.x * Mathf.Cos(radian) - Vector2.right.y * Mathf.Sin(radian);
                axisX[1] = Mathf.Sin(radian);  //Vector2.right.x * Mathf.Sin(radian) + Vector2.right.y * Mathf.Cos(radian);
    
                axisY[0] = -Mathf.Sin(radian);// //Vector2.up.x * Mathf.Cos(radian) - Vector2.up.y * Mathf.Sin(radian);
                axisY[1] = Mathf.Cos(radian);// Vector2.up.x * Mathf.Cos(radian) - Vector2.up.y * Mathf.Sin(radian);
            }
    
            //dot
            float dot(float[] axisA, float[] axisB)
            {
                return Mathf.Abs(axisA[0] * axisB[0] + axisA[1] * axisB[1]);
            }
            float dot(float[] axisA, Vector2 axisB)
            {
                return Mathf.Abs(axisA[0] * axisB.x + axisA[1] * axisB.y);
            }
            float dot(Vector2 axisA, float[] axisB)
            {
                return Mathf.Abs(axisA.x * axisB[0] + axisA.y * axisB[1]);
            }
            float dot(Vector2 axisA, Vector2 axisB)
            {
                return Mathf.Abs(axisA.x * axisB.x + axisA.y * axisB.y);
            }
    
            public bool isCollision(OBB obb)
            {
                float[] centerVec = new float[] {
                    this.center[0] - obb.center[0],
                    this.center[1] - obb.center[1],
                };
                if (dot(centerVec, this.axisX) > this.halfWidth + obb.halfWidth * dot( obb.axisX, this.axisX) + obb.halfHeight * dot( obb.axisY, this.axisX))
                {
                    return false;
                }
                if (dot(centerVec, this.axisY) > this.halfHeight + obb.halfWidth * dot( obb.axisX, this.axisY) + obb.halfHeight * dot( obb.axisY, this.axisY))
                {
                    return false;
                }
                if (dot(centerVec, obb.axisX) > obb.halfWidth + this.halfWidth * dot( this.axisX, obb.axisX) + this.halfHeight * dot( this.axisY, obb.axisX))
                {
                    return false;
                }
                if (dot(centerVec, obb.axisY) > obb.halfHeight + this.halfWidth * dot( this.axisX, obb.axisY) + this.halfHeight * dot(this.axisY, obb.axisY))
                {
                    return false;
                }
                return true;
            }
        }
    

      

    旧代码:

        public class OBB
        {
            public Vector2 axisX = Vector2.zero;
            public Vector2 axisY = Vector2.zero;
    
            public float halfWidth;
            public float halfHeight;
    
            public float[] center = new float[2];
    
            public OBB(float angle)
            {
                updateAngle(angle);
            }
    
            public void updateAngle(float angle) {
                //通过矩形旋转计算当前矩形的2个单位检测轴
                float radian = Mathf.PI / 180 * angle;
                axisX[0] = Mathf.Cos(radian); // Vector2.right.x * Mathf.Cos(radian) - Vector2.right.y * Mathf.Sin(radian);
                axisX[1] = Mathf.Sin(radian);  //Vector2.right.x * Mathf.Sin(radian) + Vector2.right.y * Mathf.Cos(radian);
    
                axisY[0] = -Mathf.Sin(radian);// //Vector2.up.x * Mathf.Cos(radian) - Vector2.up.y * Mathf.Sin(radian);
                axisY[1] = Mathf.Cos(radian);// Vector2.up.x * Mathf.Cos(radian) - Vector2.up.y * Mathf.Sin(radian);
            }
    
            //dot
            float dot(float[] axisA, float[] axisB)
            {
                return Mathf.Abs(axisA[0] * axisB[0] + axisA[1] * axisB[1]);
            }
            float dot(float[] axisA, Vector2 axisB)
            {
                return Mathf.Abs(axisA[0] * axisB[0] + axisA[1] * axisB[1]);
            }
            float dot(Vector2 axisA, float[] axisB)
            {
                return Mathf.Abs(axisA[0] * axisB[0] + axisA[1] * axisB[1]);
            }
            float dot(Vector2 axisA, Vector2 axisB)
            {
                return Mathf.Abs(axisA[0] * axisB[0] + axisA[1] * axisB[1]);
            }
    
            public bool isCollision(OBB obb)
            {
                float[] centerVec = new float[] {
                    this.center[0] - obb.center[0],
                    this.center[1] - obb.center[1],
                };
                if (dot(centerVec, this.axisX) > this.halfWidth + dot(obb.halfWidth * obb.axisX, this.axisX) + dot(obb.halfHeight * obb.axisY, this.axisX)) {
                    return false;
                }
                if (dot(centerVec, this.axisY) > this.halfHeight + dot(obb.halfWidth * obb.axisX, this.axisY) + dot(obb.halfHeight * obb.axisY, this.axisY))
                {
                    return false;
                }
                if (dot(centerVec, obb.axisX) > obb.halfWidth + dot(this.halfWidth * this.axisX, obb.axisX) + dot(this.halfHeight * this.axisY, obb.axisX))
                {
                    return false;
                }
                if (dot(centerVec, obb.axisY) > obb.halfHeight + dot(this.halfWidth * this.axisX, obb.axisY) + dot(this.halfHeight * this.axisY, obb.axisY))
                {
                    return false;
                }
                return true;
            }
        }
  • 相关阅读:
    HDU 1160 dp中的路径问题
    zzuli 1907: 小火山的宝藏收益
    POJ 3414 dfs广搜直接应用
    http://acm.zzuli.edu.cn/zzuliacm/problem.php?cid=1158&pid=5 二分函数的间接应用
    LightOJ 1067 组合数取模
    九段美到极致的句子
    质数和分解
    codevs 1080 线段树练习
    codevs 2806 红与黑
    codevs 2152 滑雪
  • 原文地址:https://www.cnblogs.com/cocotang/p/10830364.html
Copyright © 2020-2023  润新知