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, 30 June 2012

Displaying Hemesh meshes as RetainedShapes (VBO)

Very much taken with my success in rendering toxiclibs (Karsten Schmidt) mesh sketches in the processing-2.0 ide using VBO (for efficiency) I thought I would give the Hemesh (Frederick Vanhoutte) the same treatment, for this sketch I was used the latest version of the library hemesh_b1_7agx3, and processing version 2.0a6 (or greater). I have published the conversion library at github, but it is at a very early stage as yet.  I have also posted this sketch at open processing but currently opengl sketches (is supposed to be fixed for processing-2.0?) won't run on that site.

   1 import mshape.*;
   2 import wblut.hemesh.core.*;
   3 import wblut.hemesh.creators.*;
   4 import wblut.hemesh.modifiers.*;
   5 
   6 PShape retainedMesh;
   7 PShape retainedInverse;
   8 ArcBall arcball;   
   9 HE_Mesh mesh;
  10 HE_Mesh invMesh;
  11 int RES = 32;  // original was 20
  12 MeshToVBO mshape;
  13 
  14 void setup() {
  15   size(800, 800, P3D);
  16   arcball = new ArcBall(this);
  17   mshape = new MeshToVBO(this);  
  18   smooth(16);  
  19   float[][][] values = new float[RES + 1][RES + 1][RES + 1];
  20   for (int i = 0; i < RES + 1; i++) {
  21     for (int j = 0; j < RES + 1; j++) {
  22       for (int k = 0; k < RES + 1; k++) {
  23         values[i][j][k] = 2.1 * noise(0.35 * i, 0.35 * j, 0.35 * k);
  24       }
  25     }
  26   }
  27 
  28   HEC_IsoSurface creator = new HEC_IsoSurface();
  29   creator.setResolution(RES, RES, RES);// number of cells in x,y,z direction
  30   creator.setSize(400.0f / RES, 400.0 / RES, 400.0 / RES);// cell size
  31   creator.setValues(values);// values corresponding to the grid points
  32   // values can also be double[][][]
  33   creator.setIsolevel(1);// isolevel to mesh
  34   creator.setInvert(false);// invert mesh
  35   creator.setBoundary(100);// value of isoFunction outside grid
  36   // use creator.clearBoundary() to rest boundary values to "no value".
  37   // A boundary value of "no value" results in an open mesh
  38 
  39   mesh = new HE_Mesh(creator);
  40   mesh.modify(new HEM_Smooth().setIterations(10).setAutoRescale(true));
  41   creator.setInvert(true);
  42   invMesh = new HE_Mesh(creator);
  43   invMesh.modify(new HEM_Smooth().setIterations(10).setAutoRescale(true));
  44   noStroke();
  45   // silver
  46   retainedMesh = mshape.meshToRetained(mesh, 192, 192, 192);
  47   //white marble
  48   retainedInverse = mshape.meshToRetained(invMesh, 249, 246, 224);
  49 }
  50 
  51 
  52 void draw() {
  53   background(0);
  54   lights();
  55   lightSpecular(80, 80, 80);
  56   directionalLight(80, 80, 80, 0, 0, -1);
  57   ambientLight(50, 50, 50);
  58   translate(400, 400, 0);
  59   arcball.update();
  60   shape(retainedMesh);
  61   shape(retainedInverse);
  62 }

TwinIso sketch rendered in processing-2.0 ide as two vbo objects

Wednesday, 27 June 2012

Retained Shape for Toxiclibs Mesh

