Qt Quick 3D - Einfaches Skinning-Beispiel
Zeigt, wie man eine einfache Skinning-Animation in „ Qt Quick 3D “ rendert.

In der Regel werden die meisten Skin-Animationen mit Modellierungswerkzeugen erstellt, und Quick3D unterstützt über den Balsam-Importer auch glTF-Formate sowie Qt Design Studio. Dieses Beispiel zeigt, wie die einzelnen Eigenschaften für die Skin-Animation in Quick3D verwendet werden.
Hinweis: Alle Daten in diesem Beispiel stammen aus „gfTF-Tutorial Skins“.
Erstellen Sie eine Skinning-Geometrie.
Um benutzerdefinierte Geometriedaten zu verwenden, definieren wir eine Geometrie mit Positionen, Gelenken, Gewichten und Indizes.
Q_OBJECT
QML_NAMED_ELEMENT(SkinGeometry)
Q_PROPERTY(QList<QVector3D> positions READ positions WRITE setPositions NOTIFY positionsChanged)
Q_PROPERTY(QList<qint32> joints READ joints WRITE setJoints NOTIFY jointsChanged)
Q_PROPERTY(QList<float> weights READ weights WRITE setWeights NOTIFY weightsChanged)
Q_PROPERTY(QList<quint32> indexes READ indexes WRITE setIndexes NOTIFY indexesChanged)Jede Position ist eine Scheitelpunktposition, und jeder Scheitelpunkt verfügt über 4 Gelenk-Indizes und entsprechende Gewichte.
Richten Sie die Skinned-Daten in QML ein
Positionsdaten und Indizes
Wir zeichnen 8 Dreiecke mit 10 Scheitelpunkten. Die folgende Tabelle zeigt den QML-Code und eine Visualisierung der Scheitelpunkte.
| QML-Code | Visualisiert |
|---|---|
|
|
Daten zu Gelenken und Gewichten
Jeder Scheitelpunkt muss die Indizes der Gelenke angeben, die während des Skinning-Prozesses Einfluss auf ihn haben sollen. Für jeden Scheitelpunkt speichern wir diese Indizes als 4D-Vektoren (Qt begrenzt die Anzahl der Gelenke, die einen Scheitelpunkt beeinflussen dürfen, auf 4). Unsere Geometrie wird nur zwei Gelenkknoten (0 und 1) haben, aber da wir 4D-Vektoren verwenden, setzen wir die verbleibenden beiden Gelenkindizes und ihre Gewichte auf 0.
joints: [
0, 1, 0, 0, // vertex 0
0, 1, 0, 0, // vertex 1
0, 1, 0, 0, // vertex 2
0, 1, 0, 0, // vertex 3
0, 1, 0, 0, // vertex 4
0, 1, 0, 0, // vertex 5
0, 1, 0, 0, // vertex 6
0, 1, 0, 0, // vertex 7
0, 1, 0, 0, // vertex 8
0, 1, 0, 0 // vertex 9
]Die entsprechenden Gewichtungswerte sind unten aufgeführt.
weights: [
1.00, 0.00, 0.0, 0.0, // vertex 0
1.00, 0.00, 0.0, 0.0, // vertex 1
0.75, 0.25, 0.0, 0.0, // vertex 2
0.75, 0.25, 0.0, 0.0, // vertex 3
0.50, 0.50, 0.0, 0.0, // vertex 4
0.50, 0.50, 0.0, 0.0, // vertex 5
0.25, 0.75, 0.0, 0.0, // vertex 6
0.25, 0.75, 0.0, 0.0, // vertex 7
0.00, 1.00, 0.0, 0.0, // vertex 8
0.00, 1.00, 0.0, 0.0 // vertex 9
]Skelett- und Gelenkhierarchie
Für das Skinning fügen wir dem „ Model “ eine Skelett -Eigenschaft hinzu:
skeleton: qmlskeleton
Skeleton {
id: qmlskeleton
Joint {
id: joint0
index: 0
skeletonRoot: qmlskeleton
Joint {
id: joint1
index: 1
skeletonRoot: qmlskeleton
eulerRotation.z: 45
}
}
}Die beiden „ Joints“ sind in einer „ Skeleton “ miteinander verbunden. Wir drehen „ joint1 “ um 45 Grad um die z-Achse. Die folgenden Abbildungen zeigen, wie die Gelenke in der Geometrie platziert sind und wie das anfängliche Skelett ausgerichtet ist.
| Gelenke in der Geometrie | Ausgangsskelett |
|---|---|
|
|
Platzieren von Modellen mit „inverseBindPoses“
Sobald ein Modell über eine gültige „ skeleton “ verfügt, muss die Ausgangsposition des Skeletts definiert werden. Dies legt die Basis für die Skelettanimation fest: Wird ein Gelenk aus seiner Ausgangsposition verschoben, bewegen sich die Scheitelpunkte des Modells entsprechend den Tabellen „ joints “ und „ weights “. Die Geometrie jedes Knotens wird auf besondere Weise festgelegt: „ Model.inverseBindPoses “ wird auf die Inverse der Matrix gesetzt, die das Gelenk in seine Ausgangsposition transformieren würde. Um es in die Mitte zu verschieben, setzen wir einfach für beide Gelenke dieselbe Transformation: eine Matrix, die um -0,5 entlang der x-Achse und um -1,0 entlang der y-Achse verschiebt.
| QML-Code | Ausgangsposition | Ergebnis |
|---|---|---|
|
|
|
Animieren mit Gelenkknoten
Nachdem wir nun ein Skinned-Objekt vorbereitet haben, können wir es animieren, indem wir die Eigenschaften des „ Joint“ ändern, insbesondere „eulerRotation“.
Timeline {
id: timeline0
startFrame: 0
endFrame: 1000
currentFrame: 0
enabled: true
animations: [
TimelineAnimation {
duration: 5000
from: 0
to: 1000
running: true
}
]
KeyframeGroup {
target: joint1
property: "eulerRotation.z"
Keyframe {
frame: 0
value: 0
}
Keyframe {
frame: 250
value: 90
}
Keyframe {
frame: 750
value: -90
}
Keyframe {
frame: 1000
value: 0
}
}
}Ein umfassenderer Ansatz zum Skinning
Das Skelett ist eine Ressource, doch seine Hierarchie und Position werden für die Transformation des Modells verwendet.
Anstelle eines „ Skeleton “-Knotens können wir den Ressourcentyp „ Skin “ verwenden. Da der Typ „ Skin “ kein räumlicher Knoten in der Szene ist, hat seine Position keinen Einfluss auf das Modell. Ein minimal funktionsfähiger „Skin“-Knoten besteht normalerweise aus einer Knotenliste, Gelenken und optionalen inversen Bindungsmatrizen („inverseBindPoses“).
Mit dem Element „ Skin “ lässt sich das vorherige Beispiel wie folgt schreiben:
skin: Skin {
id: skin0
joints: [
joint0,
joint1
]
inverseBindPoses: [
Qt.matrix4x4(1, 0, 0, -0.5,
0, 1, 0, -1,
0, 0, 1, 0,
0, 0, 0, 1),
Qt.matrix4x4(1, 0, 0, -0.5,
0, 1, 0, -1,
0, 0, 1, 0,
0, 0, 0, 1)
]
}Aus dem Codeausschnitt geht hervor, dass der „ Skin “ nur zwei Listen enthält, nämlich „joints“ und „inverseBindPoses“. Dies unterscheidet sich vom Ansatz „ Skeleton “, da hier keine eigene Hierarchie vorhanden ist und stattdessen die Hierarchie der vorhandenen Knoten genutzt wird.
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.




