为cocos2d-x添加快速OBB盒碰撞检测
来源:互联网 发布:网络保密十条禁令 编辑:程序博客网 时间:2024/05/03 09:49
原理:
根据 Stefan Gottschalk的理论(Collision Queries using Oriented Bounding Boxes, Ph.D. Thesis, Department of Computer Science, University of North Carolina at Chapel Hill, 1999) ,若两个obb盒有交集,则必然存在一些坐标轴,使这两个obb在此坐标轴上的投影有重合部分。
在3d情况下,满足此条件的坐标轴必然存在于obb的边对应的六条轴(每个obb三条),或是同时垂直于obb A的一条边轴与obb B的一条边轴的九条坐标轴,共十五条坐标轴之中。
而在2d情况下,满足此条件的坐标轴必然存在于两个obb的4条边对应的轴之中。
所以对于cocos2d来说,判断两个obb是否有交集,只需判断这两个obb在这四条有效轴上的投影是否有重合。或者以一种更高效的方法来说:取一个obb的边作为轴,判断另一个obb的是否有满足条件的顶点,对这条轴的投影点在这条边之内。循环判断四条边。只有当此四条边均有定点满足条件时,这两个obb是有交集的。
代码:
引用于 http://www.flipcode.com/archives/2D_OBB_Intersection.shtml
我使用了引文中判断obb相交的代码。但是在此之前需将cocos2d-x中的节点信息转化为判断代码使用的数据。
//OBB结构
struct OrientedBoundingBox {
void Init(cocos2d::CCNode* node);//CCNode转化为OBB
bool IsOverlapsTo(const OrientedBoundingBox& other);//引文中的判断函数
Vector2d vertex[4];//四个顶点,0 is lower left
Vector2d axis[2];// 0点延伸的两个坐标轴向量(简化运算),长度为对应边的长度分之一
float origin[2];/** origin[a] = vertes[0].dot(axis[a]); */
};
//转化函数
void OrientedBoundingBox::Init( cocos2d::CCNode* node ) {
// 需要先取得尺寸和锚点
CCSize size = node->getContentSize();
CCPoint anchor = node->getAnchorPoint();
// 转化为世界坐标
vertex[0] = Vector2df(node->convertToWorldSpaceAR(ccp(-anchor.x*size.width, -anchor.y*size.height ) ) );
vertex[1] = Vector2df(node->convertToWorldSpaceAR(ccp((1-anchor.x)*size.width, -anchor.y*size.height ) ) );
vertex[2] = Vector2df(node->convertToWorldSpaceAR(ccp((1-anchor.x)*size.width,(1-anchor.y)*size.height ) ));
vertex[3] = Vector2df(node->convertToWorldSpaceAR(ccp(-anchor.x*size.width, (1-anchor.y)*size.height ) ) );
// 设置轴的长度为 1/边长,则其点乘的结构必然在【0,1】之间
axis[0] = vertex[1] - vertex[0];
axis[0] = axis[0] / axis[0].getLengthSQ();
axis[1] = vertex[3] - vertex[0];
axis[1] = axis[1] / axis[1].getLengthSQ();
origin[0] = vertex[0].dotProduct(axis[0]);
origin[1] = vertex[0].dotProduct(axis[1]);
}
//OBB other是否有顶点落在OBB this的axis上
bool OrientedBoundingBox::IsOverlapsTo( const OrientedBoundingBox& other ) {
for (int i=0; i < 2; ++i) {
// 查询other的顶点在axis上的最大最小值 double t = other.vertex[0].dotProduct(axis[i]);
double tMin = t;
double tMax = t;
for (int j = 1; j < 4; ++j) {
t = other.vertex[j].dotProduct(axis[i]);
if (t < tMin) {
tMin = t;
} else if (t > tMax) {
tMax = t;
}
}
// 最大最小值是否在this的这条边内 if ((tMin > 1 + origin[i]) || (tMax < origin[i])) {
return false;
}
}
return true;
}
//判断
bool InterSection::IsNodeOverlapsToNode( cocos2d::CCNode* nodeA, cocos2d::CCNode* nodeB ) {
OrientedBoundingBox boxA,boxB;
boxA.Init(nodeA);
boxB.Init(nodeB);
// 四条轴必须均满足此条件才有交集 return (boxA.IsOverlapsTo(boxB) && boxB.IsOverlapsTo(boxA) );
}
-by yuchenl
- 为cocos2d-x添加快速OBB盒碰撞检测
- cocos2d-x添加快速OBB碰撞检测
- Cocos2d-X添加快速OBB碰撞检测
- 基于cocos2d-x的2D空间中的OBB(Orient Bounding Box)碰撞检测算法
- Cocos2d-x教程(34)-三维物体OBB碰撞检测算法
- 基于cocos2d-x的2D空间中的OBB(Orient Bounding Box)碰撞检测算法
- cocos2d-x 碰撞检测
- cocos2d-x 碰撞检测
- cocos2d-x 检测碰撞
- Cocos2d-x碰撞检测
- OBB碰撞检测算法
- 碰撞检测之OBB-OBB检测
- 碰撞检测之OBB-OBB的SweepTest
- cocos2d-x如何检测碰撞
- cocos2d-x 矩形碰撞检测
- Cocos2d-x如何检测碰撞
- cocos2d-x 检测矩形碰撞
- cocos2d-x中的碰撞检测
- TDD实践之路--泛型和匿名方法在DELPHI单元测试中的妙用
- Memcached全面剖析–总结篇
- 11款用于优化、分析源代码的Java工具
- android游戏绘制屏幕
- 一个用于远程执行SQL脚本的函数
- 为cocos2d-x添加快速OBB盒碰撞检测
- Java通过SSH2协议执行远程Shell脚本
- 艰难求职路。。
- 人类概念学习的复杂度 complexity of human concept learning
- div 在flash上方解决方法
- UIWebView获取正在加载的URL和网页title
- TCP流式套接字的select模式编程
- AE粒子笔记
- Windows下手动安装PostgreSQL