旋轉矩形碰撞檢測 OBB方向包圍盒算法


  在cocos2dx中進行矩形的碰撞檢測時需要對旋轉過的矩形做碰撞檢查,由於游戲沒有使用Box2D等物理引擎,所以采用了OBB(Oriented bounding box)方向包圍盒算法,這個算法是基於SAT(Separating Axis Theorem)分離軸定律的。

  分離軸定律:兩個凸多邊形物體,如果我們能找到一個軸,使得兩個在物體在該軸上的投影互不重疊,則這兩個物體之間沒有碰撞發生,該軸為Separating Axis。也就是說兩個多邊形在所有軸上的投影都發生重疊,則判定為碰撞;否則,沒有發生碰撞。

  現在,我們來考慮一下矩形,矩形有4條邊,那么就有4條軸,由於矩形的對邊是平行的,所以有兩條軸是重復的,我們僅需要檢查相鄰的兩個軸,那么兩個矩形就需要檢查4個軸。

  檢查投影有兩種方法:第一種,把每個矩形的4個頂點投影到一個軸上,這樣算出4個頂點最長的連線距離,以后同樣對待第二個矩形,最后判斷2個矩形投影距離是否重疊。第二種,把2個矩形的半徑距離投影到軸上,以后把2個矩形的中心點連線投影到軸上,以后判斷2個矩形的中心連線投影,和2個矩形的半徑投影之和的大小。

  由於已經有很多文章來介紹OBB的原理,所以這里並不過多解釋,我只將我實現的源碼列出來僅供大家參考,代碼已經經過測試,如下:

#ifndef _OBBRECT_H_
#define _OBBRECT_H_

#include <math.h>

class OBBRect {
public:
    OBBRect(float x, float y, float width, float height, float rotation = 0.0f)
        : _x(x), _y(y), _width(width), _height(height), _rotation(rotation) {
        resetVector();
    }

    bool intersects(OBBRect& other) {
        float distanceVector[2] = {
            other._x - _x,
            other._y - _y
        };

        for (int i = 0; i < 2; ++i) {
            if (getProjectionRadius(_vectors[i]) + other.getProjectionRadius(_vectors[i])
                <= dot(distanceVector, _vectors[i])) {
                return false;
            }
            if (getProjectionRadius(other._vectors[i]) + other.getProjectionRadius(other._vectors[i])
                <= dot(distanceVector, other._vectors[i])) {
                return false;
            }
        }

        return true;
    }

private:
    void resetVector() {
        _vectors[0][0] = cos(_rotation);
        _vectors[0][1] = sin(_rotation);
        _vectors[1][0] = -_vectors[0][1];
        _vectors[1][1] = _vectors[0][0];
    }

    float dot(float a[2], float b[2]) {
        return abs(a[0] * b[0] + a[1] * b[1]);
    }

    float getProjectionRadius(float vector[2]) {
        return (_width * dot(_vectors[0], vector) / 2 
            + _height * dot(_vectors[1], vector) / 2);
    }

    float _x;
    float _y;
    float _width;
    float _height;
    float _rotation;
    float _vectors[2][2];
};

#endif // _OBBRECT_H_

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM