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

  • 简介
    上一篇完成了碰撞点的初步获取,这回阅读的是碰撞点的第二步获取。
  • 碰撞点截取
    因为有一定可能使得取得的B上的碰撞点在A的宽度范围之外,这样一来,范围之外的点属于没有意义的点,所以需要根据A的宽度将点截断在A的宽度范围内。
  • 代码
/*参数列表:vOut[2]输出结果,vIn[2]输入的碰撞点候选点,normal侧方向上的向量(假设以矩形A坐标系为主)
offset侧方向上的坐标值。
这假设前面是以A坐标系为主,vIn[2]是获取自矩形B上的顶点且已经转换到世界坐标
*/
int ClipSegmentToLine(ClipVertex vOut[2], ClipVertex vIn[2],
	const Vec2& normal, float offset, char clipEdge)
{
	int numOut = 0;
	// Calculate the distance of end points to the line
	//将B的世界坐标vIn转换到A的局部坐标,仅限于sideNormal方向上的坐标值
	//这里normal在外面取的是矩阵的列向量,所以下面的计算实际上是原本矩阵中
	//某个轴方向上的逆运算,Dot(normal, vIn[0].v)就是算坐标(x,y)中的x或者y
	//从世界坐标变换到A坐标系的x或者y,offset实际存放的是A矩形在normal方向
	//上的矩形某个端点的x或者y坐标值(投影)。最终distance(0/1)得到的如果是小0的数字
	//说明两个点在矩形AsideNormal方向长度的范围内。
	float distance0 = Dot(normal, vIn[0].v) - offset;
	float distance1 = Dot(normal, vIn[1].v) - offset;

	//这里就是直接记录结果
	if (distance0 <= 0.0f) vOut[numOut++] = vIn[0];
	if (distance1 <= 0.0f) vOut[numOut++] = vIn[1];

	//如果有一个点在范围之外
	if (distance0 * distance1 < 0.0f)
	{
		//这里算出矩形A的端点在两个碰撞点之间的位置
		float interp = distance0 / (distance0 - distance1);
		//然后求出那个A端点的位置,作为截断
		vOut[numOut].v = vIn[0].v + interp * (vIn[1].v - vIn[0].v);
		//存储一些相关信息
		if (distance0 > 0.0f)
		{
			vOut[numOut].fp = vIn[0].fp;
			vOut[numOut].fp.e.inEdge1 = clipEdge;
			vOut[numOut].fp.e.inEdge2 = NO_EDGE;
		}
		else
		{
			vOut[numOut].fp = vIn[1].fp;
			vOut[numOut].fp.e.outEdge1 = clipEdge;
			vOut[numOut].fp.e.outEdge2 = NO_EDGE;
		}
		++numOut;
	}
	return numOut;
}

对A的两边的边界分别计算,这样一来,点都会被调整到A的宽度范围内。下面连读两次调用了截断函数。分别是不同的sideNormal方向。

//4.筛选碰撞顶点,计算出合适的碰撞点
	//前面已经得到了两个矩形上的顶点,这两个顶点需要再加工一下
	//实际上就是将顶点限制在sideNormal方向上的negSide和posSide范围之间
	ClipVertex clipPoints1[2];
	ClipVertex clipPoints2[2];
	int np;//取得的点个数

	//clipPoints1此时是结果接收,incidentEdge是前面获得的与碰撞相关的
	//矩形顶点,输入sideNormal,这个类似剪裁,当在矩形A坐标系下,incidentEdge中B的
	//顶点如果超出了negSide和posSide的范围,就剪裁到范围内,剪裁方向是-sideNormal。
	np = ClipSegmentToLine(clipPoints1, incidentEdge, -sideNormal, negSide, negEdge);
	if (np < 2)
		return 0;

	//经过上面的剪裁后,现在其基础上剪裁sideNormal方向
	np = ClipSegmentToLine(clipPoints2, clipPoints1, sideNormal, posSide, posEdge);
	if (np < 2)
		return 0;
上一篇:平价无线蓝牙耳机推荐,小米和南卡蓝牙耳机哪个好用?


下一篇:量化版——使用TF Lite将Mobilenet SSD目标检测移植至安卓客户端