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 › Performance of large numbers of objects
Page Index Toggle Pages: 1
Performance of large numbers of objects (Read 2591 times)
Performance of large numbers of objects
Oct 18th, 2008, 11:26pm
 
Hi,

I'm a moderately new-to-Processing person with little Java experience, but moderately good experience with 3D work.

My sketch is loading a dataset from MySQL, which works fine. I have an object to represent what I want to draw, and load/init about 5300 of these.

My rendering code is:
Quote:
void draw() {
  background(20);
  lights();
  camera1.feed();
  text("System count: "+system_count,15,20);
  for(int i=1;i<systems.length;i++) {
    println("Doing "+i+"/"+system_count+"");
    pushMatrix();
    translate(systems[i].getX(),systems[i].getY(),systems[i].getZ());
    sphere(5);
    popMatrix();
  }
  println("Done drawing frame");
}


As you might guess from the printlns, this takes a long while to draw a frame. I'm looking for this to be capable of realtime-timescale performance, so a 0.06-frames-per-second rate is hardly acceptable! :p

My objects are:
Quote:
class Color
{
  private int r,g,b;
  Color(int ar, int ag, int ab) {
    r = ar;
    g = ag;
    b = ab;
  }
  public int getR(){return this.r;}
  public int getG(){return this.g;}
  public int getB(){return this.b;}
}
class System
{
  private float x,y,z,radius,secstatus;
  private int id;
  private String name;
  private Color sec_color;
  System(float xpos,float ypos, float zpos, float rradius, int sysid, String sysname, float security) {
   id = sysid;
   name = sysname;
   x = xpos;
   y = ypos;
   z = zpos;
   radius = rradius;
   secstatus = security;
   if (security >= 1.0) {
     sec_color = new Color(0,223,51);
   } else if (security > 0.8) {
     sec_color = new Color(116,223,0);
    } else if (security > 0.6) {
     sec_color = new Color(200,223,0);
   } else if (security > 0.4) {
     sec_color = new Color(233,141,0);
   } else if (security > 0.2) {
     sec_color = new Color(223,99,0);
   } else {
     sec_color = new Color(223,16,0);
   }
   secstatus = security;
  }
  public float getX(){return (this.x);}
  public float getY(){return (this.y);}
  public float getZ(){return (this.z);}
  public float getRadius(){return this.radius;}
  public float getSecStatus() {return this.secstatus;}
  public int getId(){return this.id;}
  public String getName(){return this.name;}
  public Color getColor(){return this.sec_color;}
}



Is there an alternative rendering method I could use to improve the performance of this sketch while retaining the 3D nature of the objects. Once this works I'll be drawing connecting lines in places and then displaying a 2D overlay over the scene, if that makes sense, so suggestions on achieving this would be great Smiley
Re: Performance of large numbers of objects
Reply #1 - Oct 19th, 2008, 12:18am
 
Couple of things off the top of my head:

1. If you're going to use the sphere() function, also use sphereDetail() to make them much simpler. You could do a check to see how close each object is to the camera, and if it's very close, use a high sphere detail -- but if it's quite far away, crank the sphere detail *way* down.

2. I actually wouldn't use sphere() at all, though. What kind of look are you going for? There's a good chance you could use a simple, flat image (a JPEG or PNG) to represent each object -- it's a cheat, but often a very effective one, especially when you're talking about tiny spheres or point particles.

Hope that's helpful.
Re: Performance of large numbers of objects
Reply #2 - Oct 19th, 2008, 12:28am
 
This is for a map application, so I could get away with the image hack. Is there a simple way to keep the image oriented at the observing camera with OCD?
Re: Performance of large numbers of objects
Reply #3 - Oct 20th, 2008, 2:17am
 
At the risk of way overcomplicating things, there's a really slick function in OpenGL that's built for exactly this. It lets you skip all the reverse-engineering of camera angles and just tell the graphics card: "Make this flat."

To use it, I start with the GLGraphics library, which you can get here:

