2

I need to draw a polygon with Qt3D, but i found how i can do this with triangles. So. I found a code, that works more tightly with OpenGL from Qt3D. It was drawing the line but i changed one to draw triangles. When i set setPrimitiveType(Qt3DRender::QGeometryRenderer::TriangleStrip);, then it works. But i wanna use setPrimitiveType(Qt3DRender::QGeometryRenderer::Triangles);, that don't work for some reason and don't draw anything. Maybe i did wrong configuration of vertex and index attributes? Or maybe i use incorrect input? (Example of my input is in the bottom)

void MainWindow::drawTriangles(const QPolygonF polygon, QColor color, Qt3DCore::QEntity *_rootEntity)
{
    int numOfVertices = polygon.size();
    auto *geometry = new Qt3DRender::QGeometry(_rootEntity);

    // Create and fill vertex buffer
    QByteArray bufferBytes;
    bufferBytes.resize(3 * numOfVertices * static_cast<int>(sizeof(float)));
    float *positions = reinterpret_cast<float*>(bufferBytes.data());

    for(auto point : polygon){
        float fHalfMapWidth = (dFittedMaxMapX_ - dFittedMinMapX_) / 2;
        float fHalfMapHeight = (dFittedMaxMapY_ - dFittedMinMapY_) / 2;

        *positions++ = static_cast<float>(point.x() - (dFittedMinMapX_ + fHalfMapWidth));
        *positions++ = 0.0f; //We need to drow only on the surface
        *positions++ = static_cast<float>(point.y() - (dFittedMinMapY_ + fHalfMapHeight));
    }

    auto *buf = new Qt3DRender::QBuffer(geometry);
    buf->setData(bufferBytes);

    auto *positionAttribute = new Qt3DRender::QAttribute(geometry); // Create a vertex attribute
    positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
    positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); // In vertex buffer we store floats
    positionAttribute->setVertexSize(3); // Size of a vertex
    positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); // Type of an attribute
    positionAttribute->setBuffer(buf); // Set vertex buffer
    positionAttribute->setByteStride(3 * sizeof(float)); // Stride between vertices
    geometry->addAttribute(positionAttribute); // Add the attribute in our  Qt3DRender::QGeometry

    // Create and fill an index buffer
    QByteArray indexBytes;
    indexBytes.resize(numOfVertices * static_cast<int>(sizeof(unsigned int))); // start to end
    unsigned int *indices = reinterpret_cast<unsigned int*>(indexBytes.data());
    for(unsigned int i = 0; i < static_cast<unsigned int>(numOfVertices); ++i) {
        *indices++ = i;
    }

    auto *indexBuffer = new Qt3DRender::QBuffer(geometry);
    indexBuffer->setData(indexBytes);

    auto *indexAttribute = new Qt3DRender::QAttribute(geometry); // Create an index attribute
    indexAttribute->setVertexBaseType(Qt3DRender::QAttribute::UnsignedInt); // In the index buffer we will store Unsigned int
    indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute); // Type of an attribute
    indexAttribute->setBuffer(indexBuffer); // Set the index buffer
    indexAttribute->setCount(static_cast<unsigned int>(numOfVertices)); // As i understand, this is a number of vertices
    geometry->addAttribute(indexAttribute); // Add attribute in our Qt3DRender::QGeometry


    auto *poly = new Qt3DRender::QGeometryRenderer(_rootEntity);
    poly->setGeometry(geometry); 
    //poly->setPrimitiveType(Qt3DRender::QGeometryRenderer::TriangleStrip); - Working variant
    poly->setPrimitiveType(Qt3DRender::QGeometryRenderer::Triangles); // - This is not working variant

    //Create a material
    auto *material = new Qt3DExtras::QPhongMaterial(_rootEntity);
    material->setAmbient(color);

    auto *trianglesEntity = new Qt3DCore::QEntity(_rootEntity);
    trianglesEntity->addComponent(poly); // Add our primitives
    trianglesEntity->addComponent(material); // Add material
}

I tried to use three and four points. When i use 4 points, then it draws if i set primitive type to "TriangleStrip". But with "Triangles" It's don't work in both cases.

mapBorder << QPointF(300,200) << QPointF(100,200) << QPointF(200,0) << QPointF(300,200) << QPointF(200,0) << QPointF(500,200) << QPointF(500,300); 
drawTriangles(mapBorder, QColor(Qt::black), mapEntity_);

Or can you to give me another suggestion how to draw polygon or triangle.

Ligvest O
  • 295
  • 2
  • 13
  • with 4 points and triangleStrip you are drawing 2 triangles, try to reorder your triangle in a clockwise order, i think you are doing it counterclockwise. or maybe reverse the default you have set https://doc.qt.io/qt-5.11/qt3drender-qcullface.html – Paltoquet Feb 21 '19 at 07:50
  • I tried to change my points order to clockwise and it have worked. Nice! But i need to draw both cases (clockwise and counterclockwise). Do you mean that i can change this behavior by using QCullFace? If so, could you help me to understand how to use it in my case? I don't really understand, what i have to do after these code lines `// using namespace Qt3DRender; QRenderStateSet *renderStateSet = new QRenderStateSet(); QCullFace *cullFront = new QCullFace(); cullFront->setMode(QCullFace::Front); renderStateSet->addRenderState(cullFront);` – Ligvest O Feb 21 '19 at 08:30

1 Answers1

2

Your points are set in clockwise order you can reorder them or set a different behaviour via this link: doc.qt.io/qt-5.11/qt3drender-qcullface.html

If you need both i would give a try to Qt3DRender::QCullFace::NoCulling

Paltoquet
  • 1,184
  • 1
  • 10
  • 18