We implement 3D snow simulation using the material point method (MPM) and a renderer in OpenGL. Snow is extremely challenging to simulate because it has material characteristics of both liquids and solids. The MPM simulation approach is implemented based on a 2013 paper by Stomakhin et al., and offers a reasonable runtime and control over some intuitive properties of the material. We show that plausible results can be obtained even with relatively coarse particle and grid resolution, and replicate some of the demonstrations from the original paper. We also implement basic 3D rendering of snow scenes, and iteratively implemented optimizations to improve simulation runtime.
There are many ways to simulate snow, each with strengths and weaknesses. Mesh based methods have significant trouble modeling fracture, because of the need to explicitly define fracture of a contiguous solid. Pure grid based methods struggle with plasticity because deforming a grid results in a great deal of nonlinear computation. And particle-only methods suffer from inefficiency due to a high demand for nearest neighbor queries to compute dynamics. The material point method is a simulation method well-suited for continuum materials. MPM addresses these problems by using the grid as a "scratch-pad" for computations, while maintaining Lagrangian state as point particles with mass, volume, and velocity. MPM is mesh-free and avoids directly computing interactions between particles by interpolating particle properties onto a 3D grid, a computes physics on this grid.
Our simulator defines as primitives snow particles and rectangular/planar interactable collision objects. Our implementation of MPM closely resembles the implementation provided in the paper. Here is an overview of our approach, numbered consistently with the diagram above:
We decided to focus on physics over rendering for this project, and approximated the appearance of our snow by rendering the particles as translucent cubes. This gives us the ability to see how densely the snow packs, while avoiding the overhead associated with rendering using a volumetric pathtracer, which is the suggested method.
Our rendering is done using OpenGL primitives. We populate the VBO and VAO appropriately for a few types of objects, notably cubes, planes and grid lines.
Simulating snow with a large number of particles is extremely computationally intensive, even using a relatively efficient method like MPM. We found our code to be prohibitively slow on first draft, and took numerous steps to speed it up. Some examples:
Our implementation also provides a way to save simulations as videos. In addition to the live rendering, the program optionally saves the rendered frames into an .avi video file. This is especially useful for rendering at high grid resolution to improve physics accuracy, where each frame takes a few seconds or minutes to compute.
The biggest problem we encountered was runtime efficiency. Our initial implementation focused on getting everything to work, but was very inefficient, so after the initial implementation, we spent a lot of time rewriting the code for efficiency, as described in the "Optimization" section. With greater optimization came increasing complexity, as we discovered/introduced weirder and weirder bugs in our code over time.
Another major challenge was CMake, and integrating/compiling the various libraries we used. This was our first time working with CMake. Each library seemed to have a slightly different way of integrating, and given our limited experience, figuring it the integration involved much trial and error. Furthermore, we were entirely unable to compile our project on Ubuntu machines (e.g. home desktops, instructional machines) due to system-specific compilation issues.
Starting this project, we worried that it would be next to impossible to debug our simulation code. Since the individual steps don't have a very interpretable or testable effect on the particles, we figured it would be hard to tell if our computations were accurate. Even visualizing something like the grid forces would yield vague insight at best without additional expertise. Ultimately, what we are all intuitively familiar with is the visualized dynamics of snow, so we eventually were forced to simply visually inspect our results for debugging. This ended up being easier than we thought; some bugs exhibit quite obvious patterns when visualized, especially when the simulation quality is reduced to allow for real-time simulation for debugging purposes. Between this and careful proofreading of the code, we were able to catch all the bugs. In the future, if the source materials provide clear explanation (which the Stomakhin paper generally did), we can be less wary to implement our pipeline end-to-end.
Despite our optimizations, we were not able to scale up our simulation to reference numbers given in the Stomakhin paper. However, we were still able to see some plausible snow dynamics. This is a good reminder that in graphics, one's work does not have to be perfect to produce valuable results.
On the other hand, in terms of frameworks, setup and system specifics, we underestimated the degree to which problems would arise. This may partly be the result of us starting our project on a barebones basis, and may also be partly because graphics code appears to be very beginner-unfriendly. There doesn't seem to be any way around this other than just getting good at it, but good to keep in mind.
We demonstrate some of the simuluation results in this section. Note that in all demonstration videos, there exist transparent walls on the four sides of the scene area, and snow particles will collide and stick to these walls, despite being transparent.
There are four main physical parameters that control the material property of the snow, and by tuning these coefficents, we can create different types of snow. The hardening coefficient and Young's modulus determines how fast snow breaks apart, and controls whether the snow is brittle/icy or ductile/watery. The critical compression and critical stretch are two parameters that determine when snow breaks apart, and whether snow is chunky/wet or powdery/dry.
|
|
|
|
|
|
We'll also demonstrate how snow interacts with rigid objects. Here, a rigid cube "cannonball" hits a tower of snow at two different velocities.
|
|
Here is a "snowplow" throwing up snow.
|
Here, a snowball crashes into the wall. Note that upon collision, a portion of the snowball fractures and falls off, while another portion sticks to the wall and falls off slowly.
|
Ankit bootstrapped all of the OpenGL setup (shaders, VBO/VAO/basic drawing stuff) as well as wrangling with GLFW. He implemented most of the user/GUI features e.g. camera panning/movement, and also discovered and/or wrote many of the simulation optimizations. Finally, to his great disdain, he also tackled a great many CMake-related issues.
Andy set up the libraries and the first 3 steps of the physics simulation using GLM and Eigen, including the initial code for interpolation, SVD, etc. He also implemented several features in collision code, set up test scenes, and determined good demos for said scenes by tweaking simulation parameters. Finally, he worked on the milestone and final submission deliverables.
Brandon wrote the rest of the physics simulation and optimized grid node usage. He also took care of refactors to the Grid class, wrote collision code, set up test scenes, and wrote sampling routines to populate snow objects with randomly distributed particles. Finally, he also worked on the milestone and final submission deliverables.