Обработка вершин с костяной анимацией
Введение
Qt Quick 3D поддерживает обработку вершин для скелетной анимации геометрии мешей.
См. Пример простой обработки костяной анимацией для практической демонстрации скелетной анимации.
В большинстве случаев разработчики приложений не будут использовать API обработки костей вручную. Обычный рабочий процесс заключается в использовании внешнего инструмента для создания контента для определения скелета и кожи (это иногда также называется риггингом), а затем использовании инструмента Balsam Asset Import Tool для преобразования актива в собственный формат Qt Quick 3D.
Определение скелета
Основой скелетной анимации является Skeleton. Это абстрактное представление того, как модель может перемещаться, вдохновленное тем, как физический скелет работает у позвоночных. «Кости» скелета представлены иерархией узлов Joint. Конечно, они не обязательно должны представлять реальные кости.
Skeleton {
id: qmlskeleton
Joint {
id: joint0
index: 0
skeletonRoot: qmlskeleton
Joint {
id: joint1
index: 1
skeletonRoot: qmlskeleton
}
Joint {
id: joint2
index: 2
skeletonRoot: qmlskeleton
}
}
} Подключение скелета к модели
Чтобы применить скелет к модели, установите свойство skeleton модели:
Model {
skeleton: qmlskeleton
... Для того чтобы скелет повлиял на модель, геометрия модели должна содержать информацию об обработке костей. Это делается путем включения атрибутов вершин с JointSemantic и WeightSemantic в буфере вершин.
Атрибут JointSemantic определяет, какие суставы скелета могут влиять на данную вершину. Для этого используются индексные значения, указанные в Joint.index. Поскольку этот атрибут содержит 4 индекса, максимум 4 сустава могут влиять на одну вершину.
Атрибут WeightSemantic описывает степень влияния этих суставов. Он содержит четыре значения с плавающей точкой, каждое из которых определяет вес, придаваемый суставу с индексом в соответствующей позиции в атрибуте JointSemantic.
Например, учитывая скелет выше, если у вершины есть следующие атрибуты:
JointSemantic атрибут |
WeightSemantic атрибут |
|---|---|
QVector4D(2, 0, 0, 0) |
QVector4D(1.0, 0.0, 0.0, 0.0) |
эта вершина будет на 100% зависеть от сустава2, и она будет перемещаться точно так же, как и этот сустав. Последние три индекса в атрибуте JointSemantic игнорируются, поскольку соответствующие веса равны 0.0.
В качестве другого примера, с такими атрибутами:
JointSemantic атрибут |
WeightSemantic атрибут |
|---|---|
QVector4D(1, 2, 0, 0) |
QVector4D(0.5, 0.25, 0.0, 0.0) |
вершина будет перемещаться на 50% от перемещения сустава1 плюс 25% от перемещения сустава2.
Кроме того, поскольку скелет является абстрактным представлением, модель должна указать информацию о геометрии для суставов. По причинам производительности это не делается путем прямого указания информации. Вместо этого Model.inverseBindPoses содержит обратное преобразование матрицы, необходимое для перемещения каждого сустава в исходное положение.
Анимация скелета
Преобразование сустава в скелете приведет к перемещению всех вершин, связанных с этим суставом. Поскольку Joint наследуется от Node, скелет можно анимировать, просто используя стандартные QML анимации.
NumberAnimation {
target: joint1
property: "eulerRotation.z"
duration: 5000
from: -90
to: 90
running: true
} Хотя можно создать сложные анимации, вложенные SequentialAnimation, ParallelAnimation и NumberAnimation, обычно удобнее использовать анимации временной шкалы для анимации моделей с обработкой костей.
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-6.0/quick3d-vertex-skinning.html