I've recently posted a sketch to Open Processing, which demonstrates the huge performance improvement possible using PShape retained shape for processing-2.0. Unfortunately this cannot be run in the browser online (at present), but will work if you download it to your computer. Here is the important code for translating the mesh to PShape. Do this in setup (as I have done in sketch above) to get maximum performance benefit.
66 PShape meshToRetained(Mesh3D mesh, boolean smth) {        
67   PShape retained = createShape(TRIANGLES);
68   retained.enableStyle();
69   retained.fill(200, 200, 200);
70   retained.ambient(50);
71   retained.emissive(10);
72   retained.specular(50);
73   if (smth) {
74     mesh.computeVertexNormals();
75     for (Face f : mesh.getFaces()) {
76       retained.normal(f.a.normal.x, f.a.normal.y, f.a.normal.z);
77       retained.vertex(f.a.x, f.a.y, f.a.z);
78       retained.normal(f.b.normal.x, f.b.normal.y, f.b.normal.z);
79       retained.vertex(f.b.x, f.b.y, f.b.z);
80       retained.normal(f.c.normal.x, f.c.normal.y, f.c.normal.z);
81       retained.vertex(f.c.x, f.c.y, f.c.z);
82     }
83   } 
84   else {
85     for (Face f : mesh.getFaces()) {
86       retained.normal(f.normal.x, f.normal.y, f.normal.z);
87       retained.vertex(f.a.x, f.a.y, f.a.z);
88       retained.vertex(f.b.x, f.b.y, f.b.z);
89       retained.vertex(f.c.x, f.c.y, f.c.z);
90     }
91   }
92   retained.end();
93   return retained;
94 }
In this sketch I also discovered how to update the PShape root, which is very nice feature and necessary, if for example you have made changes to the underlying mesh, eg laplacian transform.
58 void keyPressed() {
59   if (key == 'l') {
60     new LaplacianSmooth().filter(mesh, 1);
61     PShape changed = meshToRetained(mesh, true);
62     retained.updateRoot(changed);
63   }
64 }

Implicit Function Script running in processing-2.0a6 IDE

Tuesday, 19 June 2012

Added posterize utility to my pixelation library

I have revised my pixelation library to include a posterize utility. What this does is to convert the image to one with restricted color "channels" using a processing filter. Here is one such sketch (note removal of much cruft from draw() to library, ie hidden).
import pde2cfdg.*;

/**
 * Two cfdg files are written to the sketch folder one for design one for data,
 * this means it easier to edit the design (eg to replace CIRCLE with a custom shape)
 * The output png file is written to the sketch folder,
 */

ProcessingToCF cfdg;
int dotSize = 3;
void setup() {
  size(1280, 1024);
  background(255);
  colorMode(HSB, 1.0);
  cfdg = new ProcessingToCF(this);
  cfdg.setDotSize(dotSize);
  cfdg.setPathToCFDG("/home/tux/CF3/cfdg");  
  cfdg.posterize(4);  
  cfdg.getInput();
  cfdg.writeCFDG();
}

void draw() {
}

