首页 > 解决方案 > Qt3D 我可以列出来自 Qt3DRender::QGeometryRenderer 的所有顶点吗?

问题描述

例如

    Qt3DCore::QEntity *sphereEntity = new Qt3DCore::QEntity(rootEntity);
    Qt3DExtras::QSphereMesh *sphereMesh = new Qt3DExtras::QSphereMesh;
    sphereMesh->setRadius(3);

    Qt3DCore::QTransform *sphereTransform = new Qt3DCore::QTransform;
    sphereTransform->setScale(3);

    sphereEntity->addComponent(sphereMesh);
    sphereEntity->addComponent(sphereTransform);

我可以得到所有sphereMesh的顶点吗?

它是由sphereTransform转换的顶点吗?

或如何获得转换后的顶点?

我想我可以使用 QAttribute,但我需要一些例子。


更新:

我努力了:

    // plane
    Qt3DCore::QEntity *planeEntity = new Qt3DCore::QEntity(rootEntity);
    Qt3DExtras::QPlaneMesh *planeMesh = new Qt3DExtras::QPlaneMesh;
    planeMesh->setWidth(1);
    planeMesh->setHeight(1);

    Qt3DCore::QTransform *planeform = new Qt3DCore::QTransform;
    planeform->setRotation(QQuaternion::fromAxisAndAngle(QVector3D(1, 0, 0), 90.0f));
    planeform->setScale(10);
    planeEntity->addComponent(planeMesh);
    planeEntity->addComponent(material);
    planeEntity->addComponent(planeform);

    // ----------------

    QList<QVector4D> list;
    for ( auto attribute : planeMesh->geometry()->attributes() ) {
        if (attribute->name() == Qt3DRender::QAttribute::defaultPositionAttributeName()) {
            Qt3DRender::QBuffer *buffer = attribute->buffer();

            const QByteArray &data = buffer->data();
            for ( int i = 0 ; i < attribute->count() ; i++ ) {
                int vertexOffset = i * attribute->byteStride();
                int offset = vertexOffset + attribute->byteOffset();


                const char *vertexData = attribute->buffer()->data().constData() + (i * attribute->byteStride() + attribute->byteOffset());
                qDebug() << (int)vertexData;
                const float *typedVertexData = reinterpret_cast<const float*>(vertexData);
                list << QVector4D(typedVertexData[0], typedVertexData[1], typedVertexData[2], 1.0) ;

                qDebug() << list.last();

            } // for
        } // if
    } // for

它的输出:

QVector4D(0, 0, 0, 1)
QVector4D(1.57402e-38, 1.34525e-43, 0, 1)
QVector4D(0, 7.00649e-45, 1.52015e-23, 1)
QVector4D(1.52015e-23, 0, 0, 1)

我改造它:

    qDebug() << (list[0] * planeform->matrix());
    qDebug() << (list[1] * planeform->matrix());
    qDebug() << (list[2] * planeform->matrix());
    qDebug() << (list[3] * planeform->matrix());
    // ---- output --------
    QVector4D(0, 0, 0, 1)
    QVector4D(1.57402e-37, 0, -1.34525e-42, 1)
    QVector4D(0, 1.52015e-22, 9.06081e-30, 1)
    QVector4D(1.52015e-22, 0, 0, 1)

我认为它太小了。我如何解决它?

标签: c++qtqt3d

解决方案


关于你的第一个问题:

QSphereMesh是 的一个实例QGeometryRenderer。QGeometryRenderer 有一个函数geometry(),它返回相应的QGeometry. QGeometry反过来有一个函数attributes(),它返回存储的属性(顶点、法线、索引等)的向量。您可以遍历此属性向量并检查name()属性的 ,即它是否等于QAttribute::defaultPositionAttributeName()。这(至少我认为)返回 Qt3D 现成网格使用的顶点属性的默认名称。然后,您可以使用QAttributelike byteStride()count()等的其他函数来重建实际顶点(查找类似“QByteArray to array of X”的内容,其中 X 是属性缓冲区的数据类型)。

关于你的第二个问题:

不,顶点不会被转换。Qt3DmodelView为您构造一个矩阵并将其添加到着色器中——这意味着您可以modelView在自定义着色器中使用,而无需手动添加它。查看 Qt3D自动添加的变量和制服列表。您可以将每个顶点的值放入QVector4D最后一个数字为 a 的位置1(例如 eg (0.1, 5.4, 13.2, 1.0)),然后将其与从变换中获得的矩阵相乘:transform->matrix()。我认为你必须从右边乘以矩阵,这有点违反直觉:vector x matrix.


推荐阅读