Linear Blend Skinning - cmu462/Scotty3D GitHub Wiki
Now that we have a skeleton set up, we need to link the skeleton to the mesh in order to get the mesh to follow the movements of the skeleton. We will implement linear blend skinning in Mesh::linearBlendSkinning()
.
Task 3a Naive Linear Blend Skinning
The easiest way to do this is to update each of mesh vertices' positions in relation to the bones (Joint
s) in the skeleton. Your implementation should have the following basic steps for each vertex:
- Compute the vertex's position with respect to each joint
j
in the skeleton inj
's coordinate frame when no transformations have been applied to the skeleton (bind pose, vertex bind position). - Find where this vertex would end up (in world coordinates) if it were transformed along with bone
j
. - Find the closest point on joint
j
's bone segment (axis
) and compute the distance to this closest point. - Store the transformed location and distance for each
j
in anLBSInfo
structure, which has been defined for you indynamic_scene/mesh.h
. - Compute the resulting position of the vertex by doing a weighted average of the positions from each bone, as stored in the
LBSInfo
structures. The weights for the weighted average should be the inverse distance to the joint, so closer bones have a stronger influence.
Below we have an equation representation. ![height=16px](https://raw.githubusercontent.com/wiki/cmu462/Scotty3Dmedia/task4_dev_eq_images/0080.png|height=12px]] is the new vertex position. media/task4_dev_eq_images/0081.png is the weight metric computed as the inverse of distance between vertex media/task4_dev_eq_images/0082.png and closest point on joint media/task4_dev_eq_images/0083.png. media/task4_dev_eq_images/0084.png is the vertex's position with respect to joint [[media/task4_dev_eq_images/0085.png) after joint's transformations has been applied.
In Scotty3D, the linearBlendSkinning()
function gets called on every frame draw iteration, recomputing all skinning related quantities. In this function, you should read vertex bind positions from Vertex::bindPosition
, and write the resulting skinned positions to Vertex::position
. Be careful about mutating any other quantities in linearBlendSkinning()
, or else the repeated calls to this function my lead to strange behavior.
Task 3b Linear Blend Skinning with Threshold
After you implemented the method in Task 3a, you probably noticed that parts of the mesh that is very far away moves when you move a joint. In part 3b, we will implement a threshold to limit the volume that each joint affects. You should change your code such that when parameter useCapsuleRadius
is true, you check the distance between the vertex and the closest point on the joint, and if it is more than the joint's capsuleRadius, you do not let that joint affect this vertex. In your code, don't forget to properly handle the case where a vertex is not affected by any bones!
media/animation_3_demo_nothreshold.gif
Naive linear blend skinning affects other parts of the mesh, not just the arm. Also, the arm does not follow the joint exactly because other joints hold it back.
Linear blend skinning with threshold allows us to better pose our characters.