基于2D多边形的碰撞检测和响应(三)
2008-02-28 10:20
549 查看
三、对快速移动的物体做进一步扩展
上述方法处理慢速移动物体时会取得非常好的效果。但是当物体移动的非常快时,碰撞系统将失去准确性,丢失碰撞,或者允许物体之间相互穿越,这可不是我们所期望的。
这里我们还是使用分离坐标轴的方法,并进一步扩展,并使用该算法检测未来某时刻的碰撞和交叠。
原理还是相同的,可以使用下面的图片解释:
现在需要使用投影数学。如果投影间隔没有相交,将速度投影到分离轴上,并计算两个间隔的碰撞时间。
相对于静态分离轴算法,我们需要测试一个扩展的轴。显然这个是速度矢量轴。
那么我们现在有3个选择:
1. 间隔交叠
2. 间隔不相交,但是将在未来某个时刻发生碰撞
3. 间隔不相交,并且不会在未来发生碰撞
第三种可能性意味着物体不会在该帧处发生碰撞,而且分离轴真正分离了物体。因此物体不会发生碰撞。
AxisSeparatePolygons()函数将反映这种现象,并返回重叠量或者碰撞时间。为了区别两者,当检测到交叠时,将返回一个负值。如果检测到未来的碰撞,将返回一个正值。该函数看起来如下:
[align=left] [/align]
这里Offset是多边形A和多边形B之间的相对距离,并且Vel是多边形A相对于多边形B的相对速度。
求解碰撞平面的算法与MTD非常相似。只是碰撞将优于交叠,如果检测到未来的碰撞,将选择最新的一个。
如果没有发现碰撞并且只检测到了交叠,那么就像以前一样,选择交叠最小的那个轴。
碰撞检测函数将返回碰撞的法向,还有碰撞的深度(负值)和碰撞时间(正值)之一。最后的伪代码如下…
[align=left] [/align]
现在,你拥有了一个可以检测未来碰撞的的检测系统,或者当重叠的时候,返回碰撞平面和碰撞深度/时间
上述方法处理慢速移动物体时会取得非常好的效果。但是当物体移动的非常快时,碰撞系统将失去准确性,丢失碰撞,或者允许物体之间相互穿越,这可不是我们所期望的。
这里我们还是使用分离坐标轴的方法,并进一步扩展,并使用该算法检测未来某时刻的碰撞和交叠。
原理还是相同的,可以使用下面的图片解释:
现在需要使用投影数学。如果投影间隔没有相交,将速度投影到分离轴上,并计算两个间隔的碰撞时间。
相对于静态分离轴算法,我们需要测试一个扩展的轴。显然这个是速度矢量轴。
那么我们现在有3个选择:
1. 间隔交叠
2. 间隔不相交,但是将在未来某个时刻发生碰撞
3. 间隔不相交,并且不会在未来发生碰撞
第三种可能性意味着物体不会在该帧处发生碰撞,而且分离轴真正分离了物体。因此物体不会发生碰撞。
AxisSeparatePolygons()函数将反映这种现象,并返回重叠量或者碰撞时间。为了区别两者,当检测到交叠时,将返回一个负值。如果检测到未来的碰撞,将返回一个正值。该函数看起来如下:
[align=left] [/align]
bool AxisSeparatePolygons(Vector Axis, Polygon A, Polygon B, Vector Offset, Vector Vel, float& t, float tmax); |
求解碰撞平面的算法与MTD非常相似。只是碰撞将优于交叠,如果检测到未来的碰撞,将选择最新的一个。
如果没有发现碰撞并且只检测到了交叠,那么就像以前一样,选择交叠最小的那个轴。
碰撞检测函数将返回碰撞的法向,还有碰撞的深度(负值)和碰撞时间(正值)之一。最后的伪代码如下…
[align=left] [/align]
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) return false; // 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], xOffset, xVel, taxis[iNumAxes], t)) return false; iNumAxes++; } // test separation axes of 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], xOffset, xVel, taxis[iNumAxes], t)) return false; iNumAxes++; } // test separation axes of 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, taxis[iNumAxes], t)) return false; iNumAxes++; } if (!FindMTD(xAxis, taxis, iNumAxes, N, t)) return false; // make sure the polygons gets pushed away from each other. if (N * xOffset < 0.0f) N = -N; return true; } |
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; // if overlapped, do < 0 float d1 = min1 - max0; // if overlapped, d1 > 0 // separated, test dynamic intervals if (d0 > 0.0f || d1 > 0.0f) { float v = Vel dot N; // small velocity, so only the overlap test will be relevant. if (fabs(v) < 0.0000001f) return false; float t0 =-d0 / v; // time of impact to d0 reaches 0 float t1 = d1 / v; // time of impact to d0 reaches 1 // sort the times. if (t0 > t1) { float temp = t0; t0 = t1; t1 = temp; } // take the minimum positive taxis = (t0 > 0.0f)? t0 : t1; // intersection time too late or back in time, no collision if (taxis < 0.0f || taxis > tmax) return true; return false; } else { // overlap. get the interval, as a the smallest of |d0| and |d1| // return negative number to mark it as an overlap taxis = (d0 > d1)? d0 : d1; return false; } } |
bool FindCollisionPlane (Vector* Axis, float* taxis, int iNumAxes, Vector& Ncoll, float& tcoll) { // find collision first 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(); // normalise axis } } } // found a collision if (mini != -1) return true; // nope, find overlaps mini = -1; for(int i = 0; i < iNumAxes; i ++) { float n = Axis[i].Normalise(); // axis length taxis[i] /= n; // normalise interval overlap too // remember, those numbers are negative, so take the closest to 0 if (mini == -1 || taxis[i] > tcoll) { mini = i; tcoll = taxis[i]; Ncoll = Axis[i]; } } return (mini != -1); } |
相关文章推荐
- 基于2D多边形的碰撞检测和响应(七)
- 基于2D多边形的碰撞检测和响应(二)
- 基于2D多边形的碰撞检测和响应
- 基于2D多边形的碰撞检测和响应(六)
- 基于2D多边形的碰撞检测和响应(四)
- 基于2D多边形的碰撞检测和响应(一)
- 基于2D多边形的碰撞检测和响应(五)
- 基于cocos2d-x的2D空间中的OBB(Orient Bounding Box)碰撞检测算法
- 基于HTML5及WebGL开发的2D3D第一人称漫游进行碰撞检测
- 基于cocos2d-x的2D空间中的OBB(Orient Bounding Box)碰撞检测算法
- 2D多边形碰撞检测和反馈(转)
- 基于HTML5及WebGL开发的2D3D第一人称漫游进行碰撞检测
- 2D多边形碰撞检测和反馈
- [译]在Tiled Map中使用碰撞检测(一) 创建基于Tiled Map的游戏
- HTML5吃豆豆游戏开发实战(四)2d碰撞检测、重构-第二篇
- Unity2d 弱联网游戏制作(二) 动画、场景、渲染层、碰撞检测、音乐播放
- Cocos2dx 多边形碰撞检测
- <cocos2d-x for wp7>使用cocos2d-x制作基于Tile地图的游戏:碰撞检测和收集物品(二)
- 基于网格的碰撞检测
- H5游戏开发之多边形碰撞检测