【OBB碰撞】

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

<2>思路緩存

構造OBB盒子的時候,設置角度,半寬,半高以及中心位置函數

每次更改盒子旋轉角度計算矩形2個單位檢測軸(每條軸與矩形2條邊平行2條邊垂直,即2條軸把矩形劃分紅4個等大小矩形)this

方法提供:spa

updateAngle函數:根據旋轉角度計算單位檢測軸blog

dot函數:計算A在B上面的投影,並取絕對值io

isCollision函數:計算2個OBB盒子是否發生碰撞class

<3>代碼date

isCollision函數解釋:float

首先得到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;
        }
    }
相關文章
相關標籤/搜索