Joint - Fish-In-A-Suit/Conquest GitHub Wiki
package animatedModel;
import java.util.ArrayList;
import java.util.List;
import org.lwjgl.util.vector.Matrix4f;
public class Joint {
public final int index;// ID
public final String name;
public final List<Joint> children = new ArrayList<Joint>();
private Matrix4f animatedTransform = new Matrix4f();
private final Matrix4f localBindTransform;
private Matrix4f inverseBindTransform = new Matrix4f();
public Joint(int index, String name, Matrix4f bindLocalTransform) {
this.index = index;
this.name = name;
this.localBindTransform = bindLocalTransform;
}
public void addChild(Joint child) {
this.children.add(child);
}
public Matrix4f getAnimatedTransform() {
return animatedTransform;
}
public void setAnimationTransform(Matrix4f animationTransform) {
this.animatedTransform = animationTransform;
}
public Matrix4f getInverseBindTransform() {
return inverseBindTransform;
}
protected void calcInverseBindTransform(Matrix4f parentBindTransform) {
Matrix4f bindTransform = Matrix4f.mul(parentBindTransform, localBindTransform, null);
Matrix4f.invert(bindTransform, inverseBindTransform);
for (Joint child : children) {
child.calcInverseBindTransform(bindTransform);
}
}
}
Each Joint has an index, which refers to the position in the array (which is loaded into vertex shader) at which this Joint is stored. It also has a name, which is the name of the joint in the Collada file. Furthermore, each Joint also has a list of children joints (List children).
animatedTransform is the joint transform, ie the matrix which is used to position (move, rotate) a Joint. Note that this transform is in model-space. This matrix gets loaded to the shader as a uniform array. In the vertex shader, this can be applied to a vertex to transform that vertex from it's original model-space position to the model-space position it should be at in the current pose at the current time of the animation.
The other two matrices, localBindTransform and inverseBindTransform are used to calculate animatedTransform. localBindTransform refers to the transform of a joint in relation to its parent joint. inverseBindTransform refers to the original position and rotation of the joint (therefore the word "bind"), only this time in model-space and it is inverted.
The constructor takes in the index, name and localBindTransform and stores them into corresponding fields.
addChild(Joint child)
adds a new Joint to List children of this Joint. It is only used during creation of the joint hierarchy.
getAnimatedTransform()
returns animatedTransform. This is the transform that gets loaded up to the shader and is used to deform the vertices of the mesh. It represents the transformation from the joint's bind position (orifginal position and rotation in model-space) to the joint's desired animation pose (also in model-space). This matrix is calculated by taking the desired model-space transform of the joint and multiplying it by the onverse of the model-space bind transform of the joint.
setAnimationTransform(Matrix4f animationTransform)
is used to put the joints of the animated model in a certain pose.
getInvertseBindTransform()
return the inverted model-space bind transform. The bind transform is the original model-space transform of the joint (when no animation is applied). This returns the inverse of that, which is used to calculate the animated transform matrix which gets used to trannsform vertices in the shader.
calculateBindTransform(Matrix4f parentBindTransform)
is used only during setup after the joints hierarchy has been established. This calculates the model-space bind transform of this joint like so: bindTransform = parentBindTransform * localBindTransform
, where bindTransform
is the model-space bind transform of this joint, parentBindTransform
is the model-space bind transform of the parent joint and localBindTransform
is the model-space bind transform of this joint. It then calculates and stores the inverse of model-space bind transform, for use when calculating the final animation transform each frame. It then recursively calls the method for all of the children joints, so that they too calculate and store their inverse bind-pose transform. This method has to be called only once on the root joint, and all of the model-space inverse bind pose transforms for all joints will be calculated.