[Bullet] Linking a jointed model to a Bullet softbody rope

EDIT: 2019/03/08

This workaround is no longer necessary, as the mass glitch can be fixed by modifying the number of positions solver the softbody rope uses. This can be done by getting the cfg object of the rope with cfg = rope.getCfg() and setting a higher value via cfg.setPositionsSolverIterations(x), where x is a higher value that whatever the current value is where you are still experiencing the glitch.

This solution was discovered by @JoelStienlet on the Github issue report about this problem.

Mass Glitch Workaround:

You can anchor softbody ropes to heavy objects without causing this glitch by providing a bullet node with a lower mass (‘connector’) as an intermediate anchor point.
This is not a perfect solution, but might be enough in most cases.

Here is a step-by-step:

1 - Set up your scene, objects and rope as you intend.
2 - Instead of anchoring the chosen node of your softobody rope directly to the chosen object, create a ‘connector’. Here is an example of one:

from panda3d.bullet import BulletBoxShape, BulletRigidBodyNode

shape = BulletBoxShape(.2)
connector = BulletRigidBodyNode('connector')
connector.addShape(shape)
connector.setMass(0.01)

bullet_world.attach(connector)
render.attachNewNode(connector)

3 - Set up a “BulletGenericConstraint” with limits set so as to be a ‘parent’-type constraint between your ‘connector’ and the object you wish to anchor. Here is an example of such a constraint:

anchor_object : The object to which you wish to anchor your rope.

from panda3d.bullet import BulletGenericConstraint
from panda3d.core import TransformState

tsA = TransformState.makePosHpr((0,0,0)(0,0,0))
tsB = TransformState.makePosHpr(connector.getPos(anchor_object),(0,0,0))

parent_constraint = BulletGenericConstraint(connector.node(),anchor_object.node(), tsA, tsB, True)

parent_constraint.setAngularLimit(0, 0, 0)
parent_constraint.setAngularLimit(1, 0, 0)
parent_constraint.setAngularLimit(2, 0, 0)

bullet_world.attachConstraint(parent_constraint, True)

The last argument in ‘attachConstraint’, ‘True’, ensures the connector and anchor_object do not collide with eachother. As a result, a collision mask is not necessary to prevent it.

4 - Then, anchor the chosen node of your rope to the ‘connector’, as described in the original post.

NOTE: Softbody rope anchors are not immobile; which is to say that they can stretch if a force is imparted to them. As a result, if a heavy weight or another force pulls on a rope that is anchored to another object, the anchor points will stretch and move under the force thusly enacted. I have not yet found a solution for this.