Water Balloon Simulator

By Ryan Kehlenbeck































Overall goal of the project


    The Overall goal of the project was to create a water balloon mesh that can roll around in a 3D environment. The water balloon is procedurally generated, deformable, and collides with other objects in the world. The environment contains a ground level with a grass texture, boxes with a wooden box texture, and a “sun” that acts as a light source. The sun and balloon use Blinn-Phong shading with alpha blending so they are slightly transparent. The balloon is moved about the scene using the ‘wasd’ keys and moves with respect to the camera. The camera is a third person style camera focused on the center of the balloon that can switch between following the balloon or being locked to a certain position with the ‘f’ key.






























Technical difficulties encountered


Creating the Water Balloon


    The water balloon is generated using spherical coordinates. Given the center, radius, number of vertical subdivisions, and number of horizontal subdivisions, the location of each vertex in the water ballon can be found with the following formulas. The “knot” on top of the balloon is simply a circle of points connected to the north pole.


Bottom Point

South Pole = (center.x, center.y - radius, center.z)


Body

For [n = 1:horizontalSlices]

      [m = 0:verticalSlices - 1]

θ = π * ((horizontalSlices + 1) - n) / (horizontalSlices + 1)

φ = 2 * π * m / verticalSlices


x = center.x + radius * sin(θ) * sin(φ)

y = center.y + radius * cos(θ)

z = center.z + radius * sin(θ) * cos(φ)


Top Point

North Pole = (center.x, center.y + radius, center.z)






























Calculating Normals


    In order for the displacement of each vertex of the balloon to be visible, the normals had to be redrawn at every step. If they were not, the original normals would be used which would make the balloon always reflect light like a perfect sphere. The normal for each vertex is calculated by normalizing the sum of the normals for each adjacent face.


Face Normal

If a triangle consists of vertices a, b, and c:

v1 = b - a

v2 = c - a

face.normal = v1.cross(v2)


Vertex Normal

For each face:

a.normal += face.normal

b.normal += face.normal

c.normal += face.normal


For each vertex:

vertex.normal.normalize()


    The result can be seen in the following images where the partially flattened bottom of the balloon is not lit and the fully flattened balloon reflects all of the light properly.






























Physics


    The water balloon maintains its shape by keeping an array of displacements for each point in relation to the center of the balloon. The center of the balloon is then moved and the points adjust themselves accordingly based on the following formulas from the paper Meshless Deformations Based On Shape Matching. The expected position g(t) for each point is calculated at each step based on the center point and α is the stiffness factor between 0 and 1.


force(t) = mass * gravity

velocity(t + h) = velocity(t) + α * (g(t) - position(t))/h + h * force(t) / m

position(t + h) = position(t) + h * velocity(t + h)


    Even though these equations did move each point to its expected position, they ended up overshooting the position and the forces continued to grow. I added a random damping component to each point to create a wobble effect and gravity to make the balloon a little weighted. The formulas resulted in the following:


damping = randomFloat(-0.8, 7.5)

force(t) = mass * gravity - damping * v(t)


    The values used for stiffness and gravity were 0.01 and (0, -10, 0) respectively. This resulted in the balloon wobbling to a stop instead of overshooting the expected position or stopping at exactly the expected position right away.















Collision Detection


    In order to detect collisions between the boxes and the water balloon, at each step, each box takes the position of the water balloon’s center and the balloon’s radius and determines whether the point on the outside of the water balloon that is closest to the center of the box is at, or inside the bounds of the box. If the balloon is inside a box, the distance that it is inside of the box is added to the center of the balloon in the opposite direction of the collision, resulting in the balloon “bouncing” backwards.

























References

Wikipedia - For procedurally drawing a sphere

https://en.wikipedia.org/wiki/Spherical_coordinate_system

https://en.wikipedia.org/wiki/List_of_common_coordinate_transformations#From_spherical_coordinates


Stack Overflow - For figuring out how to calculate the vertex normals

http://stackoverflow.com/questions/16340931/calculating-vertex-normals-of-a-mesh


Meshless Deformations Based on Shape Matching - For the sphere physics

http://matthias-mueller-fischer.ch/publications/MeshlessDeformations_SIG05.pdf


Texturelib - For the grass texture

http://texturelib.com/Textures/grass/grass/grass_grass_0071_02_preview.jpg


Textures101.com - For the box texture

http://textures101.com/textures/Wood/Planks/2011/7/18/tn1_seamless_9_bcluz.jpg