Character Animation - Skinning
Path of the code: [06_skinning]
The objective of this scene is to model skeleton-based character deformation using linear blend skinning and dual quaternion skinning.
In the current state of the program an animated skeleton can be played, and a mesh which is expected to be deformed by skinning. The animation of the skeleton is already coded, but there is no interpolation between key poses. The geometrical deformation of the associated mesh by skinning is not coded either.
Proposed mesh and skeleton animation
Three mesh model with their animated skeletong are already coded - A cylindrical model following two different bending motions fully procedurally generated- A rectangular bar model following a bending and twisting motion fully procedurally generated
- A more complex pre-made character with runing, walking and idle motion. The character and motions are stored as external files (loaders are provided).
- - Note that the file format doesn’t follow any standard, but correspond, in this case, to a simple ASCII format easy to read and parse
- - You can find all the elements of the character description in assets/marine.
- - Note that standard file format handling skinning are often more complex to analyse. An example of such format is Collada: an open XML based format, but several other software specific format (.3ds, .blend, .fbx, etc.) can also handle skinning.
Skeleton encoding
The skeleton is stored in a simple format assuming tree like organization from the root node. - A vector stores for each node/joint its geometry encoded as 3D position and rotation (quaternion).- The geometry is expressed in a local coordinate frame with respect to the parent joint.
- This vector is build such that child joints are always encoded after their respective parent
- Another vector indicates the parent index of the k-th entry within the vector, therefore storing the connectivity of the tree structure.
- Given the local geometry and the tree connectivity, the function skeleton_local_to_global() compute the global 3D coordinates of each joint.
Skeleton motion
The method skeleton_animation_structure::evaluate_local() is expected to compute the interpolation of the skeleton at a given time \(t\). In the current state, the nearest(/smaller integer) neighbor is picked which leads to discontinuous motion.- > Complete the function evaluate_local (file skeleton/skeleton.cpp) to compute a smooth skeleton motion through time
- Note that the structure affine_rt stores a rigid transform as a rotation (internally stored as a quaternion) and a position (vec3)
-
- A linear interpolation of rotation in the space of quaternion is available (LERP) in the rotation structure
- You can also code a SLERP interpolation
Linear Blend Skinning
The function skinning_LBS_compute() (file skinning.cpp) is expected to compute the deformation for each vertex with respect to the linear blend skinning formulation. The function receives in parameters- - the deformed mesh positions (and normals) to be filled
- - the current skeleton geometry and the associated rest pose (already in global coordinate system)
- - the positions (and normals) of the mesh in the rest pose
- - the skinning weights (stored in variable rig_structure).
Dual quaternion skinning
Linear Blend Skinning leads to candy wrapper artifact in the case of the twisting bar.- > Implement a Dual Quaternion Skinning and use it for the deformation of the bar. This artifact should disapear.
- Note: the character is not set for dual quaternion skinning, and some joint animation may lead to artifacts if applied with the current weights to this character.
- - There is no dual quaternion class already coded, it is up to you to add the necessary structures and functions.
- - Think first on how you can model a dual number with code.
-
- - The number \(\epsilon\) doesn't "exists" explicitely in code, but you can model a structure implementing the algebraic properties applied on the "real" and "dual" part of a dual quaternion (it follows the same spirit than implementing a "complex number" or "quaterion" structure for instance).
- - You don't have to implement all the properties of dual numbers as only a subset is needed to implement dual-quaternion skinning (especially dealing with its dual part).
- a) Standard operations between two dual numbers \(\hat{a}=a+\epsilon a'\), and \(\hat{b}=b+\epsilon b'\)
-
- \(\hat{a}+\hat{b}=(a+\epsilon a')+(b+\epsilon b')=a+b+\epsilon\,(a'+b')\)
- \(\hat{a}-\hat{b}=(a+\epsilon a')-(b+\epsilon b')=a-b+\epsilon\,(a'-b')\)
- \(\hat{a} \times \hat{b}=(a+\epsilon a')(b+\epsilon b')=a b + \epsilon\, (a' b + a b') \)
- \(\displaystyle \hat{a} / \hat{b}=\frac{a+\epsilon a'}{b+\epsilon b'}=\frac{a}{b} + \epsilon\, \frac{a' b - b a'}{b^2} \)
-
- Note: As a rule of thumb, the dual part follows the rules of differentiation - thus the use of dual numbers for automatic differentiation.
- b) Convert unit quaternion \((q_0)\) + translation \((t)\) to a unit dual quaternion \((\hat{q})\)
-
- \(\hat{q}=q_0 + \epsilon \,q_t\,q_0/2\):
- with \(q_t=(t_x, t_y, t_z, 0)\) the associated quaternion to the translation coordinates.
- c) Convert a unit dual quaternion \((\hat q=q_0+\epsilon q_\epsilon)\) into a unit quaternion \(q\) and translation \(t\):
-
- \(q=q_0\)
- \(t=(q_t.x, q_t.y, q_t.z)\) with \(q_t=2\,q_\epsilon\,q_0^{\star}\)
-
- \(q_0^{\star}\) conjugate of \(q_0\).
- d) Normalize a non unit dual quaternion \(\hat{Q}=Q_0+\epsilon Q_\epsilon\) into a unit dual quaternion \(\hat{q}=q_0+\epsilon q_\epsilon\):
-
- \(\hat{q}=\hat{Q}/\|Q_0\|=Q_0/\|Q_0\|+\epsilon \, Q_\epsilon/\|Q_0\|\)
Possible extensions (ex. for final project)
- - Make you character controlable interactively (ex. using the keyboard) in adapting its displacement and orientation.
- - Code the possibility to switch between different animations: running, walking, idle, and automatize these transitions when appropriate with respect to the motion of the character.