http://users.design.ucla.edu/~acolubri/processing/glgraphics/home/index.html

Include that at the top of your project, along with one thing you'll need from the Java OpenGL library:

Code:

import javax.media.opengl.GL;
import codeanticode.glgraphics.*;


Then, be sure to declare a GLTexture in your project, and in your setup() initialize it w/ whatever image you want as the map point, e.g.:

Code:

mapPointTexture = new GLTexture(this,"yourfile.jpg");


Then -- brace yourself -- you'd draw the map points like this in your draw() function:

Code:

pgl = (PGraphicsOpenGL) g;
gl = pgl.gl;

pgl.beginGL();
gl.glEnable(GL.GL_TEXTURE_2D);
gl.glBindTexture(GL.GL_TEXTURE_2D,mapPointTexture.getTextureID());

gl.glEnable(GL.GL_POINT_SPRITE);
gl.glTexEnvi(GL.GL_POINT_SPRITE, GL.GL_COORD_REPLACE, GL.GL_TRUE);


gl.glPointSize(20); // monkey with this
gl.glPointParameteri(GL.GL_POINT_SIZE_MAX, 100); // this too

gl.glEnable(GL.GL_POINT_SMOOTH);

gl.glBegin(GL.GL_POINTS);

/* here you would iterate through all your points; each time through your loop, however you set it up, you just need to call one of these: */

gl.glVertex3f(yourPointLocX,yourPointLocY,yourPointLocZ);

/* and 'yourPointLocX' etc. would be replaced w/ whatever variables or data structure you're holding the coordinate in, of course */

gl.glEnd();
gl.glDisable(GL.GL_POINT_SPRITE);
pgl.endGL();


So that's it. Sometimes I get irritated when people jump immediately to the hard-core, Java-y, OpenGL-y solution to these problems -- it seems a bit against the spirit of Processing -- but at the same time, this is a tool designed for *exactly* what you want to do, and it's really really fast.

Hope that's helpful!
Re: Performance of large numbers of objects
Reply #4 - Oct 20th, 2008, 3:05am
 
robin thats great!
it about 2:00am here, so i wont experiment with this right now, but looking at it, it seems to be way simpler/faster than the way i usually do this sort of thing.
thanks a lot
Smiley
Re: Performance of large numbers of objects
Reply #5 - Oct 20th, 2008, 8:37am
 
Oops, forgot -- and this stuff can be rather opaque -- you'll need to declare those two variables, pgl and gl, as:

Code:

PGraphicsOpenGL pgl;
GL gl;
Re: Performance of large numbers of objects
Reply #6 - Oct 20th, 2008, 7:10pm
 
Woah, shiny. Looks great- I'll give it a shot in a few hours and see how it goes!

Overcomplicating stuff is fine if it yields good performance. I'm more than happy to tinker around with OpenGL itself, at any rate.

Many thanks, robin!
Re: Performance of large numbers of objects
Reply #7 - Oct 23rd, 2008, 12:30am
 
Hi,

Performance is great, and I've spent some good time tinkering with this. I've moved onto my next bit which involves 14,000 lines or thereabouts. This is using display lists to further speed things up; but I have an issue. Here is the code used to render.

