Gabor Puhr wrote:
Originaly I implemented what is in Erin Catto's "Soft Constraints" paper (thoug the original formula is from ODE).
Unfortunately there are a lot of usefull parameters where the result is not very good. (for example because the CFM is greater than 1)
Also the energy dissipation it very big, so I couldn't setup a spring that oscillates.
So with my colleague Tamas Umenhoffer we created a new algorithm that works with a wide variation of parameters and the energy loss is minimal.
For the new 6dof:
Pros:
- Much more accurate and stable in a lot of situation. (Especially when a sleeping chain of RBs connected with 6dof2 is pulled)
- Stable and accurate spring with minimal energy loss that works with all of the solvers. (latter is not true for the original 6dof spring)
- Servo motor functionality
- Much more accurate bouncing. 0 really means zero bouncing (not true for the original 6odf) and there is only a minimal energy loss when the value is 1 (because of the solvers' precision)
- Rotation order for the Euler system can be set. (One axis' freedom is still limited to pi/2)
Cons:
- It is slower than the original 6dof. There is no exact ratio, but half speed is a good estimation.
- At bouncing the correct velocity is calculated, but not the correct position. (it is because of the solver can correct position or velocity, but not both.)
What makes it stable that as we discussed it creates two solver constraint instead of one if the lo limit and the hi limits are not the same.
Each one is responsible only for one side. This makes possible to create the solver constraints even when the typed constraint is not violated.
This is important because when an outer force or constraint causes error in this constraint the old 6dof started to fix it only in the second step (not in the one where the error was generated)
When the hi and lo are the same it generates only one solver constraint, but similarly to the upper case it happens always so it can react to any error immediately.
Creating everything always may seems a bit overhead, but the fact is once one starts to move a chain of rigidbodies (connected with constraints) there will be a lot of error almost immediately so even the old 6dof would generate the solver constraints (just not from the very beginning).
When everything is calm the RBs are sleeping so nothing is calculated. (so no overhead)
The spring is considered as a damped harmonic oscillator. As such the balance of forces is: F = -kx - cx' . (where the k is the stiffness and c is the damping)
It is calculated that what would be the velocity of the affected body (bodies) if this much force affect it. A solver can correct velocity. So the m_constraintError is simply set to a value to try to correct the body(es) velocity to this value.
There are two fail safe "if" to not overdamp or oversample the spring. Over and above the maximum force that this solver constraint can cause is limited to the F for pulling and -cx' for pushing.
The logic here is that the spring pull the object with the force of F, but if there is dumping it can cause opposite force if the object is pushed to the equilibrium point with a big enough second force. The maximum of this is the component caused by the damping.
The servo is a very minor modification of the motor functionality. Instead of stopping it at the lo or hi limit this constraints stop it at the servo target. (that is defined by the user)
Obviously hi, lo and servo target can be positioned relative to each other in a various ways, but it can be handled with a few "if".
I felt the bounce was a small hack in the old 6odf, but it worked (more or less), so I used a similarly approach.
When the m_constraintError is calculated I check the relative velocity of the two bodies (connected with the current constraint).
If it would cause a violation of the limits in the next frame (without the correction of the solver) then I assume there is a bounce in the actual step so I just simply calculate an m_constraintError that causes a velocity flip.
(I have to admit though that it took me some time to find out the correct handling of the stopERP here.)
Changing the rotation order is very strait forward, just have to swap the axises correctly.

Thanks for Tamas to deduce all the variations correctly.
There are a couple of new setter functions for the new functionalities at the end of the class definition. I hope the functions` name are self explaining.