Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Processing 2.x/3.0 on Mac (10.10.2); framerate in P3D halved vs. Processing 1.5 #3210

Closed
rapatski opened this issue Apr 24, 2015 · 9 comments
Assignees
Labels

Comments

@rapatski
Copy link

Running the same sketch (line / vertex based) at different OSes using P3D gives various results:

Processing 1.5, OSX 10.10.2: 60 fps (using OPENGL renderer)
Processing 3.0a5, OSX 10.10.2: 25 fps
Processing 3.0a5, Win8 64bit: 55 fps

@benfry
Copy link
Contributor

benfry commented Apr 24, 2015

We can't do anything with that information unless you post a sketch for us.

@rapatski
Copy link
Author

Sorry Ben, cleaning it up and will do in a minute

@rapatski
Copy link
Author

Hmm, sorry, here: http://we.tl/FJblyy8SYi

@benfry
Copy link
Contributor

benfry commented Apr 27, 2015

Hm, I'm seeing 60 fps on my machine with 3.0a7 and it doesn't seem maxed out, though at the moment I'm on a fast machine.

@codeanticode Any thoughts here? We should be much speedier with a7. And separately, setting frameRate() higher is giving me System.err messages saying that it's disabling vsync, but from the looks of it, it's not disabling since it's pegged at 60fps.

import processing.opengl.*;

/*
  Test sketch (based on Shiffman's particle examples) exploring framerate in Processing 3.0a5
  Hit any key to display the test pattern with a fixed number of particles.
*/

PGraphicsOpenGL pgl;
GL gl;

//PeasyCam cam;

ArrayList<Pica> picas;
ArrayList<PVector> trail;


int   maxtrail   = 2000;
int   segmentlength = 3;

int    advance    = 3; 
float  strweight  = 2; 

// opacity -- particles have different opacities at different speeds
float slowopacity = 50; 
float fastopacity = 90; 
float factor = 1;

int currentcolourid = 0;

// colour id, primary/secondary, rgb
float[][][] colours = {
  { { 255, 255, 255 }, { 0, 100, 255 } },
  { { 50, 255, 150 }, { 40, 130, 250 } },
  { { 255, 0, 0 }, { 255, 0, 100 } },
  { { 160, 255, 0 }, { 255, 100, 0 } }
}; 


void setup() {

  size(1280, 700, P3D);
  //size(screen.width, screen.height, OPENGL);
  //cam = new PeasyCam(this, 900);
  //hint(DISABLE_OPENGL_2X_SMOOTH);
  //hint(ENABLE_OPENGL_4X_SMOOTH);

  picas = new ArrayList<Pica>();
  trail = new ArrayList<PVector>();

  initTestPattern();

  mouseX = width/2;
  mouseY = height/2;
}

void draw() {

  // UPDATE

  updateTrail();
  updateTargets();

  // handle trail
  handleMouseTrail();

  if (trail.size() != picas.size())
    setTargets();

  // change particle behaviour once in a wjile
  if (random(1) > .99) advance = (random(1) > .5) ? advance - 1 : advance + 1;


  // DRAW

  background(20);

  translate(width/2, height/2);

  blendMode(ADD);

  strokeWeight(strweight);
  noFill();

  // draw trail
  stroke(255, 10);
  beginShape();
  for (int j = 0; j < trail.size(); j++) {
    vertex(trail.get(j).x, trail.get(j).y, trail.get(j).z);
  }
  endShape();

  // draw particles
  for (int j = 0; j < picas.size(); j++) {
    picas.get(j).update();
    picas.get(j).draw(colours[currentcolourid][0], colours[currentcolourid][1], slowopacity*factor, fastopacity*factor);
  }

  // fps
  text(frameRate, 0, 0);

}

void keyReleased()
{
  trail.clear();
  initTestPattern(); 
}

void initTestPattern() {

  float r = min(width, height)/3*2;

  // test pattern to compare frame rates
  for (int i = 0; i < maxtrail; i++) {
    float a = i/float(maxtrail-1)*TWO_PI;
    float x = r*cos(a);//*sin(a*3);
    float y = r*sin(a);//*cos(a);

    PVector p = new PVector(x, y);
    trail.add(p);
  }

}

