We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpOpenGL and 3D Libraries › Optimizing display of lots of primitives (~200k)
Page Index Toggle Pages: 1
Optimizing display of lots of primitives (~200k) (Read 1972 times)
Optimizing display of lots of primitives (~200k)
Apr 25th, 2009, 6:45am
 
I'm working on a sketch that takes a movie (in this example an image sequence), extrudes each frame, and stacks them. Each pixel becomes a cube of the same color; 'background' pixels are keyed out. Right now, it's static, but eventually I would love to have it be dynamic, loading new frames on top of the stack. This sketch is a test run, using 50 frames of a 100x100px video. (Note the weird moire pattern is due to my laziness in keying out the 'background' pixels)

Performance is dead slow (even on my Mac Pro), which I kind of expected: I'm rendering between 200 000 and 500 000 cubes! I've read up on some possible methods to speed things up, and I would love some feedback on which might be most effective.

1) Implement Vertex Buffer Objects
2) Create a custom cube class based on rects rather than use Processing's box() class
3) Avoid rendering unnecessary cubes (how?)
4) Implement a 'preview' view using something like points, then show the cubes when the camera comes to rest
5) Instead of rending individual cubes for each frame 'layer', render an object that aggregates their geometry and texture it with the pixel array. (Note: I would need to keep the cubes array around in memory for processing, but this might be a solution for rendering)

Separate question: what's the best tool for profiling OpenGL use in a processing app?

I would really appreciate any advice on which of these (if any) would be the best place to start. If anybody has other ideas, please post them! Thanks....

