Bullet教程 Bullet大开发 第二章——对物体进行操作
前言
光是只进行物体下落的模拟,那多没意思呀!这反而让我们觉得我们的“世界”还是一如既往的静态……现在是时候来实现对物体的操作,为世界增添一点活力吧!
使用MotionState对刚体进行变换操作(刚体运动)
要想实现对物体(也就是刚体)的移动,首先需要对刚体进行一些设置:
btRigidBody* body = ……;
body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
body->setActivationState(DISABLE_DEACTIVATION);
其实这两条语句我真的讲不出它们有什么意思(Bullet用户手册和API文档也没有讲清楚),但这并不是重点,你只需要知道对刚体对象进行这些设置后,刚体对象就无法进行自由运动。
由于刚体对象没法进行自由移动,这时就需要我们来操控刚体对象了。MotionState就是用于操控刚体对象进行移动的工具,它翻译过来就是“运动状态”。btMotionState有一个方法setWorldTransform用于设置btMotionState所属的刚体对象相对于世界坐标系的变换。
在下面代码示例中,我们让刚体对象随着时间的流逝而缓缓上升:
btRigidBody* body = ……;
btTransform trans;
trans.setIdentity();
trans.setOrigin(btVector3(0.0f, time, 0.0f)); // time是一个时间变量
body->getMotionState()->setWorldTransform(trans);
除了进行位移变换之外,我们还可以对刚体对象进行旋转变换。
要想进行旋转变换,这时候就需要我们接触一个新类了——btQuaternion。我们可以在对其进行构造的同时,对其进行设置:
btQuaternion quaternion = btQuaternion(btVector3(0.0f, 1.0f, 0.0f), 45.0f / 90.0f);
第一个参数表示要绕其旋转的轴;第二个参数为旋转的角度,1.0f表示90度。
除了在构造时进行设置外,我们还可以用方法setRotaton在构造函数外进行单独设置,其参数如上所示。需要注意的是,绕轴旋转的设置只以最后一次设置为基准,也就是说下面两条语句中只有第二句有效:
quaternion.setRotation(btVector3(0.0f, 1.0f, 0.0f), 35.0f / 90.0f); // 无效
quaternion.setRotation(btVector3(1.0f, 0.0f, 0.0f), 60.0f / 90.0f); // 有效
除了方法setRotation外,还有方法setEuler和方法setEulerZYX,具体内容请自行查找API文档。
当我们对btQuaternion类进行设置完之后,就需要在btTransform中设置一下了:
trans.setRotation(quaternion);
之后再在MotionState中设置一下,就可以看见刚体对象旋转了。
btTransform类还有一个很有用的方法——setFromOpenGLMatrix。这个方法用于将OpenGL的4x4矩阵(不一定是OpenGL)设置为btTransform的矩阵数据,该方法接受指向OpenGL矩阵数据的指针。通过这个方法,可以增强btTransform变换的灵活性。
当我们不再需要操控刚体对象,想要让其进行自由移动,我们该怎么办呢?答案就是将刚体对象的设置恢复为初始状态:
int defaultFlags = body->getCollisionFlags(); // 初始设置值
body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
body->setActivationState(DISABLE_DEACTIVATION);
/* 进行移动变换操作 */
// 恢复设置
body->setCollisionFlags(defaultFlags);
body->setActivationState(DISABLE_SIMULATION);
对刚体进行直接变换
对刚体的变换,实际上我们还可以使用刚体对象的一个方法——proceedToTransform。该方法只接受一个btTransform类作为参数。
与MotionState不同的是,方法proceedToTransform不能用于表示刚体的移动状态,即使强行使用proceedToTransform进行移动变换,结果会让你失望的。
但proceedToTransform有个优点就是在使用该方法前,不必对刚体对象进行奇怪的设置;并且在变换之后,刚体仍能进行自由移动。出于这个优点,我们可以使用这个方法来使刚体对象瞬移。