0.简介

前一篇对碰撞检测的准备工作做了阅读,这回我们看第一步,分离轴定理检测矩形是否相交。

1.分离轴定理

这里面简单对分离轴定理做一个说明,这个里面有详细说明分离轴定理详细说明

大概就是比如两个凸多边形,这两个多边形分别向每条边的垂直方向做投影,如果有一个方向上的投影不相交,则两个多边形不相交,反之则相交。

具体就看上面的链接吧。

2.代码阅读

int Collide(Contact* contacts, Body* bodyA, Body* bodyB)
{

    ...    

    //C是一个从B坐标系变换到A坐标系的一个矩阵
	Mat22 C = RotAT * RotB;
	//经过Abs处理,Abs实际就是将矩阵中每个元素都进行求绝对值
	//最后absC中全部都是大于等于0的数字
	Mat22 absC = Abs(C);
	//这里将absC矩阵转置得到逆矩阵
	Mat22 absCT = absC.Transpose();

	//1.分离轴计算碰撞
	// Box A faces
	Vec2 faceA = Abs(dA) - hA - absC * hB;
  	if (faceA.x > 0.0f || faceA.y > 0.0f)
		return 0;

	// Box B faces
	Vec2 faceB = Abs(dB) - absCT * hA - hB;
	if (faceB.x > 0.0f || faceB.y > 0.0f)
		return 0;

    ...
}

上面这段代码,其中,这里就是计算出一个矩阵C,求其绝对值和其逆。

//C是一个从B坐标系变换到A坐标系的一个矩阵
Mat22 C = RotAT * RotB;
//经过Abs处理,Abs实际就是将矩阵中每个元素都进行求绝对值
//最后absC中全部都是大于等于0的数字
Mat22 absC = Abs(C);
//这里将absC矩阵转置得到逆矩阵
Mat22 absCT = absC.Transpose();

如何判断是否相交?

box2d 手册 box2d lite_Box2D

上图是只做A物体分离轴投影的结果,当然物体B也应该做一次,这里没有画出,还是画一下吧。

box2d 手册 box2d lite_源码阅读_02

这回是四个轴的投影相交情况,不难看出四个轴方向只有三个方向没有相交,实际上,只要有一个不相交两个形状就不相交。我们需要得到的就是这四个轴投影的信息,或者说这四个轴投影的重叠情况。上面的四个情况都是在世界坐标下的效果,实际计算的时候,我们需要将其转换到每个矩形的局部坐标系下算。

我们拿四个情况中的以A物体x轴方向为例(上四个图中的第二个小图)。

box2d 手册 box2d lite_源码阅读_03

box2d 手册 box2d lite_box2d 手册_04

box2d 手册 box2d lite_Box2D-Lite_05

box2d 手册 box2d lite_box2d 手册_06

// Box A faces
//dA是两个矩形终点连线的向量,做了Abs运算后,dA表示的只是数值意义。
//实际上,下面的代码是Abs(dA) - (hA + absC * hB)
//hA就是矩形A右上角的点,absC * hB就是求出B点在A矩形的局部坐标系下的四个顶点中
//x,y方向上的最大值,因为dA,hA,hB都是从(0,0)点出发的向量,所以向量中的数值仅仅
//表示数值意义
//Abs(dA) - (hA + absC * hB)对于这个式子,如果只看x轴
//实际上就是dA的x坐标表示两个矩形的中心连线在x轴投影长度为s,
//hA是矩形A的x方向在中心连线的最大投影长度a,absC*hB就是矩形B的x方向在中心连线的最大投影长度b
//如果s-a-b大于0,这说明投影不相交。
Vec2 faceA = Abs(dA) - hA - absC * hB;
if (faceA.x > 0.0f || faceA.y > 0.0f)
	return 0;

// Box B faces
Vec2 faceB = Abs(dB) - absCT * hA - hB;
if (faceB.x > 0.0f || faceB.y > 0.0f)
    return 0;