基于2D多边形的碰撞检测和响应(二)

本文介绍了如何使用扩展的分离坐标轴方法来检测并解决多边形间的碰撞问题。通过计算最小平移距离(MTD),可以有效地将相交的多边形分开,避免持续的穿透状态。

二、用于碰撞响应的扩展分离坐标轴方法

检测多边形相交是非常有用的方法,但是可以做更多的事情。当多边形相交时,我想将他们移开以避免他们相交。
分离轴的方法可以非常好的用于这种情况,但是还需要作一些额外的工作。必须返回相交的深度,和推开多边形将它们分离的方向。相交的深度和方向的组合称为MTD,或者最小pingyi距离。这是用于将物体分离的的最小向量。
为了计算MTD,我们可以使用分离坐标轴。
当物体相交时,我们可以计算两个物体在每一个分离轴上的投影间隔。两个间隔交叠的部分提供了一个推动向量,你需要将其应用到其中一个物体上以便物体在轴上的投影停止交叠

“推动向量”你需要应用于A上将A推开,这样就可以使A和B分开。
显然,不能沿着一个随机的轴来推开物体。候选轴是投影在该轴上两个间隔之间交叠最小的那个。并且这个推动向量提供了最小pingyi距离。

bool Intersect(Polygon A, Polygon B, Vector& MTD)
{
// potential separation axes. they get converted into push
vectors Vector Axis[32];
// max of 16 vertices per polygon
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))
return false;
}
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))
return false;
}

// find the MTD among all the separation vectors
MTD = FindMTD(Axis, iNumAxis);

// makes sure the push vector is pushing A away from B
Vector D = A.Position – B.Position;
if (D dot MTD < 0.0f)
MTD = -MTD;

return true;
}

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)
return true;

// find the interval overlap
float d0 = maxa - minb;
float d1 = maxb - mina;
float depth = (d0 < d1)? d0 : d1;

// convert the separation axis into a push vector (re-normalise
// the axis and multiply by interval overlap)
float axis_length_squared = Axis dot Axis;

Axis *= depth / axis_length_squared;
return false;
}

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将不会被推开。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值