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

Sunday, 1 April 2012

Experimenting with processing-2.0a5 (and PShape)

Recently I've been following developments with processing 2.0, in particular I was interested as to whether DXL export would be re-implemented, however it looks as though a "volunteer" is needed, Andres has sketched out how the new P3D works under the hood, and is hoping for someone to step in. I might have fancied giving it a go before I got into exporting Hemesh and Toxiclibs sketches to povray mesh2 objects (mesh2 objects are much nicer than plain triangle mesh). Anyway one really neat feature of processing-2.0 is being able to group 3D shapes. I thought I would have a go re-implementing a menger sponge, here is the code.
   1 float angle = 0.0;
   2 float angleStep = PI / 360.0;
   3 final float MIN_SIZE = 33;
   4 PShape menger; // NB: using processing 2.0 syntax to group vertices
   5 
   6 void setup() {
   7   size(1000, 1000, P3D);
   8   menger = createShape(PShape.GROUP);
   9   createMenger(0, 0, 0, width * 0.8);
  10 }
  11 
  12 void draw() {
  13   background(20, 20, 200);
  14   noStroke();
  15   lights();
  16   defineLights();
  17   render();
  18 }
  19 
  20 void render() {
  21   angle = (angle + angleStep) % TWO_PI;
  22   translate(width / 2, height / 2, -width / 2);
  23   rotateZ(angle);
  24   rotateY(angle);
  25   shape(menger);
  26 }
  27 
  28 /**
  29  * A recursive function creates and stores custom cubes 
  30  * to menger PShape.GROUP. Requires processing 2.0a5+
  31  * @param x
  32  * @param y
  33  * @param z
  34  * @param sz 
  35  */
  36 
  37 void createMenger(float xx, float yy, float zz, float sz) {
  38   float u = sz / 3;
  39   if (sz < MIN_SIZE) { // recursion limited by minimum cube size
  40     noStroke();
  41     menger.addChild(createCube(xx, yy, zz, sz)); // create and add a cube
  42   } 
  43   else {
  44     for (int i = -1; i <= 1; i++) {
  45       for (int j = -1; j <= 1; j++) {
  46         for (int k = -1; k <= 1; k++) {
  47           if ((abs(i) + abs(j) + abs(k)) > 1) {
  48             createMenger(xx + (i * u), yy + (j * u), zz + (k * u), u);
  49           }
  50         }
  51       }
  52     }
  53   }
  54 }
  55 
  56 /**
  57  * A function to create a custom cube PShape
  58  * Requires processing 2.0a5+
  59  * @param x float centre
  60  * @param y float centre
  61  * @param z float centre
  62  * @param sz size
  63  */
  64 
  65 PShape createCube(float xx, float yy, float zz, float sz) {
  66   PShape cube = createShape(QUADS);
  67   // Front face
  68   cube.fill(255);
  69   cube.normal(0, 0, 1);
  70   cube.vertex(-sz / 2 + xx, -sz / 2 + yy, -sz / 2 + zz);
  71   cube.vertex(+sz / 2 + xx, -sz / 2 + yy, -sz / 2 + zz);
  72   cube.vertex(+sz / 2 + xx, +sz / 2 + yy, -sz / 2 + zz);
  73   cube.vertex(-sz / 2 + xx, +sz / 2 + yy, -sz / 2 + zz);
  74 
  75   // Back face
  76 
  77   cube.normal(0, 0, -1);
  78   cube.vertex(-sz / 2 + xx, -sz / 2 + yy, +sz / 2 + zz);
  79   cube.vertex(+sz / 2 + xx, -sz / 2 + yy, +sz / 2 + zz);
  80   cube.vertex(+sz / 2 + xx, +sz / 2 + yy, +sz / 2 + zz);
  81   cube.vertex(-sz / 2 + xx, +sz / 2 + yy, +sz / 2 + zz);
  82 
  83   // Left face
  84 
  85   cube.normal(1, 0, 0);
  86   cube.vertex(-sz / 2 + xx, -sz / 2 + yy, -sz / 2 + zz);
  87   cube.vertex(-sz / 2 + xx, -sz / 2 + yy, +sz / 2 + zz);
  88   cube.vertex(-sz / 2 + xx, +sz / 2 + yy, +sz / 2 + zz);
  89   cube.vertex(-sz / 2 + xx, +sz / 2 + yy, -sz / 2 + zz);
  90 
  91   // Right face
  92 
  93   cube.normal(-1, 0, 0);
  94   cube.vertex(+sz / 2 + xx, -sz / 2 + yy, -sz / 2 + zz);
  95   cube.vertex(+sz / 2 + xx, -sz / 2 + yy, +sz / 2 + zz);
  96   cube.vertex(+sz / 2 + xx, +sz / 2 + yy, +sz / 2 + zz);
  97   cube.vertex(+sz / 2 + xx, +sz / 2 + yy, -sz / 2 + zz);
  98 
  99   // Top face
 100 
 101   cube.normal(0, 1, 0);
 102   cube.vertex(-sz / 2 + xx, -sz / 2 + yy, -sz / 2 + zz);
 103   cube.vertex(+sz / 2 + xx, -sz / 2 + yy, -sz / 2 + zz);
 104   cube.vertex(+sz / 2 + xx, -sz / 2 + yy, +sz / 2 + zz);
 105   cube.vertex(-sz / 2 + xx, -sz / 2 + yy, +sz / 2 + zz);
 106 
 107   // Bottom face
 108 
 109   cube.normal(0, -1, 0);
 110   cube.vertex(-sz / 2 + xx, +sz / 2 + yy, -sz / 2 + zz);
 111   cube.vertex(+sz / 2 + xx, +sz / 2 + yy, -sz / 2 + zz);
 112   cube.vertex(+sz / 2 + xx, +sz / 2 + yy, +sz / 2 + zz);
 113   cube.vertex(-sz / 2 + xx, +sz / 2 + yy, +sz / 2 + zz);
 114   cube.end();
 115   return cube;
 116 }
 117 
 118 void defineLights() {
 119   // Orange point light on the right
 120   pointLight(150, 100, 0, // Color
 121   200, -150, 0); // Position
 122 
 123   // Blue directional light from the left
 124   directionalLight(0, 102, 255, // Color
 125   1, 0, 0);    // The x-, y-, z-axis direction
 126 
 127   // Yellow spotlight from the front
 128   spotLight(255, 255, 109, // Color
 129   0, 40, 200, // Position
 130   0, -0.5, -0.5, // Direction
 131   PI / 2, 2);     // Angle, concentration
 132   ambient(50);    // may be able to set finish by shape in future?
 133   specular(30);   // not sure is working here
 134 }
 135 
 136 
 137 
Since processing 2.0 opengl sketches will run in a web browser, see for yourself at open 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