YL2 - Soft body physics odyssey
We hope you're doing great!
After last month's intense work on the character creator, we were quite exhausted and wanted to take some time off. So of course I spent this time creating a custom soft body physics engine, LOL.
Before you get your hopes up - no, we still don't have a viable method for soft characters in YL2. But this work goes to show our commitment to getting fat simulation into the app as well as reducing clipping.
Read on to discover what we have tried so far and where we may go in the future.
Soft body dynamics
Soft body dynamics is a huge topic covering the behaviour of so called "soft bodies". Unlike "rigid bodies", soft bodies are able to deform (change their shape) to adapt to external influences. This makes them suitable for simulating cloth, balloons, jelly and rubber. Our hope was that we could try to adapt this technique to work on characters.
Soft body physics is something we have touched on before. In our previous attempt at it, we were using a very fake method to achieve this effect:
While it may look OK for this very specific scenario, this is not a "proper" soft body system, but rather a simple shader trick. Each vertex has no concept of its neighbors. This means if you were to texture the object, distortion would become very apparent:
(Surface is distorted by this method, which is easily noticeable on a textured surface.Open the link below.)
This method also doesn't handle multiple collisions very well, and can start clipping if too many objects interact with it:
(Multiple intersections not working as one would expect. Notice that the cube doesn't start to "take" until it has already clipped quite a bit through the object. Open the linkbelow.)
It's also challenging to get this technique to work universally on characters. Since we're not relying on physics but tricks, it means we have to do tons of "fake" tweaking to make it look good, and even then there will probably undesirable behaviour in certain circumstances.
Soft body realtime simulation
"Real" soft body dynamics (not the shader trick above) is very computationally heavy, which is why it has previously been the domain of film and other pre-rendered media. However, with modern hardware and greatly parallelized algorithms (often times accelerated by GPUs) this is now becoming feasible to do in real time.
There are already several external libraries handling soft body dynamics in Unity. Currently, "NVIDIA Flex" and "Obi Soft body" are the two main contenders, but there have been more. Sadly, because of the very difficult and niche nature of soft body physics, the market for it doesn't seem to be the most lucrative. Several soft body libraries have been made for Unity only to be discontinued from what I assume is lack of funding and consumer interest.
Problems with external libraries
While current soft body libraries are very featured and optimized, they have the huge draw back that they're not designed with changing objects in mind. You're only meant to initialize a soft body once and then put into the simulation. That is a big problem for us, since we need to be able to support inflation, which essentially alters the shape of the character and thus would require a reinitialization. While it is possible to reinitialize shapes in these libraries, you're not meant to do it frequently, more as a pre-computation step, so there is a significant hiccup each time you do so. Furthermore, the particles are reset in the process.
Obi also has the drawback that it runs on the CPU, and since we have a custom method for skinning that runs on the GPU, it means we would have to fetch data from the GPU, process it through Obi on CPU, and then push it back to GPU which is a very slow thing to do.
By creating a custom soft body physics engine, we are free to design it with inflation in mind from the very start, so we're able to change shapes in it with virtually no penalty.
For the past couple of months, I've been reading up like crazy on the latest research regarding real time soft body dynamics. After our intense work on the character creator, I felt like I was about to burst unless I got a chance try out my ideas. So with the "time off", it felt like a perfect opportunity to finally have a stab at it.
Custom soft body physics engine - Results
NOTE! We recommend opening the gyazo links below each image for the experience.
Essentially how a modern soft body physics engine work is through so called "constraints". Each constraint has a very specific purpose, such as limiting the distance between particles. The engine then just steps through all the particles, applies the constraints, while also applying things like gravity and checking for collisions.
The core engine and its constraints took about two weeks to implement. We started with simple balls, which is like the "hello world" of soft body physics, before moving on to more complex shapes.
Firstly, we just wanted to get gravity, velocity and collision going:
(A soft body, w/o any constraints, colliding with a sphere.)
(Same scenario, but this time a constraint limiting distance between neighboring vertices has been added to the simulation.)
Each collider shape had to be manually implemented into our custom physics engine. Sphere is the most simple shape, but eventually we managed to get all the math and algorithms to handle box colliders as well:
(Collision against box colliders.)
Next, we started working on more constraints to better approximate a soft body ball:
(A volume constraint trying to retain the object's initial volume by simulating internal pressure.)
(Volume constraint being applied in slow motion.)
(A bending constraint trying to retain each triangle's angle towards neighboring triangles.)
(Volume constraint + bending constraint working together.)
(Volume + bending in slow motion. Unfortunately an older iteration, but couldn't find a more recent recording.)
(Volume + bending later iteration performance test.)
(First test of soft bodies interacting with eachother using sphere proxies.)
(Later iteration on soft body vs soft body collision. Using different method to better approximate collision.)
(Same as above but placed closer to eachother.)
By the time we had these results, we started feeling ready to try and apply these effects on a character.
(Smashing a cube into the butt cheeks of a simulated soft character.)
(There is an invisible collider on her right side, in case you wonder why her right butt cheek is being affected.)
Despite the wobbliness, there's something fun and appealing about it. But it's definitely too wobbly to be viable, unfortunately. Of course we are able to make it less wobbly and make it match the skinned position more closely, however, that would also loose its soft behavior, which is why we wanted to do this in the frist place. And this is the core of the problem which we are facing with this tech - how do we actually combine soft body physics with an animated character?
Next, we tested the very scenario that made us go for our own custom implementation in the first place - inflation.
(Belly being inflated while an obstacle is in the way. Open the link below.)
(Smashing a box into an inflated belly. Open the link below.)
(Inflated belly reacting to multiple collider influences, and correctly adjusting its shape w/o any clipping. Open the link below.)
Even though the tech is far too wobbly to be viable, it was still fun to see it fully realized in regards to inflation.
In case you weren't convinced about the problems with this tech - a final video:
(Things going crazy when trying to match a position. Open the link below.)
Again, the big question here is how we're supposed to combine this technique with animated characters, because as you can see here, when moving the character around, things get crazy, and it's not simple to solve by just tweaking variables. It may very well be that this tech is fundamentally unsuitable for this type of problem, which is not necessarily that surprising when thinking about it. Essentially what we're doing here is simulating a surface and an internal pressure. But that's not how bodies work. A body is made up of bones and flesh, not a surface inflated by air. So it's not surprising this doesn't behave as flesh and bones.
Perhaps another approach to solve this problem could be to use something like NVIDIA Flex does, with simulations of volume (voxelized shapes) rather than surface. However, then we're back to square one with how we're supposed to reinitialize a voxlized soft body to match a new shape (after inflation is applied) in a fast and efficient manner, not to mention how translation between the old voxelized shape and the new one is supposed to work in order to retain particle state.
Perhaps a future approach could be something more like our original one, with using a simple constraint to offset vertices, but maybe there's a way to do it without causing so much distortion. Or perhaps there's a way to combine these two technologies into a new one.
While this soft body implementation didn't pan out the way we were hoping, I'm still happy I spent this time working on it. I needed to try out these ideas. Now when we know it isn't a viable path, we are free to explore other options. We've learnt a lot from implementing it.
We may also be able to salvage parts of it, or perhaps use it for other things than characters (like cloth).
This month, we took some time off working on the character editor, and instead went back to exploring soft body physics. We implemented our own soft body physics engine. While the results are quite fun, they aren't what we were looking for. It seems we will have to look elsewhere for a more viable method.
Enjoy your weekend!