Скелетная анимация вершин
Введение
Qt Quick 3D поддерживает скелетную анимацию вершин для геометрии мешей.
См. Пример простой анимации для практического демонстрирования скелетной анимации.
В большинстве случаев разработчики приложений не будут использовать API скелетной анимации вручную. Обычный рабочий процесс заключается в использовании внешнего инструмента создания контента для определения скелета и обвязки (иногда это также называется *риггингом*), а затем использование Инструмента импорта ресурсов Balsam для преобразования ресурса в собственный формат Qt Quick 3D.
Определение скелета
Основой скелетной анимации является Скелет. Это абстрактное представление о том, как модель может двигаться, вдохновленное тем, как работает физический скелет у позвоночных. "Кости" скелета представлены иерархией узлов Сочленения. Разумеется, они не обязательно должны представлять собой реальные кости.
Skeleton {
id: qmlskeleton
Joint {
id: joint0
index: 0
skeletonRoot: qmlskeleton
Joint {
id: joint1
index: 1
skeletonRoot: qmlskeleton
}
Joint {
id: joint2
index: 2
skeletonRoot: qmlskeleton
}
}
} Подключение скелета к модели
Для применения скелета к модели установите свойство скелета модели:
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.1/quick3d-vertex-skinning.html