void handleMouseTrail() {

  if (mousePressed) {
    if (trail.size() < maxtrail) {

      PVector mouse = new PVector(mouseX - width/2, mouseY - height/2);
      PVector last  = (trail.size() > 0) ? trail.get(trail.size()-1) : mouse.get();
      int numsegs = (trail.size() > 0) ? floor(PVector.dist(mouse, last)/segmentlength) : 1;

      for (int i = 0; i < numsegs; i++) {
        PVector p = PVector.add(last, PVector.mult(PVector.div(PVector.sub(mouse, last), float(numsegs)), i));
        trail.add(p);
      }
    } 
    else {
      trail.clear();
    }
  }

}

void setTargets() {

  // append or shorten the pica array depending on the number of 'groups'
  if (picas.size() < trail.size()) {
    for (int i = picas.size(); i < trail.size(); i++) {
      float maxspeed = i%20; //(i%40)/2.0; // note: hardcoded values!
      float maxforce = 0.5 + (i%10)/20.0; //random(0.59, 0.6); // note: hardcoded values!

      Pica b = new Pica(i, mouseX - width/2, mouseY - height/2, 0, maxspeed, maxforce, 16);
      b.target = trail.get(i).get();
      picas.add(b);
    }
  } 
  else
    if (picas.size() > trail.size())
    {
      for (int i = picas.size()-1; i > trail.size()-1; i--) {
        picas.remove(i);
      }
    }
}


void updateTrail()
{

  for (int j = 0; j < trail.size(); j++) {
    trail.set(j, arbitraryAxisRotation(trail.get(j), new PVector(0, 1, 0), 0.003));
  }

}

void updateTargets() {
  // set targets
  for (int j = 0; j < picas.size(); j++) {
    picas.get(j).target_index = (picas.get(j).target_index + advance)%trail.size();
    if (picas.get(j).target_index < 0) picas.get(j).target_index += trail.size();

    //PVector target = new PVector(text_points[j][picas[j][i].target_index].x, text_points[j][picas[j][i].target_index].y, 0);
    picas.get(j).target = trail.get(picas.get(j).target_index);
  }
}


// functions

color mapColor(float value, float minvalue, float maxvalue, float[] mincolor, float[] maxcolor) {

  float r, g, b;
  float dr, dg, db;

  float time = (value - minvalue) / (maxvalue - minvalue);

  dr = maxcolor[0] - mincolor[0];
  dg = maxcolor[1] - mincolor[1];
  db = maxcolor[2] - mincolor[2];

  r = mincolor[0] + time*dr;
  g = mincolor[1] + time*dg;
  b = mincolor[2] + time*db;

  color c = color(r, g, b);
  return c;

}

PVector arbitraryAxisRotation(PVector vector, PVector axis, float theta) {
  PVector result = new PVector(0, 0, 0);
  float x = vector.x;
  float y = vector.y;
  float z = vector.z;
  float u = axis.x;
  float v = axis.y;
  float w = axis.z;
  result.x = u*(u*x + v*y + w*z) * (1 - cos(theta)) + x*cos(theta) + (-w*y + v*z) * sin(theta);
  result.y = v*(u*x + v*y + w*z) * (1 - cos(theta)) + y*cos(theta) + (w*x - u*z) * sin(theta);
  result.z = w*(u*x + v*y + w*z) * (1 - cos(theta)) + z*cos(theta) + (-v*x + u*y) * sin(theta);
  return result;
}

// Arrive
// Credits: Daniel Shiffman <http://www.shiffman.net>

class Pica {

  PVector loc;
  PVector vel;
  PVector acc;

  int index;

  PVector target;
  int target_index;

  float r;

  float maxforce;
  float maxspeed;

  PVector[] history;

