Data, Ecology, Art

Code Blog

Massive Poly Rendering in Processing

Following up on Basic Rendering, I added some 100,000 spheres to my render scene for the sweetWire music video. I am controlling camera with scripted camera animations and beautiful easing functions by Roger Antonsen, who co-authored this code overall. The code is a bit longer here, but it’s nothing compared to the trouble I get trying to do the same thing in Maya. Of course this will only run if you feed it lots of pointCloud data.

int startFrame = 1;
int currFrame = startFrame; 
int endFrame = 294; //last frame plus one
int radius = -3000; 
int close = 0;
float sphereSize = 2.3; 

boolean render = false ; 

Table table;
ArrayList<PVector> vectors;

String filename = "2020_1_19_13_7_11";

int frameWidth = 1920; 
int frameHeight = 1080;

void settings() {
  size(frameWidth, frameHeight, P3D);
  smooth(8);
}
void setup() {
  perspective(PI/4.0, 1.75, 1, 100000);
  //data
  table = loadTable("../3D/captures/"+filename+"/frame"+startFrame+".csv");
  vectors = new ArrayList<PVector>();
  for (int i = 0; i< table.getRowCount(); i++) {
    float xPos = table.getFloat(i, 0); 
    float yPos = table.getFloat(i, 1);
    float zPos = table.getFloat(i, 2); 
    if (mag(xPos, yPos, zPos) > 0) {
      vectors.add(new PVector(xPos, yPos, zPos - 2000));
    }
  }
}
float ease(float p, float g) {
  p = constrain(p, 0, 1);
  if (p < 0.5) 
    return 0.5 * pow(2*p, g);
  else
    return 1 - 0.5 * pow(2*(1 - p), g);
}

void draw() {
  background(255);

  if (currFrame <= endFrame) {
    loadStrip(currFrame);
  }

  lights();
  clear();
  noStroke();
  for (PVector P : vectors) {
    pushMatrix();
    translate(P.x, P.y, P.z);
    sphereDetail(6);
    noStroke();
    ambient(255);
    emissive(255);
    sphere(sphereSize);
    popMatrix();
  }
  //linear number
  float centerX = 0 + 0.0 * width/2.0;
  float centerY = 0 + 0.0 * height/2.0;
  float centerZ = 0 + 0;

  float currLinear = (currFrame % endFrame) / float(endFrame);
  float currCubic = ease(currLinear, 2.1); 
  float angle = TWO_PI * currCubic+1.3;
  radius = int(radius + (12.5*currCubic)); 
  float eyeX = radius * cos(angle)+300;
  float eyeY = 500;//height, remember higher number is lower
  float eyeZ = radius * sin(angle);

  //float currCubic = TWO_PI * ease(currLinear, 2.1);
  float spin = sin(currCubic*TWO_PI)/3.0; 
  float upX = 1 * cos(spin + HALF_PI);
  float upY = 1 * sin(spin + HALF_PI);
  float upZ = 0;

  camera(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ);

  if (render == true && currFrame <= endFrame) {
    saveFrame(filename+"_preview/"+filename+"_frame_"+currFrame+".png"); 
    println ("saved" + filename+"_frame_"+currFrame+".png");
  }
  if (currFrame <= endFrame) {
    currFrame++;
  }
}

void keyPressed() {

  if (key == 'a') {
    //render out the whole thing, the GO button
    currFrame = 1; 
    render = true;
  }

  if (keyCode == RIGHT) {
    //forward
    if (currFrame <= endFrame) {
      currFrame++;
      println("now at "+currFrame);
    } else {
      currFrame = 1;
    }; 
    table = loadTable("../3D/captures/"+filename+"/frame"+currFrame+".csv");
  }
  if (keyCode == LEFT) {
    //back
    if (currFrame > 1) {
      currFrame--;
      println("now at "+currFrame);
    } else {
      currFrame = endFrame;
    }
    table = loadTable("../3D/captures/"+filename+"/frame"+currFrame+".csv");
  }


  if (key == 'f') {
    //fast forward
    if (currFrame <= endFrame) {
      currFrame = currFrame + 10;
      println("now at "+currFrame);
    } else {
      currFrame = 1;
    }
    table = loadTable("../3D/captures/"+filename+"/frame"+currFrame+".csv");
  }

  if (key == 's') {
    //save a frame
    saveFrame("screenCapture"+currFrame+".png"); 
    println("saved frame at "+currFrame);
  }
}

void loadStrip(int l) {
  table = loadTable("../3D/captures/"+filename+"/frame"+l+".csv");
  vectors = new ArrayList<PVector>();
  for (int i = 0; i< table.getRowCount(); i++) {
    float xPos = table.getFloat(i, 0); 
    float yPos = table.getFloat(i, 1);
    float zPos = table.getFloat(i, 2); 
    if (mag(xPos, yPos, zPos) > 0) {
      vectors.add(new PVector(xPos, yPos, zPos - 2000));
    }
  }
}

Greg Niemeyer