二、用于碰撞响应的扩展分离坐标轴方法
检测多边形相交是非常有用的方法,但是可以做更多的事情。当多边形相交时,我想将他们移开以避免他们相交。 分离轴的方法可以非常好的用于这种情况,但是还需要作一些额外的工作。必须返回相交的深度,和推开多边形将它们分离的方向。相交的深度和方向的组合称为MTD,或者最小平移距离。这是用于将物体分离的的最小向量。
为了计算MTD,我们可以使用分离坐标轴。
当物体相交时,我们可以计算两个物体在每一个分离轴上的投影间隔。两个间隔交叠的部分提供了一个推动向量,你需要将其应用到其中一个物体上以便物体在轴上的投影停止交叠
“推动向量”你需要应用于A上将A推开,这样就可以使A和B分开。
显然,不能沿着一个随机的轴来推开物体。候选轴是投影在该轴上两个间隔之间交叠最小的那个。并且这个推动向量提供了最小平移距离。
bool Intersect(Polygon A, Polygon B, Vector& MTD) {
// 电位分离轴。他们被转换成推动 vectors Vector Axis[32]; // 每个多边形最大的16个顶点的
int iNumAxis =0;
for(J = A.num_vertices - 1, I =0; I < A. num_vertices; J = I, I ++) {
Vector E = A.vertex[I] - A.vertex[J]; Axis[iNumAxis++]= Vector(-E.y, E.x); if(AxisSeparatePolygons(N, A, B))
returnfalse;
}
for(J = B. num_vertices - 1, I =0; I < B.num_vertices; J = I, I ++) {
Vector E = B.vertex[I] - B.vertex[J]; Axis[iNumAxis++]= Vector(-E.y, E.x); if(AxisSeparatePolygons (N, A, B))
returnfalse;
}
// 找到所有的分离向量之间的MTD MTD = FindMTD(Axis, iNumAxis); // 确保将向量a推动远离b
Vector D = A.Position - B.Position; if(D dot MTD <0.0f)
MTD =-MTD; returntrue; }
bool AxisSeparatePolygons(Vector& Axis, Polygon A, Polygon B) { float mina, maxa; float minb, maxb;
CalculateInterval(Axis, A, mina, maxa); CalculateInterval(Axis, B, minb, maxb); if(mina > maxb || minb > maxa)
returntrue; // 查找间隔重叠
float d0 = maxa - minb; float d1 = maxb - mina;
float depth =(d0 < d1)? d0 : d1;
// 将分离轴为推力矢量(重新恢复正常的轴乘区间重叠)
float axis_length_squared = Axis dot Axis; Axis *= depth / axis_length_squared; returnfalse; }
Vector FindMTD(Vector* PushVectors,int iNumVectors) { Vector MTD = PushVector[0];
float mind2 = PushVector[0] dot PushVector[0]; for(int I =1; I < iNumVectors; I ++) {
float d2 = PushVector[I]* PushVector[I]; if(d2 < mind2) {
mind2 = d2;
MTD = PushVector[I]; } }
return MTD; }
一旦得到了MTD向量,可以使用如下的方式将他们分开。
A.Postion += MTD *0.5f; B.Position -= MTD *0.5f;
显然,如果物体A是静态的,那么B将被完全的MTD推开(B.Position-=MTD)而A将不会被推开。
三、对快速移动的物体做进一步扩展
上述方法处理慢速移动物体时会取得非常好的效果。但是当物体移动的非常快时,碰撞系统将失去准确性,丢失碰撞,或者允许物体之间相互穿越,这可不是我们所期望的。
这里我们还是使用分离坐标轴的方法,并进一步扩展,并使用该算法检测未来某时刻的碰撞和交叠。
原理还是相同的,可以使用下面的图片解释:
现在需要使用投影数学。如果投影间隔没有相交,将速度投影到分离轴上,并计算两个间隔的碰撞时间。