Authors: Kehan Xu (LinkedIn | Github | Personal Website), Fengshi Zheng (Github) and Jiahong Wang
This is our group project for Physically-based Simulation course at ETH Zurich. We implemented position based fluids (PBF) in 3D space with Taichi, a high-performance parallel language wrapped in python.
When doing fluid simulation, fluid is modeled as a bunch of small particles. Enforcing incompressibility (i.e. constant density) is crucial to achieve visual realism.
Position based fluids follows the idea of the position based dynamics framework: it proposes an iterative density solver to solve a set of positional constraints that enforce constant density.
Position Based Fluids yields stable simulation even under large time steps, while still achieving similar incormpressibility and convergence to smoothed-particle hydrodynamics (SPH) method.
We follow the method described in the PBF paper, including the improvement of vorticity confinement and XSPH viscosity (Section 4 and 5).
Pseudocode of the simulation process:
For each iteration:
For each particle:
Update velocity with external forces
Update position with updated velocity
Modify position to meet the constraints (constant density)
Re-compute velocity with the modified position
We also add logic for object collision so as to not only simulate fluid itself but also meshes surrounded by fluid. In this case, the collision is between the object and multiple fluid particles. The method to model collision by imposing nonpenetration constraints is referred from here.
Simply run python main.py
to start fluid simulation.
You can adjust parameters for fluid simulation and visualization in config.py
.
The implementation of position based fluids is in pbf.py
. rigidbody.py
contains the code for object collison.
In every frame, the simulation output is a bunch of particle positions. We use splashsurf to reconstruct surface for particle data. The generated water mesh is then rendered using Blender, along with other objects (ball, torus, terrain etc.).
We have written a script for this purpose, see the rendering branch.