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),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,1)
QVector4D(1.57402e-38,1.34525e-43,1)
QVector4D(0,7.00649e-45,1.52015e-23,1)
QVector4D(1.52015e-23,1)

然后我转换它:

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

我觉得它太小了。我该如何解决

解决方法

关于你的第一个问题:

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

关于你的第二个问题:

不,顶点不会被变换。 Qt3D 为您构造一个 modelView 矩阵并将其添加到着色器 - 这意味着您可以使用例如modelView 在您的自定义着色器中,而无需手动添加它。检查 Qt3D 自动添加的变量和制服的 this list。您可以将每个顶点的值放入 QVector4D 中,其中最后一个数字是 1(例如 (0.1,5.4,13.2,1.0))并将其与您可以从变换中获得的矩阵相乘:{{ 1}}。我认为您必须从右侧乘以矩阵,这有点违反直觉:transform->matrix()