Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QGeometryRenderer: How to render an isosurface from quadrilateral patches?

QGeometryRenderer: How to render an isosurface from quadrilateral patches?

Scheduled Pinned Locked Moved Solved General and Desktop
qt3dqt3drender
3 Posts 2 Posters 1.0k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • F Offline
    F Offline
    Finn
    wrote on 5 Jan 2019, 15:24 last edited by
    #1

    The question is a mirror of a stackoverflow post.

    I extracted an isosurface with the dual marching cubes algorithm.

    From the algorithm, I got the following data:

    # cube.obj wavefront file
    ## shared vertices (cartesian coordinates)
    v 1.0 1.0 0.0
    v 0.0 1.0 0.0
    v 0.0 0.0 0.0
    v 1.0 0.0 0.0
    v 1.0 0.0 1.0
    v 0.0 0.0 1.0
    v 0.0 1.0 1.0
    v 1.0 1.0 1.0
    ## faces (vertex indices are forming quad patches)
    f 1 4 3 2
    f 5 6 3 4
    f 7 2 3 6
    f 8 5 4 1
    f 8 1 2 7
    f 8 7 6 5
    

    (Plotting triangulated surfaces is explained here).

    Main question: Is it possible to render an isosurface from this quadrilateral face data with Qt3d?

    Bonus question: How can I make the surface transparent or plot it as a wireframe?

    This is how far I got:

    #include <QApplication>
    #include <QWidget>
    #include <Qt3DExtras/Qt3DWindow>
    #include <Qt3DExtras/QOrbitCameraController>
    #include <Qt3DRender/QCamera>
    #include <Qt3DCore/QEntity>
    #include <Qt3DCore/QTransform>
    #include <Qt3DRender/QGeometryRenderer>
    #include <Qt3DRender/QAttribute>
    #include <Qt3DRender/QBuffer>
    #include <Qt3DExtras/QPhongAlphaMaterial>
    
    int main(int argc, char* argv[])
    {
        QApplication app(argc, argv);
    
        // Root entity
        auto *rootEntity = new Qt3DCore::QEntity();
    
        // Window container
        auto qt3DWindow = new Qt3DExtras::Qt3DWindow();
        qt3DWindow->setRootEntity(rootEntity);
        auto widget = QWidget::createWindowContainer(qt3DWindow);
    
        // Camera
        auto *camController = new Qt3DExtras::QOrbitCameraController(rootEntity);
    
        qt3DWindow->setRootEntity(rootEntity);
        qt3DWindow->camera()->lens()->setPerspectiveProjection(45.0f, 16.0f / 9.0f, 0.1f, 100.0f);
        qt3DWindow->camera()->setPosition(QVector3D(2.5, -8, 0.0));
        qt3DWindow->camera()->setViewCenter(QVector3D(0, 0, 0));
    
        // For camera controls
        camController->setLinearSpeed(50.f);
        camController->setLookSpeed(180.f);
        camController->setCamera(qt3DWindow->camera());
    
        // Material
        auto *material = new Qt3DExtras::QPhongAlphaMaterial(rootEntity);
        material->setSpecular(Qt::white);
        material->setShininess(0);
        material->setAmbient(Qt::red);
        material->setAlpha(0.5);
    
        // Transform
        auto *transform = new Qt3DCore::QTransform;
        transform->setScale(1.0f);
    
        auto *customMeshEntity = new Qt3DCore::QEntity(rootEntity);
    
        // Custom Mesh
        auto *customMeshRenderer = new Qt3DRender::QGeometryRenderer;
        auto *customGeometry = new Qt3DRender::QGeometry(customMeshRenderer);
    
        auto *vertexDataBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer, customGeometry);
        auto *indexDataBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::IndexBuffer, customGeometry);
    
        // Vertices
        auto nVertices = 8;
        auto nCoordinates = 3; // cartesian coordinates
        QByteArray vertexBufferData;
        vertexBufferData.resize(nVertices * nCoordinates * sizeof(float));
    
        auto *rawVertexArray = reinterpret_cast<float *>(vertexBufferData.data());
        // Vertex 1
        rawVertexArray[0*nCoordinates+0] = 1.0f;
        rawVertexArray[0*nCoordinates+1] = 1.0f;
        rawVertexArray[0*nCoordinates+2] = 0.0f;
        // Vertex 2
        rawVertexArray[1*nCoordinates+0] = 0.0f;
        rawVertexArray[1*nCoordinates+1] = 1.0f;
        rawVertexArray[1*nCoordinates+2] = 0.0f;
        // Vertex 3
        rawVertexArray[2*nCoordinates+0] = 0.0f;
        rawVertexArray[2*nCoordinates+1] = 0.0f;
        rawVertexArray[2*nCoordinates+2] = 0.0f;
        // Vertex 4
        rawVertexArray[3*nCoordinates+0] = 1.0f;
        rawVertexArray[3*nCoordinates+1] = 0.0f;
        rawVertexArray[3*nCoordinates+2] = 0.0f;
        // Vertex 5
        rawVertexArray[4*nCoordinates+0] = 1.0f;
        rawVertexArray[4*nCoordinates+1] = 0.0f;
        rawVertexArray[4*nCoordinates+2] = 1.0f;
        // Vertex 6
        rawVertexArray[5*nCoordinates+0] = 0.0f;
        rawVertexArray[5*nCoordinates+1] = 0.0f;
        rawVertexArray[5*nCoordinates+2] = 1.0f;
        // Vertex 7
        rawVertexArray[6*nCoordinates+0] = 0.0f;
        rawVertexArray[6*nCoordinates+1] = 1.0f;
        rawVertexArray[6*nCoordinates+2] = 1.0f;
        // Vertex 8
        rawVertexArray[7*nCoordinates+0] = 1.0f;
        rawVertexArray[7*nCoordinates+1] = 1.0f;
        rawVertexArray[7*nCoordinates+2] = 1.0f;
    
        vertexDataBuffer->setData(vertexBufferData);
    
        // Faces
        unsigned nFaces = 6;
        unsigned nIndicesPerFace = 4;
        QByteArray indexBufferData;
        indexBufferData.resize(nFaces * nIndicesPerFace * sizeof(ushort));
    
        auto *rawIndexArray = reinterpret_cast<ushort *>(indexBufferData.data());
        // Face 1
        rawIndexArray[0*nIndicesPerFace+0] = 1;
        rawIndexArray[0*nIndicesPerFace+1] = 4;
        rawIndexArray[0*nIndicesPerFace+2] = 3;
        rawIndexArray[0*nIndicesPerFace+3] = 2;
        // Face 2
        rawIndexArray[1*nIndicesPerFace+0] = 5;
        rawIndexArray[1*nIndicesPerFace+1] = 6;
        rawIndexArray[1*nIndicesPerFace+2] = 3;
        rawIndexArray[1*nIndicesPerFace+3] = 4;
        // Face 3
        rawIndexArray[2*nIndicesPerFace+0] = 7;
        rawIndexArray[2*nIndicesPerFace+1] = 2;
        rawIndexArray[2*nIndicesPerFace+2] = 3;
        rawIndexArray[2*nIndicesPerFace+3] = 6;
        // Face 4
        rawIndexArray[3*nIndicesPerFace+0] = 8;
        rawIndexArray[3*nIndicesPerFace+1] = 5;
        rawIndexArray[3*nIndicesPerFace+2] = 4;
        rawIndexArray[3*nIndicesPerFace+3] = 1;
        // Face 5
        rawIndexArray[4*nIndicesPerFace+0] = 8;
        rawIndexArray[4*nIndicesPerFace+1] = 1;
        rawIndexArray[4*nIndicesPerFace+2] = 2;
        rawIndexArray[4*nIndicesPerFace+3] = 7;
        // Face 6
        rawIndexArray[5*nIndicesPerFace+0] = 8;
        rawIndexArray[5*nIndicesPerFace+1] = 7;
        rawIndexArray[5*nIndicesPerFace+2] = 6;
        rawIndexArray[5*nIndicesPerFace+3] = 5;
    
        indexDataBuffer->setData(indexBufferData);
    
        // Attributes
        auto *positionAttribute = new Qt3DRender::QAttribute();
        positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute);
        positionAttribute->setBuffer(vertexDataBuffer);
        positionAttribute->setDataType(Qt3DRender::QAttribute::Float);
        positionAttribute->setDataSize(nCoordinates);
        positionAttribute->setByteOffset(0);
        positionAttribute->setByteStride(nCoordinates * sizeof(float));
        positionAttribute->setCount(nVertices);
        positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
    
        auto *indexAttribute = new Qt3DRender::QAttribute();
        indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute);
        indexAttribute->setBuffer(indexDataBuffer);
        indexAttribute->setDataType(Qt3DRender::QAttribute::UnsignedShort);
        indexAttribute->setDataSize(1);
        indexAttribute->setByteOffset(0);
        indexAttribute->setByteStride(0);
        indexAttribute->setCount(nFaces*nIndicesPerFace);
    
        customGeometry->addAttribute(positionAttribute);
        customGeometry->addAttribute(indexAttribute);
    
        customMeshRenderer->setInstanceCount(1);
        customMeshRenderer->setFirstVertex(0);
        customMeshRenderer->setIndexOffset(1); // first index is 1
        customMeshRenderer->setFirstInstance(0);
        customMeshRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::Patches);
        customMeshRenderer->setVerticesPerPatch(nIndicesPerFace);
        customMeshRenderer->setGeometry(customGeometry);
        customMeshRenderer->setVertexCount(nFaces * nIndicesPerFace);
    
        customMeshEntity->addComponent(customMeshRenderer);
        customMeshEntity->addComponent(transform);
        customMeshEntity->addComponent(material);
    
        qt3DWindow->setRootEntity(rootEntity);
        widget->show();
    
        return QApplication::exec();
    }
    

    The rendered scene remains empty, so I assume I did something wrong here. I am grateful for any help!

    A 1 Reply Last reply 5 Jan 2019, 15:57
    0
    • F Finn
      5 Jan 2019, 15:24

      The question is a mirror of a stackoverflow post.

      I extracted an isosurface with the dual marching cubes algorithm.

      From the algorithm, I got the following data:

      # cube.obj wavefront file
      ## shared vertices (cartesian coordinates)
      v 1.0 1.0 0.0
      v 0.0 1.0 0.0
      v 0.0 0.0 0.0
      v 1.0 0.0 0.0
      v 1.0 0.0 1.0
      v 0.0 0.0 1.0
      v 0.0 1.0 1.0
      v 1.0 1.0 1.0
      ## faces (vertex indices are forming quad patches)
      f 1 4 3 2
      f 5 6 3 4
      f 7 2 3 6
      f 8 5 4 1
      f 8 1 2 7
      f 8 7 6 5
      

      (Plotting triangulated surfaces is explained here).

      Main question: Is it possible to render an isosurface from this quadrilateral face data with Qt3d?

      Bonus question: How can I make the surface transparent or plot it as a wireframe?

      This is how far I got:

      #include <QApplication>
      #include <QWidget>
      #include <Qt3DExtras/Qt3DWindow>
      #include <Qt3DExtras/QOrbitCameraController>
      #include <Qt3DRender/QCamera>
      #include <Qt3DCore/QEntity>
      #include <Qt3DCore/QTransform>
      #include <Qt3DRender/QGeometryRenderer>
      #include <Qt3DRender/QAttribute>
      #include <Qt3DRender/QBuffer>
      #include <Qt3DExtras/QPhongAlphaMaterial>
      
      int main(int argc, char* argv[])
      {
          QApplication app(argc, argv);
      
          // Root entity
          auto *rootEntity = new Qt3DCore::QEntity();
      
          // Window container
          auto qt3DWindow = new Qt3DExtras::Qt3DWindow();
          qt3DWindow->setRootEntity(rootEntity);
          auto widget = QWidget::createWindowContainer(qt3DWindow);
      
          // Camera
          auto *camController = new Qt3DExtras::QOrbitCameraController(rootEntity);
      
          qt3DWindow->setRootEntity(rootEntity);
          qt3DWindow->camera()->lens()->setPerspectiveProjection(45.0f, 16.0f / 9.0f, 0.1f, 100.0f);
          qt3DWindow->camera()->setPosition(QVector3D(2.5, -8, 0.0));
          qt3DWindow->camera()->setViewCenter(QVector3D(0, 0, 0));
      
          // For camera controls
          camController->setLinearSpeed(50.f);
          camController->setLookSpeed(180.f);
          camController->setCamera(qt3DWindow->camera());
      
          // Material
          auto *material = new Qt3DExtras::QPhongAlphaMaterial(rootEntity);
          material->setSpecular(Qt::white);
          material->setShininess(0);
          material->setAmbient(Qt::red);
          material->setAlpha(0.5);
      
          // Transform
          auto *transform = new Qt3DCore::QTransform;
          transform->setScale(1.0f);
      
          auto *customMeshEntity = new Qt3DCore::QEntity(rootEntity);
      
          // Custom Mesh
          auto *customMeshRenderer = new Qt3DRender::QGeometryRenderer;
          auto *customGeometry = new Qt3DRender::QGeometry(customMeshRenderer);
      
          auto *vertexDataBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer, customGeometry);
          auto *indexDataBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::IndexBuffer, customGeometry);
      
          // Vertices
          auto nVertices = 8;
          auto nCoordinates = 3; // cartesian coordinates
          QByteArray vertexBufferData;
          vertexBufferData.resize(nVertices * nCoordinates * sizeof(float));
      
          auto *rawVertexArray = reinterpret_cast<float *>(vertexBufferData.data());
          // Vertex 1
          rawVertexArray[0*nCoordinates+0] = 1.0f;
          rawVertexArray[0*nCoordinates+1] = 1.0f;
          rawVertexArray[0*nCoordinates+2] = 0.0f;
          // Vertex 2
          rawVertexArray[1*nCoordinates+0] = 0.0f;
          rawVertexArray[1*nCoordinates+1] = 1.0f;
          rawVertexArray[1*nCoordinates+2] = 0.0f;
          // Vertex 3
          rawVertexArray[2*nCoordinates+0] = 0.0f;
          rawVertexArray[2*nCoordinates+1] = 0.0f;
          rawVertexArray[2*nCoordinates+2] = 0.0f;
          // Vertex 4
          rawVertexArray[3*nCoordinates+0] = 1.0f;
          rawVertexArray[3*nCoordinates+1] = 0.0f;
          rawVertexArray[3*nCoordinates+2] = 0.0f;
          // Vertex 5
          rawVertexArray[4*nCoordinates+0] = 1.0f;
          rawVertexArray[4*nCoordinates+1] = 0.0f;
          rawVertexArray[4*nCoordinates+2] = 1.0f;
          // Vertex 6
          rawVertexArray[5*nCoordinates+0] = 0.0f;
          rawVertexArray[5*nCoordinates+1] = 0.0f;
          rawVertexArray[5*nCoordinates+2] = 1.0f;
          // Vertex 7
          rawVertexArray[6*nCoordinates+0] = 0.0f;
          rawVertexArray[6*nCoordinates+1] = 1.0f;
          rawVertexArray[6*nCoordinates+2] = 1.0f;
          // Vertex 8
          rawVertexArray[7*nCoordinates+0] = 1.0f;
          rawVertexArray[7*nCoordinates+1] = 1.0f;
          rawVertexArray[7*nCoordinates+2] = 1.0f;
      
          vertexDataBuffer->setData(vertexBufferData);
      
          // Faces
          unsigned nFaces = 6;
          unsigned nIndicesPerFace = 4;
          QByteArray indexBufferData;
          indexBufferData.resize(nFaces * nIndicesPerFace * sizeof(ushort));
      
          auto *rawIndexArray = reinterpret_cast<ushort *>(indexBufferData.data());
          // Face 1
          rawIndexArray[0*nIndicesPerFace+0] = 1;
          rawIndexArray[0*nIndicesPerFace+1] = 4;
          rawIndexArray[0*nIndicesPerFace+2] = 3;
          rawIndexArray[0*nIndicesPerFace+3] = 2;
          // Face 2
          rawIndexArray[1*nIndicesPerFace+0] = 5;
          rawIndexArray[1*nIndicesPerFace+1] = 6;
          rawIndexArray[1*nIndicesPerFace+2] = 3;
          rawIndexArray[1*nIndicesPerFace+3] = 4;
          // Face 3
          rawIndexArray[2*nIndicesPerFace+0] = 7;
          rawIndexArray[2*nIndicesPerFace+1] = 2;
          rawIndexArray[2*nIndicesPerFace+2] = 3;
          rawIndexArray[2*nIndicesPerFace+3] = 6;
          // Face 4
          rawIndexArray[3*nIndicesPerFace+0] = 8;
          rawIndexArray[3*nIndicesPerFace+1] = 5;
          rawIndexArray[3*nIndicesPerFace+2] = 4;
          rawIndexArray[3*nIndicesPerFace+3] = 1;
          // Face 5
          rawIndexArray[4*nIndicesPerFace+0] = 8;
          rawIndexArray[4*nIndicesPerFace+1] = 1;
          rawIndexArray[4*nIndicesPerFace+2] = 2;
          rawIndexArray[4*nIndicesPerFace+3] = 7;
          // Face 6
          rawIndexArray[5*nIndicesPerFace+0] = 8;
          rawIndexArray[5*nIndicesPerFace+1] = 7;
          rawIndexArray[5*nIndicesPerFace+2] = 6;
          rawIndexArray[5*nIndicesPerFace+3] = 5;
      
          indexDataBuffer->setData(indexBufferData);
      
          // Attributes
          auto *positionAttribute = new Qt3DRender::QAttribute();
          positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute);
          positionAttribute->setBuffer(vertexDataBuffer);
          positionAttribute->setDataType(Qt3DRender::QAttribute::Float);
          positionAttribute->setDataSize(nCoordinates);
          positionAttribute->setByteOffset(0);
          positionAttribute->setByteStride(nCoordinates * sizeof(float));
          positionAttribute->setCount(nVertices);
          positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
      
          auto *indexAttribute = new Qt3DRender::QAttribute();
          indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute);
          indexAttribute->setBuffer(indexDataBuffer);
          indexAttribute->setDataType(Qt3DRender::QAttribute::UnsignedShort);
          indexAttribute->setDataSize(1);
          indexAttribute->setByteOffset(0);
          indexAttribute->setByteStride(0);
          indexAttribute->setCount(nFaces*nIndicesPerFace);
      
          customGeometry->addAttribute(positionAttribute);
          customGeometry->addAttribute(indexAttribute);
      
          customMeshRenderer->setInstanceCount(1);
          customMeshRenderer->setFirstVertex(0);
          customMeshRenderer->setIndexOffset(1); // first index is 1
          customMeshRenderer->setFirstInstance(0);
          customMeshRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::Patches);
          customMeshRenderer->setVerticesPerPatch(nIndicesPerFace);
          customMeshRenderer->setGeometry(customGeometry);
          customMeshRenderer->setVertexCount(nFaces * nIndicesPerFace);
      
          customMeshEntity->addComponent(customMeshRenderer);
          customMeshEntity->addComponent(transform);
          customMeshEntity->addComponent(material);
      
          qt3DWindow->setRootEntity(rootEntity);
          widget->show();
      
          return QApplication::exec();
      }
      

      The rendered scene remains empty, so I assume I did something wrong here. I am grateful for any help!

      A Offline
      A Offline
      amartya1998
      wrote on 5 Jan 2019, 15:57 last edited by
      #2

      @Finn I need some help in extracting the isosurface https://forum.qt.io/topic/98234/surface-rendering-of-volumetric-data

      1 Reply Last reply
      0
      • F Offline
        F Offline
        Finn
        wrote on 7 Jan 2019, 15:54 last edited by
        #3

        I found a solution. Please see my stackoverflow post.

        1 Reply Last reply
        1

        2/3

        5 Jan 2019, 15:57

        • Login

        • Login or register to search.
        2 out of 3
        • First post
          2/3
          Last post
        0
        • Categories
        • Recent
        • Tags
        • Popular
        • Users
        • Groups
        • Search
        • Get Qt Extensions
        • Unsolved