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, 25 December 2011

Anatomy of a PovRAY rendered processing sketch

Here is a fairly full example of a processing sketch, which has been exported to PovRAY format and rendered from the processing ide using my processing library. Two PovRAY file are created a hilbert.ini file (which stores render settings and is used to set for example aspect ratio of the sketch and width of the cylinders representing stroke) and hilbert.pov (that contains the PovRAY scene description, background from a template, foreground from processing).

Here is the processing file:-

   1 
   2 /**
   3  * A 3D LSystem example with a SimpleGrammar 
   4  * Features use of a my sin/cos lookup tables for rotation. 
   5  * There is a fixed precision of 1 degree in my lookup tables(note degree rather than radian input for 
   6  * lookup tables) 
   7  * This LSystem library is available at Kenai version 0.7.2
   8  * http://kenai.com/projects/l-system-utilities/downloads
   9  * Comment out 'size(800, 600, P3D);' and uncomment the opengl lines for a better experience
  10  * works best with new opengl (formerly opengl2, else there is clipping)
  11  */
  12 
  13 /* 
  14  * Copyright (c) 2011 Martin Prout
  15  * 
  16  * This demo & library is free software; you can redistribute it and/or
  17  * modify it under the terms of the GNU Lesser General Public
  18  * License as published by the Free Software Foundation; either
  19  * version 2.1 of the License, or (at your option) any later version.
  20  * 
  21  * http://creativecommons.org/licenses/LGPL/2.1/
  22  * 
  23  * This library is distributed in the hope that it will be useful,
  24  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  26  * Lesser General Public License for more details.
  27  * 
  28  * You should have received a copy of the GNU Lesser General Public
  29  * License along with this library; if not, write to the Free Software
  30  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  31  */
  32 import povexport.*;
  33 import povexport.povwriter.*;
  34 import lsystem.util.*;
  35 import lsystem.turtle.*;
  36 import lsystem.collection.*;
  37 import lsystem.*;
  38 //import processing.opengl.*; // optimised for new version (else there is clipping)
  39 // It'll be even better when I get PShapes3D to work!!!
  40 
  41 Grammar grammar;
  42 Process povray;
  43 boolean record = false;
  44 PovExporter export;
  45 
  46 float distance = 300;  // reduce size or increase depth for old opengl (see above)
  47 int depth = 2;
  48 
  49 // adjust centre of hilbert
  50 float[] adjust = {
  51   0.0, 0.5, 1.5, 3.5, 7.5
  52 };
  53 
  54 
  55 float THETA = radians(90);
  56 float PHI = radians(90);
  57 String production = "";
  58 
  59 void setup() {
  60   size(800, 600, P3D);
  61   LUT.initialize(); 
  62   setupGrammar();
  63   export = new PovExporter(this);
  64   export.chooseTemplate(); // launch custom template file chooser
  65   export.setPovrayPath("/usr/local/bin/povray"); // set once only
  66   export.storeSettings(); // NB: call storeSettings() after changes
  67   // Quality 1 ...7... 11 (low ... medium ... high)
  68   export.createIniFile(dataPath("hilbert.ini"), 11); 
  69   export.addDeclareOption("SWIDTH", "10");
  70   export.writeIniFile();
  71   float fov = PI/3.0; 
  72   float cameraZ = (height/2.0) / tan(fov/2.0); 
  73   perspective(fov, float(width)/float(height), cameraZ/2.0, cameraZ*2.0);
  74 }
  75 
  76 
  77 
  78 /**
  79  * Encapulates the lsystem rules, and calls the grammar to create the production rules
  80  * depth is number of repeats, and distance is adjusted according to the number of repeats
  81  */
  82 
  83 void setupGrammar() {
  84   grammar = new SimpleGrammar(this, "A");   // this only required to allow applet to call dispose()
  85   grammar.addRule('A', "B>F<CFC<F>D+F-D>F<1+CFC<F<B1^");
  86   grammar.addRule('B', "A+F-CFB-F-D1->F>D-1>F-B1>FC-F-A1^");
  87   grammar.addRule('C', "1>D-1>F-B>F<C-F-A1+FA+F-C<F<B-F-D1^");
  88   grammar.addRule('D', "1>CFB>F<B1>FA+F-A1+FB>F<B1>FC1^");
  89   production = grammar.createGrammar(depth);
  90   if (depth > 0) {
  91     distance *= 1/(pow(2, depth) - 1);
  92   }
  93 }
  94 
  95 void draw() {
  96   background(20, 20, 200);
  97   strokeWeight(distance/10);
  98   lights();
  99   ambientLight(80, 80, 80);
 100   directionalLight(100, 100, 100, -1, -1, 1);
 101   ambient(122, 122, 122); 
 102   lightSpecular(30, 30, 30); 
 103   specular(122, 122, 122); 
 104   shininess(0.7);
 105 
 106   translate(width/2, height/2, 0);
 107   rotateX(LUT.sin(frameCount));
 108   rotateY(LUT.cos(frameCount));
 109 
 110   translate(-distance * adjust[depth], distance/2 * adjust[depth], -distance/2 * depth);   
 111   if (record) {    
 112     noLights();    // let PovRAY do the lighting
 113     noLoop();      // don't loop while recording sketch
 114     beginRaw(PovExporter.POV, dataPath("hilbert.pov"));
 115   }
 116   try {  
 117     if (povray != null && povray.waitFor() == 0) {      
 118       display();
 119     }
 120     else
 121       render();
 122   }
 123   catch(InterruptedException e) {
 124     e.printStackTrace();
 125   }
 126   if (record) {
 127     endRaw();
 128     record = false;
 129     loop();
 130   }
 131 }
 132 
 133 void display() {
 134   PImage img = loadImage(dataPath("hilbert.png"), "png");
 135   background(img);
 136 }
 137 
 138 void render() {
 139   int repeats = 1;  
 140   fill(191, 191, 191);
 141   CharacterIterator it = grammar.getIterator(production);
 142   for (char ch = it.first(); ch != CharacterIterator.DONE; ch = it.next()) {
 143     switch (ch) {
 144     case 'F':
 145       translate(0, 0, distance/2.0);
 146       line(0, 0, -distance/2.0, 0, 0, distance/2.0);
 147       translate(0, 0, distance/2.0);
 148       break;
 149     case '+':
 150       rotateX(THETA * repeats);
 151       repeats = 1;
 152       break;
 153     case '-':
 154       rotateX(-THETA * repeats);
 155       repeats = 1;
 156       break;  
 157     case '>':
 158       rotateY(THETA * repeats);
 159       repeats = 1;
 160       break;
 161     case '<':
 162       rotateY(-THETA * repeats);
 163       repeats = 1;
 164       break;
 165     case '^':
 166       rotateZ(PHI * repeats);
 167       repeats = 1;
 168       break;
 169     case '1':
 170       repeats += 1;
 171       break;  
 172     case 'A':
 173     case 'B':
 174     case 'C':
 175     case 'D': 
 176       break;
 177     default:
 178       System.err.println("character " + ch + " not in grammar");
 179     }
 180   }
 181 }
 182 
 183 void keyReleased() {
 184   switch(key) {
 185   case '+':
 186     if (depth <= 3) { // guard against a depth we can't handle
 187       depth++;
 188       distance = 300;
 189       setupGrammar();
 190     }
 191     break;
 192   case '-':
 193     if (depth >= 2) {
 194       depth--;
 195       distance = 300;
 196       setupGrammar();
 197     }
 198     break;
 199   case 'r':
 200     record = true;
 201     break;
 202   case 't':
 203     povray = export.rayTrace(); 
 204     break;
 205   }
 206 }
 207 


