draw multiple points with different colors in a QQuickItem

1.7k views Asked by At

i want to render a plot with a lot of points (>1.000.000) and different colors in a custom QQuickItem.

Later I want to animate these Points (fading between coordinates and colors), so I think QQuickPaintedItem is not fast enough for this and I must using the updatePaintNode interface of QQuickItem.

The problem is to set the color for each point. Must I create for each Point a QSGGeometryNode and add Geometry and ColorMaterial? Or is there a faster solution?

Best Regards

2

There are 2 answers

4
501 - not implemented On

I worked a little bit with openGL and found a solution that worked for me

The normal OpenGL examples used QSGGeometry::Point2D to set up the verticies. But there is a Version with color support,too (QSGGeometry::defaultAttributes_ColoredPoint2D()). So I can set up the verticies with

  vertices[i].set(x, y, r,g, b, a);

//EDIT: the next problem is that the gui freezes from time to time , if the QSGeometry-Object has to many verticies. I don't know why. The GUI is slow down after allocate the memory for the verticies, so this approach has not good performance.

//EDIT 2:

I added a simplified code of the current updatePaint-method. If the data object is very huge (>2.000.000 points), the widgets renders the points but than the whole gui is hanging and stuttering.

QSGNode *HistogramView::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *)
{
QSGGeometryNode *node = 0;
QSGGeometry *geometry = 0;

if (!oldNode) {
    node = new QSGGeometryNode;
    geometry = new QSGGeometry(QSGGeometry::defaultAttributes_ColoredPoint2D(), data.size());
    geometry->setDrawingModeelsize(GL_POINTS);
    node->setGeometry(geometry);
    node->setFlag(QSGNode::OwnsGeometry);

    QSGVertexColorMaterial *material = new QSGVertexColorMaterial();
    //material->setColor(QColor(255, 0, 0));
    node->setMaterial(material);
    node->setFlag(QSGNode::OwnsMaterial);

} else {
    node = static_cast<QSGGeometryNode *>(oldNode);
    geometry = node->geometry();
    geometry->allocate(222);
}
QSGGeometry::ColoredPoint2D *vertices = geometry->vertexDataAsColoredPoint2D();
for (int i = 0; i < data.size(); i++) {
        vertices[id].set(x, y,red, green, blue, 255);
        }
    }
}
node->markDirty(QSGNode::DirtyGeometry);
return node;



}

I could localize the error. after calling initializing the QSGGeometry-object( geometry = new QSGGeometry(QSGGeometry::defaultAttributes_ColoredPoint2D(), data.size());) the gui is very slow.

Greetings

0
tonytony On

2 million elements is quite a lot, I beleive GUI freezes because of that loop inside updatePaintNode (GUI thread is blocked during updatePaintNode execution, as documentation states).

Idea #1

If you don't change the whole point array frequently, you can update in updatePaintNode only those vertices that have changed since the last paint, instead of running the huge 2kk loop every time. But AFAIK you'll still need to update all the vertices in case of histogram resizing.

Idea #2

Another potential optimization may be preparing vertex data array before updatePaintNode and then copying the whole array using memcpy or std::copy inside of updatePaintNode. Copying continuous memory array as a whole tends to be much faster than per-element copying, and since you're filling the array using the accessor function I'm not sure if it's optimized by the compiler.

Idea #3

2 million points seems too much to present on a single graph. Presenting so much data at once can hurt UX because points of different colors will overlap an user might miss valuable information.

You can reduce level of detail by merging points of the same color together and visualising these clusters instead of separate points. However, this approach will take quite an effort, so I suggest trying it when less complex solutions don't help.