Этот пример кода здесь:Как анимировать и propertly intepolate вращение QML преобразование в 3D
import QtQuick 2.0
Item {
width: 200; height: 200
Rectangle {
width: 100; height: 100
anchors.centerIn: parent
color: "#00FF00"
Rectangle {
color: "#FF0000"
width: 10; height: 10
anchors.top: parent.top
anchors.right: parent.right
}
}
}
будет производить этот вывод:
Теперь я хочу применить 3D вращение от центр этого зеленого прямоугольника. Во-первых, я хочу повернуть на X на -45 градусов (поклониться), затем на Y на -60 градусов (поворачивая влево).
Я использовал следующий C++ код пропущен с помощью GLM на стороне, чтобы помочь мне вычислить ось и угол:
// generate rotation matrix from euler in X-Y-Z order
// please note that GLM uses radians, not degrees
glm::mat4 rotationMatrix = glm::eulerAngleXY(glm::radians(-45.0f), glm::radians(-60.0f));
// convert the rotation matrix into a quaternion
glm::quat quaternion = glm::toQuat(rotationMatrix);
// extract the rotation axis from the quaternion
glm::vec3 axis = glm::axis(quaternion);
// extract the rotation angle from the quaternion
// and also convert it back to degrees for QML
double angle = glm::degrees(glm::angle(quaternion));
Выход этих маленьких C++ программа дала мне ось {-0.552483, -0.770076, 0.318976}
и угол 73.7201
, Так что я обновил свой образец кода для этого:
import QtQuick 2.0
Item {
width: 200; height: 200
Rectangle {
width: 100; height: 100
anchors.centerIn: parent
color: "#00FF00"
Rectangle {
color: "#FF0000"
width: 10; height: 10
anchors.top: parent.top
anchors.right: parent.right
}
transform: Rotation {
id: rot
origin.x: 50; origin.y: 50
axis: Qt.vector3d(-0.552483, -0.770076, 0.318976)
angle: 73.7201
}
}
}
Что даст мне то, что я хотел бы видеть:
До сих пор так хорошо. Сейчас идет сложная часть. Как мне оживить это? Например, если я хочу перейти от {45.0, 60.0, 0} до {45.0, 60.0, 90.0}. Другими словами, я хочу, чтобы анимировать здесь
, чтобы здесь
Я подключил, что цель вращения здесь
// generate rotation matrix from euler in X-Y-Z order
// please note that GLM uses radians, not degrees
glm::mat4 rotationMatrix = glm::eulerAngleXYZ(glm::radians(-45.0f), glm::radians(-60.0f), glm::radians(90.0f);
// convert the rotation matrix into a quaternion
glm::quat quaternion = glm::toQuat(rotationMatrix);
// extract the rotation axis from the quaternion
glm::vec3 axis = glm::axis(quaternion);
// extract the rotation angle from the quaternion
// and also convert it back to degrees for QML
double angle = glm::degrees(glm::angle(quaternion));
, который дал мне ось {-0.621515, -0.102255, 0.7767}
и угол 129.007
Поэтому я добавил эту анимацию в моей выборке
ParallelAnimation {
running: true
Vector3dAnimation {
target: rot
property: "axis"
from: Qt.vector3d(-0.552483, -0.770076, 0.318976)
to: Qt.vector3d(-0.621515, -0.102255, 0.7767)
duration: 4000
}
NumberAnimation {
target: rot;
property: "angle";
from: 73.7201; to: 129.007;
duration: 4000;
}
}
, которые «почти» работы. Проблема в том, что если вы попробуете это, вы увидите, что вращение полностью отключено от нужной оси вращения для первой половины анимации, но фиксируется для последней половины анимации. Начальный поворот хорош, вращение цели хорошо, но все, что происходит между ними, недостаточно хорошее. Лучше, если я использую меньшие углы, например, 45 градусов вместо 90 градусов, и будет худшим, если я использую большие углы, например, на 180 градусов вместо 45 градусов, где он просто вращается в случайных направлениях, пока не достигнет своих конечных целей.
Как заставить эту анимацию смотреть прямо между началом вращения и вращением цели?
------------------- ------------------- EDIT
Я добавляю еще один критерий: Ответ, который я ищу , должен обязательно предоставить идентичный результат в качестве скриншотов, которые я изложил выше.
Например, разделив оси 3 вращения в 3 отдельных преобразований вращения не дает мне правильные результаты
transform: [
Rotation {
id: zRot
origin.x: 50; origin.y: 50;
angle: 0
},
Rotation {
id: xRot
origin.x: 50; origin.y: 50;
angle: -45
axis { x: 1; y: 0; z: 0 }
},
Rotation {
id: yRot
origin.x: 50; origin.y: 50;
angle: -60
axis { x: 0; y: 1; z: 0 }
}
]
даст мне это:
что неправильно.
Это действительно непонятно, потому что они обеспечивают функцию slerp в классе QQuaternion, но не отображаются в QML: http://doc.qt.io/qt-5/qquaternion.html#slerp – mchiasson
Они действительно должны добавить QuaternionAnimation для выполнения этого сферического линейного интерполятора для нас или, по крайней мере, разоблачить функцию slerp – mchiasson
, почему вы сделали это только по функциям? Почему бы не использовать декларативный характер QML? –