The problem is my strategy to attach children to this btCollisionShape. Since I can't attach children btCollisionShapes to, say, a btBoxShape, I have been removing the RigidBody/MotionState. I then try to build a RigidBody with a btCompoundShape, but with the Mass, Friction, LocalInertia, LinearVelocity, and AngularVelocity of the old shape. And then, finally, I try to btCompoundShape::addChildShape() the old shape onto this structure. On that line, I get the error: "Assertion failed! !mCachedTransformOutOfDate"
Code: Select all
bool PhysicsFactory::AddComponentChild( PhysicsComponent *parent_comp, PhysicsComponent *child_comp, btDynamicsWorld *dyn_world ){
if( !parent_comp || !child_comp || !dyn_world ){ return false; }
if( !parent_comp->is_compound_shape ){
// What we want to do is to (a) delete the Rigidbody (copy all data), (b) add the old shape as a child to this new shape (setting compoundshape transform to 0),
// (c) hang the CompoundShape where the old Shape was, and (d) remake the Rigidbody. Then have a "bool is_compound_shape" and a pointer to 'shape_child'.
// We can look for this onDelete().
parent_comp->is_compound_shape = true;
parent_comp->shape_child = parent_comp->shape;
// Backup all data from outgoing RigidBody
//Mass, Friction, LocalInertia, LinearVelocity, AngularVelocity.
btTransform old_transform = parent_comp->rbody->getWorldTransform(); // Or getCenterOfMassTransform() ?
btScalar old_friction = parent_comp->rbody->getFriction();
btVector3 old_local_inertia = parent_comp->rbody->getLocalInertia();
btVector3 old_linear_velocity = parent_comp->rbody->getLinearVelocity();
btVector3 old_angular_factor = parent_comp->rbody->getAngularFactor();
// Delete outgoing RigidBody
dyn_world->removeRigidBody( parent_comp->rbody );
delete parent_comp->rbody->getMotionState();
parent_comp->motion_state = NULL;
delete parent_comp->rbody;
parent_comp->rbody = NULL;
// Recreate incoming RigidBody
parent_comp->motion_state = CreateMotionState( &old_transform, parent_comp->snode, parent_comp->use_ogremotionstate );
parent_comp->shape = new btCompoundShape();
parent_comp->rbody = CreateRigidBody( parent_comp->mass, parent_comp->motion_state, parent_comp->shape, parent_comp->is_kinematic );
parent_comp->rbody->setUserPointer( parent_comp );
// Restore old data to incoming RigidBody
parent_comp->rbody->setFriction( old_friction );
parent_comp->rbody->setLinearVelocity( old_angular_factor );
parent_comp->rbody->setAngularFactor( old_angular_factor );
parent_comp->rbody->setWorldTransform( old_transform );
//parent_comp->rbody->setLocalInertia( old_local_inertia ); // Needed?
dyn_world->addRigidBody( parent_comp->rbody );
}
btCompoundShape *parent_comp_shape = dynamic_cast<btCompoundShape*>(parent_comp->shape);
parent_comp_shape->addChildShape( child_comp->transform, child_comp->shape ); // "Assertion failed! !mCachedTransformOutOfDate"
}
Is this even the best way of doing this? Are there other designs that make more sense?
The immediate workaround that came to my mind was to simply make *every* physics-capable object a btCompoundShape object to begin with, with an attached 'main body'. Is this performant? Would it work acceptably well in a scene with 250-300 collidables (all things being equal)?
Thanks for your help.
-skosh