Demo: Green Dragon

Articles with the tag: Technical Animation

CharSim: release and summary

System architecture for version 001

What I planned in the spec is now complete and ready for release. The GLSL shaders now work at version level 120 (compatible with OpenGL 2.2) in order to support older graphics cards.

What has been the point of the project?

  • Am familiarised with 3D APIs and shaders.
  • Have explored and incorporated third-party libraries.
  • Learn and apply knowledge of mathematics and algorithms for a technical animation framework and basic game engine.
  • Handle debugging using exception handling and gdb.
  • Designed an object-oriented framework model.
  • Used C++ standard library tools (smart pointers to automatically refcount resource objects, lambda functions and their relation to STL algorithms, vectors, lists, maps, iterators).
  • Explored C++ design patterns (abstract classes used as interfaces, compositing and inheritance patterns).
  • Have worked with the distributed version control system Git for revisions and distribution.

Of course there are many features I still want to explore ...

Read More »

Facial expressions: shader-based vertex morphing

Blending normals and positions with linear interpolation (LERP). It seems to look good.

LERP: (startPos + factor*(endPos - startPos));

GLSL Vertex Shader example:

vec3 morphPosition = vertexPosition;
morphPosition = (morphPosition + morphWeight0 * (morphPosition0 - morphPosition));
morphPosition = (morphPosition + morphWeight1 * (morphPosition1 - morphPosition));

To reduce shader computation, the (endPos - startPos) calculation can be performed on the morph target vertices before they are transferred to the device.

Vertex Shader example after optimisation:

vec3 morphPosition = vertexPosition;
morphPosition += morphWeight0 * morphPosition0;
morphPosition += morphWeight1 * morphPosition1;

Rough animation test mixing blend shapes (the mouth movement) with pre-animated armature animation (the bobbing), both interpolated using smoothstep interpolation:

And with skeletal IK animation:

Read More »

Character animation: vertex morph targets

For animation purposes, the ModelNode for the dragon character will contain a set of morph weight factors relating to the number of possible morph targets (key shapes) that have been generated for the character's expressions.


std::map<std::string, float> _keyFac;
_keyFac["MouthOpen"] = 0.5f;

The shader has a limited number of morph targets it can use (currently 2, but it can be increased to 5) so it is up to the animation update logic to choose which expressions to send to the Renderer.

If 5 expressions are used, a fair amount of artistic control can be provided. For example, three morph targets can be used for broad facial movement such as "Smile", "Frown", and "Blink" while the two remaining slots can be used to blend phoneme movement for speech animation.


std::map<std::string, uint> _keyId;
// The key's ID relates the morph mesh ...

Read More »

Character animation: facial expressions

While idle motion based on armature animation can be done, other idle motions such as blinking and mouth movement depend on mesh morphing and blending.

Blending the three: IK, armature animation and face morphing should just be a matter of combining transformation matrices and providing the necessary arrays of data to the shaders (providing this data is discussed below).

Because the dragon character's face is not warped by the armature motion, it shouldn't matter whether the mesh is warped before or after the other animations.

On face morphing:

(Assuming three meshes are generated for the dragon representing its (currently) two morph targets (what Blender calls "Shape Keys") plus a base mesh: BasisMesh, BlinkMesh and MouthOpenMesh.)

The meshes could be interpolated on the CPU (the host) and the resulting vertex array be uploaded to the GPU (the device) each frame. This would be computationally expensive for a game scenario ...

Read More »

Character skinning: finding rotation between vectors

Solving the angle problem: How to find the rotation between two vectors.

This solution is implemented in the Math class and will be invoked by the bezier curve-following IK method in the SkeletonNode class.

Given two normalised vectors, the cosine of the angle between them can be found using the dot product:

quat rotation(vec3 v1, vec3 v2)
    // v1 dot v2 = |v1| * |v2| * angle_cos
    // If the vectors are normalised, their magnitudes will be '1', and so:
    v1 = normalise(v1)
    v2 = normalise(v2)
    float angle_cos = dot(v1, v2)

The rotation axis can be found using the cross product of both vectors:

...rotation() cont'd...
vec3 axis = normalise(cross(v1, v2))

Optimal forms for creating quaternion:

Naive rotation() method (ignoring special cases such as angle=0):

...rotation() cont'd...
float angle = acos(angle_cos)
return quaternion_from_axisangle(angle, axis)

The quaternion_from_axisangle() function likely uses trigonometry (such as the cosine function) to convert the given ...

Read More »

Character rigging: vertex weight painting

The weight of each vertex in a vertex group defines how much it is influenced by the bone associated with that group.

Armature weight painting successfully completed. Testing to see if updated mesh and armature works in game environment.

Not using Three.js Blender exporter's Morph Animation option, which generates 100+ MB files. Just going to create a mesh for each shape key (i.e. blink, mouth open), which can then be blended with the basis mesh by the game engine.

Read More »

Page 1 / 4 Older »