Here is the generated PovRAY ini file ( hilbert.ini ) :-

   1 ; hilbert.ini
   2 
   3 
   4 
   5 Input_File_Name=/home/sid/sketchbook/rodHilbert/data/hilbert.pov
   6 Output_File_Name=/home/sid/sketchbook/rodHilbert/data/hilbert.png
   7 Width=800
   8 Height=600
   9 Declare=ASPECT_RATIO=1.3333
  10 Quality=11
  11 Output_File_Type=N16
  12 Antialias=on
  13 Sampling_Method=2
  14 Max_Image_Buffer_Memory=516
  15 Declare=SWIDTH=10

Here is the generated hilbert.pov (scene description file)

   1 // Persistence Of Vision Ray Tracer Scene Description File
   2 // File:  Simple Scene <template for povwriter>
   3 // Vers: 3.7
   4 // Date: March 2011
   5 // Auth: Martin Prout 
   6 
   7 // +w300 +h300
   8 
   9 #version 3.7;
  10 
  11 global_settings{
  12   assumed_gamma 1.0
  13   radiosity{
  14     pretrace_start 0.04
  15     pretrace_end 0.01
  16     count 200
  17     recursion_limit 3
  18     nearest_count 10
  19     error_bound 0.5
  20   }
  21 }
  22 
  23 #include "colors.inc"
  24 #include "skies.inc"
  25 
  26 // --------------- begin declare adjustments to scene -------------------------
  27 
  28 // Default values in case not using ini file or they are not declared there ---
  29 #ifndef (ScaleP5)
  30 #declare ScaleP5 = 1.0;     // scale factor
  31 #end
  32 #ifndef (TransXP5)
  33 #declare TransXP5 = -10;    // translate in X axis
  34 #end
  35 #ifndef (TransYP5)
  36 #declare TransYP5 = 40;    // translate in Y axis
  37 #end
  38 #ifndef (TransZP5)
  39 #declare TransZP5 = -15;    // translate in Z axis
  40 #end
  41 #ifndef (RotYP5)
  42 #declare RotYP5 = 15;       // rotate around Y axis
  43 #end
  44 #ifndef (RotXP5)
  45 #declare RotXP5 = 0;        // rotate around X axis
  46 #end
  47 #ifndef (RotZP5)
  48 #declare RotZP5 = 0;         // rotate around Z axis
  49 #end
  50 // ---------------end of declare adjustments to scene
  51 
  52 //----------------declare default colors
  53 #declare CornellRed = rgb<0.57, 0.025, 0.025>;  // Right wall Cornell Box
  54 #declare CornellGreen = rgb<0.025, 0.236, 0.025>; // Left wall Cornell Box
  55 #declare LineFill = rgb<1.0, 0.9, 0.8>; // polygon outline color
  56 #declare LineCol = rgb<0.3, 0.225, 0.12>; // polygon outline color
  57 #declare TransFill = rgbf<1.0, 0.95, 0.8, 0.7>; // polygon outline color
  58 #declare BuddhaGold = rgb<195, 160, 4>/255; // Custom Gold
  59 //----------------end declare default colors #### paste sketch after this ####
  60 
  61 //----------------begin declare finish
  62 
  63 #declare Finish0=finish{diffuse 0.75 emission 0}  // Stroke
  64 #declare Finish1=finish{diffuse 0.78 emission 0}  // Cornell Box Light Patch
  65 #declare Finish2=finish{emission 0.1 phong 0.5 phong_size 10.0}   // Processing object finish
  66 
  67 //----------------end declare finish
  68 #ifndef (SWIDTH)
  69 #declare SWIDTH=0.4; // processing equivalent is stroke width
  70 #end
  71 //----------------begin declare pigment
  72 
  73 #declare Pigment0 = pigment{rgb<1, 1, 1>}  // Cornell Box Light Patch
  74 
  75 //----------------end declare pigment
  76 
  77 //----------------begin declare texture
  78 
  79 #declare WhiteT=texture{pigment{White} finish{Finish0}} //
  80 #declare RedT=texture{pigment{CornellRed} finish{Finish0}}   // Cornell Box Walls
  81 #declare GreenT=texture{pigment{CornellGreen} finish{Finish0}} //
  82 #declare Texture0=texture{pigment{LineFill} finish{Finish1}} // this is for 'stroke' color
  83 
  84 //----------------end declare texture
  85 
  86 #ifndef (ASPECT_RATIO)
  87 #declare ASPECT_RATIO=1.25;
  88 #end
  89 
  90 //----------------declare scene Settings
  91 #declare camera0 = camera {            // define additional cameras to suit viewing preferences
  92    location <-1.5, 30.0, -150.0>
  93    direction <0.0, 0.0, 2.0>
  94    up  <0.0, 1.0, 0.0>
  95    right <ASPECT_RATIO, 0.0, 0.0>
  96    look_at <0.0, 25.0, 35.0>
  97 }
  98 
  99 #declare light0 = light_source { <100.0, 100.0, -200.0> colour White }
 100 
 101 #declare ground0 = plane { <0.0, 1.0, 0.0>, 0.0  // a reflective ground plane
 102    pigment { NeonBlue }
 103    finish {reflection 0.15}
 104 }
 105 
 106 //------------------end of declare scene settings
 107 
 108 // -----------------set the scene
 109 
 110 camera { camera0 }              // ------------------------------------------
 111                                 //  The use of declared values makes it possible to easily 
 112 light_source{ light0 }          //  change the way the scene is rendered. Just define an
 113                                 //  additional camera say for your template, and do the
 114 sky_sphere{ S_Cloud3 }          //  substitution here. Retain the original definition and
 115                                 //  you can easily backtrack. Definitions can also be saved
 116 plane{ ground0 }                //  as included file see colors.inc for an example.
 117                                 // ---------------------------------------------  
 118 // -----------------end set the scene
 119 
 120 // -----------------processing sketch begins here------------------------
 121 
 122 // ----------------- triangle and line macros -----------------------------------------------------------
 123 
 124 /**
 125 Adjust global triangle mesh here, or at #declare for Finish2, if you change my_hue you will lose color data
 126 from the processing sketch, however as sketch colors are also #declare, you can safely change those declares, 
 127 unless they are used in other parts of processing scene (eg checker color Red, Blue). You can change these 
 128 as well but just remember to hand edit them back to original (this is particularly important for light source)
 129 Note a built in scale to 20% of original sketch size, units in PovRAY are different
 130 */
 131 
 132 #macro my_triangle ( x1, y1, z1, x2, y2, z2, x3, y3, z3, my_hue )  
 133      triangle{<x1 * 0.2,y1 * 0.2,z1 * 0.2>,<x2 * 0.2,y2 * 0.2,z2 * 0.2>,<x3 * 0.2,y3 * 0.2,z3 * 0.2> 
 134      texture{ pigment{ color my_hue } finish{ Finish2 } } }    
 135 #end 
 136 
 137 /**
 138 Adjust global line properties here, or at #declare for SWIDTH, LineCol, Texture0
 139 Note a built in scale to 20% of original sketch size, units in PovRAY are different
 140 */
 141 
 142 #macro my_line ( x1, y1, z1, x2, y2, z2 )  
 143 blob { threshold 0.65 cylinder { <x1* 0.2 , y1 * 0.2, z1 * 0.2>, <x2 * 0.2, y2* 0.2, z2 * 0.2>, SWIDTH 1 pigment{ LineCol } texture{ Texture0 } } }
 144 #end 
 145 
 146 //------------------ end of macro definitions --------------------------------------
 147 
 148 
 149 
 150 
 151 
 152 // --------------Begin declare colours from sketch
 153 // If empty then sketch colors already colored
 154 // --------------end of declare colours for sketch
 155 
 156 
 157 // --------------processing sketch begins here
 158 
 159 
 160 union{
 161 my_line( -170.59784, 5.289253, 614.4487, -170.59784, 62.154816, 532.19116 )
 162 my_line( -170.59784, 62.154816, 532.19116, -145.00394, -17.362999, 477.2196 )
 163 my_line( -145.00394, -17.362999, 477.2196, -145.00394, -74.228546, 559.4772 )
 164 my_line( -145.00394, -74.228546, 559.4772, -48.33464, -53.175613, 574.03125 )
 165 my_line( -48.33464, -53.175613, 574.03125, -48.334625, 3.68993, 491.77368 )
 166 my_line( -48.334625, 3.68993, 491.7737, -73.92855, 83.20775, 546.74524 )
 167 my_line( -73.92855, 83.20775, 546.74524, -73.928566, 26.342207, 629.0028 )
 168 my_line( -73.928566, 26.342207, 629.0028, 22.74073, 47.39514, 643.557 )
 169 my_line( 22.74073, 47.39514, 643.557, 22.740757, 104.2607, 561.29944 )
 170 my_line( 22.74076, 104.2607, 561.29944, 119.41006, 125.313644, 575.85364 )
 171 my_line( 119.41006, 125.313644, 575.85364, 119.41003, 68.448105, 658.1112 )
 172 my_line( 119.410034, 68.448105, 658.1112, 145.00397, -11.06971, 603.13965 )
 173 my_line( 145.00397, -11.06971, 603.13965, 145.004, 45.795837, 520.8821 )
 174 my_line( 145.004, 45.795837, 520.8821, 48.3347, 24.742905, 506.3279 )
 175 my_line( 48.3347, 24.742905, 506.32794, 48.33468, -32.122643, 588.5855 )
 176 my_line( 48.33468, -32.12264, 588.5855, 73.928604, -111.64046, 533.61395 )
 177 my_line( 73.928604, -111.64046, 533.61395, 73.92865, -54.77489, 451.35638 )
 178 my_line( 73.92865, -54.77489, 451.35638, 170.59795, -33.72196, 465.91058 )
 179 my_line( 170.59795, -33.72196, 465.91058, 170.59792, -90.58751, 548.16815 )
 180 my_line( 170.59792, -90.58751, 548.16815, 196.19185, -170.10533, 493.19662 )
 181 my_line( 196.19185, -170.10532, 493.19662, 196.19188, -113.23977, 410.93906 )
 182 my_line( 196.1919, -113.23977, 410.93906, 99.52259, -134.2927, 396.38492 )
 183 my_line( 99.52259, -134.2927, 396.38492, 99.522545, -191.15823, 478.6425 )
 184 my_line( 99.522545, -191.15823, 478.64252, 2.8532486, -212.21115, 464.08832 )
 185 my_line( 2.8532486, -212.21115, 464.08832, -22.74069, -132.69333, 519.0599 )
 186 my_line( -22.740692, -132.69333, 519.0599, -119.40999, -153.74625, 504.50568 )
 187 my_line( -119.40999, -153.74625, 504.50568, -93.81604, -233.26407, 449.53412 )
 188 my_line( -93.81604, -233.26407, 449.53412, -93.815994, -176.3985, 367.27655 )
 189 my_line( -93.815994, -176.3985, 367.27655, -119.40994, -96.880684, 422.2481 )
 190 my_line( -119.40994, -96.880684, 422.2481, -22.740646, -75.82775, 436.8023 )
 191 my_line( -22.740646, -75.82775, 436.8023, 2.8532925, -155.34555, 381.83075 )
 192 my_line( 2.8532925, -155.34555, 381.83075, 2.8533459, -98.47998, 299.57318 )
 193 my_line( 2.8533459, -98.47998, 299.57318, -22.740602, -18.962173, 354.54474 )
 194 my_line( -22.7406, -18.962173, 354.54474, -119.4099, -40.015106, 339.99054 )
 195 my_line( -119.4099, -40.015106, 339.99054, -93.81593, -119.53291, 285.01898 )
 196 my_line( -93.81593, -119.53291, 285.01898, -93.81587, -62.667343, 202.76141 )
 197 my_line( -93.81587, -62.667343, 202.76141, -119.409836, 16.850456, 257.73297 )
 198 my_line( -119.409836, 16.850456, 257.73297, -22.74054, 37.90339, 272.28717 )
 199 my_line( -22.74054, 37.90339, 272.28717, 2.8534088, -41.61441, 217.31561 )
 200 my_line( 2.8534088, -41.61441, 217.31561, 99.522705, -20.561481, 231.86981 )
 201 my_line( 99.522705, -20.561481, 231.86981, 99.52266, -77.42706, 314.12738 )
 202 my_line( 99.52265, -77.42706, 314.12738, 196.19196, -56.374146, 328.68158 )
 203 my_line( 196.19196, -56.374146, 328.68158, 196.19202, 0.49142838, 246.42401 )
 204 my_line( 196.19202, 0.49142838, 246.42401, 170.59808, 80.00922, 301.39557 )
 205 my_line( 170.59808, 80.00922, 301.39557, 170.59802, 23.143639, 383.65314 )
 206 my_line( 170.59802, 23.143639, 383.65314, 73.92873, 2.0907135, 369.09894 )
 207 my_line( 73.92873, 2.0907135, 369.09894, 73.92877, 58.95629, 286.84137 )
 208 my_line( 73.92877, 58.956287, 286.84137, 48.334824, 138.47408, 341.81293 )
 209 my_line( 48.334824, 138.47408, 341.81293, 48.334793, 81.60849, 424.0705 )
 210 my_line( 48.334793, 81.60849, 424.0705, 145.00409, 102.66142, 438.62463 )
 211 my_line( 145.00409, 102.66142, 438.62463, 145.00412, 159.527, 356.36707 )
 212 my_line( 145.00412, 159.527, 356.36707, 119.41019, 239.04478, 411.33862 )
 213 my_line( 119.41019, 239.0448, 411.33862, 119.41016, 182.1792, 493.5962 )
 214 my_line( 119.41016, 182.1792, 493.5962, 22.74086, 161.12628, 479.042 )
 215 my_line( 22.74086, 161.12628, 479.042, 22.74089, 217.99188, 396.78442 )
 216 my_line( 22.74089, 217.99188, 396.78442, -73.928406, 196.93893, 382.23022 )
 217 my_line( -73.928406, 196.93893, 382.23022, -73.92842, 140.07333, 464.4878 )
 218 my_line( -73.92842, 140.07333, 464.4878, -48.334473, 60.555546, 409.51624 )
 219 my_line( -48.334473, 60.555542, 409.51624, -48.33445, 117.42114, 327.25867 )
 220 my_line( -48.33445, 117.42114, 327.25867, -145.00375, 96.368195, 312.70447 )
 221 my_line( -145.00375, 96.368195, 312.70447, -145.00378, 39.502594, 394.96198 )
 222 my_line( -145.00378, 39.502594, 394.96198, -170.59772, 119.02037, 449.93353 )
 223 my_line( -170.59772, 119.02037, 449.93353, -170.59769, 175.88597, 367.67603 )
 224 // -----------------------------End of processing scene
 225 // -----------------------------Adjust the processing scene
 226 translate<TransXP5, TransYP5, TransZP5>
 227 rotate<RotXP5, RotYP5, RotZP5>
 228 scale<ScaleP5, ScaleP5, ScaleP5>
 229 }

This sketch plays to the strengths of my library as the line or blob primitive is rendered pretty well.

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