最近在编写一些简单的物理引擎,在编写静态碰撞的时候遇到了小问题,经人指点后终于弄懂了,如今写出来分享下。算法
物理引擎主要是用来模拟大天然的力的做用。在我看来,物理引擎主要有两个机制:动画
这里扯一个题外话,在计算机动画里,特别是物理引擎中主要处理的是质点的位置和速度,不少大天然的物理都是近似当作由多个质点组成的。因此,碰撞主要解决的是三类问题:spa
在计算机图形学中,咱们能够利用OpenGL等图形API在三维场景中绘制一些三维图形,好比地面、桌子、小球等。可是计算机自己不知道什么是地面,什么是桌子,因此在当咱们给地面上添加一个受重力做用的静止小球,咱们看到的只会是小球一直下落,而不是静止在地面上。固然咱们能够加一些几何约束(y<0时,y=0),强行让小球在地面上,可是咱们用物理引擎模拟显然不能作,咱们能够将这种状况模拟成碰撞,这一类的碰撞都称为静态碰撞。如图1,能够看第2帧的时候小球位于地面下面,咱们能够认为这时小球是与地面相交的,生成碰撞。 rest
图1orm
咱们确定不但愿咱们的程序中物体没有静止在地面上,反而穿过地面继续下坠。咱们须要对碰撞行为进行检测。如上图,咱们能够看出在第1帧状态下,小球的位置是没有问题,但到了第2帧,小球与地面相交了。因此咱们要寻找一个经过两帧的碰撞信息就能判断出第1帧状态下小球是不是静止的。咱们结合上图分析,由于小球只受到重力做用,即小球的速度仅由其重力引起,对此,可简单的将多用力乘以第1帧和第2帧之间的时间间隔(duration),进而获得基于当前做用力下的速度数据,这个速度咱们写做Vg。因为咱们将小球做碰撞处理,因此由碰撞机制能够获得小球在第2帧的真实速度V。咱们比较Vg和V,若是实际速度V小于Vg,则可知小球在第1帧中处于静止状态。blog
那么问题来了,为何比较这两个速度就能够肯定小球在前一帧就是静止状态?咱们结合图2来分析一下。在小球第1帧静止在在地面V=0,可是咱们计算一下若是按碰撞处理的话,小球确定会产生一个方向向上的速度V'。这时咱们再跟Vg进行比较,V'<Vg,说明小球并无向上运动的趋势,因此小球的初始前一帧状态要么是静止要么是速度很是很是小,均可以近似做静态碰撞处理。ci
图2it
最后贴一段处理这个过程的代码。io
double newSepVelocity = -separatingVelocity * restitution; CVector3 accCausedVelocity = particle[0]->GetAcceleration(); if (particle[1]) accCausedVelocity -= particle[1]->GetAcceleration(); double accCausedSepVelocity = accCausedVelocity * contactNormal * duration; /*比较合外力产生的速度和碰撞后物体的速度*/ if (accCausedSepVelocity < 0) { /*newSepVelocity为正值*/ newSepVelocity += restitution * accCausedSepVelocity; if (newSepVelocity < 0) newSepVelocity = 0; }