void keyReleased() {
  switch(key) {
  case 'r':
    cfdg.setDotSize(dotSize);
    cfdg.writeCFDG();
    break;
  case '1':
  case '2':
  case '3':
  case '4':
  case '5':
  case '6':
    dotSize = key - 48;
    break;
  }
}
Here is part of the generated cfdg (with a modified dot shape, based on guigui's Captaine Archibald Haddock)
CF::Background = [b -1]

startshape phil_pai

shape dot
  rule 100{dot[r 7]}
  rule 10{dot[s 1.09 1 a -.1]}
  rule 10{dot[s 1.09 1 a -.1]}
  rule {TRIANGLE[]}
  rule {CIRCLE[]}
  rule {SQUARE[]}

import data.cfdg
The artist is my old mate Philip Sutton RA

Sunday, 17 June 2012

A custom shape for my pixelation library

Here is a che.cfdg file generated by my pixelation library, but edited to use wavy triangles in place of circles for the dots (makes for a slightly darker image). Definition of che shape is in data.cfdg (but that's a big file, with lots of dots!).
CF::Background = [b -1]

TTOP = sin(30)/sqrt(3)

startshape che

path triangle {              
    MOVETO(-0.5, -TTOP)
    loop 0, 3 [r 120]{ 
    CURVETO(0, -TTOP, -0.25, -0.1) 
    CURVETO(0.5, -TTOP, CF::Continuous)
    }
    CLOSEPOLY()
    FILL[]
}

shape dot{triangle[]}

import data.cfdg

Friday, 15 June 2012

Pixelation in processing using cfdg

Well this is pretty weird, pointless may'be, but I've created a processing library that can pixelate both png and jpg images. Library exports and runs a cfdg file (CF3) to to produce and display the pixelated image. OK perhaps there is a point, cfdg can produce high resolution images at almost any scale (that makes sense). Here is an example, I've posted the library on github:-
import pde2cfdg.*;

/**
 * Two cfdg files are written to the sketch folder one for design one for data,
 * this means it easier to edit the design (eg to replace CIRCLE with a custom shape)
 * The output png file is written to the sketch folder,
 */

ProcessingToCF cfdg;
int dotSize = 3;
void setup() {
  size(1280, 1024);
  background(255);
  colorMode(HSB, 1.0);
  cfdg = new ProcessingToCF(this);
  cfdg.setDotSize(dotSize);
  cfdg.setPathToCFDG("/home/tux/CF3/cfdg");        
  cfdg.getInput();
  cfdg.writeCFDG();
}

void draw() {
  if (cfdg.finished()) {            
    PImage img = loadImage(cfdg.outFile);
    image(img, 0, 0, img.width, img.height);
    // background(img); // preferred but blows up if output image isn't the correct size
    // noLoop();
  }
}

void keyReleased() {
  switch(key) {
  case 'r':
    cfdg.setDotSize(dotSize);
    cfdg.writeCFDG();
    break;
  case '1':
  case '2':
  case '3':
  case '4':
  case '5':
  case '6':
    dotSize = key - 48;
    break;
  }
}
I can confirm I own copyright to this and the original image which is a photo of a cross for mariners at Freshwater West beach, Pembrokeshire. The library is loosely based on this idea by guigui.

Wednesday, 13 June 2012

Porting pyglet to python 3.2

This seems to pretty straightforward, since if you hg clone the development version of pyglet (version 1.2), the built in setup.py will (when run with python3.2) do the py2to3 conversion for you. However the examples are probably best hand edited (you will learn syntax changes, especially if you use use an intelligent ide like eric5). Here is my modified events.py, enhanced to feature python3 string format. The main change from the original here is that for python3 print is now a function.

#!/usr/bin/env python3.2
# ----------------------------------------------------------------------------
# pyglet
# Copyright (c) 2006-2008 Alex Holkner
# All rights reserved.
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions 
# are met:
#
#  * Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
#  * Redistributions in binary form must reproduce the above copyright 
#    notice, this list of conditions and the following disclaimer in
#    the documentation and/or other materials provided with the
#    distribution.
#  * Neither the name of pyglet nor the names of its
#    contributors may be used to endorse or promote products
#    derived from this software without specific prior written
#    permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# ----------------------------------------------------------------------------

'''
'''

__docformat__ = 'restructuredtext'
__version__ = '$Id$'

import pyglet
from pyglet.window import key
from pyglet.window import mouse

window = pyglet.window.Window()

@window.event
def on_key_press(symbol, modifiers):
    if symbol == key.A:
        print('The "A" key was pressed.')
    elif symbol == key.LEFT:
        print('The left arrow key was pressed.')
    elif symbol == key.ENTER:
        print('The enter key was pressed.')

@window.event
def on_mouse_press(x, y, button, modifiers):
    if button == mouse.LEFT:
        print('The left mouse button was pressed x = {0}, y = {1} .'.format(x, y))

@window.event
def on_draw():
    window.clear()

pyglet.app.run()

Wednesday, 6 June 2012

Ben Tilbert-Steel (updated for processing-2.0a6)

My povwriter2 library is now working well with processing-2.0a6, and includes a built in ArcBall and mouse wheel zoom (requires use of ArcBall), to record the sketch press the record button or ('r' key especially when button is hidden). Selecting a particular Hue eg Hue.STEEL, auto-selects the Finish.STEEL. Edit the generated ini file to do offline ray tracing at higher quality settings.

   1 /** 
   2  * Copyright (c) 2012 Martin Prout
   3  * 
   4  * This demo & library is free software; you can redistribute it and/or
   5  * modify it under the terms of the GNU Lesser General Public
   6  * License as published by the Free Software Foundation; either
   7  * version 2.1 of the License, or (at your option) any later version.
   8  * 
   9  * http://creativecommons.org/licenses/LGPL/2.1/
  10  * 
  11  * This library is distributed in the hope that it will be useful,
  12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14  * Lesser General Public License for more details.
  15  * 
  16  * You should have received a copy of the GNU Lesser General Public
  17  * License along with this library; if not, write to the Free Software
  18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  19  */
  20 
  21 import povexport2.ui.arcball.*;
  22 import povexport2.ui.*;
  23 import povexport2.*;
  24 import povexport2.povwriter.*;
  25 import lsystem.Grammar;
  26 import lsystem.SimpleGrammar;              
  27 
  28 
  29 /**
  30  * A 3D LSystem example with a SimpleGrammar (if you want to do a tree use StochasticGrammar)
  31  * Relies on the processing primitive box, and thereafter it makes sense to use Processing
  32  * translate and rotate (cf my 2D eamples where I use trignometry rather than these tools)
  33  * Uses 'conventional 3D grammar'. Features PeasyCam to allow easy manipulation of the object.
  34  * To create "Ben Tilbert" set theta to 90.5 deg and phi to 89.5
  35  */
  36 
  37 ArcBall arcball;
  38 Grammar grammar;
  39 PovExporter export;
  40 float distance = 200;
  41 int depth = 4;
  42 float theta = radians(89.5);
  43 float phi = radians(90.5);
  44 String production = "";
  45 
  46 void setup() {
  47   size(1280, 1024, P3D); 
  48   export = new PovExporter(this);
  49   export.chooseTemplate();  
  50   arcball = new ArcBall(this);
  51   export.showGui("false");   // hide record button (setting is saved)
  52   export.createIniFile(dataPath("hilbert.ini"), Quality.MEDIUM);
  53   setupGrammar();
  54   noStroke();
  55 }
  56 
  57 void setupGrammar() {
  58   grammar = new SimpleGrammar(this, "X");   // this only required to allow applet to call dispose()
  59   grammar.addRule('X', "^<XF^<XFX-F^>>XFX&F+>>XFX-F>X->");
  60   production = grammar.createGrammar(depth);
  61   distance *= pow(0.5, depth);
  62 }
  63 
  64 void draw() {
  65   if (export.traced()) { // begin tracing
  66     display();
  67   } 
  68   else {
  69     background(0);
  70     lights();
  71     export.beginRaw(dataPath("hilbert.pov"));
  72     translate(width / 2, height / 2, -width / 5);
  73     arcball.update();
  74     render();
  75     export.endRaw();
  76   }
  77 }
  78 
  79 void 
  80 render() {
  81   translate(-distance*3.5, distance*3.5, -distance*3.5);  // center the hilbert 
  82   export.setHue(Hue.STEEL); 
  83   lightSpecular(204, 204, 204); 
  84   specular(255, 255, 255); 
  85   shininess(1.0); 
  86   CharacterIterator it = grammar.getIterator(production);
  87   for (char ch = it.first(); ch != CharacterIterator.DONE; ch = it.next()) {
  88     switch (ch) {
  89     case 'F': 
  90       translate(0, distance/-2, 0);
  91       box(distance/9, distance, distance/9);
  92       translate(0, distance/-2, 0);
  93       break;
  94     case '-':
  95       rotateX(theta);
  96       break;
  97     case '+':
  98       rotateX(-theta);
  99       break;
 100     case '>':
 101       rotateY(theta);
 102       break;
 103     case '<':
 104       rotateY(-theta);
 105       break;
 106     case '&':
 107       rotateZ(-phi);
 108       break;
 109     case '^':
 110       rotateZ(phi);
 111       break;
 112     case 'X':
 113       break;  
 114     default:
 115       System.err.println("character " + ch + " not in grammar");
 116     }
 117   }
 118 }
 119 
 120 void display() {
 121   background(loadImage(dataPath("hilbert.png")));
 122 }
 123 

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