如何获得 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 是分配给给定项目的所有转换的列表。这是因为可以将多个转换分配给单个 ItemQQuickItem::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 属性 定义的转换。它不检查 scalerotation 属性。如果您使用它们,您应该使用适当的 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;
}

在我的用例中,我使用它来获取对象的模型矩阵,然后与视图和投影矩阵相乘以计算模型-视图-投影矩阵。