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

Data limitation using QSGGeometryNode?



  • I am using Qt 5.8. I am attempting to draw circular points using QSGGeometry::DrawTriangles (using QSGGeometry::DrawPoints draws points as rectangles/squares--not desired). In order to do this I am drawing 8 triangles that gives the illusion of a circle. Each data point will have 8 triangles associated with it. The number of data points can vary at any given time. After a (user) specified amount of time as a data point is added, one data point is removed. There seems to be an error in the allocation of data when a certain amount of points are to be drawn. I used setVertexDataPattern(QSGGeometry::StreamPattern); in the construction of the QSGGeometryNode; in hopes of getting the desired output. On each draw call, I call m_geometry.allocate(m_pts.size() * MAX_VERTICES), where MAX_VERTICES = 24 in case the number of points since the last draw call has changed. I have attempted to use GL_POLYGON (since it would require fewer vertices), but the same problem happens.
    What is the proper way to handle drawing lots of data with varying sizes? I have created a sample that allows you to change the number of points displayed.

    main.qml

    import QtQuick 2.8
    import QtQuick.Window 2.2
    import TestModule 1.0
    
    Window {
        visible: true
        width: 640
        height: 480
        title: qsTr("Hello World")
    
        Rectangle {
            color: "black"
            width: parent.width
            height: parent.height * .90
            anchors.top: parent.top
    
            MouseArea {
               anchors.fill: parent
               onClicked: {
                   Qt.quit();
               }
           }
    
           TestItem {
               id: testItem
               anchors.fill: parent
               ptCount: 25000
               color: "green"
           }
        }
        Rectangle {
            anchors.horizontalCenter: parent.horizontalCenter
            anchors.bottom: parent.bottom
            height: parent.height * .10
            width: parent.width
            border.color: "pink"
            color: "lightgray"
            TextInput {
                anchors.fill: parent
                anchors.centerIn: parent
                id: textInput
                text: "enter max number of points here"
                horizontalAlignment: TextInput.AlignHCenter
                verticalAlignment: TextInput.AlignVCenter
                color: "steelblue"
                onEditingFinished: testItem.ptCount = parseInt(textInput.text)
                validator: IntValidator{bottom: 1}
            }
        }
    }
    

    TestItem.h

    #include <QQuickItem>
    
    class QSGGeometryNode;
    
    class TestItem : public QQuickItem
    {
            Q_OBJECT
    
            Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY  colorChanged)
            Q_PROPERTY(qint32 ptCount READ ptCount WRITE setPtCount NOTIFY ptCountChanged)
    
        public:
            explicit TestItem(QQuickItem *parent = 0);
    
            QColor color();
            void setColor(const QColor &color);
    
            void setPtCount(const qint32& newVal);
            qint32 ptCount();
    
        signals:
            void colorChanged();
            void ptCountChanged();
    
        protected:
            QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
            void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
    
            QColor m_color;
            qint32 m_ptCount;
    };
    

    TestItem.cpp

    #include "TestItem.h"
    #include <QSGNode>
    #include <QSGVertexColorMaterial>
    
    TestItem::TestItem(QQuickItem *parent) : QQuickItem(parent), m_color(Qt::green), m_ptCount(25000)
    {
        setFlag(ItemHasContents, true);
    }
    
    QColor TestItem::color()
    {
        return m_color;
    }
    
    void TestItem::setColor(const QColor &color)
    {
        m_color = color;
        update();
        emit colorChanged();
    }
    
    void TestItem::setPtCount(const qint32 &newVal)
    {
        if (newVal < 0)
            m_ptCount = 25000;
        else
            m_ptCount = newVal;
        update();
        emit ptCountChanged();
    }
    
    qint32 TestItem::ptCount()
    {
        return m_ptCount;
    }
    
    QSGNode *TestItem::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *)
    {
        QSGGeometryNode *node = nullptr;
        QSGGeometry *geometry = nullptr;
    
        if (!oldNode)
        {
            node = new QSGGeometryNode;
            geometry = new QSGGeometry(QSGGeometry::defaultAttributes_ColoredPoint2D(), m_ptCount * 3);
            geometry->setDrawingMode(GL_TRIANGLES);
            node->setGeometry(geometry);
            node->setFlag(QSGNode::OwnsGeometry);
    
            QSGVertexColorMaterial *material = new QSGVertexColorMaterial;
            node->setMaterial(material);
            node->setFlag(QSGNode::OwnsMaterial);
        }
        else
        {
            node = static_cast<QSGGeometryNode *>(oldNode);
            geometry = node->geometry();
            geometry->allocate(m_ptCount * 3);
        }
    
        QSGGeometry::ColoredPoint2D *vertices = geometry->vertexDataAsColoredPoint2D();
        qreal triWidth = 250/boundingRect().width() + 10;
    
        for (int i = 0; i < m_ptCount; ++i)
        {
            QColor color;
            if (i == m_ptCount - 1)
                color = Qt::white;
            else
                color = m_color;
            qreal x0 = (boundingRect().width() * .90/m_ptCount) * i ;
            qreal y0 = 60 * sinf(x0* 3.14/180); // 60 just varies the height of the wave
    
            qreal x1 = x0 + 0.05 * boundingRect().width(); // 0.05 so that we have 5% space on each side
            qreal y1 = y0 + boundingRect().height()/2;
    
            vertices[i * 3].set(x1, y1, color.red(), color.green(), color.blue(), color.alpha());
            vertices[i * 3 + 1].set(x1 + triWidth, y1, color.red(), color.green(), color.blue(), color.alpha());
            vertices[i * 3 + 2].set(x1 + triWidth, y1 + triWidth, color.red(), color.green(), color.blue(), color.alpha());
        }
        node->markDirty(QSGNode::DirtyGeometry);
    
        return node;
    }
    
    void TestItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
    {
        update();
        QQuickItem::geometryChanged(newGeometry, oldGeometry);
    }
    

Log in to reply