使用 setActivationState()
来设置状态, getActivationState()
获取状态
btRigidBody
和 btSoftBody
都继承自 btCollisionObject
对象
下述内容翻译整理自Bullet Physics官方文档—传送门
btRigidBody
是刚体对象的基类,它派生自 btCollisionObject
,因此它保留了指向 btCollisionShape
的指针。注意 Object 与 Shape
class btRigidBody : public btCollisionObject
{
...
btMotionState* m_optionalMotionState;
...
}
出于性能和内存使用考虑,建议尽可能共享 btCollisionShape
对象(对于用户自定义的不同刚体对象,若它们有相同的碰撞形状,则可以向它们传递该形状的指针,下述第二种构造方式中 btCollisionShape* collisionShape
传递指针)。
Bullet 中的刚体有三种类型:
Dynamic,Static 和 Kinematic Rigid Bodies
当速度低于给定时间内的阈值时,Bullet 会自动停用动态(Dynamic)刚体。停用(休眠)刚体不会占用任何处理时间,除了轻微的宽相位碰撞检测影响(允许活动对象激活/唤醒休眠对象)
所有这些刚体都需要加入到动态世界(dynamics world)中。可以为刚体指定碰撞形状。这种形状可以用来计算质量分布,也称为惯性矩(或转动惯量,可形式地理解为一个物体对于旋转运动的惯性)。
对于动态对象(dynamic objects),可以使用碰撞形状(collision shape)近似局部惯性矩,否则使用零向量(默认参数),即下述两种构造方式中的第四个参数。
// 用构造信息的btRigidBody构造函数
btRigidBody::btRigidBody(const btRigidBodyConstructionInfo & constructionInfo)
// btRigidBody构造函数用于向后兼容。
btRigidBody::btRigidBody( btScalar mass,
btMotionState* motionState,
btCollisionShape* collisionShape,
const btVector3 & localInertia = btVector3(0,0,0)
)
两者虽然看起来有所区别,但在内部的实现基本一致,都会用到 btRigidBodyConstructionInfo
btRigidBody::btRigidBody(const btRigidBody::btRigidBodyConstructionInfo& constructionInfo)
{
setupRigidBody(constructionInfo);
}
btRigidBody::btRigidBody(btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia)
{
btRigidBodyConstructionInfo cinfo(mass, motionState, collisionShape, localInertia);
setupRigidBody(cinfo);
}
btRigidBodyConstructionInfo
结构体(structure)提供了用于创建刚体的信息。
将质量设置为零(mass = 0
)将创建固定(非动力学)刚体,即上述的第二种刚体对象。
可以使用运动状态(motion state,即 btMotionState
)同步物理对象和图形对象之间的世界变换。如果提供了运动状态,则刚体将从运动状态初始化其初始世界变换。
MotionState是什么?
MotionState是一种让Bullet为您完成所有繁重工作的方式,可以将要模拟的对象的世界变换转换到程序的渲染部分。
在大多数情况下,游戏循环会在每帧之前迭代所有要模拟的对象。
对于每个对象,可以从物理实体更新渲染对象的位置。
Bullet使用一种名为MotionState的东西来省去这项工作。
MotionState还有多个其他好处:
// btMotionState.h
#ifndef BT_MOTIONSTATE_H
#define BT_MOTIONSTATE_H
#include "btTransform.h"
// btMotionState接口类允许动力学世界使用图形同步和内插更新的世界变换。
// 对于优化,可能只同步移动对象(使用setWorldPosition/setWorldOrientation)
class btMotionState
{
public:
virtual ~btMotionState()
{
}
virtual void getWorldTransform(btTransform& worldTrans) const = 0;
//Bullet only calls the update of worldtransform for active objects
virtual void setWorldTransform(const btTransform& worldTrans) = 0;
};
#endif //BT_MOTIONSTATE_H
两种方法:
btRigidBody::getWorldTransform(btTransform& worldTrans)
btRigidBody::setWorldTransform(const btTransform& worldTrans)
下述代码描述了使用 Ammo.js 构造 RigidBody 的简单代码:
// 第一刚体的碰撞形状(下面列举的是一个Box)
let shape = new Ammo.btBoxShape(new Ammo.btVector3(2, 2, 2));
// transform 用于描述刚体初始化时的位置和旋转量
let transform = new Ammo.btTransform();
transform.setIdentity(); // 初始化
transform.setOrigin(new Ammo.btVector3(pos.x, pos.y, pos.z));
transform.setRotation(new Ammo.btQuaternion(quat.x, quat.y, quat.z, quat.w));
let motionState = new Ammo.btDefaultMotionState(transform);
let localInertia = new Ammo.btVector3(0, 0, 0);
shape.calculateLocalInertia(mass, localInertia);
let rbInfo = new Ammo.btRigidBodyConstructionInfo(mass, motionState, shape, localInertia);
let body = new Ammo.btRigidBody(rbInfo);
// 所有这些刚体都需要加入到动态世界(dynamics world)中。
physicsWorld.addRigidBody(body);
Rotation & Inertia Tensors