Qt 3D Custom geometry/mesh from file - incorrect result.



  • Hey

    So I run into a problem I can't figure out, something tells me its to do with setByteOffset/setByteStride but no idea, if someone could have a look and help me wrap my head around that would be great.

    Runnable example:

    QTorusMesh gets made as it should.
    Pyramid - has bad normals, no idea why
    From code - I only get 2 faces...

    main.cpp

    #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>
    
    namespace {
        struct IndirectElementDrawBuffer { // Element Indirect
            uint count;
            uint instancesCount;
            uint firstIndex;
            uint baseVertex;
            uint baseInstance;
        };
    
        struct IndirectArrayDrawBuffer { // Array Indirect
            uint count;
            uint instancesCount;
            uint first;
            uint baseInstance;
        };
    }
    
    
    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 *transformX = new Qt3DCore::QTransform;
    //    transform->setScale3D(QVector3D(1.5, 1, 0.5));
        transformX->setRotation(QQuaternion::fromAxisAndAngle(QVector3D(1, 0, 0), 45.f));
    
        Qt3DRender::QMaterial *material = new Qt3DExtras::QPhongMaterial(root);
    
        torus->addComponent(mesh);
        torus->addComponent(transformX);
        torus->addComponent(material);
    
    
        // here we start adding Pyramid
    
        // 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(0.5f, 0.5f, 0.5f);
    
        //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();
    
    
        Qt3DCore::QEntity *customDrawArrayIndirectEntity = new Qt3DCore::QEntity(root);
    
        // Transform
        Qt3DCore::QTransform *transform = new Qt3DCore::QTransform;
        transform->setScale(8.0f);
        transform->setTranslation(QVector3D(10.0f, 0.0, 0.0f));
    
        // Custom Mesh (TetraHedron)
        Qt3DRender::QGeometryRenderer *customMeshRenderer = new Qt3DRender::QGeometryRenderer;
        Qt3DRender::QGeometry *customGeometry = new Qt3DRender::QGeometry(customMeshRenderer);
    
        Qt3DRender::QBuffer *vertexDataBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer, customGeometry);
        Qt3DRender::QBuffer *indirectDrawDataBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::DrawIndirectBuffer, customGeometry);
    
    
        QVector<QVector3D> orderedPositionVertices;
        // 12 vertices with position, normal, color
        orderedPositionVertices.reserve(12 * (1 + 1 + 1));
    
        orderedPositionVertices << v0 << n0 << white;
        orderedPositionVertices << v1 << n1 << white;
        orderedPositionVertices << v2 << n2 << white;
    
        orderedPositionVertices << v3 << n3 << white;
        orderedPositionVertices << v1 << n1 << white;
        orderedPositionVertices << v0 << n0 << white;
    
        orderedPositionVertices << v0 << n0 << white;
        orderedPositionVertices << v2 << n2 << white;
        orderedPositionVertices << v3 << n3 << white;
    
        orderedPositionVertices << v1 << n1 << white;
        orderedPositionVertices << v3 << n3 << white;
        orderedPositionVertices << v2 << n2 << white;
    
        QByteArray vertexBufferData;
        vertexBufferData.resize(orderedPositionVertices.size() * sizeof(QVector3D));
        memcpy(vertexBufferData.data(), orderedPositionVertices.data(), orderedPositionVertices.size() * sizeof(QVector3D));
    
        QByteArray indirectBufferData;
        indirectBufferData.resize(sizeof(IndirectArrayDrawBuffer));
        IndirectArrayDrawBuffer *indirectStruct = reinterpret_cast<IndirectArrayDrawBuffer *>(indirectBufferData.data());
        indirectStruct->count = 12U;
        indirectStruct->baseInstance = 0U;
        indirectStruct->instancesCount = 1U;
        indirectStruct->first = 0U;
    
        vertexDataBuffer->setData(vertexBufferData);
        indirectDrawDataBuffer->setData(indirectBufferData);
    
        // Attributes
        Qt3DRender::QAttribute *positionAttribute = new Qt3DRender::QAttribute();
        positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute);
        positionAttribute->setBuffer(vertexDataBuffer);
        positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float);
        positionAttribute->setVertexSize(3);
        positionAttribute->setByteOffset(0);
        positionAttribute->setByteStride(9 * sizeof(float));
        positionAttribute->setCount(12);
        positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
    
        Qt3DRender::QAttribute *normalAttribute = new Qt3DRender::QAttribute();
        normalAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute);
        normalAttribute->setBuffer(vertexDataBuffer);
        normalAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float);
        normalAttribute->setVertexSize(3);
        normalAttribute->setByteOffset(3 * sizeof(float));
        normalAttribute->setByteStride(9 * sizeof(float));
        normalAttribute->setCount(12);
        normalAttribute->setName(Qt3DRender::QAttribute::defaultNormalAttributeName());
    
        Qt3DRender::QAttribute *colorAttribute = new Qt3DRender::QAttribute();
        colorAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute);
        colorAttribute->setBuffer(vertexDataBuffer);
        colorAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float);
        colorAttribute->setVertexSize(3);
        colorAttribute->setByteOffset(6 * sizeof(float));
        colorAttribute->setByteStride(9 * sizeof(float));
        colorAttribute->setCount(12);
        colorAttribute->setName(Qt3DRender::QAttribute::defaultColorAttributeName());
    
        Qt3DRender::QAttribute *indirectAttribute = new Qt3DRender::QAttribute();
        indirectAttribute->setAttributeType(Qt3DRender::QAttribute::DrawIndirectAttribute);
        indirectAttribute->setBuffer(indirectDrawDataBuffer);
        indirectAttribute->setByteOffset(0);
        indirectAttribute->setByteStride(0);
        indirectAttribute->setCount(1);
    
        customGeometry->addAttribute(positionAttribute);
        customGeometry->addAttribute(normalAttribute);
        customGeometry->addAttribute(colorAttribute);
        customGeometry->addAttribute(indirectAttribute);
    
        customMeshRenderer->setInstanceCount(1);
        customMeshRenderer->setIndexOffset(0);
        customMeshRenderer->setFirstInstance(0);
        customMeshRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::Triangles);
        customMeshRenderer->setGeometry(customGeometry);
        // 4 faces of 3 points
        customMeshRenderer->setVertexCount(12);
    
        customDrawArrayIndirectEntity->addComponent(customMeshRenderer);
        customDrawArrayIndirectEntity->addComponent(transform);
        customDrawArrayIndirectEntity->addComponent(material);
    
    
    
    
        // here we load box from fbx/obj/other format as arrays;
    
        QVector3D cubeMesh_vertices[] = {
                QVector3D(-17.37067, -39.26975, 0),
                QVector3D(17.37067, -39.26975, 0),
                QVector3D(-17.37067, 39.26975, 0),
                QVector3D(17.37067, 39.26975, 0),
                QVector3D(-17.37067, -39.26975, 56.2908),
                QVector3D(17.37067, -39.26975, 56.2908),
                QVector3D(-17.37067, 39.26975, 56.2908),
                QVector3D(17.37067, 39.26975, 56.2908)
        };
    
        QVector3D cubeMesh_normals[] = {
                QVector3D(0.0, 0, -1),
                QVector3D(0.0, -1, 0),
                QVector3D(-1.0, 0, 0),
                QVector3D(0.0, 0, -1),
                QVector3D(0.0, -1, 0),
                QVector3D(1.0, 0, 0),
                QVector3D(0.0, 0, -1),
                QVector3D(0.0, 1, 0),
                QVector3D(-1.0, 0, 0),
                QVector3D(0.0, 0, -1),
                QVector3D(1.0, 0, -0),
                QVector3D(0.0, 1, 0),
                QVector3D(0.0, 0, 1),
                QVector3D(0.0, -1, 0),
                QVector3D(-1.0, 0, 0),
                QVector3D(0.0, -0, 1),
                QVector3D(0.0, -1, 0),
                QVector3D(1.0, -0, 0),
                QVector3D(-0.0, 0, 1),
                QVector3D(0.0, 1, 0),
                QVector3D(-1.0, -0, -0),
                QVector3D(0.0, 0, 1),
                QVector3D(1.0, 0, 0),
                QVector3D(0.0, 1, 0)
        };
        int faceIndices[] = {3, 2, 0, 3, 0, 1, 3, 5, 2, 2, 5, 4, 7, 6, 4, 7, 4, 5, 1, 0, 6, 1, 6, 7, 3, 1, 5, 1, 7, 5, 2, 6, 0, 6, 2, 4,};
    
    
        QVector<float> orderedPositionVerticesx;
    
        // 36 vertices with position, normal, color - 6 sides -  12 triangles, each 3 verts = 36 total
        orderedPositionVerticesx.reserve(36 * 3); // *3 because we have 3 for ver normal & uv
        int nVerts = 36;
        int faces = 12;
    
        for (int x = 0; x < nVerts; x++) {
            orderedPositionVerticesx << cubeMesh_vertices[faceIndices[x]].x() << cubeMesh_vertices[faceIndices[x]].y() << cubeMesh_vertices[faceIndices[x]].z() << cubeMesh_normals[x].x() << cubeMesh_normals[x].y() << cubeMesh_normals[x].z() << 0.0 << 0.0 << 0.0;
            //populate our array with vector/ uv / normal / etc etc etc
        }
        qDebug() << orderedPositionVerticesx;
        // copy the data from vector to qbytearray
        QByteArray m_vertexBufferX;
        m_vertexBufferX.resize(orderedPositionVerticesx.size() * sizeof(float));
        memcpy(m_vertexBufferX.data(), orderedPositionVerticesx.data(), orderedPositionVerticesx.size() * sizeof(float)); // copy our mixed array to QByteArray
    
    
        QByteArray m_indexBufferX;
        m_indexBufferX.resize(nVerts * sizeof(int));
        memcpy(m_indexBufferX.data(), faceIndices, nVerts * sizeof(int)); // copy our faceIndices indices in to QByteArray ? not sure here.
    
    
    
        Qt3DRender::QGeometryRenderer *myCube = new Qt3DRender::QGeometryRenderer; // make GeometryRender Node - this is the main one that holds all attributes of shape/mesh/geo ?
        Qt3DRender::QGeometry *myCubeGeo = new Qt3DRender::QGeometry(myCube); // it holds geometry ?
    
    
        Qt3DRender::QAttribute *m_positionAttribute = new Qt3DRender::QAttribute(); // vertex attribute
        Qt3DRender::QAttribute *m_normalAttribute = new Qt3DRender::QAttribute(); // normal attribute
        Qt3DRender::QAttribute *m_texCoordAttribute = new Qt3DRender::QAttribute(); //texCord - useless for now ?
        Qt3DRender::QAttribute *m_indexAttribute = new Qt3DRender::QAttribute(); // faceIndices indices ?
    
    
        Qt3DRender::QBuffer *m_vertexBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer, myCubeGeo);
        Qt3DRender::QBuffer *m_indexBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::IndexBuffer, myCubeGeo);
        m_vertexBuffer->setData(m_vertexBufferX);
        m_indexBuffer->setData(m_indexBufferX);
        //Qt3DRender::QBuffer *m_NORBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer, myCubeGeo);
        //Qt3DRender::QBuffer *m_colorBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer, geometry);
    
    
        m_positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
        m_positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float);
        m_positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); // specify type of buffer?
        m_positionAttribute->setBuffer(m_vertexBuffer);
        m_positionAttribute->setVertexSize(3);// why 3? coz we have 3verts in triangle?
        m_positionAttribute->setByteOffset(0);
        m_positionAttribute->setByteStride(9 * sizeof(float));
        m_positionAttribute->setCount(nVerts);
    
        m_texCoordAttribute->setName(Qt3DRender::QAttribute::defaultTextureCoordinateAttributeName());
        m_texCoordAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float);
        m_texCoordAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); // this should be uv cords but its vertex... why ?
        m_texCoordAttribute->setBuffer(m_vertexBuffer);//??
        m_texCoordAttribute->setVertexSize(3);// why 2?
        m_texCoordAttribute->setByteOffset(6 * sizeof(float));
        m_texCoordAttribute->setByteStride(9 * sizeof(float));
        m_texCoordAttribute->setCount(nVerts);
    
        m_normalAttribute->setName(Qt3DRender::QAttribute::defaultNormalAttributeName());
        m_normalAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float);
        m_normalAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); // this should be normal ? not sure... weird! maybe its type of buffer of vertex so it knows its vert/uv/normal ?
        m_normalAttribute->setBuffer(m_vertexBuffer);
        m_normalAttribute->setVertexSize(3);
        m_normalAttribute->setByteOffset(3 * sizeof(float));
        m_normalAttribute->setByteStride(9 * sizeof(float));
        m_normalAttribute->setCount(nVerts);
    
        //m_indexAttribute->setAttributeType(Qt3DRender::QAttribute::DrawIndirectAttribute);
        //m_indexAttribute->setBuffer(m_indexBuffer);
        //m_indexAttribute->setByteOffset(0);
        //m_indexAttribute->setByteStride(0);
        //m_indexAttribute->setCount(1);
    
        m_indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute);
        m_indexAttribute->setVertexBaseType(Qt3DRender::QAttribute::UnsignedShort);
        m_indexAttribute->setBuffer(m_indexBuffer);
        m_indexAttribute->setByteOffset(0);
        m_indexAttribute->setByteStride(0);
        m_indexAttribute->setCount(faces * 3);
    
    
        myCubeGeo->addAttribute(m_positionAttribute);
        myCubeGeo->addAttribute(m_normalAttribute);
        myCubeGeo->addAttribute(m_indexAttribute);
        myCubeGeo->addAttribute(m_texCoordAttribute);
    
    
        myCube->setInstanceCount(1);
        myCube->setIndexOffset(0);
        myCube->setFirstInstance(0);
        myCube->setPrimitiveType(Qt3DRender::QGeometryRenderer::Triangles);
        myCube->setGeometry(myCubeGeo);
        myCube->setVertexCount(36);
    
    
        Qt3DCore::QEntity *cubeEntity = new Qt3DCore::QEntity(root);
    
        Qt3DCore::QTransform *transformXy = new Qt3DCore::QTransform;
        //transformXy->setScale3D(QVector3D(10.5, 10, 100.5));
        transformXy->setScale3D(QVector3D(.5, .5, .5));
        transformXy->setRotation(QQuaternion::fromAxisAndAngle(QVector3D(1, 0, 0), 45.f));
    
        cubeEntity->addComponent(myCube);
        cubeEntity->addComponent(transformXy);
        cubeEntity->addComponent(material);
    
    
        return root;
    }
    
    
    int main(int argc, char *argv[]) {
    
        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();
    }
    

    cmake.txt

    cmake_minimum_required(VERSION 3.9)
    project(Qt_3D_01)
    
    
    set(CMAKE_CXX_STANDARD 17)
    set(CMAKE_INCLUDE_CURRENT_DIR ON)
    set(CMAKE_AUTOMOC ON)
    set(CMAKE_AUTOUIC ON)
    
    
    add_executable(Qt_3D_01 main.cpp quadMesh.cpp quadMesh.h quadMeshGeometry.cpp quadMeshGeometry.h)
    
    
    find_package(Qt5Core REQUIRED)
    find_package(Qt5Widgets REQUIRED)
    find_package(Qt5Gui REQUIRED)
    find_package(Qt5Network REQUIRED)
    
    find_package(Qt5 REQUIRED COMPONENTS Core Gui Widgets 3DCore 3DExtras 3DRender 3DInput)
    
    
    
    qt5_use_modules(${PROJECT_NAME} Core Widgets Gui Network Concurrent 3DCore 3DExtras 3DRender 3DInput)
    target_link_libraries(${PROJECT_NAME}
            Qt5::Widgets
            Qt5::Core
            Qt5::Gui
            Qt5::Network
            Qt5::Concurrent
            Qt5::3DCore
            Qt5::3DExtras
            Qt5::3DRender
            Qt5::3DInput)
    
    
    

Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.