1

e.g.

    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);

Can I get all sphereMesh's vertexes ?

And are it's vertexes tranformed by sphereTransform ?

or How can I get the tranformed vertexes ?

I think I can use QAttribute, but I need some examples.


update:

I have tried:

    // 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

and it's output:

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)

and I transform it :

    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)

I think it is too small. How do I fix it?

xyLi
  • 27
  • 5
  • You may have a look into the Qt3d implementation of GLTF export `qt5/qt3d/src/plugins/sceneparsers/gltfexport/gltfexporter.cpp` how the data is exported for general meshes with unknown mesh type, i.e. `meshInfo.meshType == TypeNone` – vre Feb 03 '21 at 12:18

1 Answers1

1

Regarding your first question:

QSphereMesh is an instance of QGeometryRenderer. QGeometryRenderer has a function geometry() which returns the respective QGeometry. QGeometry in turn has a function attributes() which returns a vector of the stored attributes (vertices, normals, indices, etc.). You can iterate over this vector of attributes and check the name() of the attribute, i.e. whether it is equal to QAttribute::defaultPositionAttributeName(). This (I think at least) returns the default name for the vertex attribute used by Qt3D ready-made meshes. You can then use the other functions of QAttribute like byteStride(), count(), etc. to reconstruct the actual vertices (look for something like "QByteArray to array of X" where X is the data type of the buffer of the attribute).

Regarding your second question:

No, the vertices won't be transformed. Qt3D constructs a modelView matrix for you and adds it to the shader - which means you can use e.g. modelView in your custom shader without having to manually add it. Checkout this list of variables and uniforms that Qt3D adds automatically. You could put the values for each vertex into a QVector4D where the last number is a 1 (like e.g. (0.1, 5.4, 13.2, 1.0)) and multiply it with the matrix you can get from the transform: transform->matrix(). I think you have to multiply the matrix from the right which is a bit counter intuitive: vector x matrix.

Florian Blume
  • 3,237
  • 17
  • 37
  • I update the code I have tried, but it looks like wrong. – xyLi Jan 26 '21 at 14:42
  • Hm weird, looking from the code it should work... I just tried to get it to run and it seems that the byte array has size 0. You can check this by calling `attribute->buffer()->data().size()`. Maybe try to populate an attribute yourself manually and then check if the size is also 0. I don't have time to look further into this issue right now unfortunately. – Florian Blume Jan 27 '21 at 10:30
  • 1
    Wow, `attribute->buffer()->data().size()`'s value is **0**. But... I think it should have data... How amazing.. – xyLi Jan 27 '21 at 11:48
  • Yes exactly, maybe try to manually create an attribute and see what happens when you call `size()` there. I saw a post claiming that you have to `syncData` to `true` on the buffer but that only works for data generators which generate data on the fly but we don't have that here... – Florian Blume Jan 27 '21 at 14:37