如何获得 QQuickItem 的变换矩阵?
How can I get transform matrix for QQuickItem?
我用 QGraphicsItem
工作了很长时间,它有 transform()
功能。现在我不会对 QQuickItem
做同样的事情,但不幸的是它错过了 transform()
。所以我的问题 - 如何获得 QQuickItem
?
的变换矩阵
QSGTransformNode class 在场景图中实现转换。在 updatePaintNode
函数中,参数 updatePaintNodeData
提供指向与此 QQuickItem
关联的 QSGTransformNode
的指针。
QSGNode *MyQuickItem::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *data)
{
QSGTransformNode *transformNode = data->transformNode;
qDebug() << transformNode->matrix();
实际上 QQuickItem
提供了 transform()
方法,但是它 return 是分配给给定项目的所有转换的列表。这是因为可以将多个转换分配给单个 Item
。 QQuickItem::transform
的 return 类型是 QQmlListProperty<QQuickTransform>
— 它是 QML list<Transform>
类型的包装器(参见 documentation for Item)。它可以迭代,产生 QQuickTransform *
个元素。 QQuickTransform
是一个转换的基础 class,它提供一个虚方法 applyTo
接受一个 QMatrix4x4 *
参数并在其上应用转换。
QML 允许实例化多个 QQuickTransform
子 classes(用于平移、旋转和缩放)并且允许用户定义自定义转换(例如用于倾斜)。
要获得所需的单个变换矩阵,您必须从单位矩阵开始,然后依次应用给定 QQuickItem
的所有变换。
QMatrix4x4 transformOfItem(QQuickItem *item)
{
QQmlListProperty transformations = item->transform();
const int count = transformations.count(&transformations);
// Prepare result structure, it will be default-initialized to be an identity matrix
QMatrix4x4 transformMatrix;
// Apply sequentially all transformation from the item
for(int i = 0; i applyTo(&transformMatrix);
}
return transformMatrix;
}
注意函数return是一个转换矩阵QMatrix4x4
——它比旧的QTransform
基于3x3转换矩阵,所以不能无损转换。如果需要,您可以使用 QMatrix4x4::toAffine
获取 QMatrix
(3x3) 并使用它来创建 QTransform
对象。但是,如果您的 QQuickItem
转换包含非亲和元素,它们将会丢失。
编辑
还有一件事需要注意:我发布的方法仅适用于通过分配给 transform
属性 定义的转换。它不检查 scale
和 rotation
属性。如果您使用它们,您应该使用适当的 QQuickItem
方法检查它们的值并调整 returned 矩阵以包括这两个额外的转换。
这是一个正确的解决方案,基于 Michael 之前提供的代码,但已修复实际工作,因此您不必花 20 分钟弄清楚如何使用 QQmlListProperty
QMatrix4x4 YourQQuickItem::get_model_matrix() {
QMatrix4x4 result;
// Compose model matrix from our transform properties in the QML
QQmlListProperty<QQuickTransform> transformations = transform();
const int count = transformations.count(&transformations);
for (int i=0; i<count; i++) {
QQuickTransform *transform = transformations.at(&transformations, i);
transform->applyTo(&result);
}
return result;
}
在我的用例中,我使用它来获取对象的模型矩阵,然后与视图和投影矩阵相乘以计算模型-视图-投影矩阵。
我用 QGraphicsItem
工作了很长时间,它有 transform()
功能。现在我不会对 QQuickItem
做同样的事情,但不幸的是它错过了 transform()
。所以我的问题 - 如何获得 QQuickItem
?
QSGTransformNode class 在场景图中实现转换。在 updatePaintNode
函数中,参数 updatePaintNodeData
提供指向与此 QQuickItem
关联的 QSGTransformNode
的指针。
QSGNode *MyQuickItem::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *data)
{
QSGTransformNode *transformNode = data->transformNode;
qDebug() << transformNode->matrix();
实际上 QQuickItem
提供了 transform()
方法,但是它 return 是分配给给定项目的所有转换的列表。这是因为可以将多个转换分配给单个 Item
。 QQuickItem::transform
的 return 类型是 QQmlListProperty<QQuickTransform>
— 它是 QML list<Transform>
类型的包装器(参见 documentation for Item)。它可以迭代,产生 QQuickTransform *
个元素。 QQuickTransform
是一个转换的基础 class,它提供一个虚方法 applyTo
接受一个 QMatrix4x4 *
参数并在其上应用转换。
QML 允许实例化多个 QQuickTransform
子 classes(用于平移、旋转和缩放)并且允许用户定义自定义转换(例如用于倾斜)。
要获得所需的单个变换矩阵,您必须从单位矩阵开始,然后依次应用给定 QQuickItem
的所有变换。
QMatrix4x4 transformOfItem(QQuickItem *item) { QQmlListProperty transformations = item->transform(); const int count = transformations.count(&transformations); // Prepare result structure, it will be default-initialized to be an identity matrix QMatrix4x4 transformMatrix; // Apply sequentially all transformation from the item for(int i = 0; i applyTo(&transformMatrix); } return transformMatrix; }
注意函数return是一个转换矩阵QMatrix4x4
——它比旧的QTransform
基于3x3转换矩阵,所以不能无损转换。如果需要,您可以使用 QMatrix4x4::toAffine
获取 QMatrix
(3x3) 并使用它来创建 QTransform
对象。但是,如果您的 QQuickItem
转换包含非亲和元素,它们将会丢失。
编辑
还有一件事需要注意:我发布的方法仅适用于通过分配给 transform
属性 定义的转换。它不检查 scale
和 rotation
属性。如果您使用它们,您应该使用适当的 QQuickItem
方法检查它们的值并调整 returned 矩阵以包括这两个额外的转换。
这是一个正确的解决方案,基于 Michael 之前提供的代码,但已修复实际工作,因此您不必花 20 分钟弄清楚如何使用 QQmlListProperty
QMatrix4x4 YourQQuickItem::get_model_matrix() {
QMatrix4x4 result;
// Compose model matrix from our transform properties in the QML
QQmlListProperty<QQuickTransform> transformations = transform();
const int count = transformations.count(&transformations);
for (int i=0; i<count; i++) {
QQuickTransform *transform = transformations.at(&transformations, i);
transform->applyTo(&result);
}
return result;
}
在我的用例中,我使用它来获取对象的模型矩阵,然后与视图和投影矩阵相乘以计算模型-视图-投影矩阵。