Drawing a lot of points

I have been porting a processing sketch of Jared Tarbell’s Happy place from Aaron Penne (https://github.com/aaronpenne/generative_art/tree/master/ppy_terminal/sketches/tarbell/happyplace_port)

In the processing sketch the code uses stroke and points:

    stroke(0,85);
    point(x+random(-z,z),y+random(-z,z));

At the moment for each of the drawing objects I have used an ofMesh in OF_PRIMITIVE_POINTS mode, however as points accumulate exponentially the frame rate slows down. This does happen in the processing sketch as well, but it seems to take a lot longer.

In my OF port once I get to ta total number of points (each also has a colour) around 6450000 things slow down more than I would like to. I am aware that this is a lot of data, and it is reflective of the machine I am using.

However is there a better way to store and draw large numbers of points- I would love to increase my current amount 10 fold, so around 60 million.

1 Like

Hi @fresla,
I haven’t worked with this Processing sketch, and I haven’t been thru the github code too much, but here are a few thoughts:

  1. Do you need an ofMesh? In a quick pass of the sketch on github, it didn’t look like it used the ofMesh equivalent, but maybe I missed it. Maybe a std::vector of glm::vec2 would work for the points (or glm::vec3 if you need 3D).
  2. Vectors manage their own memory; sometimes they move to new locations and they copy themselves when they do, which takes time and resources, especially when they’re big. They have some class functions to help with this, like std::vector::reserve(), std::vector::resize(), etc. ofMesh uses a vector to store its vertices. So for lots of vertices, you could try pre-allocating some memory:
// in ofApp::setup()
int num = 60000000; // the maximum number you want to accumulate
mesh.getVertices().reserve(num);
  1. Also, you can try and use references as much as possible, and avoid copies. Many of the oF functions already return references, like ofMesh::getVertices(). If you don’t want to change anything in the reference, it can be const. Copies are slow, especially if they’re made often and/or if the objects are large.
  2. Can you draw the ofMesh only after its accumulated a chunk of new vertices? I noticed recently that /math/noiseField2DExample also accumulates and draws vertices in an ofMesh, but that it added a whole bunch of vertices way more quickly when it wasn’t having to redraw the whole mesh every cycle. I’d try it with one of these, or with a counter:
// in ofApp::draw()
int nextDraw = 8192
if(mesh.getVertices.size() % nextDraw  == 0) {mesh.draw();}
// or
if(ofGetFrameNum() % nextDraw == 0) {mesh.draw(); nextDraw *= 1.05;}  // another way
  1. Can you use an ofFbo to draw points and then forget about them? If you don’t clear an ofFbo between each draw, new elements will accumulate over old ones in the Fbo. I always forget to call ofSetBackgroundAuto(false) in ofApp::setup() when I accumulate drawings in an Fbo.
  2. Like (5) above, you could draw the ofMesh into an ofFbo when it gets to a certain size, then clear it and accumulate new vertices. Then draw the next mesh over the previous one in the Fbo without erasing it.
  3. If you have a gpu, you could try a using a shader, and storing vertices in a texture, which requires a pair of ofFbo (one for reading and one for writing). There is an awesome example of this in /gl/gpuParticleSystemExample. In theory, each pixel of an RGBA texture could store 2 different 2D points. 60 million points could be stored in a 5500 x 5500 texture. You would do any computations with them in the shader though. There may be a benefit to the texture being a power of 2 and/or being square, but I’m speculating. Your gpu needs to support the programmable renderer in oF.

OK hope one of these helps! Let us know if one of them does, and maybe others will chime in on this topic.

1 Like