Quote:
// Render function
void draw() {
  background(20);
  //  lights();
  fill(60);
  camera1.feed();
  text("System count: "+system_count,15,-120);
  text("Jump count: "+jumps.length,15,-95);
  text("Framerate: "+frameRate,15,-145);
  text("Frame count: "+frameCount,15,-170);
  pgl = (PGraphicsOpenGL) g;
  gl = pgl.gl;
  pgl.beginGL();
  gl.glEnable(GL.GL_BLEND);
  gl.glBlendFunc(GL.GL_SRC_ALPHA,GL.GL_ONE); 
  if (jumplines_list > 0){
    gl.glCallList(jumplines_list);
  }
  else{
    drawJumpLines();
  }
  if (system_list > 0){
    gl.glCallList(system_list);
  }
  else{
    drawSystems();
  }
  pgl.endGL(); 
}
void drawSystems() {
  system_list = gl.glGenLists(1);
  gl.glNewList(system_list, GL.GL_COMPILE);
  gl.glEnable(GL.GL_TEXTURE_2D);
  gl.glDisable(GL.GL_DEPTH_TEST);
  gl.glBindTexture(GL.GL_TEXTURE_2D,mapPointTexture.getTextureID());
  gl.glEnable(GL.GL_POINT_SPRITE);
  gl.glTexEnvi(GL.GL_POINT_SPRITE, GL.GL_COORD_REPLACE, GL.GL_TRUE);
  gl.glPointSize(5); // monkey with this
  gl.glPointParameteri(GL.GL_POINT_SIZE_MAX, 300); // this too
  gl.glEnable(GL.GL_POINT_SMOOTH);
  gl.glBegin(GL.GL_POINTS);
  for(int i=1;i<systems.length;i++) {
    gl.glColor4f(systems[i].getColor().getR(),systems[i].getColor().getG(),systems[i].getColor().getB(),1);
    gl.glVertex3f(systems[i].getX(),systems[i].getY(),systems[i].getZ());
  }
  gl.glEnd();
  gl.glDisable(GL.GL_POINT_SPRITE);
  gl.glDisable(GL.GL_POINT_SMOOTH);
  gl.glDisable(GL.GL_TEXTURE_2D);
  gl.glEnable(GL.GL_DEPTH_TEST);
  gl.glEndList();
}
void drawJumpLines() {
  jumplines_list = gl.glGenLists(1);
  gl.glNewList(jumplines_list, GL.GL_COMPILE);
  gl.glEnable(GL.GL_LINE_SMOOTH);
  gl.glLineWidth(1);
  gl.glBegin(GL.GL_LINES);
  gl.glColor4f(1,1,0,1);
  gl.glVertex3f(161.06699276931,65.31673234822,-103.31412962963);
  gl.glVertex3f(160.35095263718,58.267086646097,-109.06391055446);
  for(int i=1;i<jumps.length;i++) {
    gl.glVertex3f(jumps[i].getSystem1().getX(),jumps[i].getSystem1().getY(),jumps[i].getSystem1().getZ());
    gl.glVertex3f(jumps[i].getSystem2().getX(),jumps[i].getSystem2().getY(),jumps[i].getSystem2().getZ());
  }
  gl.glEnd();
  gl.glDisable(GL.GL_LINE_SMOOTH);
  gl.glEndList(); 
}



The two constantised glVertex3f calls render correctly, forming the line I am expecting between two points (That is using data captured using println from that function). But the two functions in the loop are both calling with good data, yet not producing the correct results (that is, lines).

A friend of mine well versed in OGL has decided the pixies are to blame for this one. Anyone else got any ideas?
Re: Performance of large numbers of objects
Reply #8 - Oct 23rd, 2008, 2:15am
 
I have no idea what the problem is, but just wanted to say that I totally just learned something new based on your modifications/extensions here. Awesome. Smiley
Re: Performance of large numbers of objects
Reply #9 - Oct 23rd, 2008, 10:14am
 
robin sloan wrote on Oct 23rd, 2008, 2:15am:
I have no idea what the problem is, but just wanted to say that I totally just learned something new based on your modifications/extensions here. Awesome. Smiley

Glad to hear it Smiley I'm going to be starting to write up some docs/tutorials on my site (http://talkunafraid.co.uk) I think- it's been an awesome learning experience on the OpenGL front for me :p

Edit: First one up on OCD, will do one on OGL/Display Lists tonight: http://www.talkunafraid.co.uk/2008/10/processing-obsessive-camera-direction/
Re: Performance of large numbers of objects
Reply #10 - Oct 26th, 2008, 10:12pm
 
Apologies for the doublepost, but here's the working code!
Happily runs at 250 FPS with 6,000 systems and 14,000 jumplines rendered each frame on not too mad hardware (8800GTS, E6600, 2GB RAM).