  Pica(int index, float x, float y, float z, float maxspeed, float maxforce, int maxtrail) {

    this.index = index;
    this.target_index = index;

    acc = new PVector(0,0);
    vel = new PVector(0,0);
    loc = new PVector(x, y, z);

    r = 3.0;

    this.maxspeed = maxspeed;
    this.maxforce = maxforce;

    history = new PVector[maxtrail];

  }

  // Method to update location
  void update() {

    //update target
    arrive(target);

    // Update velocity
    vel.add(acc);
    // Limit speed
    vel.limit(maxspeed);
    loc.add(vel);
    // Reset accelertion to 0 each cycle
    acc.mult(0);

    for(int i = history.length-1; i > 0; i--) {
      history[i] = history[i-1];
    }
    history[0] = new PVector(loc.x, loc.y, 0);

  }

  void draw(float[] _colour1, float[] _colour2, float _slowopacity, float _fastopacity) {

    noFill();
    //stroke(0);
    beginShape();

    //if(history.length > 0)
    //rect(history[0].x, history[0].y, 5, 5);

    for(int i = 1; i < history.length; i++) {

      if(history[i] != null) {
        float angle = atan((history[i].x - history[i-1].x) / (history[i].y - history[i-1].y)); // ugly, same value can be derived from steer

        color c = mapColor(abs(angle), 0, PI/2.0, _colour1, _colour2); // vloeiende overgangen
        float o = map(vel.mag(), 0, 20, _slowopacity, _fastopacity); // opacity

        stroke(c, o); //255 - i/float(history.length)*255);
        vertex(history[i].x, history[i].y);
      }

    }
    endShape();

  }

  void arrive(PVector target) {
    acc.add(steer(target, true));
  }

  PVector steer(PVector target, boolean slowdown) {

    PVector steer;  
    PVector desired = PVector.sub(target, loc); 
    float d = desired.mag(); 

    if (d > 0) {

      desired.normalize();
      if ((slowdown) && (d < 100.0f)) {
        desired.mult(maxspeed*(d/100.0f)); // This damping is somewhat arbitrary
      }
      else {
        desired.mult(maxspeed);
      }

      steer = PVector.sub(desired, vel);
      steer.limit(maxforce);  // Limit to maximum steering force

    }
    else {
      steer = new PVector(0,0);
    }

    return steer;
  }

}

@rapatski
Copy link
Author

What happens when you just up the maxtrail particle count until even your fast machine struggles? Like mentioned before, I'm seeing a 30fps difference between 1.5 and 3.0

On 27 Apr 2015, at 13:30, Ben Fry notifications@github.com wrote:

Hm, I'm seeing 60 fps on my machine with 3.0a7 and it doesn't seem maxed out, though at the moment I'm on a fast machine.

@codeanticode Any thoughts here? We should be much speedier with a7. And separately, setting frameRate() higher is giving me System.err messages saying that it's disabling vsync, but from the looks of it, it's not disabling since it's pegged at 60fps.

import processing.opengl.*;

/*
Test sketch (based on Shiffman's particle examples) exploring framerate in Processing 3.0a5
Hit any key to display the test pattern with a fixed number of particles.
*/

PGraphicsOpenGL pgl;
GL gl;

//PeasyCam cam;

ArrayList picas;
ArrayList trail;

int maxtrail = 2000;
int segmentlength = 3;

int advance = 3;
float strweight = 2;

// opacity -- particles have different opacities at different speeds
float slowopacity = 50;
float fastopacity = 90;
float factor = 1;

int currentcolourid = 0;

// colour id, primary/secondary, rgb
float[][][] colours = {
{ { 255, 255, 255 }, { 0, 100, 255 } },
{ { 50, 255, 150 }, { 40, 130, 250 } },
{ { 255, 0, 0 }, { 255, 0, 100 } },
{ { 160, 255, 0 }, { 255, 100, 0 } }
};

