Devamardeep Hayatpur - CSC418 Bonus Assignment


Note: This article may not render correctly on Safari, if you see issues with the page, please switch to Chrome. It might also be a bit big, so feel free to zoom out to a comfortable size. A live version of this article is available here.

I love animations of "squishy" objects bouncing around and colliding with each other.

Softbody Simulation Playground by C4D4U

How to make Twizzlers by chargedcapactor

Softbody Tetris V8 by C4D4U

They are so satisfying to watch! I really liked C4D4U's Tetris simulation, what if it was an actual playable game?


These animations probably took a few hours to render out. But to make an interactive Tetris simulation, it must run in real-time. Ideally, I would also like for my game to run on the web, so, I tried out some of the existing physics simulation libraries.

My first attempt using ammo.js for physics, and three.js for rendering. Not stable!

The existing solutions were not robust or reliable. Here, I will describe my approach from a neat observation I made.


Observation

The soft body blocks in a Tetris simulation have a positional constraint: they can only move along the x and y axes.

Therefore, we can make a pretty good guess of how a block will look by just running a 2D soft body simulation on the xy plane, and extrude the result of that simulation into 3D. Running 2D soft body simulations is much easier than running a 3D soft body simulation, and can be done in real-time.

We can fake this 3D soft body simulation by considering just one slice of vertices (Drag to rotate).


Implementation

For the 2D physics simulation, I will use LiquidFun, an extension of Box2D with support for procedural animation of physical bodies. It was originally written in C++ but can be compiled to JS. I started off with a few blocks, and it seems to run well!

A few elastic shapes, the physics simulation runs at a timestep of 1.0 / 30.0 with 8 position iterations and 3 velocity iterations per timestep. Here, I used p5.js for the 2D rendering (live version).

Extending this 2D simulation into 3D requires a bit more work. Based on my 2D vertices, I did some geometry processing to create a jelly-like rounded rectangle block.

Unfortunately, I have not quite gotten around to creating the geometry for all faces, there was an annoying bug with constructing the left face of the object which I still need to fix.

3D soft-body Tetris-like blocks! Using Liquidfun and three.js (live version)

After I fix the faces, the next step is to make my own mass spring system to deal with these 2D simulations based on the work we used for A8. From what I can tell, LiquidFun is not optimized for running on the web.


Discussion

This seems like a cute solution to a very specific subset of 3D soft body simulation problems. But I wanted to see how far I can push it.

A lot of objects in real life have passive positional constraints, it's rare for us to move an object in all 3 positional DoF (degrees of freedom) simultaneously. For instance, bouncing a ball involves 2 positional DoF (on plane tangent to its curve), driving a car involves the 2 positional DoF along the ground (no flying cars yet!). Even hair on fur might be projected onto a 2D surface (i.e. the skin) where the actual physics simulation is running.

The path of a bouncing ball usually lies on a flat plane (unless it's really windy) (Drag to rotate).


3D Deformation

The objects in the other two soft body simulations I showed on the first page are also acting mostly on a 2D plane. But they are still deforming in 3D, which my solution does not adequately address.

Just extruding from the 2D simulation won't work well to produce the "blobby" shape.

I thought of two ways to approach this problem:

1. Instead of naively extruding from the 2D simulation, try to make an educated guess of the positions of new vertices based on properties of the object (i.e. elasticity).

But if the shape was something other than a blob (i.e. if it was a cylinder), then it'll be pretty hard to guess how the physics would propagate.

2. Run two 2D soft body simulations on xy planes at slightly different z-offsets. From the results of these two planes, interpolate the 3D position of all the vertices in the mesh.

Two planes, P1, P2 are placed at slightly different z-offsets. A 2D physics simulation runs on each plane which informs the final shape of our object (Drag to rotate).

This one seems promising! I did not get a chance to implement it, but I imagine we can use techniques from the last two assignments for minimizing an energy function. As input, we could use the vertices from the two physics simulations along with the original shape of the mesh and try to find positions for these vertices that are faithful to the original shape while setting vertices at those slices to their positions in the 2D physics simulation.


Positional Constraints May Change

Even though objects have positional constraints, the constriants may change over time (i.e. a ball might be bounced and change its trajectory). It could be interesting to have a physics simulation that somehow adapts to the motion of the object (meaning that the "physics plane" doesn't need to be static).


Groups of objects

Objects in a 3D scene are also usually placed at all kinds of 3D positions. It's unreasonable to construct a single 2D plane with a physics simulation than can somehow cover the entire scene. So, we can instead run various simulations for objects that are close to one another and have similar positional constraints.

Running more than one physics simulations for different "groups" of objects (Drag to rotate).


Other Types of Fluid Simulations

So far, I have looked at soft body simulations, which are a subset of fluid simulations (where the body is expected to retain its shape to some degree[1]). What about simulating other types of fluids, like water:

Water particle simulation from LiquidFun (live version).

I haven't made the actual water surface yet, to do that I will need to use an algorithm that can construct a surface from a bunch of points. One way to do this would to model my points as metaballs, and render them using marching squares. But there are probably way better approaches.


Some more thoughts

If two objects have different positional constraints, then there is no way to create a 2D physics plane that capture interactions between them. A complete system may fall back on a less robust 3D soft body simulation in this case.

For cases where an object's position is not constrained to 3DoF but is also not on a flat 2D plane, maybe we can run these simulations on 2D surfaces rather than 2D planes, i.e. with non-Euclidean physics, I have no idea how this would work but it's fun to think about.

Overall, I only got around to implement a very simple case of my idea, it's probably the case that everything I talked about doesn't work in practice. I hope this was an enjoyable read!


Acknowledgements

All interactive figures are rendered with Zdog.