Cloth Simulation Using Numerical Integration: Fans
A Project By Maxwell Omdal & David Kinney
With this project, we implement a cloth simulation using the midpoint integration technique. The cloth is first defined using a series of springs connected in a grid, and then using Hooke's law and numerical integration, we update the position and velocity of the cloth at each time step. However, in a vacuum, cloth does not behave very interestingly, so we implemented air drag and sphere-based collision detection. At the end, we'll introduce our attempt at collision detection on more complex meshes using a node-triangle intersection algorithm, and an octree to reduce computation.
We downloaded this free image of the earth here.
Controls
- To orbit the camera, use the arrow keys.
- To interact with the cloth, click and drag around it and a fan will appear
- Reset the animation using the 'R' key
- To pause, press SPACEBAR
User Interaction
We wanted a way for the user to interact with the cloth, and we wanted it to feel playful. Since we had an implementation for air drag on the cloth, and a robust collision detection system, we decided we'd let users click on the screen to cast a fan into the 3D space that would adjust the "wind" direction. To help users visualize the direction of wind, we spawn a particle emitter at the fan's location and blow dust particles in the "wind" direction.
Simulating Cloth
The cloth can be modeled as a collection of interconnected springs, and we track the nodes where the springs connect. For each node, we have a velocity and a position attribute. Using numerical integration (the midpoint method), we can estimate the continuous updates in the positions of each node using a discrete technique. Using Hooke's law, as well as the masses assigned to each node, we can calculate every node's acceleration, and integrate to get the velocity and position. For each frame, we can then define the number of time steps we would like to take, or the number of discrete updates per frame. The cloth class is flexible, making it easy for us to add more nodes, change the size, stretch, and color.
The cloth successfully responds to collisions with spheres. If a cloth collides with a sphere, a portion of its velocity is reflected, to imitate an elastic collision, and a portion of its velocity directed into the sphere is lost, to emulate the transfer of energy to the mesh.
Air Drag
In addition to the per-vertex physics calculated for the springs, the user can also direct a wind force by holding down the left mouse button near the center of the screen. This places a fan at the mouse's current screen position and blows a current of air in its direction. The force this places on the cloth is calculated using Raleigh's drag equation and is applied to each triangle in its mesh.
Realistic Simulation
Although our simulation is only an approximation of real physical interactions, we wanted it to appear as natural and realistic as possible. To do this, we compared the motion of a towel when a blowdryer was directed at it, and we tried to match this motion as closely as possible with our fan interactions.
Full Demo
Future Work: Octrees and Complex Meshes
We attempted to create a system for handling triangle-based mesh collisions with the cloth, but we fell short, after not being able to find the proper collision response. One of the challenges with this type of approach is the computational expense of testing thousands of triangles multiple times a frame for multiple nodes. If we have a cloth made up of 2500 nodes, and a mesh with 5000 triangles it would require 2500*5000=12500000 collision tests. In order to reduce this, we implemented octrees that recursively divides our mesh and greatly reduces the number of computations by only checking the triangles in the octant that the node is in. So, for example, if we set the max number of triangles per octant to 20, then there would be 2500*20=50000 triangle-line collision tests and about 2500*3=7500 line-box collision tests for a total of 57500 tests, which is only 0.46% of the tests required without an octree. This is possible because the octree is computed at setup, and only has to be computed once.