反转父qt3d实体变换(不适用于缩放3D)
由于比这个最小测试用例更复杂的原因,我需要另一个实体(反转父qt3d实体变换(不适用于缩放3D),qt,qml,qt-quick,qt3d,Qt,Qml,Qt Quick,Qt3d,由于比这个最小测试用例更复杂的原因,我需要另一个实体(parentEntity,洋红色框)的子实体(parentEntity,青色框),但是childEntity应该独立于parentEntity的转换 因此,我添加了这个处理程序: QtQuick.Connections { target: parentTransform onMatrixChanged: { // cancel parent's transform var m = parentT
parentEntity
,洋红色框)的子实体(parentEntity
,青色框),但是childEntity
应该独立于parentEntity
的转换
因此,我添加了这个处理程序:
QtQuick.Connections {
target: parentTransform
onMatrixChanged: {
// cancel parent's transform
var m = parentTransform.matrix
var i = m.inverted()
childTransform.matrix = i
// debug:
console.log(parentTransform.matrix.times(i))
}
}
这对于取消父对象的平移和旋转效果很好,但对于缩放效果不佳
当父级的scale3D
不是[1,1,1]并且还设置了旋转时,则childEntity
出现扭曲,尽管parentTransform.matrix
乘以childTransform.matrix
给出了4x4恒等式。为什么?
最小测试用例:(加载到QQuickView
)
问题在于QTransform节点没有将转换存储为一般4x4矩阵。相反,is将矩阵分解为3个变换,这些变换按固定顺序应用:
- S-a对角标度矩阵
- R-旋转矩阵
- T-翻译
从父QTransform中的相应参数计算逆S^-1,R^-1 T^-1非常简单。您最终是如何解决这个问题的?Opened:这里有一个非常好的解释:如果我有3个额外的嵌套实体,像这样:
e0
,e1
,e2
从父到子,那么哪一个应该有S^-1
?哪个R^-1
?哪个T^-1
?只需再次检查正确的顺序=)实体需要嵌套,因此e0包含e1包含e2。我认为正确的顺序应该是:e0有S^-1 e1有R^-1=R^T e2有T^-1=-T
import QtQml 2.12 as QtQml
import QtQuick 2.12 as QtQuick
import QtQuick.Controls 2.12 as QtQuickControls
import QtQuick.Scene3D 2.0
import Qt3D.Core 2.0
import Qt3D.Render 2.0
import Qt3D.Input 2.0
import Qt3D.Extras 2.0
Scene3D {
function change_translation_and_rotation() {
parentTransform.translation.x = 0.1
parentTransform.translation.y = 0.5
parentTransform.translation.z = 2
parentTransform.rotationX = 30
parentTransform.rotationY = 60
parentTransform.rotationZ = 10
}
function change_rotation_and_scale() {
parentTransform.rotationX = 30
parentTransform.rotationY = 60
parentTransform.rotationZ = 10
parentTransform.scale3D.x = 0.1
parentTransform.scale3D.y = 0.5
parentTransform.scale3D.z = 2
}
function reset_transform() {
parentTransform.translation.x = -0.5
parentTransform.translation.y = 0
parentTransform.translation.z = 0.5
parentTransform.rotationX = 0
parentTransform.rotationY = 0
parentTransform.rotationZ = 0
parentTransform.scale3D.x = 1
parentTransform.scale3D.y = 1
parentTransform.scale3D.z = 1
}
data: [
QtQml.Connections {
target: parentTransform
onMatrixChanged: {
// cancel parent's transform
var m = parentTransform.matrix
var i = m.inverted()
childTransform.matrix = i
// debug:
console.log(parentTransform.matrix.times(i))
}
},
QtQuick.Column {
spacing: 5
QtQuick.Repeater {
id: buttons
model: ["change_translation_and_rotation", "change_rotation_and_scale", "reset_transform"]
delegate: QtQuickControls.Button {
text: modelData.replace(/_/g, ' ')
font.bold: focus
onClicked: {focus = true; scene3d[modelData]()}
}
}
}
]
id: scene3d
anchors.fill: parent
aspects: ["render", "logic", "input"]
Entity {
id: root
components: [RenderSettings {activeFrameGraph: ForwardRenderer {camera: mainCamera}}, InputSettings {}]
Camera {
id: mainCamera
projectionType: CameraLens.PerspectiveProjection
fieldOfView: 45
aspectRatio: 16/9
nearPlane : 0.1
farPlane : 1000.0
position: Qt.vector3d(-3.46902, 4.49373, -3.78577)
upVector: Qt.vector3d(0.41477, 0.789346, 0.452641)
viewCenter: Qt.vector3d(0.0, 0.5, 0.0)
}
OrbitCameraController {
camera: mainCamera
}
Entity {
id: parentEntity
components: [
CuboidMesh {
xExtent: 1
yExtent: 1
zExtent: 1
},
PhongMaterial {
ambient: "#6cc"
},
Transform {
id: parentTransform
translation: Qt.vector3d(-0.5, 0, 0.5)
}
]
Entity {
id: childEntity
components: [
CuboidMesh {
xExtent: 0.5
yExtent: 0.5
zExtent: 0.5
},
PhongMaterial {
ambient: "#c6c"
},
Transform {
id: childTransform
translation: Qt.vector3d(-0.5, 0, 0.5)
}
]
}
}
QtQuick.Component.onCompleted: reset_transform()
}
}