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, 27 August 2011

Experiments with numpy and pyprocessing (a revised voronoi)

This sketch does not appear to benefit from the use of numpy, but it is on my path to learning how to use numpy in more intensive pixel manipulation, (currently other experiments on GrayScott diffusion are not going too well. I'm failing to dynamically update pixels, which is frustrating because otherwise the code seems good using pyunit from eric5). I thought about trying processing.py but I don't think I can use numpy there, possibly directly using jython, but that all that seems diversionary?

"""
Copyright (c) 2011 Martin Prout
 
This example is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
http://creativecommons.org/licenses/LGPL/2.1/
NB: use of numpy does not seem to speed things up, however is probaby more sparing
of system resources (memory in particular)

np_voronoi.py example
"""

from pyprocessing import *
from random import randint
import numpy as np

def setup():
    """
    pyprocessing setup
    """
    size(800,  600)
    n = randint(200, 300) # number of cells
    nx = np.random.randint(width, size=(n))      # numpy does randint(low, high) but high is excluded
    ny = np.random.randint(height, size= (n))   # if high = None, like here low defaults to randint(0, low)
    nh = np.random.randint(256, size=(3,  n))

    for y in xrange(height):
        for x in xrange(width):
            # find the closest cell center
            dmin = hypot_squared(width - 1, height - 1)          # more intelligible version
            #dmin = ((width - 1) * (width - 1)) + ((height - 1) * (height - 1)) # optimized version?
            j = -1
            for i in xrange(n):
                d = hypot_squared((nx[i] - x),  (ny[i] - y))           # more intelligible version
                #d = ((nx[i] - x) * (nx[i] - x)) + ((ny[i] - y) * (ny[i] - y)) # optimized version?
                if d < dmin:
                    dmin = d
                    j = i
            setScreen(x, y, color(nh[0][j], nh[1][j], nh[2][j])) 

def hypot_squared(a, b):
    """
    Must be cheaper to calculate than hypot
    """
    return (a * a) + (b * b)            

run()



Thursday, 18 August 2011

Rules based generation of processing sketches

In a way somewhat akin to the contextfreeart (cfdg) rules Adam Parrish has explored the possibility of such a grammar and rules to generate processing sketches.  I have played with extended his java code to do the following:-

  1. Explore java jdk 7.0 coin features (switch on String and implied generics diamond)
  2. Add weighting to the rules
  3. Extend to 3D
  4. Extend to pyprocessing
  5. Explore using NetBeans 7.0.1 git plugin
See the results at Github

I found that I could clone and pull from GitHub within NetBeans, however I needed to use command line git to push changes back to Master (on GitHub).
I think the switch on String is really neat (replaces a nasty chain of if else), if you are using NetBeans-7.0.1 with library and source set to jdk 1.7.0 the ide suggests and completes the changes for you. The 3D works best with P3D mode, or with OPENGL using the disable depth test hint. I had the idea of immediately running the generated sketches, I thought this would work best with pyprocessing (no antlr/compile stages required) so I re-factored the lot to pure python.

Wednesday, 10 August 2011

Animation of PovRAY ray traced processing sketches

There are plenty examples of processing sketches ray traced using sunflow converted to animations, so I thought I would show how you could do the same using my povwriter library to export the processing sketch to PovRAY format. Then I used PovRAY to create a series of images (animation frames), that I stitched together using ffmpeg. I'm not sure how it is done on Windows or the Mac, but for linux you only need enter povray ttest.ini on the command line to set the recording going (you will need ttest.pov in the same directory as the ini file in this case.

Here is ttest.ini file:-

; POV-Ray animation ini file

Input_File_Name="ttest.pov"

Initial_Frame=1
Final_Frame=360
Initial_Clock=0
Final_Clock=1

Cyclic_Animation=on
Pause_when_Done=off

Here is the relevant bit of the ttest.pov file:-

// -----------------------------Adjust the processing scene
translate<TransXP5, TransYP5, TransZP5>
rotate<RotXP5, clock * 360, RotZP5>
scale<ScaleP5, ScaleP5, ScaleP5>
}

here is the commands to stitch the images together:-
ffmpeg -f image2 -i ttest%3d.png movie.mp4


TTest from monkstone on Vimeo.

Tuesday, 2 August 2011

3DTurtle interface for my LSystems library