Ignore the 'loading' parts- that's related to the loading of this data from a MySQL database, plus some XML web requests.

Quote:
void draw() {
  background(20);
  //  lights();
  fill(60);
  if (loaded) {
    camera1.feed();
    pgl = (PGraphicsOpenGL) g;
    gl = pgl.gl;
    pgl.beginGL();
    gl.glEnable(GL.GL_BLEND);
    gl.glBlendFunc(GL.GL_SRC_ALPHA,GL.GL_ONE);
    translate(focal_x,focal_y,focal_z);
    sphere(10);
    if (jumplines_list > 0){
      gl.glCallList(jumplines_list);
    }
    else{
      drawJumpLines();
    }
    if (system_list > 0){
      gl.glCallList(system_list);
    }
    else{
      drawSystems();
    }
    pgl.endGL();
  } else {
    if (!loadStarted) {
      println("Data not yet loaded, starting load");
      text("Starting loading...",60,60);
      loadData();
    }
    text("EVE Tactical Map 1.0",60,120);
    rect(60,60,loadProgress,20);
  }
}


Quote:
void drawSystems() {
  system_list = gl.glGenLists(1);
  gl.glNewList(system_list, GL.GL_COMPILE);
  gl.glEnable(GL.GL_TEXTURE_2D);
  gl.glDisable(GL.GL_DEPTH_TEST);
  gl.glBindTexture(GL.GL_TEXTURE_2D,mapPointTexture.getTextureID());
  gl.glEnable(GL.GL_POINT_SPRITE);
  gl.glTexEnvi(GL.GL_POINT_SPRITE, GL.GL_COORD_REPLACE, GL.GL_TRUE);
  gl.glPointSize(5);
  gl.glPointParameteri(GL.GL_POINT_SIZE_MAX, 300);
  gl.glEnable(GL.GL_POINT_SMOOTH);
  gl.glBegin(GL.GL_POINTS);
  for(int i=1;i<systems.length;i++) {
    gl.glColor4f(systems[i].getColor().getR(),systems[i].getColor().getG(),systems[i].getColor().getB(),1);
    gl.glVertex3f(systems[i].getX(),systems[i].getY(),systems[i].getZ());
  }
  gl.glEnd();
  gl.glDisable(GL.GL_POINT_SPRITE);
  gl.glDisable(GL.GL_POINT_SMOOTH);
  gl.glDisable(GL.GL_TEXTURE_2D);
  gl.glEnable(GL.GL_DEPTH_TEST);
  gl.glEndList();
}
void drawJumpLines() {
  jumplines_list = gl.glGenLists(1);
  gl.glNewList(jumplines_list, GL.GL_COMPILE);
  gl.glEnable(GL.GL_LINE_SMOOTH);
  gl.glLineWidth(1);
  gl.glBegin(GL.GL_LINES);
  for(int i=1;i<jumps.length;i++) {
    gl.glColor4f(jumps[i].getColor().getR(),jumps[i].getColor().getG(),jumps[i].getColor().getB(),1);
    gl.glVertex3f(jumps[i].getSystem1().getX(),jumps[i].getSystem1().getY(),jumps[i].getSystem1().getZ());
    gl.glVertex3f(jumps[i].getSystem2().getX(),jumps[i].getSystem2().getY(),jumps[i].getSystem2().getZ());
  }
  gl.glEnd();
  gl.glDisable(GL.GL_LINE_SMOOTH);
  gl.glEndList(); 
}



Result: http://assets.talkunafraid.co.uk//2008/10/tacmap.jpg
Re: Performance of large numbers of objects
Reply #11 - Nov 9th, 2008, 11:02am
 
