I am working on a pretty ambitious project that enables players to build their own worlds using generic shapes and constraints.
The physical simulation runs into problems when the player chains number (more than one) of dynamic bodies via constraints to a static body.
If the mass of the bodies varies greatly the constraints tend to become very "soft" or break completely.
What feels odd is that I can attach very heavy object to a static body with no problem. If there is another body between them though both constraints tend to break. I do not need constraints that never break. What I would like to have is some consistency in behaviour.
I have reproduced this issue in the bullet example browser using this code:
Code: Select all
btCollisionShape* shape = new btBoxShape(btVector3(2, 2, 2));
m_collisionShapes.push_back(shape);
float mass = 1;
btTransform tr;
tr.setIdentity();
tr.getBasis().setEulerZYX(0, 0, 0);
tr.setOrigin(btVector3(btScalar(0.), btScalar(6), btScalar(0.)));
btRigidBody* pBodyA = createRigidBody(0, tr, shape);
pBodyA->setActivationState(DISABLE_DEACTIVATION);
tr.setOrigin(btVector3(btScalar(10), btScalar(6), btScalar(0)));
btRigidBody* pBodyB = createRigidBody(mass, tr, shape);
pBodyB->setActivationState(DISABLE_DEACTIVATION);
tr.setOrigin(btVector3(btScalar(20), btScalar(6), btScalar(0)));
btRigidBody* pBodyC = createRigidBody(mass * 300, tr, shape);
pBodyC->setActivationState(DISABLE_DEACTIVATION);
btTransform frameInLeft, frameInRight;
frameInLeft = btTransform::getIdentity();
frameInLeft.setOrigin(btVector3(btScalar(5), btScalar(0), btScalar(0)));
frameInRight = btTransform::getIdentity();
frameInRight.setOrigin(btVector3(btScalar(-5), btScalar(0), btScalar(0)));
{
btGeneric6DofConstraint* pGen6DOF = new btGeneric6DofConstraint(*pBodyA, *pBodyB, frameInLeft, frameInRight, true);
pGen6DOF->setAngularLowerLimit(btVector3(0, 0, 0));
pGen6DOF->setAngularUpperLimit(btVector3(-1, 0, 0));
m_dynamicsWorld->addConstraint(pGen6DOF, true);
}
{
btGeneric6DofConstraint* pGen6DOF = new btGeneric6DofConstraint(*pBodyB, *pBodyC, frameInLeft, frameInRight, true);
pGen6DOF->setAngularLowerLimit(btVector3(0, 0, 0));
pGen6DOF->setAngularUpperLimit(btVector3(-1, 0, 0));
m_dynamicsWorld->addConstraint(pGen6DOF, true);
}
I tried to address such situations by increasing number of solver iterations and setting higher constraint ERP. That is however not enough in some cases (and I don't want to use extreme number of solver iterations anyway).
I have also limited the maximum mass for a body in the simulation and I scale down the inertia tensor calculated if it's too big. It helps but it's dirty and I would like to get rid of such a hack.
I will be thankful for any hint or advice,
Petr