BulletPhysics物理引擎手册(4)

Bullet讨论群:533030320

介绍一下活动状态

如果我们打开wireframe来看demo的时候,白色的线框在物体禁止后不久就会变成绿色。因为Bullet的内部有优化处理,所以只有在debug模式中可以看见,当然对CPU有深远影响。如果Objects的速度在规定时间内小于给定阈值,则物体的状态会被switch成非活动物体(静止物体)。其实Bullet在btDbvtBroadphase中维护了两个动态包围盒树结构。一个用来存放活动物体(活动树),另外一个存放静止或者非活动物体(非活动树)。因此,在一个物体被设为非活动时被推送到另外一个树中。

这样就可以让Bullet直接跳过静止物体而去处理移动物体,而且粗碰撞检测broad phase object只对活动树中的物体进行树内部的碰撞检测,然后用活动物体树对静态物体树进行碰撞检测,但很重要的事是静态树中的物体不会进行内部的互相碰撞检测,这样可以非常有效的降低处理时间。如果活动物体碰到了静态物体,并带动它,那么这个静态的物体会被switch成活动的物体,重新推回活动树中。Bullet在决定把活动物体重新switch成静态之前会对其进行必要的计算。 这两个活动/静态的状态就像把物体睡着和唤醒一般。

note:需要注意的是质量为零也就是默认为拥有无限质量的物体永远被放在静态树中,所以永远不会被bullet系统移动位置,除非你去主动移动,运动学物体?

这个优化当然也有一个缺点,万一有些时候,物体有意以极其慢的速度行进着,那么bullet会把它swich成静态的。比如有一个物体在边缘摇摇欲坠teetering,这时候它以非常小的角速度移动,然后就悲剧的被设置成了静止物体,但是这是不符合现实的,一个物体以一个角度悬挂在边缘上,他应该掉落才对。

一个通常的做法使稍微调整tweak物体静止条件的阈值,可以使用setSleepingThresholds()函数设置任何一个刚体的静止条件阈值。作为最后的resort,我们可以强制所有物体都是活动的,setActivationState(DISABLE_DEACTIVATION)在每个新生成的物体上使用该函数,就可以了,但是这会让我们失去部分性能,因为所有的物体都会被检测碰撞。

多米诺效应 – 感觉好高级

既然物体都在活动的状态,那么我们就有必要提一下多米诺效应。整个一群接触的物体(通常被称为islands群岛?)同时被睡眠sleep同时大量降低CPU开销是可能的。一旦Bullet检测到一段时间内没有一个物体在移动,那么他们都会被设为睡眠sleep。

看上去我们可以很方便的放置更多的物体到模拟系统中去,但是要注意。当这些islands(后面都称成片的接触型接触物体为islands)变得越来越大,组成物体越来越多,但是只要其中一个被轻推,然后整个一片islands全部被唤醒,同时进行互相碰撞,唤醒一个物体,然后全部被一一推送到活动树中,这时候整个系统像龟爬一样慢…在这种情况下我们遇到了性能瓶颈。

太多活动物体在太短的时间内要处理会导致“死亡螺旋”,这种情况在步进式模拟系统中会出现,比如我们必须要花20ms来模拟16ms内发生的事,这样我们就慢了4ms,所以系统必须为了补偿这个时间损失,则会在下一步中额外处理这4ms的损失,如果每一步都需要4ms,如果步进10次,就整整延迟了40ms,就像个死亡螺旋。

这会导致模拟系统越来越卡,直到所有东西被处理完。
Bullet让你处理这类情况,通过调整时间和stepSimulation()中的第三个参数,也就是期望模拟频率,如果降低频率的话就可以增加内部的模拟时间,那么每一步的模拟步就会很大。

总结

之前我们已经介绍了一些通用的物体管理系统,去支持将来的项目和扩展。一些debug技巧和可替换的渲染接口等。在接下来的章节中我会介绍更加高级的鼠标控制,射线和constraints主题。

感谢阅读

你可能感兴趣的:(物理引擎)