如何使用 Bullet Physics 进行 spring 约束?

How to make a spring constraint with Bullet Physics?

我想测试 Bullet Physics 的 spring 约束。所以我创建了一个悬停在地面上的静态盒子和一个从它上面垂下的动态盒子。但是激活 spring 行为没有任何作用!盒子确实是自由悬挂的。我知道它是因为它可以自由旋转。但是它不会振荡或任何东西。

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();

怎么了?我经常使用 StiffnessDamping 参数。但它没有改变。设置线性下限和上限使盒子在 y 方向移动,但它仍然不振荡。是的,重力被激活了。

好的,我通过查看 Bullet 提供的示例项目找到了解决方案(本可以更早地想到这个想法)。我学到的三件事:

  • spring 约束将不会 违反线性限制。我以前的方法的问题是线性运动要么被锁定,要么限制在指定的 spring 刚度范围内太小的范围内。现在没有更多限制(通过将下限设置为高于上限)。
  • 刚度太小,所以连接的物体表现得好像它们可以在线性限制内自由移动。您可以在下面的代码中查看这些值,我从示例项目中获取了它们。
  • btGeneric6DofSpringConstraintbtGeneric6DofSpring2Constraint 之间的行为略有不同。前者似乎减少了非 spring 轴的紫罗兰色(在我的例子中是 x 轴和 z 轴)。后者似乎应用了更强的阻尼。但这些只是初步观察。
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();