name changes and preparation for more cleanup

This commit is contained in:
Andrew Meadows 2015-04-26 15:24:30 -07:00
parent b760a03360
commit e3d29d74af
5 changed files with 91 additions and 64 deletions

View file

@ -50,7 +50,7 @@ EntityMotionState::~EntityMotionState() {
_entity = NULL; _entity = NULL;
} }
MotionType EntityMotionState::computeMotionType() const { MotionType EntityMotionState::computeObjectMotionType() const {
if (_entity->getCollisionsWillMove()) { if (_entity->getCollisionsWillMove()) {
return MOTION_TYPE_DYNAMIC; return MOTION_TYPE_DYNAMIC;
} }
@ -67,7 +67,7 @@ void EntityMotionState::stepKinematicSimulation(quint64 now) {
// which is different from physical kinematic motion (inside getWorldTransform()) // which is different from physical kinematic motion (inside getWorldTransform())
// which steps in physics simulation time. // which steps in physics simulation time.
_entity->simulate(now); _entity->simulate(now);
// TODO: we can't use ObjectMotionState::measureAcceleration() here because the entity // TODO: we can't use measureBodyAcceleration() here because the entity
// has no RigidBody and the timestep is a little bit out of sync with the physics simulation anyway. // has no RigidBody and the timestep is a little bit out of sync with the physics simulation anyway.
// Hence we must manually measure kinematic velocity and acceleration. // Hence we must manually measure kinematic velocity and acceleration.
} }
@ -100,7 +100,7 @@ void EntityMotionState::getWorldTransform(btTransform& worldTrans) const {
// This callback is invoked by the physics simulation at the end of each simulation step... // This callback is invoked by the physics simulation at the end of each simulation step...
// iff the corresponding RigidBody is DYNAMIC and has moved. // iff the corresponding RigidBody is DYNAMIC and has moved.
void EntityMotionState::setWorldTransform(const btTransform& worldTrans) { void EntityMotionState::setWorldTransform(const btTransform& worldTrans) {
measureAcceleration(); measureBodyAcceleration();
_entity->setPosition(bulletToGLM(worldTrans.getOrigin()) + ObjectMotionState::getWorldOffset()); _entity->setPosition(bulletToGLM(worldTrans.getOrigin()) + ObjectMotionState::getWorldOffset());
_entity->setRotation(bulletToGLM(worldTrans.getRotation())); _entity->setRotation(bulletToGLM(worldTrans.getRotation()));
@ -128,63 +128,65 @@ void EntityMotionState::setWorldTransform(const btTransform& worldTrans) {
void EntityMotionState::updateObjectEasy(uint32_t flags, uint32_t step) { void EntityMotionState::updateObjectEasy(uint32_t flags, uint32_t step) {
if (flags & (EntityItem::DIRTY_POSITION | EntityItem::DIRTY_VELOCITY)) { if (flags & (EntityItem::DIRTY_POSITION | EntityItem::DIRTY_VELOCITY)) {
if (flags & EntityItem::DIRTY_POSITION) { if (flags & EntityItem::DIRTY_POSITION) {
_sentPosition = _entity->getPosition() - ObjectMotionState::getWorldOffset(); _sentPosition = getObjectPosition() - ObjectMotionState::getWorldOffset();
btTransform worldTrans; btTransform worldTrans;
worldTrans.setOrigin(glmToBullet(_sentPosition)); worldTrans.setOrigin(glmToBullet(_sentPosition));
_sentRotation = _entity->getRotation(); _sentRotation = getObjectRotation();
worldTrans.setRotation(glmToBullet(_sentRotation)); worldTrans.setRotation(glmToBullet(_sentRotation));
_body->setWorldTransform(worldTrans); _body->setWorldTransform(worldTrans);
} }
if (flags & EntityItem::DIRTY_VELOCITY) { if (flags & EntityItem::DIRTY_VELOCITY) {
updateObjectVelocities(); updateBodyVelocities();
} }
_sentStep = step; _sentStep = step;
_body->activate();
} }
if (flags & EntityItem::DIRTY_MATERIAL) { if (flags & EntityItem::DIRTY_MATERIAL) {
updateMaterialProperties(); updateBodyMaterialProperties();
} }
if (flags & EntityItem::DIRTY_MASS) { if (flags & EntityItem::DIRTY_MASS) {
float mass = _entity->computeMass(); ShapeInfo shapeInfo;
_entity->computeShapeInfo(shapeInfo);
float mass = computeObjectMass(shapeInfo);
btVector3 inertia(0.0f, 0.0f, 0.0f); btVector3 inertia(0.0f, 0.0f, 0.0f);
_body->getCollisionShape()->calculateLocalInertia(mass, inertia); _body->getCollisionShape()->calculateLocalInertia(mass, inertia);
_body->setMassProps(mass, inertia); _body->setMassProps(mass, inertia);
_body->updateInertiaTensor(); _body->updateInertiaTensor();
} }
_body->activate();
} }
void EntityMotionState::updateMaterialProperties() { void EntityMotionState::updateBodyMaterialProperties() {
_body->setRestitution(_entity->getRestitution()); _body->setRestitution(getObjectRestitution());
_body->setFriction(_entity->getFriction()); _body->setFriction(getObjectFriction());
_body->setDamping(fabsf(btMin(_entity->getDamping(), 1.0f)), fabsf(btMin(_entity->getAngularDamping(), 1.0f))); _body->setDamping(fabsf(btMin(getObjectLinearDamping(), 1.0f)), fabsf(btMin(getObjectAngularDamping(), 1.0f)));
} }
void EntityMotionState::updateObjectVelocities() { void EntityMotionState::updateBodyVelocities() {
if (_body) { if (_body) {
_sentVelocity = _entity->getVelocity(); _sentVelocity = getObjectLinearVelocity();
setVelocity(_sentVelocity); setBodyVelocity(_sentVelocity);
_sentAngularVelocity = _entity->getAngularVelocity(); _sentAngularVelocity = getObjectAngularVelocity();
setAngularVelocity(_sentAngularVelocity); setBodyAngularVelocity(_sentAngularVelocity);
_sentGravity = _entity->getGravity(); _sentGravity = getObjectGravity();
setGravity(_sentGravity); setBodyGravity(_sentGravity);
_body->setActivationState(ACTIVE_TAG); _body->setActivationState(ACTIVE_TAG);
} }
} }
void EntityMotionState::computeShapeInfo(ShapeInfo& shapeInfo) { void EntityMotionState::computeObjectShapeInfo(ShapeInfo& shapeInfo) {
if (_entity->isReadyToComputeShape()) { if (_entity->isReadyToComputeShape()) {
_entity->computeShapeInfo(shapeInfo); _entity->computeShapeInfo(shapeInfo);
} }
} }
float EntityMotionState::computeMass(const ShapeInfo& shapeInfo) const { float EntityMotionState::computeObjectMass(const ShapeInfo& shapeInfo) const {
return _entity->computeMass(); return _entity->computeMass();
} }

View file

@ -31,12 +31,11 @@ public:
static void setOutgoingEntityList(QSet<EntityItem*>* list); static void setOutgoingEntityList(QSet<EntityItem*>* list);
static void enqueueOutgoingEntity(EntityItem* entity); static void enqueueOutgoingEntity(EntityItem* entity);
EntityMotionState() = delete; // prevent compiler from making default ctor
EntityMotionState(EntityItem* item); EntityMotionState(EntityItem* item);
virtual ~EntityMotionState(); virtual ~EntityMotionState();
/// \return MOTION_TYPE_DYNAMIC or MOTION_TYPE_STATIC based on params set in EntityItem /// \return MOTION_TYPE_DYNAMIC or MOTION_TYPE_STATIC based on params set in EntityItem
virtual MotionType computeMotionType() const; virtual MotionType computeObjectMotionType() const;
virtual void updateKinematicState(uint32_t substep); virtual void updateKinematicState(uint32_t substep);
virtual void stepKinematicSimulation(quint64 now); virtual void stepKinematicSimulation(quint64 now);
@ -51,11 +50,11 @@ public:
// these relay incoming values to the RigidBody // these relay incoming values to the RigidBody
virtual void updateObjectEasy(uint32_t flags, uint32_t step); virtual void updateObjectEasy(uint32_t flags, uint32_t step);
virtual void updateMaterialProperties(); virtual void updateBodyMaterialProperties();
virtual void updateObjectVelocities(); virtual void updateBodyVelocities();
virtual void computeShapeInfo(ShapeInfo& shapeInfo); virtual void computeObjectShapeInfo(ShapeInfo& shapeInfo);
virtual float computeMass(const ShapeInfo& shapeInfo) const; virtual float computeObjectMass(const ShapeInfo& shapeInfo) const;
virtual bool shouldSendUpdate(uint32_t simulationFrame); virtual bool shouldSendUpdate(uint32_t simulationFrame);
virtual void sendUpdate(OctreeEditPacketSender* packetSender, uint32_t step); virtual void sendUpdate(OctreeEditPacketSender* packetSender, uint32_t step);
@ -71,6 +70,17 @@ public:
virtual void setShouldClaimSimulationOwnership(bool value) { _shouldClaimSimulationOwnership = value; } virtual void setShouldClaimSimulationOwnership(bool value) { _shouldClaimSimulationOwnership = value; }
virtual bool getShouldClaimSimulationOwnership() { return _shouldClaimSimulationOwnership; } virtual bool getShouldClaimSimulationOwnership() { return _shouldClaimSimulationOwnership; }
virtual float getObjectRestitution() const { return _entity->getRestitution(); }
virtual float getObjectFriction() const { return _entity->getFriction(); }
virtual float getObjectLinearDamping() const { return _entity->getDamping(); }
virtual float getObjectAngularDamping() const { return _entity->getAngularDamping(); }
virtual const glm::vec3& getObjectPosition() const { return _entity->getPosition(); }
virtual const glm::quat& getObjectRotation() const { return _entity->getRotation(); }
virtual const glm::vec3& getObjectLinearVelocity() const { return _entity->getVelocity(); }
virtual const glm::vec3& getObjectAngularVelocity() const { return _entity->getAngularVelocity(); }
virtual const glm::vec3& getObjectGravity() const { return _entity->getGravity(); }
protected: protected:
EntityItem* _entity; EntityItem* _entity;
quint8 _accelerationNearlyGravityCount; quint8 _accelerationNearlyGravityCount;

View file

@ -36,10 +36,10 @@ const glm::vec3& ObjectMotionState::getWorldOffset() {
} }
// static // static
uint32_t _simulationStep = 0; uint32_t _worldSimulationStep = 0;
void ObjectMotionState::setSimulationStep(uint32_t step) { void ObjectMotionState::setWorldSimulationStep(uint32_t step) {
assert(step > _simulationStep); assert(step > _worldSimulationStep);
_simulationStep = step; _worldSimulationStep = step;
} }
ObjectMotionState::ObjectMotionState() : ObjectMotionState::ObjectMotionState() :
@ -65,13 +65,13 @@ ObjectMotionState::~ObjectMotionState() {
assert(_body == NULL); assert(_body == NULL);
} }
void ObjectMotionState::measureAcceleration() { void ObjectMotionState::measureBodyAcceleration() {
// try to manually measure the true acceleration of the object // try to manually measure the true acceleration of the object
uint32_t numSubsteps = _simulationStep - _lastSimulationStep; uint32_t numSubsteps = _worldSimulationStep - _lastSimulationStep;
if (numSubsteps > 0) { if (numSubsteps > 0) {
float dt = ((float)numSubsteps * PHYSICS_ENGINE_FIXED_SUBSTEP); float dt = ((float)numSubsteps * PHYSICS_ENGINE_FIXED_SUBSTEP);
float invDt = 1.0f / dt; float invDt = 1.0f / dt;
_lastSimulationStep = _simulationStep; _lastSimulationStep = _worldSimulationStep;
// Note: the integration equation for velocity uses damping: v1 = (v0 + a * dt) * (1 - D)^dt // Note: the integration equation for velocity uses damping: v1 = (v0 + a * dt) * (1 - D)^dt
// hence the equation for acceleration is: a = (v1 / (1 - D)^dt - v0) / dt // hence the equation for acceleration is: a = (v1 / (1 - D)^dt - v0) / dt
@ -81,20 +81,20 @@ void ObjectMotionState::measureAcceleration() {
} }
} }
void ObjectMotionState::resetMeasuredAcceleration() { void ObjectMotionState::resetMeasuredBodyAcceleration() {
_lastSimulationStep = _simulationStep; _lastSimulationStep = _worldSimulationStep;
_lastVelocity = bulletToGLM(_body->getLinearVelocity()); _lastVelocity = bulletToGLM(_body->getLinearVelocity());
} }
void ObjectMotionState::setVelocity(const glm::vec3& velocity) const { void ObjectMotionState::setBodyVelocity(const glm::vec3& velocity) const {
_body->setLinearVelocity(glmToBullet(velocity)); _body->setLinearVelocity(glmToBullet(velocity));
} }
void ObjectMotionState::setAngularVelocity(const glm::vec3& velocity) const { void ObjectMotionState::setBodyAngularVelocity(const glm::vec3& velocity) const {
_body->setAngularVelocity(glmToBullet(velocity)); _body->setAngularVelocity(glmToBullet(velocity));
} }
void ObjectMotionState::setGravity(const glm::vec3& gravity) const { void ObjectMotionState::setBodyGravity(const glm::vec3& gravity) const {
_body->setGravity(glmToBullet(gravity)); _body->setGravity(glmToBullet(gravity));
} }

View file

@ -59,28 +59,29 @@ public:
static void setWorldOffset(const glm::vec3& offset); static void setWorldOffset(const glm::vec3& offset);
static const glm::vec3& getWorldOffset(); static const glm::vec3& getWorldOffset();
static void setSimulationStep(uint32_t step); // The WorldSimulationStep is a cached copy of number of SubSteps of the simulation, used for local time measurements.
static void setWorldSimulationStep(uint32_t step);
ObjectMotionState(); ObjectMotionState();
~ObjectMotionState(); ~ObjectMotionState();
void measureAcceleration(); void measureBodyAcceleration();
void resetMeasuredAcceleration(); void resetMeasuredBodyAcceleration();
// An EASY update does not require the object to be removed and then reinserted into the PhysicsEngine // An EASY update does not require the object to be removed and then reinserted into the PhysicsEngine
virtual void updateObjectEasy(uint32_t flags, uint32_t frame) = 0; virtual void updateObjectEasy(uint32_t flags, uint32_t frame) = 0;
virtual void updateMaterialProperties() = 0; virtual void updateBodyMaterialProperties() = 0;
virtual void updateObjectVelocities() = 0; virtual void updateBodyVelocities() = 0;
MotionStateType getType() const { return _type; } MotionStateType getType() const { return _type; }
virtual MotionType getMotionType() const { return _motionType; } virtual MotionType getMotionType() const { return _motionType; }
virtual void computeShapeInfo(ShapeInfo& info) = 0; virtual void computeObjectShapeInfo(ShapeInfo& info) = 0;
virtual float computeMass(const ShapeInfo& shapeInfo) const = 0; virtual float computeObjectMass(const ShapeInfo& shapeInfo) const = 0;
void setVelocity(const glm::vec3& velocity) const; void setBodyVelocity(const glm::vec3& velocity) const;
void setAngularVelocity(const glm::vec3& velocity) const; void setBodyAngularVelocity(const glm::vec3& velocity) const;
void setGravity(const glm::vec3& gravity) const; void setBodyGravity(const glm::vec3& gravity) const;
void getVelocity(glm::vec3& velocityOut) const; void getVelocity(glm::vec3& velocityOut) const;
void getAngularVelocity(glm::vec3& angularVelocityOut) const; void getAngularVelocity(glm::vec3& angularVelocityOut) const;
@ -93,7 +94,7 @@ public:
virtual bool shouldSendUpdate(uint32_t simulationStep); virtual bool shouldSendUpdate(uint32_t simulationStep);
virtual void sendUpdate(OctreeEditPacketSender* packetSender, uint32_t frame) = 0; virtual void sendUpdate(OctreeEditPacketSender* packetSender, uint32_t frame) = 0;
virtual MotionType computeMotionType() const = 0; virtual MotionType computeObjectMotionType() const = 0;
virtual void updateKinematicState(uint32_t substep) = 0; virtual void updateKinematicState(uint32_t substep) = 0;
@ -113,6 +114,20 @@ public:
virtual void setShouldClaimSimulationOwnership(bool value) { } virtual void setShouldClaimSimulationOwnership(bool value) { }
virtual bool getShouldClaimSimulationOwnership() { return false; } virtual bool getShouldClaimSimulationOwnership() { return false; }
// These pure virtual methods must be implemented for each MotionState type
// and make it possible to implement more complicated methods in this base class.
virtual float getObjectRestitution() const = 0;
virtual float getObjectFriction() const = 0;
virtual float getObjectLinearDamping() const = 0;
virtual float getObjectAngularDamping() const = 0;
virtual const glm::vec3& getObjectPosition() const = 0;
virtual const glm::quat& getObjectRotation() const = 0;
virtual const glm::vec3& getObjectLinearVelocity() const = 0;
virtual const glm::vec3& getObjectAngularVelocity() const = 0;
virtual const glm::vec3& getObjectGravity() const = 0;
protected: protected:
void setRigidBody(btRigidBody* body); void setRigidBody(btRigidBody* body);

View file

@ -196,7 +196,7 @@ void PhysicsEngine::relayIncomingChangesToSimulation() {
motionState->updateObjectEasy(flags, _numSubsteps); motionState->updateObjectEasy(flags, _numSubsteps);
} }
if (flags & (EntityItem::DIRTY_POSITION | EntityItem::DIRTY_VELOCITY)) { if (flags & (EntityItem::DIRTY_POSITION | EntityItem::DIRTY_VELOCITY)) {
motionState->resetMeasuredAcceleration(); motionState->resetMeasuredBodyAcceleration();
} }
} else { } else {
// the only way we should ever get here (motionState exists but no body) is when the object // the only way we should ever get here (motionState exists but no body) is when the object
@ -206,7 +206,7 @@ void PhysicsEngine::relayIncomingChangesToSimulation() {
// it is possible that the changes are such that the object can now be added to the physical simulation // it is possible that the changes are such that the object can now be added to the physical simulation
if (flags & EntityItem::DIRTY_SHAPE) { if (flags & EntityItem::DIRTY_SHAPE) {
ShapeInfo shapeInfo; ShapeInfo shapeInfo;
motionState->computeShapeInfo(shapeInfo); motionState->computeObjectShapeInfo(shapeInfo);
btCollisionShape* shape = _shapeManager.getShape(shapeInfo); btCollisionShape* shape = _shapeManager.getShape(shapeInfo);
if (shape) { if (shape) {
addObject(shapeInfo, shape, motionState); addObject(shapeInfo, shape, motionState);
@ -340,7 +340,7 @@ void PhysicsEngine::stepSimulation() {
// lock on the tree before we re-lock ourselves. // lock on the tree before we re-lock ourselves.
// //
// TODO: untangle these lock sequences. // TODO: untangle these lock sequences.
ObjectMotionState::setSimulationStep(_numSubsteps); ObjectMotionState::setWorldSimulationStep(_numSubsteps);
_entityTree->lockForWrite(); _entityTree->lockForWrite();
lock(); lock();
_dynamicsWorld->synchronizeMotionStates(); _dynamicsWorld->synchronizeMotionStates();
@ -485,7 +485,7 @@ void PhysicsEngine::addObject(const ShapeInfo& shapeInfo, btCollisionShape* shap
btVector3 inertia(0.0f, 0.0f, 0.0f); btVector3 inertia(0.0f, 0.0f, 0.0f);
float mass = 0.0f; float mass = 0.0f;
btRigidBody* body = NULL; btRigidBody* body = NULL;
switch(motionState->computeMotionType()) { switch(motionState->computeObjectMotionType()) {
case MOTION_TYPE_KINEMATIC: { case MOTION_TYPE_KINEMATIC: {
body = new btRigidBody(mass, motionState, shape, inertia); body = new btRigidBody(mass, motionState, shape, inertia);
body->setCollisionFlags(btCollisionObject::CF_KINEMATIC_OBJECT); body->setCollisionFlags(btCollisionObject::CF_KINEMATIC_OBJECT);
@ -498,13 +498,13 @@ void PhysicsEngine::addObject(const ShapeInfo& shapeInfo, btCollisionShape* shap
break; break;
} }
case MOTION_TYPE_DYNAMIC: { case MOTION_TYPE_DYNAMIC: {
mass = motionState->computeMass(shapeInfo); mass = motionState->computeObjectMass(shapeInfo);
shape->calculateLocalInertia(mass, inertia); shape->calculateLocalInertia(mass, inertia);
body = new btRigidBody(mass, motionState, shape, inertia); body = new btRigidBody(mass, motionState, shape, inertia);
body->updateInertiaTensor(); body->updateInertiaTensor();
motionState->setRigidBody(body); motionState->setRigidBody(body);
motionState->setKinematic(false, _numSubsteps); motionState->setKinematic(false, _numSubsteps);
motionState->updateObjectVelocities(); motionState->updateBodyVelocities();
// NOTE: Bullet will deactivate any object whose velocity is below these thresholds for longer than 2 seconds. // NOTE: Bullet will deactivate any object whose velocity is below these thresholds for longer than 2 seconds.
// (the 2 seconds is determined by: static btRigidBody::gDeactivationTime // (the 2 seconds is determined by: static btRigidBody::gDeactivationTime
const float DYNAMIC_LINEAR_VELOCITY_THRESHOLD = 0.05f; // 5 cm/sec const float DYNAMIC_LINEAR_VELOCITY_THRESHOLD = 0.05f; // 5 cm/sec
@ -527,10 +527,10 @@ void PhysicsEngine::addObject(const ShapeInfo& shapeInfo, btCollisionShape* shap
} }
} }
body->setFlags(BT_DISABLE_WORLD_GRAVITY); body->setFlags(BT_DISABLE_WORLD_GRAVITY);
motionState->updateMaterialProperties(); motionState->updateBodyMaterialProperties();
_dynamicsWorld->addRigidBody(body); _dynamicsWorld->addRigidBody(body);
motionState->resetMeasuredAcceleration(); motionState->resetMeasuredBodyAcceleration();
} }
void PhysicsEngine::bump(EntityItem* bumpEntity) { void PhysicsEngine::bump(EntityItem* bumpEntity) {
@ -597,7 +597,7 @@ void PhysicsEngine::removeObjectFromBullet(ObjectMotionState* motionState) {
// private // private
bool PhysicsEngine::updateObjectHard(btRigidBody* body, ObjectMotionState* motionState, uint32_t flags) { bool PhysicsEngine::updateObjectHard(btRigidBody* body, ObjectMotionState* motionState, uint32_t flags) {
MotionType newType = motionState->computeMotionType(); MotionType newType = motionState->computeObjectMotionType();
// pull body out of physics engine // pull body out of physics engine
_dynamicsWorld->removeRigidBody(body); _dynamicsWorld->removeRigidBody(body);
@ -609,7 +609,7 @@ bool PhysicsEngine::updateObjectHard(btRigidBody* body, ObjectMotionState* motio
// get new shape // get new shape
btCollisionShape* oldShape = body->getCollisionShape(); btCollisionShape* oldShape = body->getCollisionShape();
ShapeInfo shapeInfo; ShapeInfo shapeInfo;
motionState->computeShapeInfo(shapeInfo); motionState->computeObjectShapeInfo(shapeInfo);
btCollisionShape* newShape = _shapeManager.getShape(shapeInfo); btCollisionShape* newShape = _shapeManager.getShape(shapeInfo);
if (!newShape) { if (!newShape) {
// FAIL! we are unable to support these changes! // FAIL! we are unable to support these changes!
@ -628,7 +628,7 @@ bool PhysicsEngine::updateObjectHard(btRigidBody* body, ObjectMotionState* motio
_shapeManager.releaseShape(oldShape); _shapeManager.releaseShape(oldShape);
// compute mass properties // compute mass properties
float mass = motionState->computeMass(shapeInfo); float mass = motionState->computeObjectMass(shapeInfo);
btVector3 inertia(0.0f, 0.0f, 0.0f); btVector3 inertia(0.0f, 0.0f, 0.0f);
body->getCollisionShape()->calculateLocalInertia(mass, inertia); body->getCollisionShape()->calculateLocalInertia(mass, inertia);
body->setMassProps(mass, inertia); body->setMassProps(mass, inertia);
@ -663,8 +663,8 @@ bool PhysicsEngine::updateObjectHard(btRigidBody* body, ObjectMotionState* motio
if (! (flags & EntityItem::DIRTY_MASS)) { if (! (flags & EntityItem::DIRTY_MASS)) {
// always update mass properties when going dynamic (unless it's already been done above) // always update mass properties when going dynamic (unless it's already been done above)
ShapeInfo shapeInfo; ShapeInfo shapeInfo;
motionState->computeShapeInfo(shapeInfo); motionState->computeObjectShapeInfo(shapeInfo);
float mass = motionState->computeMass(shapeInfo); float mass = motionState->computeObjectMass(shapeInfo);
btVector3 inertia(0.0f, 0.0f, 0.0f); btVector3 inertia(0.0f, 0.0f, 0.0f);
body->getCollisionShape()->calculateLocalInertia(mass, inertia); body->getCollisionShape()->calculateLocalInertia(mass, inertia);
body->setMassProps(mass, inertia); body->setMassProps(mass, inertia);