void setup() {

size(1280, 700, P3D);
//size(screen.width, screen.height, OPENGL);
//cam = new PeasyCam(this, 900);
//hint(DISABLE_OPENGL_2X_SMOOTH);
//hint(ENABLE_OPENGL_4X_SMOOTH);

picas = new ArrayList();
trail = new ArrayList();

initTestPattern();

mouseX = width/2;
mouseY = height/2;
}

void draw() {

// UPDATE

updateTrail();
updateTargets();

// handle trail
handleMouseTrail();

if (trail.size() != picas.size())
setTargets();

// change particle behaviour once in a wjile
if (random(1) > .99) advance = (random(1) > .5) ? advance - 1 : advance + 1;

// DRAW

background(20);

translate(width/2, height/2);

blendMode(ADD);

strokeWeight(strweight);
noFill();

// draw trail
stroke(255, 10);
beginShape();
for (int j = 0; j < trail.size(); j++) {
vertex(trail.get(j).x, trail.get(j).y, trail.get(j).z);
}
endShape();

// draw particles
for (int j = 0; j < picas.size(); j++) {
picas.get(j).update();
picas.get(j).draw(colours[currentcolourid][0], colours[currentcolourid][1], slowopacity_factor, fastopacity_factor);
}

// fps
text(frameRate, 0, 0);

}

void keyReleased()
{
trail.clear();
initTestPattern();
}

void initTestPattern() {

float r = min(width, height)/3*2;

// test pattern to compare frame rates
for (int i = 0; i < maxtrail; i++) {
float a = i/float(maxtrail-1)_TWO_PI;
float x = r_cos(a);//_sin(a_3);
float y = r_sin(a);//_cos(a);

PVector p = new PVector(x, y);
trail.add(p);

}

}

void handleMouseTrail() {

if (mousePressed) {
if (trail.size() < maxtrail) {

  PVector mouse = new PVector(mouseX - width/2, mouseY - height/2);
  PVector last  = (trail.size() > 0) ? trail.get(trail.size()-1) : mouse.get();
  int numsegs = (trail.size() > 0) ? floor(PVector.dist(mouse, last)/segmentlength) : 1;

  for (int i = 0; i < numsegs; i++) {
    PVector p = PVector.add(last, PVector.mult(PVector.div(PVector.sub(mouse, last), float(numsegs)), i));
    trail.add(p);
  }
} 
else {
  trail.clear();
}

}

}

void setTargets() {

// append or shorten the pica array depending on the number of 'groups'
if (picas.size() < trail.size()) {
for (int i = picas.size(); i < trail.size(); i++) {
float maxspeed = i%20; //(i%40)/2.0; // note: hardcoded values!
float maxforce = 0.5 + (i%10)/20.0; //random(0.59, 0.6); // note: hardcoded values!

  Pica b = new Pica(i, mouseX - width/2, mouseY - height/2, 0, maxspeed, maxforce, 16);
  b.target = trail.get(i).get();
  picas.add(b);
}

}
else
if (picas.size() > trail.size())
{
for (int i = picas.size()-1; i > trail.size()-1; i--) {
picas.remove(i);
}
}
}

void updateTrail()
{

for (int j = 0; j < trail.size(); j++) {
trail.set(j, arbitraryAxisRotation(trail.get(j), new PVector(0, 1, 0), 0.003));
}

}

void updateTargets() {
// set targets
for (int j = 0; j < picas.size(); j++) {
picas.get(j).target_index = (picas.get(j).target_index + advance)%trail.size();
if (picas.get(j).target_index < 0) picas.get(j).target_index += trail.size();

//PVector target = new PVector(text_points[j][picas[j][i].target_index].x, text_points[j][picas[j][i].target_index].y, 0);
picas.get(j).target = trail.get(picas.get(j).target_index);

}
}

// functions

color mapColor(float value, float minvalue, float maxvalue, float[] mincolor, float[] maxcolor) {

float r, g, b;
float dr, dg, db;

float time = (value - minvalue) / (maxvalue - minvalue);

dr = maxcolor[0] - mincolor[0];
dg = maxcolor[1] - mincolor[1];
db = maxcolor[2] - mincolor[2];

r = mincolor[0] + time_dr;
g = mincolor[1] + time_dg;
b = mincolor[2] + time*db;

color c = color(r, g, b);
return c;

}

