Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Qt3D adding custom geometry from arrays & creating entities?



  • Hey !

    Well, this is exciting, long story short, I implemented FBX library in my CPP application - imported arrays of vertexes[],normals[],faceIndices[] and more to get mesh data. I then passed it to a raytracer library and wuaila it renders! Now the time has come to pass the same data to 3d renderer for user - quick feedback & synchronize camera/views/geometry/everything else. From what I can see I sadly can't use the existing arrays of data to share between the 2 engines so I have to copy all vertex/etc(boo ) - or I'm wrong? In any case, I started to read on how to import custom meshes into Qt3D. Oh boy, thats a read... in any case I noticed there are quite a few "versions" of qt3D older, never etc. I got a little lost. So to start it clear I used this amazing example > https://vicrucann.github.io/tutorials/qt3d-cmake/ to start with (by the way I'm QtWidgets guy, no qml here ), once I got that in I started dropping in this example > https://github.com/qt/qt3d/commit/891ef957f9d0a2890d4917649eb48ab5d17634ab

    The resulting code is something like this (scroll below)

    Now what I hit a wall with is the new/old naming...
    What are the new calls for these functions? :
    //positionAttribute->setType(GL_FLOAT_VEC3);
    //positionAttribute->setName(Qt3DRender::QMeshData::defaultPositionAttributeName());
    And how to create new "node/mesh/QtEntity" that can house mesh data that then I attached to another node that goes inside the render engine? I take the engine is a "treeView" that I add to it/or to its children to build up tree?

    Thanks in advance for help!

    #include <iostream>
    #include <QGuiApplication>
    
    #include <Qt3DCore/QEntity>
    #include <Qt3DCore/QTransform>
    #include <Qt3DCore/QAspectEngine>
    
    #include <Qt3DRender/qrenderaspect.h>
    #include <Qt3DRender/QCamera>
    #include <Qt3DRender/QMaterial>
    
    #include <Qt3DExtras/Qt3DWindow>
    #include <Qt3DExtras/QTorusMesh>
    #include <Qt3DExtras/QOrbitCameraController>
    #include <Qt3DExtras/QPhongMaterial>
    #include <Qt3DRender/qbuffer.h>
    
    
    #include <Qt3DRender>
    
    #include "quadMesh.h"
    
    Qt3DCore::QEntity *createTestScene() {
       Qt3DCore::QEntity *root = new Qt3DCore::QEntity;
       Qt3DCore::QEntity *torus = new Qt3DCore::QEntity(root);
    
       Qt3DExtras::QTorusMesh *mesh = new Qt3DExtras::QTorusMesh;
    
       mesh->setRadius(5);
       mesh->setMinorRadius(1);
       mesh->setRings(100);
       mesh->setSlices(20);
    
       Qt3DCore::QTransform *transform = new Qt3DCore::QTransform;
    //    transform->setScale3D(QVector3D(1.5, 1, 0.5));
       transform->setRotation(QQuaternion::fromAxisAndAngle(QVector3D(1, 0, 0), 45.f));
    
       Qt3DRender::QMaterial *material = new Qt3DExtras::QPhongMaterial(root);
    
       torus->addComponent(mesh);
       torus->addComponent(transform);
       torus->addComponent(material);
    
    
    
    
       Qt3DCore::QEntity *mePyramide = new Qt3DCore::QEntity(root);
    
       QtSomething::Node? *myMesh = new Mesh?
       // add my pyramide object here for mesh ?
    
       Qt3DRender::QGeometryRenderer *customMeshRenderer = new Qt3DRender::QGeometryRenderer;
       Qt3DRender::QGeometry *customGeometry = new Qt3DRender::QGeometry(myMesh );
    
       Qt3DRender::QBuffer *vertexDataBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer, customGeometry);
       Qt3DRender::QBuffer *indexDataBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::IndexBuffer, customGeometry);
       QByteArray vertexBufferData;
       vertexBufferData.resize(4 * (3 + 3 + 3) * sizeof(float));
    
       // Vertices
       QVector3D v0(-1.0f, 0.0f, -1.0f);
       QVector3D v1(1.0f, 0.0f, -1.0f);
       QVector3D v2(0.0f, 1.0f, 0.0f);
       QVector3D v3(0.0f, 0.0f, 1.0f);
    
       // Faces Normals
       QVector3D n023 = QVector3D::normal(v0, v2, v3);
       QVector3D n012 = QVector3D::normal(v0, v1, v2);
       QVector3D n310 = QVector3D::normal(v3, v1, v0);
       QVector3D n132 = QVector3D::normal(v1, v3, v2);
    
       // Vector Normals
       QVector3D n0 = QVector3D(n023 + n012 + n310).normalized();
       QVector3D n1 = QVector3D(n132 + n012 + n310).normalized();
       QVector3D n2 = QVector3D(n132 + n012 + n023).normalized();
       QVector3D n3 = QVector3D(n132 + n310 + n023).normalized();
    
       // Colors
       QVector3D red(1.0f, 0.0f, 0.0f);
       QVector3D green(0.0f, 1.0f, 0.0f);
       QVector3D blue(0.0f, 0.0f, 1.0f);
       QVector3D white(1.0f, 1.0f, 1.0f);
    
       QVector<QVector3D> vertices = QVector<QVector3D>()
               << v0 << n0 << red
               << v1 << n1 << blue
               << v2 << n2 << green
               << v3 << n3 << white;
    
       float *rawVertexArray = reinterpret_cast<float *>(vertexBufferData.data());
       int idx = 0;
    
    
       Q_FOREACH (const QVector3D &v, vertices) {
               rawVertexArray[idx++] = v.x();
               rawVertexArray[idx++] = v.y();
               rawVertexArray[idx++] = v.z();
           }
    
       // Indices (12)
       QByteArray indexBufferData;
       indexBufferData.resize(4 * 3 * sizeof(ushort));
       ushort *rawIndexArray = reinterpret_cast<ushort *>(indexBufferData.data());
    
       // Front
       rawIndexArray[0] = 0;
       rawIndexArray[1] = 1;
       rawIndexArray[2] = 2;
       // Bottom
       rawIndexArray[3] = 3;
       rawIndexArray[4] = 1;
       rawIndexArray[5] = 0;
       // Left
       rawIndexArray[6] = 0;
       rawIndexArray[7] = 2;
       rawIndexArray[8] = 3;
       // Right
       rawIndexArray[9] = 1;
       rawIndexArray[10] = 3;
       rawIndexArray[11] = 2;
    
       vertexDataBuffer->setData(vertexBufferData);
       indexDataBuffer->setData(indexBufferData);
    
       Qt3DRender::QAttribute *positionAttribute = new Qt3DRender::QAttribute();
       positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute);
       positionAttribute->setBuffer(vertexDataBuffer);
       //positionAttribute->setType(GL_FLOAT_VEC3);
       positionAttribute->setByteOffset(0);
       positionAttribute->setByteStride(9 * sizeof(float));
       positionAttribute->setCount(4);
       //positionAttribute->setName(Qt3DRender::QMeshData::defaultPositionAttributeName());
    
       Qt3DRender::QAttribute *normalAttribute = new Qt3DRender::QAttribute();
       normalAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute);
       normalAttribute->setBuffer(vertexDataBuffer);
       //normalAttribute->setType(GL_FLOAT_VEC3);
       normalAttribute->setByteOffset(3 * sizeof(float));
       normalAttribute->setByteStride(9 * sizeof(float));
       normalAttribute->setCount(4);
       //normalAttribute->setName(Qt3DRender::QMeshData::defaultNormalAttributeName());
    
       Qt3DRender::QAttribute *colorAttribute = new Qt3DRender::QAttribute();
       colorAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute);
       colorAttribute->setBuffer(vertexDataBuffer);
       //colorAttribute->setType(GL_FLOAT_VEC3);
       colorAttribute->setByteOffset(6 * sizeof(float));
       colorAttribute->setByteStride(9 * sizeof(float));
       colorAttribute->setCount(4);
       //colorAttribute->setName(Qt3DRender::QMeshData::defaultColorAttributeName());
    
       Qt3DRender::QAttribute *indexAttribute = new Qt3DRender::QAttribute();
       indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute);
       indexAttribute->setBuffer(indexDataBuffer);
       //colorAttribute->setType(GL_UNSIGNED_SHORT);
       colorAttribute->setByteOffset(0);
       colorAttribute->setByteStride(0);
       colorAttribute->setCount(12);
    
       customGeometry->addAttribute(positionAttribute);
       customGeometry->addAttribute(normalAttribute);
       customGeometry->addAttribute(colorAttribute);
       customGeometry->addAttribute(indexAttribute);
    
       customMeshRenderer->setGeometry(customGeometry);
    
       myPyramide->addComponent(myMesh );
       myPyramide->addComponent(transform);
       myPyramide->addComponent(material);
    
    
       root->addComponent(myPyramide);
    
       return root;
    }
    
    
    int main(int argc, char *argv[]) {
    
       //qmlRegisterType<quadMesh>("de.wplm.mesh", 1, 0, "QuadMesh");
       //qRegisterMetaType<quadMesh>("de.wplm.mesh", 1, 0, "QuadMesh")
    
       QGuiApplication app(argc, argv);
       Qt3DExtras::Qt3DWindow view;
       Qt3DCore::QEntity *scene = createTestScene();
    
       // camera
       Qt3DRender::QCamera *camera = view.camera();
       camera->lens()->setPerspectiveProjection(45.0f, 16.0f / 9.0f, 0.1f, 1000.0f);
       camera->setPosition(QVector3D(0, 0, 40.0f));
       camera->setViewCenter(QVector3D(0, 0, 0));
    
       // manipulator
       Qt3DExtras::QOrbitCameraController *manipulator = new Qt3DExtras::QOrbitCameraController(scene);
       manipulator->setLinearSpeed(50.f);
       manipulator->setLookSpeed(180.f);
       manipulator->setCamera(camera);
    
       view.setRootEntity(scene);
       view.show();
    
       return app.exec();
    }
    
    


  • Wops got sorta lucky, found out updated part of the triangle part:
    https://code.woboq.org/qt5/qt3d/tests/manual/custom-mesh-cpp-indirect/main.cpp.html

    Except that triangle normals are flipped and messed up ;- )

    humh the longer I look at it the less I like it, I think this is old/outdated way of adding meshes to the scene. Just by going here https://doc.qt.io/qt-5.10/qt3drender-qbuffer-obsolete.html we can see that they marked the 2 buffers we made as absolute. So I'm fairly sure this is NOT the way to do it.


Log in to reply