I found the tips brought up in this thread to be enormously useful!  I have implemented a sprite texture into a sketch involving a large number of points on an undulating surface.  It's far smoother than my non-OpenGL code.
 At the risk of opening up another can of worms for my self, I was wondering if anyone has tips on implementing perspective to the sprites.  Is there a mode that can be called in order to allow point sprites to be scaled based on their distance from the camera?  Or do I need to draw a polygon and map the texture and use rotation to get it facing the camera again?
  I suppose the other option is to compute the distance from the camera and apply that to the glPointSize of each point as I iterate through all of them.  Just seems like something that might be hardwired in OpenGL.  
Thanks!
Re: Performance of large numbers of objects
Reply #12 - Nov 9th, 2008, 12:45pm
 
*Update from previous reply*

I'm updating here on my search for distance-to-camera based sprite sizes, so hopefully someone will still check here.  After more digging I found Ness's other post on the topic here:
http://processing.org/discourse/yabb_beta/YaBB.cgi?board=OpenGL;action=display;num=1212648257  

I found the reference to the PointParameter constants and functions which seems to be the ticket.  After delving way over my head into OpenGL forums to see how these parameters work, I still can't get it running.  Seems to be a data problem with what I am passing to the gl.glPointParameterfvARB(GL.GL_POINT_DISTANCE_ATTENUATION_ARB,###)
function.

I am passing it this array :
float [] glPersp = { 0.01f,0.01f,0.01f };  (glPersp replaces the ###)

and I get this error: "The method glPointParameterfvARB(int,float[], int) in the type GL is not applicable for the arguments (int, float[])"

The error seems to be telling me that I am passing an extra integer to the method.  Perhaps its late, and I'm just not seeing the problem.  Or maybe these functions just aren't very robust in JOGL and I am in way over my head with OpenGL!  Anyways, if ness or anyone else has some insight on how to implement the PointParameter tools mentioned in the above mentioned post I would appreciate it.

Here is a snippet of the broken code for iterating through a 3D array to draw point sprites at different locations specified by by my array.

Quote:
  void render(){

    float [] glPersp = { 0.01f,0.01f,0.01f }; // array for DISTANCE_ATTENTUATION

    pgl.beginGL();
    gl.glEnable(GL.GL_TEXTURE_2D);
    gl.glBindTexture(GL.GL_TEXTURE_2D,mapPointTexture.getTextureID());

    gl.glEnable(GL.GL_POINT_SPRITE);
    gl.glTexEnvi(GL.GL_POINT_SPRITE, GL.GL_COORD_REPLACE, GL.GL_TRUE);

    //point parameters:
    gl.glPointParameterfARB( GL.GL_POINT_FADE_THRESHOLD_SIZE_ARB, 1.1);
    gl.glPointParameterfARB( GL.GL_POINT_SIZE_MIN_ARB, 1.0 );
    gl.glPointParameterfARB( GL.GL_POINT_SIZE_MAX_ARB, 10.0 );
    gl.glPointParameterfvARB( GL.GL_POINT_DISTANCE_ATTENUATION_ARB,glPersp);  // this one returns the error
    
    //gl.glPointSize(rad);  //not used right now in hopes of getting above parameters to work
    gl.glEnable(GL.GL_POINT_SMOOTH);
    gl.glBegin(GL.GL_POINTS); 

    for(int a = 0; a < numA; a ++){

        gl.glVertex3f(grid[a][b][0],grid[a][b][1],grid[a][b][2]); //x,y, and z coordinates held in 3D grid array
      }
    }
    gl.glEnd();
    gl.glDisable(GL.GL_POINT_SPRITE);
    gl.glDisable(GL.GL_POINT_SMOOTH);
    gl.glDisable(GL.GL_TEXTURE_2D); 
    pgl.endGL(); 

  }




Time for some sleep...
Re: Performance of large numbers of objects
Reply #13 - Mar 17th, 2009, 3:56pm
 
archo_p, Did you ever figure out how to adjust the size based on the camera distance?  I'm trying to do something similar with text.  If you're z close to the camera, display text.  I was trying to use the zFar feature of perspective but that cuts the entire scene.
Page Index Toggle Pages: 1