How to render Point Cloud efficiently?

edited August 2015 in Questions about Code

Hello!

For random point cloud generated in realtime, what data structure in Processing is appropriate for its rendering? I tried with PShape, but only got 10~15 FPS for 20,000 points.

PShape boxCloud;

void setup() {
  size(400, 400, P3D);
  smooth();
}

void draw() {
  background(0);
  translate(width/2, height/2);
  gen();
  shape(boxCloud);
}

void gen()
{
  boxCloud = createShape();
  boxCloud.beginShape(POINTS);
  boxCloud.stroke(255);
  for (int i = 0; i < 20000; i++) {
    boxCloud.vertex(random(-50, 50), random(-50, 50), random(-50, 50));
  }
  boxCloud.endShape();
}

I've test ofMesh in openFrameworks, it can run at almost 60 FPS rendering 200,000 points. Is it possible to do that in Processing?

Answers

  • Note that you aren't just rendering a point cloud each frame. You're also creating a new point cloud every single frame. Are you sure this is what you want to do?

  • Yes, I intend to have a dynamic point cloud. I tried to create just one PShape in setup(), then update it with PShape.setVertex() each frame, the performance is much better now, which is about 25~30 FPS.

    PShape boxCloud;
    
    void setup() {
      size(400, 400, P3D);
      smooth();
      genCloud();
    }
    
    void draw() {
      background(0);
      translate(width/2, height/2);
      updateCloud();
      shape(boxCloud);
    }
    
    void genCloud()
    {
      boxCloud = createShape();
      boxCloud.beginShape(POINTS);
      boxCloud.stroke(255);
      for (int i = 0; i < 20000; i++) {
        boxCloud.vertex(0, 0, 0);
      }
      boxCloud.endShape();
    }
    
    void updateCloud()
    {
      for (int i = 0; i < boxCloud.getVertexCount(); i++) {
        PVector v = new PVector(random(-50, 50), random(-50, 50), random(-50, 50));
        boxCloud.setVertex(i, v);
      }
    }
    

    AFAIK, the rendering of ofMesh in openFrameWorks is implemented with OpenGL vertex array. Is PShape the Processing's counterpart to ofMesh? If not, which one is capable of doing that 200,000 points rendering at 60 FPS?

    Thank you for your reply!

  • And, HE_Mesh lib may be a little overwhelming for this simple task. Besides that, I want to render each points as "POINTS", HE_Mesh renderer's drawVertices() renders each vertex as a cube, and I haven't find a way to change that property.

  • I tried to create just one PShape in setup(), then update it

    try doing the same for the PVector in line 30 - create it outside the loop, update it inside.

    i also seem to remember people posting faster versions of random()

  • Thank you!

    Just done that, but it seems doesn't improve significantly.

    Sorry for the random(), it is supposed to be other realtime generated values, I use random() just for simplicy here. I tested with v.set(0, 0, 0), and it doesn't make much difference either, .

  • I timed updateCloud() and shape(boxCloud). More than 90% of the time is spent in shape(). I don't think tweaking updateCloud() will help much.

    Bill

  • Answer ✓

    is processing 1.5.1 and GlGraphics a possibility? i've used it a couple of times. it allows easy access to VBOs etc

    https://codeanticode.wordpress.com/2011/05/16/glgraphics-099-released/

    http://glgraphics.sourceforge.net/

    look at the million cubes example, or the particle system example.

    example by me, 900,000 static lines, rotating camera.

    https://www.flickr.com/photos/31962137@N00/5966878196/in/photolist-a6gP1h

  • (i'm guessing this is at a lower level than shape and therefore quicker)

  • edited August 2015

    and here's the thread with the random() replacements (doing a 2d version of your point cloud). see specifically davbol's post where he uses a LCG

    http://forum.processing.org/one/topic/why-does-this-simple-program-run-at-such-a-low-framerate.html

  • here you go, didn't take long to modify the above:

    runs fine on my PC, not even maxing out one core of my centrino processor (2009 vintage) and nvidia GT130M.

    // 200,000 random points
    // processing 1.5.1 and glGraphics
    // acd 2015-08-05
    
    import codeanticode.glgraphics.*;
    import peasy.*;
    import processing.opengl.*;
    
    int COUNT = 200000;
    int SZ = 50;
    
    GLModel points;
    PeasyCam cam;
    
    void setup() {
      size(720, 720, GLConstants.GLGRAPHICS);
      points = new GLModel(this, COUNT, POINTS, GLModel.DYNAMIC);
      points.initColors();
      points.setColors(0);
      update();
    
      cam = new PeasyCam(this, SZ);
      cam.setMaximumDistance(2000);
      cam.setMinimumDistance(20);
    }
    
    void draw() {
    
      GLGraphics renderer = (GLGraphics)g;
      renderer.beginGL();
      background(255);
      stroke(0);
      renderer.model(points);
      renderer.endGL();
      update();
    }
    
    void update() {
      points.beginUpdateVertices();
      for (int i = 0 ; i < COUNT ; i++) {
        // TODO optimise this
        points.updateVertex(i, random(-SZ, SZ), random(-SZ, SZ), random(-SZ, SZ));
      }
      points.endUpdateVertices();
    }
    
  • Thank you koogs! That approach does work in Processing 1.5.1. I'll keep digging. Thanks to KevinWorkman and billhsu for your reply!

Sign In or Register to comment.