I need a simple distance constraint to connect particles in a chain. So far, I am emulating it using Point2PointConstraint, which works very well, but my initial measures show that DistanceJoint would be much faster. I don't need pivots etc. Just spheres connected by theirs centers of mass.
I implemented it in JBullet (2.72) to try it out before moving to 2.82 C/C++ version. The code works fine for very small timestep = 0.001, it is noticeably vibrating for dt=0.002, and my model explodes using any larger timestep. The emulated version goes nicely up to 0.01, so there is clearly something wrong. I would really appreciate your help. There are few topics on Distance Constraint on this board but no working source code given.
EDIT: It turned out that the code is working fine. I will leave it here for the future reference. The instabilities were caused by a too rigid spring connecting the user-input proxy vector and the chain. Decreasing the stiffness solved the problem. The question is why it was stable using the Point2PointConstraint? The source code below was almost directly derived from p2p version.
Code: Select all
@Override
public void solveConstraint(float dt) {
float desiredDistance = 1.0f;
Vector3f vel = Stack.alloc(Vector3f.class);
Vector3f normal = Stack.alloc(Vector3f.class);
Vector3f posA = rbA.getCenterOfMassPosition(Stack.alloc(Vector3f.class));
Vector3f posB = rbB.getCenterOfMassPosition(Stack.alloc(Vector3f.class));
normal.sub(posA, posB);
float actualDistance = normal.length();
float depth = desiredDistance - actualDistance;
normal.normalize();
Vector3f velA = rbA.getLinearVelocity(Stack.alloc(Vector3f.class));
Vector3f velB = rbB.getLinearVelocity(Stack.alloc(Vector3f.class));
vel.sub(velA, velB);
//tau = 0.3f, damping = 1.0f, bodies invMass = 1.0f
float relVel = normal.dot(vel);
float k = 1.0f / (rbA.getInvMass() + rbB.getInvMass());
float impulse = (depth * setting.tau / dt * k - setting.damping * relVel * k);
appliedImpulse += impulse;
Vector3f impulseVec = Stack.alloc(Vector3f.class);
impulseVec.scale(impulse, normal);
rbA.applyCentralImpulse(impulseVec);
impulseVec.negate();
rbB.applyCentralImpulse(impulseVec);
}