旋转矩形碰撞检测 OBB方向包围盒算法
2015-04-17 23:46
866 查看
在cocos2dx中进行矩形的碰撞检测时需要对旋转过的矩形做碰撞检查,由于游戏没有使用Box2D等物理引擎,所以采用了OBB(Oriented bounding box)方向包围盒算法,这个算法是基于SAT(Separating Axis Theorem)分离轴定律的。
分离轴定律:两个凸多边形物体,如果我们能找到一个轴,使得两个在物体在该轴上的投影互不重叠,则这两个物体之间没有碰撞发生,该轴为Separating Axis。也就是说两个多边形在所有轴上的投影都发生重叠,则判定为碰撞;否则,没有发生碰撞。
现在,我们来考虑一下矩形,矩形有4条边,那么就有4条轴,由于矩形的对边是平行的,所以有两条轴是重复的,我们仅需要检查相邻的两个轴,那么两个矩形就需要检查4个轴。
检查投影有两种方法:第一种,把每个矩形的4个顶点投影到一个轴上,这样算出4个顶点最长的连线距离,以后同样对待第二个矩形,最后判断2个矩形投影距离是否重叠。第二种,把2个矩形的半径距离投影到轴上,以后把2个矩形的中心点连线投影到轴上,以后判断2个矩形的中心连线投影,和2个矩形的半径投影之和的大小。
由于已经有很多文章来介绍OBB的原理,所以这里并不过多解释,我只将我实现的源码列出来仅供大家参考,代码已经经过测试,如下:
分离轴定律:两个凸多边形物体,如果我们能找到一个轴,使得两个在物体在该轴上的投影互不重叠,则这两个物体之间没有碰撞发生,该轴为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_
相关文章推荐
- 矩形旋转碰撞,OBB方向包围盒算法实现
- 矩形旋转碰撞,OBB方向包围盒算法实现
- 矩形旋转碰撞,OBB方向包围盒算法实现
- 矩形旋转碰撞,OBB方向包围盒算法实现
- 矩形旋转碰撞,OBB方向包围盒算法实现
- 弹幕射击游戏中旋转矩形碰撞检测的算法描述
- 码农干货系列【1】--方向包围盒(OBB)碰撞检测
- 码农干货系列【1】--方向包围盒(OBB)碰撞检测
- 码农干货系列【1】--方向包围盒(OBB)碰撞检测
- 码农干货系列【1】--方向包围盒(OBB)碰撞检测
- OBB包围盒及其碰撞检测算法(一)
- 圆与旋转矩形的碰撞检测(下篇)
- 圆与未旋转矩形的碰撞检测(上篇)
- 矩形检测碰撞算法
- 圆与未旋转矩形的碰撞检测(上篇)
- 【COCOS2DX-游戏开发之三六】圆与未旋转矩形的碰撞检测(上篇)
- 碰撞检测算法:点和矩形碰撞、点和圆形碰撞、矩形碰撞、圆形碰撞
- 圆与未旋转矩形的碰撞检测(上篇)
- 碰撞检测算法:点和矩形碰撞、点和圆形碰撞、矩形碰撞、圆形碰撞
- 圆与未旋转矩形的碰撞检测(上篇)