Box2D-Lite源码阅读笔记(6)

0.简介

上一篇介绍了碰撞检测部分,这次阅读后面的碰撞点计算和最小碰撞深度计算的代码。

1.获取碰撞点和碰撞深度

碰撞后要计算出碰撞点,因为在计算运动方向,转动惯量等数据的时候需要碰撞点信息,碰撞深度是为了分离两个物体用的信息,因为物体碰撞时刻,不能正好点边接触,两个物体可能会有一些交叉,这个交叉导致碰撞点会落在形状内部,而不是边界,并且两个物体分离,运动状态信息也需要这个交叉深度来进行各种视觉效果上的平衡。

	// Find best axis
	Axis axis;//选定的轴
	float separation;//最小分离距离
	Vec2 normal;//正面的方向

	//2.找最大相交的轴方向和深度

	axis = FACE_A_X;//记录轴,这里是A的x轴方向的轴
	//最小分离距离,分离距离的方向是从四个分离轴方向中选的
	separation = faceA.x;
	//如果在A的坐标系下,中心连线的x大于0,说明物体B在A的右边,那么
	//就以A的x轴正方向为normal,这里了的normal在后面被认为是A矩形的"前面"
	//其中RotA.col1就是矩形A坐标系的x轴正方向
	normal = dA.x > 0.0f ? RotA.col1 : -RotA.col1;
	//这里是两个系数,Tol我猜是tolerance,翻译为容忍
	const float relativeTol = 0.95f;//相对95%
	const float absoluteTol = 0.01f;//绝对1%
	//faceA和faceB里存储的就是四个分离轴方向的相交深度
	//在没有上面两个参数的时候,直接就与separation进行比较,
	//此时就是谁大选谁,有faceA与faceB来源可知,值是负数的时候才有效,
	//所以选择更大的,就是更接近与0的负数,那么其绝对值表达是就是
	//两个形状的镶嵌的深度。if判断里的式子暂时不知为何这么写,估计是个经验表达式
	if (faceA.y > relativeTol * separation + absoluteTol * hA.y)
	{
		axis = FACE_A_Y;
		separation = faceA.y;
		normal = dA.y > 0.0f ? RotA.col2 : -RotA.col2;
	}

	// Box B faces
	if (faceB.x > relativeTol * separation + absoluteTol * hB.x)
	{
		axis = FACE_B_X;
		separation = faceB.x;
		normal = dB.x > 0.0f ? RotB.col1 : -RotB.col1;
	}

	if (faceB.y > relativeTol * separation + absoluteTol * hB.y)
	{
		axis = FACE_B_Y;
		separation = faceB.y;
		normal = dB.y > 0.0f ? RotB.col2 : -RotB.col2;
	}


	//3.计算碰撞的边和线段我和位置
	// Setup clipping plane data based on the separating axis
	Vec2 frontNormal, sideNormal;
	ClipVertex incidentEdge[2];
	float front, negSide, posSide;
	char negEdge, posEdge;

	//Compute the clipping lines and the line segment to be clipped.
	switch (axis)
	{
	case FACE_A_X://如果是A坐标系x轴方向为最小分离距离
	{
		frontNormal = normal;//normal是最小分离距离方向
		//posA在frontNormal上投影,此时得到的长度是x方向上的长度,加上hA.x
		//得到的front表达的是"前面的"x轴方向的位置,碰撞物体的碰撞点会落在
		//这个normal方向的边上。
		front = Dot(posA, frontNormal) + hA.x;
		sideNormal = RotA.col2;//取垂直于FACE_A_X的另一个轴
		//计算两个侧面的坐标值,就是"前面"的上下位置限制,
		//实际就是确定另一个轴上的矩形两边边界的世界坐标值。
		float side = Dot(posA, sideNormal);
		negSide = -side + hA.y;
		posSide = side + hA.y;
		//记录两个边是什么
		negEdge = EDGE3;
		posEdge = EDGE1;
		//以A为正,计算B相交于A的边和相关的点
		//这个函数执行后会得到两个物体的相交点,
		//这个点是取自于矩形四个定向中的点,假如在矩形A坐标系下,那么取的点
		//就是矩形B上的某个顶点,一般取两个。
		ComputeIncidentEdge(incidentEdge, hB, posB, RotB, frontNormal);
	}
	break;
    //后面这些都是一样的
	case FACE_A_Y:
	{
		frontNormal = normal;
		front = Dot(posA, frontNormal) + hA.y;
		sideNormal = RotA.col1;
		float side = Dot(posA, sideNormal);
		negSide = -side + hA.x;
		posSide = side + hA.x;
		negEdge = EDGE2;
		posEdge = EDGE4;
		ComputeIncidentEdge(incidentEdge, hB, posB, RotB, frontNormal);
	}
	break;

	case FACE_B_X:
	{
		frontNormal = -normal;
		front = Dot(posB, frontNormal) + hB.x;
		sideNormal = RotB.col2;
		float side = Dot(posB, sideNormal);
		negSide = -side + hB.y;
		posSide = side + hB.y;
		negEdge = EDGE3;
		posEdge = EDGE1;
		ComputeIncidentEdge(incidentEdge, hA, posA, RotA, frontNormal);
	}
	break;

	case FACE_B_Y:
	{
		frontNormal = -normal;
		front = Dot(posB, frontNormal) + hB.y;
		sideNormal = RotB.col1;
		float side = Dot(posB, sideNormal);
		negSide = -side + hB.x;
		posSide = side + hB.x;
		negEdge = EDGE2;
		posEdge = EDGE4;
		ComputeIncidentEdge(incidentEdge, hA, posA, RotA, frontNormal);
	}
	break;
	}

代码中的变量在实际中表示如下。

各个变量位置

front是矢量,negEdge表示的negSide是坐标值posEdge也一样,属于矢量,实际都是x或者y的坐标值。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值