游戏物理引擎之静态碰撞

  最近在编写一些简单的物理引擎,在编写静态碰撞的时候遇到了小问题,经人指点后终于弄懂了,如今写出来分享下。算法

  物理引擎主要是用来模拟大天然的力的做用。在我看来,物理引擎主要有两个机制:动画

  • 做用力发生器。就是来模拟诸如重力、阻力、弹簧弹力等常见的牛顿力。
  • 碰撞。这里的碰撞是很是广义的,基本上做用力发生器模拟不了的状况都能用碰撞模拟。

  这里扯一个题外话,在计算机动画里,特别是物理引擎中主要处理的是质点的位置和速度,不少大天然的物理都是近似当作由多个质点组成的。因此,碰撞主要解决的是三类问题:spa

  • 碰撞过程当中质点的速度变化,这个很简单,由动量守恒公式(即m1v1+m2v2=m1'v1'+m2'v2')就能够模拟出来。
  • 碰撞过程当中质点的位置变化,这个属于碰撞检测问题,有许多成熟的算法,这里不作详述。
  • 静态碰撞问题。就是如何利用碰撞来模拟物理静止的过程。咱们今天就来讨论一下这个问题。

  在计算机图形学中,咱们能够利用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;
}
相关文章
相关标签/搜索