PVector arbitraryAxisRotation(PVector vector, PVector axis, float theta) {
PVector result = new PVector(0, 0, 0);
float x = vector.x;
float y = vector.y;
float z = vector.z;
float u = axis.x;
float v = axis.y;
float w = axis.z;
result.x = u_(u_x + v_y + w_z) * (1 - cos(theta)) + x_cos(theta) + (-w_y + v_z) * sin(theta);
result.y = v_(u_x + v_y + w_z) * (1 - cos(theta)) + y_cos(theta) + (w_x - u_z) * sin(theta);
result.z = w_(u_x + v_y + w_z) * (1 - cos(theta)) + z_cos(theta) + (-v_x + u*y) * sin(theta);
return result;
}

// Arrive
// Credits: Daniel Shiffman http://www.shiffman.net

class Pica {

PVector loc;
PVector vel;
PVector acc;

int index;

PVector target;
int target_index;

float r;

float maxforce;
float maxspeed;

PVector[] history;

Pica(int index, float x, float y, float z, float maxspeed, float maxforce, int maxtrail) {

this.index = index;
this.target_index = index;

acc = new PVector(0,0);
vel = new PVector(0,0);
loc = new PVector(x, y, z);

r = 3.0;

this.maxspeed = maxspeed;
this.maxforce = maxforce;

history = new PVector[maxtrail];

}

// Method to update location
void update() {

//update target
arrive(target);

// Update velocity
vel.add(acc);
// Limit speed
vel.limit(maxspeed);
loc.add(vel);
// Reset accelertion to 0 each cycle
acc.mult(0);

for(int i = history.length-1; i > 0; i--) {
  history[i] = history[i-1];
}
history[0] = new PVector(loc.x, loc.y, 0);

}

void draw(float[] _colour1, float[] _colour2, float _slowopacity, float _fastopacity) {

noFill();
//stroke(0);
beginShape();

//if(history.length > 0)
//rect(history[0].x, history[0].y, 5, 5);

for(int i = 1; i < history.length; i++) {

  if(history[i] != null) {
    float angle = atan((history[i].x - history[i-1].x) / (history[i].y - history[i-1].y)); // ugly, same value can be derived from steer

    color c = mapColor(abs(angle), 0, PI/2.0, _colour1, _colour2); // vloeiende overgangen
    float o = map(vel.mag(), 0, 20, _slowopacity, _fastopacity); // opacity

    stroke(c, o); //255 - i/float(history.length)*255);
    vertex(history[i].x, history[i].y);
  }

}
endShape();

}

void arrive(PVector target) {
acc.add(steer(target, true));
}

PVector steer(PVector target, boolean slowdown) {

PVector steer;  
PVector desired = PVector.sub(target, loc); 
float d = desired.mag(); 

if (d > 0) {

  desired.normalize();
  if ((slowdown) && (d < 100.0f)) {
    desired.mult(maxspeed*(d/100.0f)); // This damping is somewhat arbitrary
  }
  else {
    desired.mult(maxspeed);
  }

  steer = PVector.sub(desired, vel);
  steer.limit(maxforce);  // Limit to maximum steering force

}
else {
  steer = new PVector(0,0);
}

return steer;

}

}

Reply to this email directly or view it on GitHub.

@codeanticode
Copy link
Member

@benfry is the code you posted the one @rapatski uploaded earlier (his link does not longer work)?

In any case, that code is working at 60fps on a Macbook air with integrated intel graphics (HD 5000), after 56e67c9.

@benfry
Copy link
Contributor

benfry commented May 15, 2015

Yeah, I pasted it since links like that usually don't work by the time we can do anything about them.

I'll close this as fixed for 3.0a8.

@benfry benfry closed this as completed May 15, 2015
@rapatski
Copy link
Author

rapatski commented May 15, 2015 via email

@github-actions
Copy link

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jun 16, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

3 participants