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