碰撞检测教程(C++)(3)

2019-08-29 23:57

相对于静态分离轴算法,我们需要测试一个扩展的轴。显然这个是速度矢量轴。

那么我们现在有3个选择: 1. 间隔交叠

2. 间隔不相交,但是将在未来某个时刻发生碰撞 3. 间隔不相交,并且不会在未来发生碰撞

第三种可能性意味着物体不会在该帧处发生碰撞,而且分离轴真正分离了物体。因此物体不会发生碰撞。

AxisSeparatePolygons()函数将反映这种现象,并返回重叠量或者碰撞时间。为了区别两者,当检测到交叠时,将返回一个负值。如果检测到未来的碰撞,将返回一个正值。该函数看起来如下:

bool AxisSeparatePolygons(Vector Axis, Polygon A, Polygon B, Vector Offset,

Vector Vel,float& t,float tmax);

这里Offset是多边形A和多边形B之间的相对距离,并且Vel是多边形A相对于多边形B的相对速度。

求解碰撞平面的算法与MTD非常相似。只是碰撞将优于交叠,如果检测到未来的碰撞,将选择最新的一个。

如果没有发现碰撞并且只检测到了交叠,那么就像以前一样,选择交叠最小的那个轴。

碰撞检测函数将返回碰撞的法向,还有碰撞的深度(负值)和碰撞时间(正值)之一。最后的伪代码如下…

bool Collide(const Vector* A,int Anum,const Vector* B,int Bnum,const Vector& xOffset,const Vector& xVel,Vector& N,float& t) {

if(!A ||!B)

returnfalse; // All the separation axes

// note : a maximum of 32 vertices per poly is supported Vector xAxis[64];

float taxis[64]; int iNumAxes=0;

xAxis[iNumAxes]= Vector(-xVel.y, xVel.x); float fVel2 = xVel * xVel; if(fVel2 >0.00001f) {

if(!IntervalIntersect( A, Anum, B, Bnum, xAxis[iNumAxes],t))

returnfalse; iNumAxes++; }

// 测试分离轴A

for(int j = Anum-1, i =0; i < Anum; j = i, i ++) {

Vector E0 = A[j]; Vector E1 = A[i]; Vector E = E1 - E0;

xAxis[iNumAxes]= Vector(-E.y, E.x); if(!IntervalIntersect( A, Anum, B, Bnum, xAxis[iNumAxes],t))

returnfalse; iNumAxes++;

, ,, taxis[iNumAxes], , taxis[iNumAxes], xOffset xVel

xOffset xVel}

// 测试分离轴B

for(int j = Bnum-1, i =0; i < Bnum; j = i, i ++) {

Vector E0 = B[j]; Vector E1 = B[i]; Vector E = E1 - E0;

xAxis[iNumAxes]= Vector(-E.y, E.x);

if(!IntervalIntersect( A, Anum, B, Bnum, xAxis[iNumAxes], xOffset, xVel, t))

returnfalse; iNumAxes++; }

if(!FindMTD(xAxis, taxis, iNumAxes, N, t))

returnfalse;

// 确保多边形被彼此推开。 if(N * xOffset <0.0f)

N =-N; returntrue;

}

bool AxisSeparatePolygons ( Vector N, Polygon A, Polygon B, Vector Offset, Vector Vel,float&t,float tmax)

{

float min0, max0; float min1, max1;

CalculateInterval(N, A, min0, max0);

CalculateInterval(N, B, min1, max1); float h = Offset dot N; min0 += h; max0 += h; float d0 = min0 - max1;

// 如果重叠, do < 0

taxis[iNumAxes],

float d1 = min1 - max0;

// 如果重叠, d1 > 0 // 分离,测试动态间隔 if(d0 >0.0f|| d1 >0.0f) {

float v = Vel dot N;

// 速度很小,所以只能进行重叠测试。 if(fabs(v)<0.0000001f)

returnfalse; float t0 =-d0 / v;

// 时间影响D0达到0 float t1 = d1 / v;

// 时间影响D0达到1 // 排序时间。 if(t0 > t1) {

float temp = t0; t0 = t1; t1 = temp; }

// 取最小值

taxis =(t0 >0.0f)? t0 : t1; // 交叉时间太晚或时间,没有碰撞

if(taxis <0.0f|| taxis > tmax)

returntrue; returnfalse; } else {

// 重叠。得到的区间,作为最小的|D0|和|D1| // 返回负数以标记为重叠 taxis =(d0 > d1)? d0 : d1;

returnfalse;

}

}

bool FindCollisionPlane (Vector* Axis,float* taxis,int iNumAxes, Vector& Ncoll,

float& tcoll)

{

// 先找到碰撞 int mini =-1; tcoll =0.0f;

for(int i =0; i < iNumAxes; i ++) {

if(taxis[i]>0.0f) {

if(taxis[i]> tcoll) {

mini = i;

tcoll = taxis[i]; Ncoll = Axis[i]; Ncoll.Normalise();

// 将轴 } } }

// 发现了碰撞

if(mini !=-1)

returntrue; // 不,找到重叠 mini =-1;

for(int i =0; i < iNumAxes; i ++) {

float n = Axis[i].Normalise(); // 轴线长度 taxis[i]/= n;


碰撞检测教程(C++)(3).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:集装箱船舶配载注意事项 - 就深圳赤湾集装箱码头配载实例分析

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: