The processor is still doing a bit of the work on the physics but we're making direct OpenGL calls to the video card to display it. It's also been organized more efficiently for sending the video data, but it's still sending all the vertex and color data to the card each time. One step further would be a Vertex Array, which is what I believe is posted below. The positions are updated in the float buffer and then sent to the card. I got around 480fps with this one.
Take that OF
Of course, at this point, you're loosing a bit of the simplicity that makes Processing so appealing. But at least you have that flexibility - you can get hard core if you need too.
I'm trying to read up more on how to do a VBO (Vertex Buffer Object) and how it is different than the code below. I'm not completely sure how to do it. Perhaps someone else could post an example, but I'll try to figure it out and post if I do (I'd like to know myself).
Code:import processing.opengl.*;
import javax.media.opengl.GL;
import java.nio.*;
int numparticles =10000;
PGraphicsOpenGL pgl;
GL gl;
particle[] particles;
float[] xy;
float[] rgb;
FloatBuffer f;
FloatBuffer c;
void setup()
{
size(500, 500, OPENGL);
background(255);
hint(DISABLE_DEPTH_TEST);
hint(DISABLE_OPENGL_ERROR_REPORT);
noStroke();
//smooth();
pgl = (PGraphicsOpenGL) g;
gl = pgl.gl;
gl.glEnable(gl.GL_POINT_SMOOTH);
gl.glPointSize(8.0f);
gl.setSwapInterval(0); //tells it not to sync with the screen refresh rate
frameRate(2000);
particles = new particle[numparticles];
for(int i=0; i<numparticles; i++)
{
particles[i] = new particle(random(450, width-20), random(450, height-20), 10, 10, 5, 0.9,
color(0, 0, 0, 255));
}
initParticles();
}
void draw()
{
background(255);
pgl.beginGL();
gl.glEnableClientState(GL.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL.GL_COLOR_ARRAY);
gl.glVertexPointer(2,GL.GL_FLOAT,0,f);
gl.glColorPointer(4,GL.GL_FLOAT,0,c);
gl.glDrawArrays(GL.GL_POINTS,0,numparticles);
gl.glDisableClientState(GL.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL.GL_COLOR_ARRAY);
pgl.endGL();
for(int i=0; i<numparticles; i++)
{
particle p = particles[i];
p.collide();
p.move();
p.xspeed*=p.dampfactor;
p.yspeed*=p.dampfactor;
xy[i*2]=p.xpos;
xy[i*2+1]=p.ypos;
}
f.put(xy);
f.rewind();
if (frameCount%30==0) println(frameRate);
}
void initParticles() {
xy=new float[2*2*numparticles];
rgb=new float[2*4*numparticles];
for(int i=0; i<numparticles; i++) {
particle p = particles[i];
float[] cc = {
red(p.col),green(p.col),blue(p.col),alpha(p.col) };
xy[i*2]=p.xpos;
xy[i*2+1]=p.ypos;
rgb[i*4]=cc[0];
rgb[i*4+1]=cc[1];
rgb[i*4+2]=cc[2];
rgb[i*4+3]=cc[3];
}
f = ByteBuffer.allocateDirect(4 * xy.length).order(ByteOrder.nativeOrder()).asFloatBuffer();
f.put(xy);
f.rewind();
c = ByteBuffer.allocateDirect(4 * rgb.length).order(ByteOrder.nativeOrder()).asFloatBuffer();
c.put(rgb);
c.rewind();
rgb = null;
}
class particle
{
float xpos, ypos;
float xspeed, yspeed;
int ewidth;
int eheight;
float speedfactor;
float dampfactor;
color col;
particle(float x, float y,int ew, int eh, float sf, float df,color c)
{
xpos=x;
ypos=y;
xspeed=0;
yspeed=0;
ewidth=ew;
eheight=eh;
speedfactor=sf;
dampfactor=df;
col=c;
}
void collide()
{
int leftcols = (int)random(0, eheight+1);
int rightcols=(int)random(0, eheight+1);
int topcols= (int)random(0, ewidth+1);
int botcols= (int)random(0, ewidth+1);
xspeed+= (leftcols-rightcols)/speedfactor;
yspeed+= (topcols-botcols)/speedfactor;
}
void move()
{
xpos+=xspeed;
ypos+=yspeed;
if (xpos+ewidth> width || xpos-ewidth<0) xspeed*=-1;
if (ypos+eheight> height || ypos-eheight<0) yspeed*=-1;
}
}