Обработка вершин с помощью скелета
Введение
Qt Quick 3D поддерживает обработку вершин для скелетной анимации геометрии мешей.
См. Пример простой обработки с помощью скелета для практической демонстрации скелетной анимации.
В большинстве случаев разработчики приложений не будут использовать API обработки скелета вручную. Обычный рабочий процесс заключается в использовании внешнего инструмента для создания контента для определения скелета и текстуры (это иногда также называется *риггингом*), а затем использовать инструмент Balsam Asset Import Tool, чтобы преобразовать актив в родной формат 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% подвержена влиянию сустава joint2, и она будет перемещаться ровно так же, как и этот сустав. Последние три индекса в атрибуте JointSemantic игнорируются, так как соответствующие веса равны 0.0.
В качестве другого примера, с такими атрибутами:
JointSemantic атрибут |
WeightSemantic атрибут |
|---|---|
QVector4D(1, 2, 0, 0) |
QVector4D(0.5, 0.25, 0.0, 0.0) |
вершина будет перемещена на 50% от движения сустава joint1 плюс 25% от движения сустава joint2.
Кроме того, поскольку скелет является абстрактным представлением, модель должна указать информацию о геометрии для суставов. По соображениям производительности это не делается путём непосредственного указания информации. Вместо этого 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.2/quick3d-vertex-skinning.html