I've created a wrapper for my LSystems library that supports a 3D turtle as a Turtle3D interface, with one implementation RodTurtle. So now instead of rotateX() we have yaw(), rotateY() we have pitch() and rotateZ() we have roll(). RodTurtle relies on processing to hold state, therefore you should use pushMatrix() and popMatrix() to preserve/restore state (as for example in bracketed LSystems). It does not make sense to create a TurtleStack, until you have an implementation that doesn't use processings built in affine transforms (cf the standard Turtle implementation).

import lsystem.util.*;
import lsystem.turtle.*;
import lsystem.collection.*;
import lsystem.*;

import processing.opengl.*;
Grammar grammar;
Turtle3D turtle;
float distance = 300;  
int depth = 2;

// adjust centre of hilbert
float[] adjust = {
  0.0, 0.5, 1.5, 3.5, 7.5
};

// adjust resolution with depth (ie decrease)
int[] detail = {
  36, 24, 18, 15, 12
};
int THETA = 90;   // int for degree float for radians
int PHI = 90;
String production = "";

void setup() { 
  size(800, 600, OPENGL);
  configureOpenGL();
  turtle = new RodTurtle(this);
  LUT.initialize(); 
  setupGrammar();
  float fov = PI/3.0; 
  float cameraZ = (height/2.0) / tan(fov/2.0); 
  perspective(fov, float(width)/float(height), cameraZ/2.0, cameraZ*2.0); 
  noStroke();
}

void configureOpenGL() {
  hint(ENABLE_OPENGL_4X_SMOOTH);
  hint(DISABLE_OPENGL_ERROR_REPORT);
}

/**
 * Encapulates the lsystem rules, and calls the grammar to create the production rules
 * depth is number of repeats, and distance is adjusted according to the number of repeats
 */

void setupGrammar() {
  grammar = new SimpleGrammar(this, "A");   // this only required to allow applet to call dispose()
  grammar.addRule('A', "B>F<CFC<F>D+F-D>F<1+CFC<F<B1^");
  grammar.addRule('B', "A+F-CFB-F-D1->F>D-1>F-B1>FC-F-A1^");
  grammar.addRule('C', "1>D-1>F-B>F<C-F-A1+FA+F-C<F<B-F-D1^");
  grammar.addRule('D', "1>CFB>F<B1>FA+F-A1+FB>F<B1>FC1^");
  production = grammar.createGrammar(depth);
  if (depth > 0) {
    distance *= 1/(pow(2, depth) - 1);
  }
}

void draw() {
  background(20, 20, 200);
  lights();
  pushMatrix();  
  translate(width/2, height/2, 0);
  rotateX(LUT.sin(frameCount));
  rotateY(LUT.cos(frameCount));
  pushMatrix();
  translate(-distance * adjust[depth], distance/2 * adjust[depth], -distance/2 * depth);   
  render();
  popMatrix();
  popMatrix();
}


/**
 * Render wraps the drawing logic; draws a sphere at origin,
 * followed by successive turtle.draw(distance) as a capped
 * cylinder to complete the hilbert according to lsystem rules 
 * (ie whenever there is an 'F').
 */

void render() {
  int repeats = 1;  
  fill(191, 191, 191);
  ambientLight(80, 80, 80);
  directionalLight(100, 100, 100, -1, -1, 1);
  ambient(122, 122, 122); 
  lightSpecular(30, 30, 30); 
  specular(122, 122, 122); 
  shininess(0.7); 
  CharacterIterator it = grammar.getIterator(production);
  for (char ch = it.first(); ch != CharacterIterator.DONE; ch = it.next()) {
    switch (ch) {
    case 'F': 
      turtle.draw(distance); 
      break;
    case '+':
      turtle.yaw(THETA * repeats);
      repeats = 1;
      break;
    case '-':
      turtle.yaw(-THETA * repeats);
      repeats = 1;
      break;  
    case '>':
      turtle.pitch(THETA * repeats);
      repeats = 1;
      break;
    case '<':
      turtle.pitch(-THETA * repeats);
      repeats = 1;
      break;
    case '^':
      turtle.roll(PHI * repeats);
      repeats = 1;
      break;
    case '1':
      repeats += 1;
      break;  
    case 'A':
    case 'B':
    case 'C':
    case 'D': 
      break;
    default:
      System.err.println("character " + ch + " not in grammar");
    }
  }
}


void keyReleased() {
  switch(key) {
  case '+':
    if (depth <= 3) { // guard against a depth we can't handle
      depth++;
      distance = 300;
      setupGrammar();
    }
    break;
  case '-':
    if (depth >= 2) {
      depth--;
      distance = 300;
      setupGrammar();
    }
    break;
  }
}

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