Search code examples
c++physics-enginebulletphysicsbullet

How to make a spring constraint with Bullet Physics?


I want to test the spring contraint of Bullet Physics. So I created a static box hovering above the ground and a second dynamic box hanging down from it. But activating the spring behavior does nothing! The box is indeed hanging freely. I know it because it rotates freely. But it does not oscillate or anything.

btCollisionShape *boxShape = createBoxShape(0.2f, 0.2f, 0.2f);

btRigidBody *box1 = createStatic(boxShape);
btRigidBody *box2 = createDynamic(1.0f /*mass*/, boxShape);

box1->setWorldTransform(btTransform(btQuaternion::getIdentity(), { 0.0f, 2.0f, 1.0f }));
box2->setWorldTransform(btTransform(btQuaternion::getIdentity(), { 0.0f, 1.0f, 1.0f }));

btGeneric6DofSpring2Constraint *spring = new btGeneric6DofSpring2Constraint(
    *box1, *box2,
    btTransform(btQuaternion::getIdentity(), { 0.0f, -1.0f, 0.0f }),
    btTransform(btQuaternion::getIdentity(), { 0.0f,  0.0f, 0.0f })
);

// I thought maybe the linear movement is locked, but even using these lines do not help.
// spring->setLinearUpperLimit(btVector3(0.0f,  0.1, 0.0f));
// spring->setLinearLowerLimit(btVector3(0.0f, -0.1, 0.0f));

// Enabling the spring behavior for they y-coordinate (index = 1)
spring->enableSpring(1,  true);
spring->setStiffness(1, 0.01f);
spring->setDamping  (1, 0.00f);
spring->setEquilibriumPoint();

What is wrong? I played a lot with the the Stiffness and Damping parameters. But it changed nothing. Setting linear lower and upper limits makes the box movable in the y-direction, but it still not oscillates. And yes, gravity is activated.


Solution

  • Ok, I found a solution by checking out Bullet's provided example projects (could have come up with the idea earlier). Three things I have learned:

    • The spring constraint will not violate the linear limits. The problem with my former approach was that the linear movement was either locked, or limited to a too small range for the assigned spring stiffness. Now there are no more limits (by setting the lower limit above the upper one).
    • The stiffness was far too small, so the joined objects were acting as if they were freely movable inside the linear limits. You can check out the values in my code below, I got them from the example project.
    • There is a small difference in the behavior between btGeneric6DofSpringConstraint and btGeneric6DofSpring2Constraint. The former one seems to violet the non-spring-axes less (x- and z-axes in my case). The latter one seems to apply a stronger damping. But these are just first observations.
    btGeneric6DofSpringConstraint *spring = new btGeneric6DofSpringConstraint(
        *box1, *box2,
        btTransform(btQuaternion::getIdentity(), { 0.0f, -1.0f, 0.0f }),
        btTransform(btQuaternion::getIdentity(), { 0.0f,  0.0f, 0.0f }),
        true
    );
    
    // Removing any restrictions on the y-coordinate of the hanging box
    // by setting the lower limit above the upper one.
    spring->setLinearLowerLimit(btVector3(0.0f, 1.0f, 0.0f));
    spring->setLinearUpperLimit(btVector3(0.0f, 0.0f, 0.0f));
    
    // Enabling the spring behavior for they y-coordinate (index = 1)
    spring->enableSpring(1,  true);
    spring->setStiffness(1, 35.0f);
    spring->setDamping  (1,  0.5f);
    spring->setEquilibriumPoint();