2021.04.28
This release introduces more robustness, in exchange for changes to the default values for any Stiffness
and Damping
parameters.
- ADDED Solver Upgrade More realistic guides, at the expense of new default values
- ADDED Frameskip Protection Does what it says on the tin!
- ADDED Clear Initial State Return to a better time
- ADDED Passive Visualisation Understand which and when rigids are passive
- FIXED Start Frame Explosion Fixed a rare case overly eager passive rigids
- FIXED Negative Scale 2.0 Greater support for negative scale
- FIXED Rotate Order 3.0 Greater support for custom Rotate Order.
- FIXED Draw Shaded Rigids can now once again be wireframed, for less clutter whilst animating
Solver Upgrade
The solver has been upgraded for more accuracy and stability. Unfortunately, this changes the default values Stiffness
and Damping
attributes, which may require changes in your scene.
ATTENTION: Backwards Incompatibility
Ragdoll takes backwards compatibility very seriously. At no point should a scene you have created break because of an update. This however is an exception to that rule, one that I expect never to happen again.
What has changed?
Stiffness
and Damping
need higher values.
So far, we've used the Iterations
value on the solver to control how strong our constraints could be. As it happens, this isn't right. Iterations shouldn't control strength, it should only control how close the solution is to the true analytical solution.
- In the previous release, increasing this value produced an entirely different result based on how many iterations you used. At no point would it "converge" onto a true solution.
- In this and future releases, only stiffness and damping will affect the behavior of physics, with
Iterations
optionally bringing it closer to the true solution.
In practice, not much has changed. You should still increase stiffness/damping when relevant, and still increase Iterations
if you find the values aren't being respected.
What can I do?
- 👉 Increase
Stiffness
by 3-10x - 👉 Increase
Damping
by 3-10x
That is, if Stiffness
was previously 1'000, make it 10'000.
Exceptions
- For anything created with this version, no action is needed.
Projected Gauss-Seidel
(Advanced) remains unchanged.
It's not an exact science, in some cases you only need 3x, like in this case here.
Where the Yellow
line is from the previous version at 1'000 stiffness and 100 damping, the Blue
line has 3'000 stiffnes and 300 damping.
Why did this change?
The previous version was subtly faulty, so this was inevitable. In practice however, under a very particular - but useful - circumstance the solver would struggle to obey.
Circumstance
- An
Active Rigid
- Constrained to a
Passive Rigid
- Limits turned off
- Translate Guide turned
On
Use Cases
- Dynamic muscles attached to an animated skeleton
- Dynamic props attached to an animated character
- Dynamic cloth attached to a passive collider
- Basically anything that isn't a fully-dynamic character
Here was the result.
Notice how the active rigid does what the active rigid does, but is a little too excited? One workaround was to use "Projected Gauss-Seidel" in place of the default "Temporal Gauss-Seidel", however that solver isn't as accurate or fast.
You might be thinking..
Well that's an awefully specific case, when would I even hit that?
Which is when you realise..
This was previously only possible with Projected Gauss-Seidel which is less performant and less able to handle large networks of constraints like a full ragdoll.
Result
This behavior was due to a subtle bug in how constraints were solved, a deeply rooted bug that once sorted out was what caused this change to the overall behavior of Stiffness
and Damping
values.
In this release, the bug has been squashed and muscles and props now follow their passive counterpart much more accurately and without surprises.
Frameskip Protection
The simulation is like a train running on a train track. It absolute must not miss a stop, else it can't realistically figure how how to get to the subsequent stop.
Allow me to demonstrate.
Notice how everything falls apart when skipping just a handful of frames? It's trying to catch up, but the time difference is just too great to produce accurate values.
This release adds support for pausing the solver whenever a frame is skipped, meaning you either get a (A) good solve or (B) a patient solver, awaiting your return.
The behavior can be disabled in the Preferences.
Why should I care?
Consider your everyday situation of adding dynamics to a tail.
Whenever a frame is skipped, the result is garbage. This can get even more extreme during more extreme movements. But, what's worse, this garbage is expensive! It's still simulating, and trying to solve these skipped frames is more expensive than non-skipped frames. That's a bad deal.
Here what happens with frameskip protection.
See how it just stays put? It'll remember the last simulated frame, awaiting your return.
Clear Initial State
Setting the initial state can be used to relax a physics character or scene.
But once relaxed, you had no way to returning to its original creation state, until now!
- The set and cleared state are both saved with the scene
- This can rescue the initial state from breaking due to Automatic Initial State
Thanks to Jason Snyman for this suggestion!
Passive Visualisation
Rigids will now turn gray when made passive, making it easier to understand what's going on visually.
Start Frame Explosion
In a specific and rare circumstance, a passive rigid body could appear to have velocity on the start frame.
Notice here how animation starts immediately from the start frame, giving it an upwards velocity? The active rigids connected to the root on the other hand gets an even stronger velocity, for some reason.
If we move the animation to just one frame after the start frame, all is well.
A subtle bug, having to do with the rigid body being created on the second frame of the simulation, which in this case had a position the was different from the start frame. However! The animation started at the start frame, so the velocity got inherited from there instead. Yes, it's complicated. :)
And is now fixed!
Negative Scale
Ragdoll has supported scale, but negative scale has been unreliable. This release extends this support to negative scale used to mirror controls and behavior across a rig.
Before
This whole arm has a negative scale in the X-axis, from when it was mirrored across from the other side. Notice here how it look like the arm is about to move forwards, and instead move backwards.
After
This has now been fixed.
It also means you can flip entire performances with a little more ease. :)
Caveat
Avoid negative scale on the control you are animating.
- ✔️ Global negative scale
- ❌ Local negative scale
You are still better off not having any negative scales in your rig, as there is still at least one special case I found that might jump up and bite you.
And that is if the animated control itself has negative local scale.
Typically, one or more of the parents have negative scale, so as to mirror a whole hierarchy of controls. And that is ✔️. But if the control you are animating also have negative scale, you might experience this.
Notice how on rewind, it twitches at the start of playback every other time? That's because it cannot tell the whether the control has negative scale or whether it is rotated 180 degrees.
This will be addressed in a future release.
Rotate Order
The animation constraint is what translates your keyframes into physics and with the introduction of support for Rotate Order in the previous few releases it has been possible for Ragdoll to output rotations onto any control with a custom rotate order.
This release now includes support for input of custom rotate order into the simulation.
Before
Notice how changing the rotate order should have changed the axis around which the Y-animation was happening, but didn't?
After
Now it does!
Draw Shaded
The previous release revamped the rendering system in Ragdoll, but left out a the convenience attribute to disable shading when rigid bodies were used alongside animation controls.
Before | After |
---|---|
Manual Override
The behavior can be manually adjusted to taste via the Attribute Editor.