- Qt 6.4
- Qt Quick 3D
- Vertex Skinning
- Qt Quick 3D | Commercial or GPLv3

# Vertex Skinning

## Introduction

Qt Quick 3D supports vertex skinning for skeletal animation of mesh geometries.

See the Simple Skinning Example for a practical demonstration of skeletal animation.

In most cases, application developers will not be using the skinning API manually. The normal workflow is to use an external content creation tool to define the skeleton and the skin (this is sometimes also referred to as rigging), and then use the Balsam Asset Import Tool to convert the asset to Qt Quick 3D's native format.

## Defining a skeleton

The basis of skeletal animation is the Skeleton. This is an abstract representation of how the model can move, inspired by how a physical skeleton works for vertebrates. The "bones" of the skeleton is represented by a hierarchy of Joint nodes. These do not necessarily need to represent actual bones, of course.

     Skeleton {
         id: qmlskeleton
         Joint {
             id: joint0
             index: 0
             skeletonRoot: qmlskeleton
             Joint {
                 id: joint1
                 index: 1
                 skeletonRoot: qmlskeleton
             }
             Joint {
                 id: joint2
                 index: 2
                 skeletonRoot: qmlskeleton
             }

         }
     }

## Connecting a skeleton to a model

To apply a skeleton to a model, set the model's skeleton property:

     Model {
         skeleton: qmlskeleton
         ...

In order for the skeleton to have an effect, the model's geometry needs to include skinning information. This is done by including vertex attributes with `JointSemantic` and `WeightSemantic` in the vertex buffer.

The `JointSemantic` attribute determines which of the joints in the skeleton can influence a given vertex. This uses the index values specified by Joint.index. Since this attribute contains 4 indexes, a maximum of 4 joints can influence one vertex.

The `WeightSemantic` attribute describes the strength of the influence of those joints. It contains four floating point values, each value determining the weight given to the joint with the index at the corresponding position in the `JointSemantic` attribute.

For example, given the skeleton above, if a vertex has these attributes:

`JointSemantic` attribute | `WeightSemantic` attribute
--- | ---
`QVector4D(2, 0, 0, 0)` | `QVector4D(1.0, 0.0, 0.0, 0.0)`

that vertex will be 100% influenced by joint2, and it will move exactly as much as that joint. The last three indexes in the `JointSemantic` attribute are ignored since the corresponding weights are `0.0`.

As another example, with these attributes:

`JointSemantic` attribute | `WeightSemantic` attribute
--- | ---
`QVector4D(1, 2, 0, 0)` | `QVector4D(0.5, 0.25, 0.0, 0.0)`

the vertex will be moved by 50% of joint1's movement plus 25% of joint2's movement.

In addition, since the skeleton is an abstract representation, the model need to specify geometry information for the joints. For performance reasons, this is not done by specifying the information directly. Instead, Model.inverseBindPoses contains the inverse of the transformation matrix needed to move each joint to its initial position.

## Animating the skeleton

Transforming a joint in a skeleton will move all vertexes connected to that joint. Since Joint inheriths from Node, a skeleton can be animated simply by using standard QML animations.

     NumberAnimation {
         target: joint1
         property: "eulerRotation.z"
         duration: 5000
         from: -90
         to: 90
         running: true
     }

While it is possible to create complex animations by nesting SequentialAnimation, ParallelAnimation and NumberAnimation, it is generally more convenient to use timeline animations for animating skinned models.