Animation System (C++/OpenGL/Maya)
A C++/OpenGL 3D Animation System that allows the user to import Rigid Skinned objects from Maya that I created for a University project. There are two main parts to this animation system, the first being the Maya plugin that allows animated objects to be export from a Maya scene and the second is the C++/OpenGL program at loads the exported objects into a game scene. The exported animation file stores both the Skeleton and Skinning data required to replicate the rigged model within Maya.
Feature list:
Get the source on GitHub: https://github.com/LewisWard/Animation-System
Feature list:
- Custom Maya plugin for animation export
- C++ program that replicates animation exported from Maya scene
- C++ program supports hierarchical joint system
- Keyboard, Mouse and Xbox Controller supported
- Multi animation states/cycles supported (i.e. standing still to walking)
- Supports collision boxes for exported objects
Get the source on GitHub: https://github.com/LewisWard/Animation-System
Development Process and Code Samples
When I started this project I only knew a little bit of animation theory, so the first thing I did was to learn more and gain a greater understanding of animation and how to actually rig/animate a object in Maya. Once I could animate something within Maya I then started to look into writing my own Maya exporter, which I had no experience in, and also how Maya works with scene data and the Hypergraph. Once I felt that I know enough about Maya, animating and exporting I started to set up a simple SDL program to create a Window and use OpenGL.
I then turned my attention to writing the Maya Exporter plugin as without this I wouldn't get very far without some real data exported from Maya. Using the Maya C++ API I wrote a exporter which iterates over the scene within Maya to get all of the MFn::kJointCluster dependency nodes and get all the data I required from the joint clusters. Then the exporter gets all of the MFnMesh objects in the scene and builds up arrays of vertices, normal's, UV coordinates and matrix data from the meshes. Then the exporter creates indices for all of the vertices that it has collected. Finally the export writes to a file starting with a file header with some data like total number of frames and numbers of vertices, then writes all of the gather data to the file.
With the exporter complete I turned my attention back to the animation system, I started off by writing a class that could read the data in from the exported file without any animation to start off with. The next step was to get animation working now that I could render the object within my SDL application as a static mesh. Once I got the animation working I then worked on getting improved controls with mouse/keyboard and XBOX 360 controller with a camera that follows the animated object but can also rotate and zoom. I also had two states for animation, a Idle and Walking, the Idle had no animation but the walking did so when there was some user input the state would change.
I then turned my attention to writing the Maya Exporter plugin as without this I wouldn't get very far without some real data exported from Maya. Using the Maya C++ API I wrote a exporter which iterates over the scene within Maya to get all of the MFn::kJointCluster dependency nodes and get all the data I required from the joint clusters. Then the exporter gets all of the MFnMesh objects in the scene and builds up arrays of vertices, normal's, UV coordinates and matrix data from the meshes. Then the exporter creates indices for all of the vertices that it has collected. Finally the export writes to a file starting with a file header with some data like total number of frames and numbers of vertices, then writes all of the gather data to the file.
With the exporter complete I turned my attention back to the animation system, I started off by writing a class that could read the data in from the exported file without any animation to start off with. The next step was to get animation working now that I could render the object within my SDL application as a static mesh. Once I got the animation working I then worked on getting improved controls with mouse/keyboard and XBOX 360 controller with a camera that follows the animated object but can also rotate and zoom. I also had two states for animation, a Idle and Walking, the Idle had no animation but the walking did so when there was some user input the state would change.
Joint cluster are updated every frame within the Mesh::update method by cycling over every joint cluster within this Mesh object. For each joint cluster, we then need to find out how many vertices are connected to the joint cluster (set in Maya), then loop over those vertices to find out what their position is this frame and the next frame. Once we know the two frame positions we can work out the difference between them, finally we get the original position of the vertex and the original position added to the difference we computed to give us two point to use when we perform the Linear Interpolation. The result of the Linear Interpolation is applied to mesh data to update it's position in Local Space, then we need tell OpenGL to update the Array Buffer using glBufferSubData after we have cycled through all of the joint clusters.
There are some improvements that could be made to this such as moving these calculations to the GPU, performing them within the vertex shader. |
Movement is computed by getting the objects currently facing direction and multiplied by it movement direction, within the Mesh::update method.
The facing direction vector is calculated by taking the latest user input to translate and rotate the objects model matrix, then converting the matrix into a quaternion to give a new facing direction vector. Movement can be controlled with the keyboard or XBOX 360 controller. |
Drawing the animated object is very simple as we just get the array and element array buffer for the animated object, bind them and provide attribute pointers for the vertex, normal and UV data. This can be achieved by making a call to the Mesh::drawObject method.
However, as the joint cluster updates are happening on the CPU then updating the array buffer, when the Vertex Object Buffer (VBO) is created within Mesh::Constructor it is set to GL_DYNAMIC_DRAW rather then GL_STATIC_DRAW. |
Licenses for assets used:
House: http://tf3dm.com/3d-model/small-house-99333.html
Tarmac: http://www.texturegen.com/free-textures/texture-2347/
Brick: http://texturemate.com/content/free-texture-seamlessbrick21
House: http://tf3dm.com/3d-model/small-house-99333.html
Tarmac: http://www.texturegen.com/free-textures/texture-2347/
Brick: http://texturemate.com/content/free-texture-seamlessbrick21