Complex 3D output using PDF in Processing

Complex 3D output using PDF in Processing.

Sample code for PDF output of complex geometries from Processing, with a 3D shape using lines and polygons being written correctly to PDF. Uses beginRaw() / endRaw() and should probably be used with revision 0115 or later due to recent bug fixes.

Source code - pdf_complex.pde

// pdf_complex.pde - workshop.evolutionzone.com - Marius Watz
// Example using PDF to output complex 3D geometry for print.
// Press "s" to save a PDF.

import processing.opengl.*;
import processing.pdf.*;

// Trig lookup tables borrowed from Toxi. Cryptic but effective
public static final float sinLUT[];
public static final float cosLUT[];
public static final float SINCOS_PRECISION=1f;
public static final int SINCOS_LENGTH= (int) (360f/SINCOS_PRECISION);
static {
  sinLUT=new float[SINCOS_LENGTH];
  cosLUT=new float[SINCOS_LENGTH];
  for (int i=0; i< SINCOS_LENGTH; i++) {
    sinLUT[i]= (float)Math.sin(i*DEG_TO_RAD*SINCOS_PRECISION);
    cosLUT[i]= (float)Math.cos(i*DEG_TO_RAD*SINCOS_PRECISION);
  }
}

// System data
boolean dosave=false;
int num;
float pt[];
int style[];

void setup() {
  size(600, 600, OPENGL);
  framerate(24);
  background(255);

  num=150;
  pt=new float[6*num]; // rotx, roty, deg, rad, w, speed
  style=new int[2*num]; // color, render style

  // Set up arc shapes
  int index=0;
  float prob;
  for(int i=0; i< num; i++) {
    pt[index++]=random(PI*2); // Random X axis rotation
    pt[index++]=random(PI*2); // Random Y axis rotation

    pt[index++]=random(60,80); // Short to quarter-circle arcs
    if(random(100)>90) pt[index]=(int)random(8,27)*10; 

    pt[index++]=(int)random(2,50)*5; // Radius. Space them out nicely

    pt[index++]=random(4,32); // Width of band
    if(random(100)>90) pt[index]=random(40,60); // Width of band

    pt[index++]=radians(random(5,30))/5; // Speed of rotation

    // get colors
    prob=random(100);
    if(prob<30) style[i*2]=colorBlended(random(1),
    255,0,100, 255,0,0, 210);
    else if(prob<70) style[i*2]=colorBlended(random(1),
    0,153,255, 170,225,255, 210);
    else if(prob<90) style[i*2]=colorBlended(random(1),
    200,255,0, 150,255,0, 210);
    else style[i*2]=color(255,255,255, 220);

    if(prob<50) style[i*2]=colorBlended(random(1),
      200,255,0, 50,120,0, 210);
    else if(prob<90) style[i*2]=colorBlended(random(1),
      255,100,0, 255,255,0, 210);
    else style[i*2]=color(255,255,255, 220);

    style[i*2+1]=(int)(random(100))%3;
  }
}

void draw() {

  if(dosave) {
    // set up PGraphicsPDF for use with beginRaw()
    PGraphicsPDF pdf=(PGraphicsPDF)beginRaw(PDF, "pdf_complex_out.pdf"); 

    // set default Illustrator stroke styles and paint background rect.
    pdf.strokeJoin(MITER);
    pdf.strokeCap(SQUARE);
    pdf.fill(0);
    pdf.noStroke();
    pdf.rect(0,0, width,height);
  }

  background(0);

  int index=0;
  translate(width/2,height/2,0);
  rotateX(PI/6);
  rotateY(PI/6);

  for(int i=0; i< num; i++) {
    pushMatrix();

    rotateX(pt[index++]);
    rotateY(pt[index++]);

    if(style[i*2+1]==0) {
      stroke(style[i*2]);
      noFill();
      strokeWeight(1);
      arcLine(0,0, pt[index++],pt[index++],pt[index++]);
    }
    else if(style[i*2+1]==1) {
      fill(style[i*2]);
      noStroke();
      arcLineBars(0,0, pt[index++],pt[index++],pt[index++]);
    }
    else {
      fill(style[i*2]);
      noStroke();
      arc(0,0, pt[index++],pt[index++],pt[index++]);
    }

    // increase rotation
    pt[index-5]+=pt[index]/10;
    pt[index-4]+=pt[index++]/20;

    popMatrix();
  }

  if(dosave) {
    endRaw();
    dosave=false;
  }
}

// Get blend of two colors
public int colorBlended(float fract,
float r, float g, float b,
float r2, float g2, float b2, float a) {

  r2 = (r2 - r);
  g2 = (g2 - g);
  b2 = (b2 - b);
  return color(r + r2 * fract, g + g2 * fract, b + b2 * fract, a);
}

// Draw arc line
public void arcLine(float x,float y,float deg,float rad,float w) {
  int a=(int)(min (deg/SINCOS_PRECISION,SINCOS_LENGTH-1));
  int numlines=(int)(w/2);

  for(int j=0; j< numlines; j++) {
    beginShape(LINE_STRIP);
    for(int i=0; i< a; i++) vertex(cosLUT[i]*rad+x,sinLUT[i]*rad+y);
    endShape();
    rad+=2;
  }
}

// Draw arc line with bars
public void arcLineBars(float x,float y,float deg,float rad,float w) {
  int a=(int)(min (deg/SINCOS_PRECISION,SINCOS_LENGTH-1));
  a/=4;

  beginShape(QUADS);
  for(int i=0; i< a; i+=4) {
    vertex(cosLUT[i]*(rad)+x,sinLUT[i]*(rad)+y);
    vertex(cosLUT[i]*(rad+w)+x,sinLUT[i]*(rad+w)+y);
    vertex(cosLUT[i+2]*(rad+w)+x,sinLUT[i+2]*(rad+w)+y);
    vertex(cosLUT[i+2]*(rad)+x,sinLUT[i+2]*(rad)+y);
  }
  endShape();
}

// Draw solid arc
public void arc(float x,float y,float deg,float rad,float w) {
  int a=(int)min (deg/SINCOS_PRECISION,SINCOS_LENGTH-1);
  beginShape(QUAD_STRIP);
  for(int i=0; i< a; i++) {
    vertex(cosLUT[i]*(rad)+x,sinLUT[i]*(rad)+y);
    vertex(cosLUT[i]*(rad+w)+x,sinLUT[i]*(rad+w)+y);
  }
  endShape();
}

void keyPressed() {
  if(key=='s') dosave=true;
}

void mouseReleased() {
  background(255);
}

There are 5 comments to "Code: PDF for complex 3D output". You may leave your own comment.
1. claudio midolo, May 23rd, 2006 at 04:42

i will try it soon TNX marius! ;)

2. blprnt, May 23rd, 2006 at 20:11

Great example yet again, Marius! It’s got me finally digging into this PDF stuff. Thanks!

3. max, May 23rd, 2006 at 22:24

This example really saved me in a bind, thanks!

4. Dave Bollinger, February 21st, 2007 at 03:26

Hope you won’t mind… I’ve borrowed this wonderful sketch as a “torture test” for exporting to POV-Ray and published the results (credit given to the original of course) here: http://www.davebollinger.com/works/hyphae/ (though I may move it off that unrelated project page and onto a specifically pov-ray export page eventually)

5. marius watz, February 22nd, 2007 at 10:18

Dave, you are more than welcome. POV-Ray was the first tool I ever used, and I’ve been toying with the idea of trying to write an export library for it. Your biggest problem will likely be stroked lines, since that concept doesn’t really exist in 3D space.

Comment on this entry

You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>