CSCI 5611: Animation and Planning in Games
Theory behind algorithms used to bring virtual worlds to life. Computer animation topics. Real-time, interactive techniques used in modern games. Physically-based animation, motion planning, character animation, simulation in virtual worlds.
Bouncing Ball (Assignment 1 - Check In)
3D OpenGL rendering of a bouncing ball. It uses OpenGL, GLEW, GLM, and a custom shader manager based off of a homework assignment for CSC5607 Fundamentals of Computer Graphics by taught by Dr. Victoria Interrante.
This check in includes multiple camera angles. Pressing B tracks the ball while aligning the camera and increasing the projection draw distance keeping the platform in view. Pressing R resets the view to an orbiting camera.
A fragment shader and vertex shader was used to calculate lighting.
Particle Systems (Assignment 1)
I developed the animation in OpenGL with two separate GLSL shaders (one for phong illumination, and the other for particle rendering). I used tinyobjloader to load the 3D models and stb_image to load the textures.
The water simulation (without transparency) benchmarked at 212,408 particles at an average 36 frames per second on my laptop. With transparency (like the fire), I averaged ~50k particles at 40 frames per second.
I attempted to use animated textures for the camp fire, but was unable to completely animate the textures by the due date. It did create a pretty interesting visuals though!
Two required simulations in context. Water hydrant and Camp site fire
3D user-controlled camera (rotation and translation)
Particle obstacle interactions (water particles with the ball, cauldron interaction with the fire)
All four performance benchmarking (212,408 particles at an average 36 fps, thanks C++!)
[Attempted, see video] textured sprites for particles
Art Contest submission
The biggest difficulties I encountered were concerning the multiple shaders, loading the OBJ files, and wrangling all the vertex buffer objects. I had extremely limited experience with OpenGL (just a few weeks near the end of CSCI 5607), so the entire process was a learning experience. This submission doesn't have the polish I would like it to have had, but I feel like I understand OpenGL significantly more after this assignment.
Vertical Spring System (Assignment 2 - Check In)
In this assignment we will be creating a cloth simulation. For assignment 2 check in, we were expected to create a vertical thread modeled after a system of springs.
In addition to the spring simulation, I also added a few additional features to my base simulation:
Added the ability to press 'p' to enable picking mode, then drag to move draggable objects (accomplished via ray-casting)
Added the ability to press SPACE and SHIFT move up and down, respectively.
Smoothed the camera movement by moving a camera target, then linearly interpolating the eye position to that target.
Began investigating spatial hashing for object collisions. Inspired by Optimized Spatial Hashing for Collision Detection of Deformable Objects. The code has been commented out for this check in submission.
Physical Simulation (Assignment 2)
In this assignment we focused on physical simulations. I created a semi-advanced cloth as well as a 30x30x30 3D Eulerian Fluid simulation.
Realtime rendering (see video for FPS, usually ~50/60)
3D rendering, with a user-controlled camera (WASD, space to go up, shift to go down)
3D Mass-spring cloth simulation
Drag-terms (see cloth dragging on the table)
1-way cloth-object interaction with the rectangular table
Demo video shows a 30x30 cloth with obstacle interaction. Demo also shows a 60x60 flag.
Textured simulated objects (red cloth, American Flag)
Thread-parallel implementation with OpenMP. Allows the stable 60x60 flag. Maxes out at a 200x200 flag, but the threads become too long to render and increasing K makes the simulation unstable.
Attempted a spatial-data structure. Did not complete self-collision, so spatial-data structure was untested.
Billowing.blowing wind effect simulated with aerodynamic drag.
Attempted self-collision. Ran into issues with the triangle intersection and did not complete in time.
Extended the Stam GDC '03 paper with a 3D Eulerian fluid simulation. The demo shows the first attempt with water, which did not turn out very well. I had some issues imposing external forces (gravity) without the water disappearing, so I pivoted the fluid to be a smoke/fog. The demo shows a 30x30x30 simulation in the context of a steam engine locomotive.
In the additional video below, I demonstrate a 38x38x38 3D Eulerian fluid simulation at 30fps which exceeds the highest performance expectation of 200x200 (54,872 > 40,000).
Art contest submission.
At any time during the simulation, press P to toggle between picking and flying around. When picking, the mouse ray casts to the cloth. The controls of the 3D Eulerian fluid is E to emit smoke. G for gravity. And the arrow keys for directional forces.
The code is split between three branches in github.
'assignment2' is the cloth table.
'assignment2-flag' is the flag
'assignment2-fluid-3D' is the 3D simulation.
C++ / OpenGL (with shaders)
GLM for vectors
OpenMP for thread processing
Tinyobjloader for loading obj
stb_image for texture loading
Reference: Jos Stam, "Real-Time Fluid Dynamics for Games". Proceedings of the Game Developer Conference, March 2003.
"A Fast Triangle-Triangle Intersection Test" by Tomas Moller, 1997.
Motion Planning (Assignment 3 - Check In)
In this check-in, I have created a 0.5m radius game character is in a large 20m x 20m room. The character starts at the bottom left (-9,-9) and when the user presses N (for navigate, it navigates to the top right (9,9). There is a single obstacle in the room, represented by a sphere of radius 2 meters at coordinates (0,0). The user can also press M to navigate the character back to -9,-9 for a looping demo.
I am using a probabilistic roadmap (PRM) to plan a path for the agent from the start to the goal. It uses Dijkstra's algorithm for the path finding.
The code is in the #assignment3-checkin branch of my main opengl-animation repository.
Motion Planning (Assignment 3)
In this assignment, we focused on building a motion planning framework used to animate groups of agents navigating in complex environments.
For my assignment, I implemented:
Boids local interaction technique
PRM and A* global navigation strategy
The roadmap accounts for the extent of the agent with multiple obstacles
Agents are able to successfully navigate through environments with local minima
Nicely rendered 3D scenes with models to give context
Supports full 3D navigation with 3D flocking birds
The user can add and move obstacles at run time (Press "I" to interact
Dynamically choose agent start and goals at run time
The agent is animated as a virtual walking character
Character Rigging (played Mo-Cap in character animation file)
Path smoothing (walk to the furthest visible node on path)
Allow agents to rotate to reach a goal
Other things, not necessary related to the assignment:
Generates oriented boundry boxes for each entity! Includes ray casting for selecting items, and OBB-OBB collision test
ASSIMP importer with bone support. Bone matrixes are calculated on the GPU.
ASSIMP model animation support
Procedurally generated tile world! I didn't continue with it, but it was really fun to make.
Bounding box rendering
Press "I" to interact. Click to select an item (the bounding box will turn RED). Click and drag any obstacle. Rotate a selected obstacle with LEFT and RIGHT arrow keys. Click anywhere on the ground to direct a selected player entity.
Assimp for 3D models
OBB information from "Intersection method from Real-Time Rendering and Essential Mathematics for Games"
Plenty! First, importing modules required me to write my own ASSIMP importer. Since ASSIMP creates nodes in a tree format, I needed to re-write how my phong renderer worked.
The Oriented Bounding Boxes were a pain, specifically with all the change of coordinate spaces. If I had more time I would've transformed the bounding boxes with animations, allowing for the player to get "skinny" and slip through smaller paths.
For sweeping OBBs, I ended up just using small steps and testing a LERPed and SLERPed position vector and quaternion.
I originally had the oriented bounding boxes using their own modelview matrix, but simulating the object's extent around other objects caused this to quickly break down. This is a problem that was hard to track down because the bounding box renderer also used the modelview matrix. Eventually I just bit the bullet at switched to calculating the bounding box separate from the object's rendering logic.