Thank you! That's genius.. I'd had the same sort of idea as the method you're using, just wasn't sure how to implement it. The code's a little difficult for me to decipher (not used to freebasic syntax) but I'm sure if I spend a bit of time on it I'll be able to crack it. 2 initial questions though:
In the "get angular spring angle" section, how did you derive the method to get the angle of the joint? And I assume dotnormal is just the normalised dot product, or is it literally "normal" to the dot product in the sense that it's geometrically perpendicular?
Another thing.. you mention the spring torque based on sine angle being less efficient but faster - what do you mean less efficient? It seems like it'd be overall better as an optimization to avoid having to calculate the atan2 which'd require the cosine and sine.
I derive the angles between particles just like in your example, except that I store them both as scalar and a vector, where the x and y components represent cosine and sine angle. This is the same as a normalized distance vector. The dotnormal is exactly what you assume, the perpendicular dot product, or "2d cross product". Since a true cross product always returns a vector for any number of dimensions, and dot returns a scalar, I chose to call it that.
The sine based spring behaves slightly different from the "full" atan2 based one. Torque is largest at 90 degrees and goes towards zero as the distortion angle goes towards 180 degrees. This is due to the simple fact, that the value of sine is one for 90 degrees and zero for 0 and 180 degrees. The atan2 based spring works more like a Hooke's law spring in the way that it exerts a larger torque the more it is distorted. If you do not clamp angles to the (-pi, pi) range, you can even wind up the spring several full 360 degree turns.
And to save you a little trouble decipering my 600 lines of obfuscated, half finished code - this is how the spring works:
A simple "linear" Hookes law damped spring looks like this:
Force = -Stiffness coefficient * (length - rest length) - Damping coefficient * velocity projected onto normalized distance vector.
The corresponding angular spring looks like this:
Torque = -Stiffness coefficient * (angle - rest angle) - Damping coefficient * difference in angular velocity
Applying this between two rigid bodies is very simple, since angle and angular velocity data are already explicitly there. Applying it to sets of particles is slightly more difficult, because you have to calculate angle and angular velocity for each particle pair "as if" they were rigid bodies. We've already discussed anlge, but what about angular velocity:
Angular velocity = Angular momentum / moment of inertia
The moment of inertia for a particle pair is the sum of r^2 * mass, where r is the distance between the center of mass and the particle. The angular momentum is the sum of r cross momentum, which in this case is r dotnormal mass * velocity.
Hope this helps!
Cheers,
Mike