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