Material Point Method (MPM) Simulation
CIS563: Physically Based Animation — Fall 2020
C++, Houdini
Overview
I took a physically based animation course under Professor Chenfanfu Jiang. This course introduced me to physically based simulation techniques for animation of different substances, such as fluids, gasses, rigid and deformable solids, cloth, fire, smoke, and other systems. The topics covered in this course include particle systems, mass spring systems, cloth simulation, smoke and fluid simulation, and collision detection.
For the final project in this course, I implemented the Material Point Method (MPM), which is a technique used to simulate behavior of deformation of materials, representing the object as a collection of points.
Process: Setting up the Grid
I first set up the grid for the particles in order to simulate them. I have a set of variables such as resolution, grid node dimensions, total mesh mass, poisson ratio, Young’s modulus, dt, and obj file name. These can be adjusted to create different simulations. I will go through the steps for this:
First, I set the masses, velocity, and positions of the grid nodes to 0. The dimensions of the grid node are set in the parameters mentioned before.
Second, I initialize the positions for the cartesian grid in the positive direction based on the resolution and the dimensions.
Then, I set up the walls. For this simulation, I set up 6 walls which enclose the simulation in a “cube”. I push them into a vector of walls which will be used later.
After that, I use random sampling to get eight particles inside each grid block in the grid. I also initialize the deformation gradients to the identity 3x3 matrix for the particles.
I then import the selected obj file (for example, the bunny obj file) by using an obj reader. After iterating through the obj file to get the vertices and the triangles, I used the obj data along with the MeshObject class from Professor Robert Bridson’s library for mesh detection to determine whether a sampled particle fell within the mesh or not. After doing this, I get the final vector of sampled particles that I should be simulating on.
Process: Running the Simulation
I will go through the steps that I implemented for MPM.
Step 1
First, the grid attributes are cleared out, such as mass, velocity, and forces.
Step 2
In step two, the mass is transferred. This is done by looping over all the particles, and getting the 27 nearby nodes on the grid in reference to that particle, and aggregating the grid mass.
Step 3
This is done in the same loop as step 2. The momentum of the grid is updated by aggregating the multiplication of velocity, mass, and forces. This momentum is stored in the velocity variable, but will be updated in the next step.
Step 4
In this step, I iterate through all nodes i in the grid, and find the velocity by dividing every velocity by its corresponding node mass.
Step 5
After that, I apply gravity to each grid node.
Step 6
In this step, I iterate over every particle and get the nearby nodes for that particle. I then update the deformation gradient. Finally at the end of this loop, I update the force value. Then, for each grid node, I update the velocity. I do this by iterating through every grid node’s position. If the grid node’s position is in a ground/box/wall, then I have to set the velocity of that grid node to zero. I do this by iterating through every Wall and then checking if a collision occurs. If this evaluates to true, I set the velocity of the corresponding grid node to zero. Else, I update the velocity by taking into account the force and mass.
Step 7
In this step, I interpolate back to the point cloud. I do this by once again looping over all particles, then setting the particle's velocity to the zero vector, and then getting all the nearby nodes. For each nearby node, I update the particle’s velocity.
Step 8
In this step, I iterate through all the particles once more. For each particle, I initialize a 3x3 matrix to the zero matrix. Then, I get each nearby node. After that, for every nearby node, I update the matrix by performing a velocity calculation. Outside the loop for each nearby node, I update the deformation gradient per particle by using a force calculation.
Step 9
This is the final step of MPM. In this step, I move the particles with the corresponding velocity.
Simulated Results
Rabbit
Particles: 10,439
-
Poisson ratio: 0.3
-
Youngs_modulus = 5000
-
h = 0.025
-
Grid_side_index_count = 40
-
Total_mass = 900
-
Dt = 0.005
One Box (heavy)
-
Particles: 20,484
-
Poisson ratio: 0.3
-
Youngs_modulus = 10,000
-
h = 0.0142
-
Grid_side_index_count = 70
-
Total_mass = 800
-
Dt = 0.001
One Box (light)
-
Particles: 20,484
-
Poisson ratio: 0.3
-
Youngs_modulus = 20,000
-
h = 0.0142
-
Grid_side_index_count = 70
-
Total_mass = 400
-
Dt = 0.001
Two Box (different orientation)
-
Particles: 7,787
-
Poisson ratio: 0.3
-
Youngs_modulus = 5,000
-
h = 0.025
-
Grid_side_index_count = 40
-
Total_mass = 900
-
Dt = 0.005
Two Box (same orientation)
-
Particles: 14,902
-
Poisson ratio: 0.3
-
Youngs_modulus = 5,000
-
h = 0.02
-
Grid_side_index_count = 50
-
Total_mass = 900
-
Dt = 0.005
Reflection on Results
The results are what I expected for the most part. I wanted to see the difference that masses would make in the One Box heavy and not heavy simulation. The result made sense because the heavier jello box did not bounce as much as the lighter one. In addition, I wanted to test collisions by using two jello boxes at different orientations and these collisions can be seen from the result video as well. Overall, I think that if I had more time, I would want to try the different types of simulations through MPM such as snow.