Recently I've been looking at Povray, pyprocessing, and cfdg (version 3.0) as tools for creating digital images. I have branched two separate blogs where I mainly explore jruby + processing and processing.py

Saturday, 3 October 2009

The importance of 'lighting' for a 3D illusion

 Here I have created a 3D Sierpinski Triangle (tetrahedron) that looks quite rubbish, if not properly lit, as it is a slightly unfamiliar structure, and it is all too easy to lose the 3D illusion.

// tetrahedron.pde by Martin Prout

import processing.opengl.*;

PVector[] pts = {  // points of the unit tetrahedron
  new PVector(-0.5,-0.5,-0.5),
  new PVector(0.5,0.5,-0.5),
  new PVector(-0.5,0.5,0.5),
  new PVector(0.5,-0.5,0.5)
};

int TETRA_SIZE = 600;
float ROTATE_STEP = 0.001;

void setup(){
  size(800, 800, OPENGL);
}

void draw(){
  background(0);
  ambientLight(100, 100, 100);
  directionalLight(155, 0, 0, -1, -1, -1); // colored directional
  directionalLight(0, 0, 155, 1, -1, -1);  // lights essential
  directionalLight(155, 155, 0, 1, 1, 1);  // for 3D illusion
  translate(width/2, height/2, -width/2);
  noStroke();
  rotateZ(frameCount * ROTATE_STEP);
  rotateY(frameCount * ROTATE_STEP);
  rotateX(frameCount * ROTATE_STEP);
  drawSierpinski(pts);
}  

PVector midPoint(PVector a, PVector b){
  PVector result = PVector.add(a, b);
  result.div(2);
  return result;
}

void drawSierpinski(PVector[] pts){
  if (pts[0].dist(pts[1]) < 0.1){                 // limits recursion on relative size
    drawTetrahedron(pts, TETRA_SIZE); // render the tetrahedra
  }
  else{
    PVector av = midPoint(pts[0], pts[1]); // a tetrahedron midpoint vertices
    PVector bv = midPoint(pts[0], pts[2]); // b
    PVector cv = midPoint(pts[0], pts[3]); // b
    PVector dv = midPoint(pts[1], pts[2]); // d
    PVector ev = midPoint(pts[1], pts[3]); // e
    PVector fv = midPoint(pts[3], pts[2]);  // e
    PVector[] aa = {
      pts[0],
      av,
      bv,
      cv
    };
    PVector[] bb = {
      av,
      ev,
      dv,
      pts[1]
    };
    PVector[] cc = {
      cv,
      ev,
      fv,
      pts[3]
    };
    PVector[] dd = {
      bv,
      dv,
      fv,
      pts[2]
    };
    drawSierpinski(aa); // calculate further inner tetrahedra coordinates
    drawSierpinski(bb);
    drawSierpinski(cc);
    drawSierpinski(dd);
  }
}

void drawTetrahedron(PVector[] pts, float sz){
  fill(255);
  beginShape(TRIANGLES);

  vertex(pts[0].x*sz, pts[0].y*sz, pts[0].z*sz);  // 1
  vertex(pts[1].x*sz, pts[1].y*sz, pts[1].z*sz);  // 2  
  vertex(pts[2].x*sz, pts[2].y*sz, pts[2].z*sz);  // 3

  vertex(pts[2].x*sz, pts[2].y*sz, pts[2].z*sz);  // 3
  vertex(pts[0].x*sz, pts[0].y*sz, pts[0].z*sz);  // 1  
  vertex(pts[3].x*sz, pts[3].y*sz, pts[3].z*sz);  // 4  

  vertex(pts[3].x*sz, pts[3].y*sz, pts[3].z*sz);  // 4  
  vertex(pts[2].x*sz, pts[2].y*sz, pts[2].z*sz);  // 3
  vertex(pts[1].x*sz, pts[1].y*sz, pts[1].z*sz);  // 2

  vertex(pts[1].x*sz, pts[1].y*sz, pts[1].z*sz);  // 2  
  vertex(pts[3].x*sz, pts[3].y*sz, pts[3].z*sz);  // 4
  vertex(pts[0].x*sz, pts[0].y*sz, pts[0].z*sz);  // 1
  
  endShape();

}

To view the applet follow this link to my website.3D Sierpinski Triangle : Built with Processing

No comments:

Post a Comment

Followers

Blog Archive

About Me

My photo
Pembrokeshire, United Kingdom
I have developed JRubyArt and propane new versions of ruby-processing for JRuby-9.1.5.0 and processing-3.2.2