Data, Ecology, Art

Code Blog

Basic 3D Rendering in Processing

Coming from Maya, it’s not easy to accept that some projects don’t make sense to build in Maya. Although Maya has a good scripting window, some projects just exceed what Maya can handle with its complex object definitions. For example, rendering 100,000 spheres is not possible. Just creating 100,000 spheres, even as instances, brings the program to its knees. However, in Processing, no problem, because here a vertex list is just a vertex list, and there is no history, no key framing, no object state to deal with.

So, for an upcoming video project with 100,000 spheres, I had to replicate the nice Maya tools for actually making a movie in Processing. Two libraries are helpful: Peasy Camera for the camera, and AU for interpolations and smooth movements. Here is an example of a setup with a start frame, an end frame, and a nice Ease In animation.

Note what is not well documented in Peasy: The camera rotation is incremental, so of you have:

cam.rotateY(0.01);

that means rotate the camera by 0.01 radians per frame. Likewise, the lookAt function does an incremental animation from its original position to its target position over a certain amount of time. So, if you want to control the position directly, you have to set the time to 0 ms, like so:

cam.lookAt(0, 0, 0, cDist, 0);

Now it will jump from the last value of cDist to the current value of cDist in 0ms, which means instantly.

However, for the pan:

cam.pan(0, 0.1);

that is an absolute movement. You enter 0.1, you get 0.1. Anyway, here follows the code that generates a nice zoom in:

import AULib.*; 
import peasy.*;
int startFrame = 0; 
int endFrame = 300; 
boolean render = true;

PeasyCam cam; 
double angleY = 0.0; 
int frameWidth = 1920; 
int frameHeight = 1080;

void settings(){
  size(frameWidth, frameHeight, P3D);
}
void setup() {
  cam = new PeasyCam(this, 0, 0, 0, 55);
  smooth(8);
  cam.setActive(false);
  perspective(PI/3.0, width/height, 1, 100000);
}

void draw(){
  background(255);
  //linear number
  float linear = norm(300-frameCount%endFrame, startFrame, endFrame);
  float cubic = AULib.ease(AULib.EASE_IN_CUBIC, linear);
  //pay attention to start and end frames here: we are zooming in!
  float cDist = lerp(1, 1000, cubic);
  fill(50, 100, 200);  
  box(1, 10, 1);
  fill(100, 50, 200);  
  box(5);
  fill(200, 100, 50); 
  box(10, 3, 8);
  cam.rotateY(0.01);
  float yPan = 0.01; //sin((frameCount/100.0)%500);
  cam.lookAt(0, 0, 0, cDist, 0);
  cam.pan(0, yPan); 
  if (render==true && frameCount < endFrame){
  saveFrame("zoom-####.png"); }
}; 

Greg Niemeyer