Applet here (http://www.ingenuepictures.com/pixelextrusion/index.html), code below. The applet's ~3megs and may take a minute to load.


__________________________

import processing.video.*;

import peasy.org.apache.commons.math.*;
import peasy.*;
import peasy.org.apache.commons.math.geometry.*;

import processing.opengl.*;

PeasyCam cam;
PImage img;
int imgHeight;
int imgWidth;
Cube[][][] cubes = new Cube[140][287][51];
int globalCubeRadius;
color black;
color white;
PImage[] imgs=new PImage[51];

void setup() {
 size(400,400, OPENGL);
 background(0);
 lights();
 noFill();
 noStroke();
 //frameRate(30);
 for(int i=1;i<52;i++){
   imgs[i-1]=loadImage("testmov"+i+".png");
 }
 img = imgs[0];
 imgHeight=img.height;
 imgWidth=img.width;
 globalCubeRadius=5;
 cam = new PeasyCam(this,imgWidth*5/2,imgHeight*5/2, 0,700);
 cam.setMinimumDistance(60);
 cam.setMaximumDistance(1000);
 black=#000000;
 white=#d9d9d9;
 
 for(int h=0; h<51;h++){
   img=imgs[h];
   for(int i=0;i<imgWidth;i++){
     for(int j=0;j<imgHeight;j++){
       if(img.pixels[j*imgWidth+i]>=white){
         cubes[i][j][h]=new Cube(0,0,0,globalCubeRadius);
       }else{
         cubes[i][j][h]=new Cube(0,0,0,globalCubeRadius,img.pixels[j*imgWidth+i]);
       }
     }
   }
 }
   
}

void draw() {
 background(0);
 for(int h=0;h<51;h++){
   pushMatrix();
   translate(0,0,h*globalCubeRadius);
   for(int j=0;j<imgHeight;j++){
     pushMatrix();
     translate(-globalCubeRadius,j*globalCubeRadius,0);
     for(int i=0;i<imgWidth;i++){  
       translate(globalCubeRadius,0,0);
       cubes[i][j][h].drawObj();
     }
     popMatrix();
   }
 popMatrix();
 }
}


class Cube {
 float centerX, centerY, centerZ;
 int radius;
 color col;
 Boolean noColor;
 
 Cube(float cubeCenterX, float cubeCenterY, float cubeCenterZ, int cubeRadius, color cubeCol){
   centerX=cubeCenterX;
   centerY= cubeCenterY;
   centerZ=cubeCenterZ;
   radius=cubeRadius;
   col=cubeCol;
   noColor=false;
 }
 
 Cube(float cubeCenterX, float cubeCenterY, float cubeCenterZ, int cubeRadius){
   centerX=cubeCenterX;
   centerY= cubeCenterY;
   centerZ=cubeCenterZ;
   radius=cubeRadius;
   noColor=true;
 }
 
 void drawObj() {
   if(cubeExists()==true){
     fill(col);
     box(radius);
   }  
 }
 
 Boolean cubeExists(){
   if(noColor==false){
     return true;
   }else{
     return false;
   }
 }
}



Re: Optimizing display of lots of primitives (~200k)
Reply #1 - Apr 25th, 2009, 5:04pm
 
I'd say the biggest payoff is going to be pushing your commands to the video card, which means VBO, Display Lists, Shaders, Vertex Arrays, etc.  Display lists are very easy, if you don't plan to update the data constantly.
Re: Optimizing display of lots of primitives (~200k)
Reply #2 - Apr 25th, 2009, 10:18pm
 
Thanks, that's helpful. I do want to update the geometry every frame eventually so it sounds like a VBO in STREAM_DRAW argument would be most appropriate, but I might work my way up from Display lists for the exercise.

How would you profile an OpenGL-based applet?

Thanks again...
Re: Optimizing display of lots of primitives (~200k)
Reply #3 - Apr 27th, 2009, 12:22pm
 
Hi sixswitch,

I don't know if I am understanding you correctly but I think you just want to optimize your performance.

At first, replace every division of floats with multiplication.
If its an Integer Division with power of two use bit operators. Precalculate every Position of an pixelarray. (Width*Y+X) can be done before. Use one-dimensional Arrays. Make more than one check/build every step.
-----
int counter;
for(counter=0;counter<width-10;counter+=10)
{
 dothat();dothat();dothat();dothat();
 dothat();dothat();dothat();
 dothat();dothat();dothat();
}  
while(counter<WidthTimesHeight)
{
dothat();
counter++;
}
-----
Then delete every pushMatrix and popMatrix() command and make the calculation on your own. If this will be dynamic or very large make a LUT  (a table in which you save the transforamtions of every position).
To save some cubes you could delete all cubes which are not visable (detect the edges, and dont draw the ones inside, edges could be pixels without a neighbour to the left,right,top, bottom etc. )
Another thing would be not to push a new cube above an old cube which has the same position and color. Just enlarge the old one.
Then you could just draw quads instead cubes if the angle is very straight to the cam or the cubes are inside a plain filed, just draw points if the quads/cubes are far away from the cam.


I hope I could help a little bit.
Re: Optimizing display of lots of primitives (~200k)
Reply #4 - Apr 30th, 2009, 7:05pm
 
Hi Josn,

Thanks so much for all the detail. I'm going to summarize just to make sure I understand your suggestions. I have a few questions as well...

1) Precalculate the absolute positions of the cubes instead of using translate() and matrix stack calls. What data structure would you suggest for the lookup table?

2) When you say use one-dimensional arrays, do you mean to store the entire voxel-grid? For example: for a 10x10x10 space, I have one 1D array with 1000 elements, linked to a lookup table which has 4 values for each element (float x/y/z, colour)?

3) OK, so your while() loop is to iterate through a 1D array; what's the idea of the for() loop? I don't quite understand...

3) I probably won't implement visibility detection as I've found I also like the representation in points or as a 3d grid (ie just drawing the strokes of the cubes).

4) I'll actually be using quads + points to create an isometric view as well.

If anybody else is doing this sort of volumetric stuff, there are some techniques from medical imaging that are proving helpful. Subsampling the volumetric data especially; also (with points only) drawing the points as textures on layered quads.

Thanks again Josn for taking the time!
Re: Optimizing display of lots of primitives (~200k)
Reply #5 - May 1st, 2009, 9:53am
 
if you want to use points instead of boxes, then you can look at
http://www.hardcorepawn.com/pointCloudRandom/

I could run a 2Million point cloud with a nice framerate in highres on my PC (GTX260 graphic card), so I think you can have nice performance. (And that's a nice example of vertex/color buffer use to start with)
Re: Optimizing display of lots of primitives (~200k)
Reply #6 - May 1st, 2009, 10:49am
 
Wow, that's pretty stunning. Thanks Kaeltyk.
Page Index Toggle Pages: 1