Experiments with ruby-processing (processing-2.2.1) and JRubyArt for processing-3.0

Wednesday, 8 September 2010

Experimental 3D Context Free DSL in ruby-processing, a bit of a monster?

This is at fairly experimental stage, I need to decide how to order rotations/translations. At the moment order is fixed by the library script, so it doesn't matter what order they are entered you get the default order!!!

This library cannot compete with StructureSynth which is a much more refined and complete program. However if you are used to ruby it may be easier to write your rules in ruby, rather than in the EisenScript syntax. The funky extra thing is, because it is based on processing you have the animation possibilities of the 'draw' loop. My monster in some directions could be seen as a beating heart.

To use the library, create a folder for you work say "work", create a sub-folder "library" and sub-sub-folder "test_free" (or whatever better name you can think of for the library). Put the library "test_free.rb" in the sub-sub-folder. Write you sketches in the "work" directory, and run them with "rp5 run my_sketch.rb". If you want to do it the really neat way use JEdit as your editor and my macro and commando tools, then you can run the sketch from the editor. The link to the tools describes live editing, which I haven't tried with this library so I would recommend just using the run mode for now.

If you are not a ruby meddler just get StructureSynth, and learn the EisenScript language. Otherwise you will need to get ruby-processing see link in my blog header to see how. My blog header also has link to the original Jeremy Ashkenas context-free.rb on github.

The test_free.rb library


# A Context-Free library for Ruby-Processing, inspired by
# contextfreeart.org and StructureSynth
# Built on Jeremy Ashkenas context free DSL script

module Processing

  class ContextFree
 

    include Processing::Proxy

    attr_accessor :rules, :app, :xr, :yr, :zr

    AVAILABLE_OPTIONS = [:x, :y, :z, :rx, :ry, :rz, :size, :color, :hue, :saturation, :brightness, :alpha]
    HSB_ORDER         = {:hue => 0, :saturation => 1, :brightness => 2, :alpha => 3}

    # Define a context-free system. Use this method to create a ContextFree
    # object. Call render() on it to make it draw.
    def self.define(&block)
      cf = ContextFree.new
      cf.instance_eval &block
      cf
    end


    # Initialize a bare ContextFree object with empty recursion stacks.
    def initialize
      @app          = $app
      @graphics     = $app.g
      @finished     = false
      @rules        = {}
      @rewind_stack = []
      @matrix_stack = []
      @xr = 0
      @yr = 0
      @zr = 0
    end


    # Create an accessor for the current value of every option. We use a values
    # object so that all the state can be saved and restored as a unit.
    AVAILABLE_OPTIONS.each do |option_name|
      define_method option_name do
        @values[option_name]
      end
    end


    # Here's the first serious method: A Rule has an
    # identifying name, a probability, and is associated with
    # a block of code. These code blocks are saved, and indexed
    # by name in a hash, to be run later, when needed.
    # The method then dynamically defines a method of the same
    # name here, in order to determine which rule to run.
    def rule(rule_name, prob=1, &proc)
      @rules[rule_name] ||= {:procs => [], :total => 0}
      total = @rules[rule_name][:total]
      @rules[rule_name][:procs] << [(total...(prob+total)), proc]
      @rules[rule_name][:total] += prob
      unless ContextFree.method_defined? rule_name
        self.class.class_eval do
          eval <<-METH
            def #{rule_name}(options)
              merge_options(@values, options)
              pick = determine_rule(#{rule_name.inspect})
              @finished = true if @values[:size] < @values[:stop_size]
              unless @finished
                get_ready_to_draw
                pick[1].call(options)
              end
            end
          METH
        end
      end
    end


    # Rule choice is random, based on the assigned probabilities.
    def determine_rule(rule_name)
      rule = @rules[rule_name]
      chance = rand * rule[:total]
      pick = @rules[rule_name][:procs].select {|the_proc| the_proc[0].include?(chance) }
      return pick.flatten
    end


    # At each step of the way, any of the options may change, slightly.
    # Many of them have different strategies for being merged.
    def merge_options(old_ops, new_ops)
      return unless new_ops
      # Do size first
      old_ops[:size] *= new_ops[:size] if new_ops[:size]
      new_ops.each do |key, value|
        case key
        when :size
        when :x, :y, :z
          old_ops[key] = value * old_ops[:size]
        when :rz, :ry, :rx
          old_ops[key] = value * (Math::PI / 180.0)
        when :hue, :saturation, :brightness, :alpha
          adjusted = old_ops[:color].dup
          adjusted[HSB_ORDER[key]] *= value
          old_ops[:color] = adjusted
        when :width, :height
          old_ops[key] *= value
        when :color
          old_ops[key] = value
        else # Used a key that we don't know about or trying to set
          merge_unknown_key(key, value, old_ops)
        end
      end
    end


    # Using an unknown key let's you set arbitrary values,
    # to keep track of for your own ends.
    def merge_unknown_key(key, value, old_ops)
      key_s = key.to_s
      if key_s.match(/^set/)
        key_sym = key_s.sub('set_', '').to_sym
        if key_s.match(/(brightness|hue|saturation|alpha)/)
          adjusted = old_ops[:color].dup
          adjusted[HSB_ORDER[key_sym]] = value
          old_ops[:color] = adjusted
        else
          old_ops[key_sym] = value
        end
      end
    end

    # Doing a 'split' saves the context, and proceeds from there,
    # allowing you to rewind to where you split from at any moment.
    def split(options=nil, &block)
      save_context
      merge_options(@values, options) if options
      yield
      restore_context
    end

    # Saving the context means the values plus the coordinate matrix.
    def save_context
      @rewind_stack.push @values.dup
      @matrix_stack << @graphics.get_matrix
    end

    # Restore the values and the coordinate matrix as the recursion unwinds.
    def restore_context
      @values = @rewind_stack.pop
      @graphics.set_matrix @matrix_stack.pop
    end

    # Rewinding goes back one step.
    def rewind
      @finished = false
      restore_context
      save_context
    end

    # Render the is method that kicks it all off, initializing the options
    # and calling the first rule.
    def render(rule_name, starting_values={})
      @values = {:x => 0, :y => 0, :z => 0,
                 :rz => 0, :ry => 0, :rx => 0,
                 :size => 1, :width => 1, :height => 1,
                 :start_x => width/2, :start_y => height/2, :start_z => 0,
                 :color => [0.5, 0.5, 0.5, 1],
                 :stop_size => 1.5}
      @values.merge!(starting_values)
      @finished = false
      @app.reset_matrix
      @app.rect_mode CENTER
      @app.ellipse_mode CENTER
      @app.no_stroke
      @app.color_mode HSB, 1.0
      @app.translate @values[:start_x], @values[:start_y], @values[:start_z]
      self.send(rule_name, {})
    end
 
    def rotate_x rt
      @xr = rt
    end
    def rotate_y rt
      @yr = rt
    end
    def rotate_z rt
      @zr = rt
    end

    # Before actually drawing the next step, we need to move to the appropriate
    # location.
    def get_ready_to_draw
      @app.translate(@values[:x], @values[:y], @values[:z])
      @app.rotate_x(@values[:rx] + xr)
      @app.rotate_y(@values[:ry] + yr)
      @app.rotate_z(@values[:rz] + zr)
    end


    # Compute the rendering parameters for drawing a shape.
    def get_shape_values(some_options)
      old_ops = @values.dup
      merge_options(old_ops, some_options) if some_options
      @app.fill *old_ops[:color]
      return old_ops[:size], old_ops
    end


    # The shape primitives are sphere and cube
    def cube(some_options=nil)
      size, options = *get_shape_values(some_options)
      rotz = options[:rz]
      roty = options[:ry]
      rotx = options[:rx]
      @app.rotate_x rotx unless rotx.nil?
      @app.rotate_y roty unless roty.nil?
      @app.rotate_z rotz unless rotz.nil?
      @app.translate(options[:x]  * size, options[:y] * size , options[:z]  * size)
      @app.box(size)
      @app.rotate_z(-1 * rotz) unless rotz.nil?  # unwind rotations in an ordered way
      @app.rotate_y(-1 * roty) unless roty.nil?
      @app.rotate_x(-1 * rotx) unless rotx.nil?    
   
    end


    def sphere(some_options=nil)
      size, options = *get_shape_values(some_options)
      rotz = options[:rz]
      roty = options[:ry]
      rotx = options[:rx]
      @app.rotate_x rotx unless rotx.nil?
      @app.rotate_y roty unless roty.nil?
      @app.rotate_z rotz unless rotz.nil?

       @app.translate(options[:x]  * size, options[:y] * size , options[:z]  * size)

      @app.sphere_detail 10
      @app.sphere(size)
      @app.rotate_z(-1 * rotz) unless rotz.nil?  # unwind rotations in an ordered way
      @app.rotate_y(-1 * roty) unless roty.nil?
      @app.rotate_x(-1 * rotx) unless rotx.nil?    
    end
  end
end




My Test Script monster.rb



load_libraries :test_free, :control_panel

attr_reader :xrot, :yrot, :zrot

def setup_the_spiral
  @spiral = ContextFree.define do
    rule :monster do
      5.times do |i|
        split do
        cone :ry => 72 * i
        rewind
        end
      end
    end

    rule :cone do                       # two equally weighted cone rules creates the beat
      sphere :brightness => 1
      cone :size => 0.96, :y => -0.24
    end
  
    rule :cone do
      sphere :brightness => 1
      cone :size => 0.97, :y => -0.28
    end

  end
end

def setup
  size 800, 800, P3D
  configure_control
  smooth
  setup_the_spiral
end

def configure_control
  control_panel do |c|
    c.title = "Attitude Control"
    c.slider :xrot, -3.1..3.1, 0.5
    c.slider :yrot, -3.1..3.1, 0.5
    c.slider :zrot, -3.1..3.1, 1.0
  end
end
def draw
  background 0.8
  lights
  @spiral.render :monster, :start_x => 0, :start_y => 10, :start_z => -30, :size => height/200, :stop_size => 1, :color => [0, 0.8, 0.8]
  @spiral.rotate_x xrot
  @spiral.rotate_y yrot
  @spiral.rotate_z zrot    
end



 


Saturday, 4 September 2010

Using the control panel and Toxi Processing Libraries in ruby processing

Here is a sketch that shows how easy it is to add controls to your sketch in ruby-processing.


#
# <p>GrayScottControl uses the seedImage() method to use a bitmap as simulation seed.
# In this demo the image is re-applied every frame and the user can adjust the
# F coefficient of the reaction diffusion to produce different patterns emerging
# from the boundary of the bitmapped seed. Unlike some other GS demos provided,
# this one also uses a wrapped simulation space, creating tiled patterns.</p>
#
# <p><strong>usage:</strong></p>
# <ul>
# <li>click + drag mouse to locally disturb the simulation</li>
# <li>Use slider to adjust the F parameter of the simulation</li>
# <li>press reset! to do what?</li>
# <li>press save_graycsott to do save</li>
# </ul>
#

#
# Copyright (c) 2010 Karsten Schmidt (rubified by Martin Prout)
#
# This demo & library 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/
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
#

class GrayScottControl < Processing::App
  load_libraries 'simutils','toxiclibscore','colorutils','control_panel'
  include_package "toxi.sim.grayscott"
  include_package "toxi.math"
  include_package "toxi.color"

  attr_reader :gs, :tone_map, :img, :set_f

  def setup
    size 256, 256
    setup_control
    @gs = GrayScott.new width, height, true
    @img = load_image "two_prong.png"
    # create a duo-tone gradient map with 256 steps
    # NB: use '::' in place of '.' here
    @tone_map = ToneMap.new(0, 0.33, NamedColor::CRIMSON, NamedColor::WHITE, 256)
  end

  def draw
    @gs.seed_image(img.pixels, img.width, img.height)
    @gs.set_rect(mouse_x, mouse_y, 20, 20) if mouse_pressed?
    load_pixels
    10.times { @gs.update(1) }
    # read out the V result array
    # and use tone map to render colours
    gs.v.length.times do |i|
      pixels[i]=tone_map.getARGBToneFor(gs.v[i])  # NB: don't camel case convert here
    end
    @gs.setF(0.02 + set_f * 0.001)
    update_pixels
  end

  def setup_control
    control_panel do |c|
      c.title = "Control Panel"
      c.slider :set_f, 0..9, 8
      c.button :save_graycsott
      c.button :reset!
    end
  end

  def save_graycsott
    no_loop
    save_frame "toxi.png"
    loop
  end

  def reset!
    @gs.reset
  end

end




Thursday, 2 September 2010

Tone map example of Gray-Scott diffusion using toxiclibs in ruby processing

Another rubified example, showing how to use some of the toxiclibs in ruby-processing. Any observations/questions could be made on the processing alternative implementations forum, which I often watch.


#
# <p>GrayScottToneMap shows how to use the ColorGradient & ToneMap classes of the
# colorutils package to create a tone map for rendering the results of
# the Gray-Scott reaction-diffusion.</p>
#
# <p><strong>Usage:</strong><ul>
# <li>click + drag mouse to draw dots used as simulation seed</li>
# <li>press any key to reset</li>
# </ul></p>
#

#
# Copyright (c) 2010 Karsten Schmidt
#
# This demo & library 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/
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
#

class GrayScottToneMap < Processing::App
  load_libraries 'simutils','toxiclibscore','colorutils'
  include_package "toxi.sim.grayscott"
  include_package "toxi.math"
  include_package "toxi.color"
 
  NUM_ITERATIONS = 10

  attr_reader :gs, :tone_map

  def setup()
    size(256,256)
    @gs= GrayScott.new width,height, false
    @gs.set_coefficients 0.021, 0.076, 0.12, 0.06
    # create a color gradient for 256 values
    grad = ColorGradient.new
    # NamedColors are preset colors, but any TColor can be added
    # see javadocs for list of names:
    # http://toxiclibs.org/docs/colorutils/toxi/color/NamedColor::html
    # NB: use '::' in place of '.' here for these java constants
    grad.add_color_at(0, NamedColor::BLACK)
    grad.add_color_at(128, NamedColor::RED)
    grad.add_color_at(192, NamedColor::YELLOW)
    grad.add_color_at(255, NamedColor::WHITE)
    # this gradient is used to map simulation values to colors
    # the first 2 parameters define the min/max values of the
    # input range (Gray-Scott produces values in the interval of 0.0 - 0.5)
    # setting the max = 0.33 increases the contrast
    @tone_map = ToneMap.new 0, 0.33, grad
  end
 
  def draw()    
    @gs.set_rect(mouse_x, mouse_y, 20, 20) if mouse_pressed?
    load_pixels
    # update the simulation a few time steps
    NUM_ITERATIONS.times { @gs.update(1) }
    # read out the V result array
    # and use tone map to render colours
    gs.v.length.times do |i|
      pixels[i]=tone_map.getARGBToneFor(gs.v[i])  # NB: don't camel case convert here
    end
    update_pixels
  end
   
  def key_pressed
    @gs.reset()
  end

 
end



 

Wednesday, 1 September 2010

Another Example of Using Toxi Processing Libraries

Here is another rubified example, a sophisticated variant of Gray-Scott diffusion, using toxis processing libraries, this time using a bit mapped seed:-


#
# <p>GrayScottImage uses the seedImage() method to use a bitmap as simulation seed.
# In this demo the image is re-applied every frame and the user can adjust the
# F coefficient of the reaction diffusion to produce different patterns emerging
# from the boundary of the bitmapped seed. Unlike some other GS demos provided,
# this one also uses a wrapped simulation space, creating tiled patterns.</p>
#
# <p><strong>usage:</strong></p>
# <ul>
# <li>click + drag mouse to locally disturb the simulation</li>
# <li>press 1-9 to adjust the F parameter of the simulation</li>
# <li>press any other key to reset</li>
# </ul>
#

#
# Copyright (c) 2010 Karsten Schmidt
#
# This demo & library 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/
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
#

class GrayScottImage < Processing::App
  load_libraries 'simutils','toxiclibscore','colorutils'
  include_package "toxi.sim.grayscott"
  include_package "toxi.math"
  include_package "toxi.color"

  attr_reader :gs, :tone_map, :img

  def setup
    size 256, 256
    @gs = GrayScott.new width, height, true
    @img = load_image "ti_yong.png"
    # create a duo-tone gradient map with 256 steps
    # NB: use '::' in place of '.' here for these java constants
    @tone_map = ToneMap.new(0,  0.33, NamedColor::CRIMSON, NamedColor::WHITE, 256)
  end

  def draw
    @gs.seed_image(img.pixels, img.width, img.height)
    @gs.set_rect(mouse_x, mouse_y, 20, 20) if mouse_pressed?
    load_pixels
    10.times { @gs.update(1) }
    # read out the V result array
    # and use tone map to render colours
    gs.v.length.times do |i|
      pixels[i]=tone_map.getARGBToneFor(gs.v[i])  # NB: don't camel case convert here
    end
    update_pixels
  end

  def key_pressed
    case key
    when '1', '9', '3', '2', '4', '6', '5', '7', '8'
      @gs.setF(0.02 + (key.to_i - 1) * 0.001)
    when 's'
      save_frame "toxi.png"
    else
      @gs.reset()
    end
  end

end


 


I found that the image 'needed' to be 'disturbed' by a mouse-click/drag, before the numeric controls kicked in (it made me doubt my coding originally).

Using the Toxi Processing Libraries in ruby processing

Toxi aka Karsten Schmidt has created some fantastic libraries for processing that make some otherwise difficult things very easy. Here is just one example that I've tried that could be very useful in generative art.  To use processing libraries in your ruby processing sketch place each jar in folder of the same name as the jar. Then put that folder in library folder, where you've saved the sketch.


#
# <p>Hello Gray-Scott is a very basic demonstration of the underlying
# reaction-diffusion simulation. This model can be used to produce
# a wide variety of patterns, both static and animated and is therefore
# well suited for being combined with other generative techniques.</p>
#
# <p><strong>usage:</strong></p>
# <ul>
# <li>click + drag mouse to draw dots used as simulation seed</li>
# <li>press any key to reset</li>
# </ul>
#

#
# Copyright (c) 2010 Karsten Schmidt
#
# This demo & library 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/
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
#

class HelloGrayScott < Processing::App
  load_libraries 'simutils','toxiclibscore'
  include_package "toxi.sim.grayscott"
  include_package "toxi.math"

  attr_reader :gs

  def setup()
    size(256,256)
    @gs=GrayScott.new width, height, false
    @gs.set_coefficients 0.023, 0.074, 0.095, 0.03
  end

  def draw()
    @gs.set_rect mouse_x, mouse_y, 20, 20 if mouse_pressed?
    load_pixels
    10.times { @gs.update(1) }

    gs.v.length.times do |i|
        val = gs.v[i]*768
        min = (255 <= val)? 255 : val       # processing convenience min(x, y) doesn't work for me
        col= 255 - min.to_i
        pixels[i]=col<<16|col<<8|col|0xff000000
      end
    update_pixels
  end

  def key_pressed
    @gs.reset
  end

end






Reaction Diffusion at Wikipedia

Other interesting links:-

A 3D example in java

A very nice 2D example

http://toxiclibs.org/2010/02/simutils-grayscott/

Tuesday, 24 August 2010

Steps to Get Preston Lees Starfield Ruby Processing App Running on Linux

Update 13th October 2011, there should be no need for this since ruby-processing version 1.0.10, linux no longer requires fullscreen to run opengl, further 64 bit system should be automatically detected.

The original screencast can be seen here http://www.prestonlee.com/2010/05/17/3d-osx-applications-with-ruby-processing-screencast/

If you are up and running with GitHub you may wish to download the code directly from Preston Lees GitHub (and modify the starfield.rb as below) otherwise follow instructions below:-


1. Install ruby processing (follow the instructions at http://wiki.github.com/jashkenas/ruby-processing/getting-started)

2. You should create a directory starfield, and create a sub directory data

3. Download Univers66.vlw.gz from http://github.com/preston/Starfield and put it in the data folder

4. Create starfield.rb, star.rb and asychronous_object.rb in the starfield directory here is the code:-




5. In a terminal cd to the starfield directory and enter rp5 run starfield.rb

If you want export the app you will need to modify starfield.rb to require asychronous_object.rb.

Because there is currently an issue with resizing opengl applications with linux you will need to run the app in full screen
mode, use the escape key to quit full screen mode. If it hangs alt tab to another console pgrep java to get the offending process id
the issue kill -s KILL pid where pid is the process id.

Possible issues are:-

Your OS is hogging the graphics driver (solution turn down the level of eye candy)
You don't have a working 3D graphics driver (solution install a 3D graphics driver)
You are running a 64 bit operating system see my last post

Here is a screen-shot of the app running on Kubuntu, with the desktop eye candy turned down.

Running Ruby- Processing Opengl Apps on a 64 bit box

Hardware Considerations

When I came to upgrading my linux-box recently, the obvious choice was a bare bones system with a dual core AMD 64 bit processor (cheap and powerful enough). I couldn't see any point in running a 32 bit operating system on it so I installed Kubuntu 64 bit OS which provides, as default a Nouveau graphics driver to support a NVIDIA graphics processor. This driver only supports 2D acceleration, and 3D acceleration is provided by software emulation (mesa driver, slow). However the Ubuntu distro gives you the option of installing proprietary NVIDIA drivers, either using the scripts provided by Ubuntu, or direct from NVIDIA (but you are warned not to !!). Do a bit of research before installing the latest drivers directly from NVIDIA, ideally you should be comfortable compiling a kernel, updating grub etc. I usually find myself compiling a custom kernel for some reason other, so I opted for the latest drivers from NVIDIA, but then I've been using linux for at least six years.

OpenGL drivers

Like vanilla (java) processing the native libraries for opengl included are 32 bit, which is absolutely as it should be, however I don't think it should not stay that way!!!!
Fortunately the 64 bit native libraries already available, they are just stuck in a jar.
Larry Kyrala produced a script to extract the relevant 64 bit *.so files for vanilla processing. I present a modified version here.
Famous last words "It Worked For Me", I offer no guarantees and you may need to further modify the script for your installation. Depending on where you install your gems you may need to have root authority to run the script.


#!/usr/bin/env ruby

########################
# fix-rp5-opengl.rb
# based on a script by
# Larry Kyrala for
# vanilla processing
# extracts 64-bit native linux binaries
# for opengl (properly backs-up 32-bit binaries)
########################

require 'fileutils'

# script to fix ruby-processing for 64-bit linux
rp5_dir = "/var/lib/gems/1.9.1/gems/ruby-processing-1.0.9"

library_dir = File.join(rp5_dir,"library","opengl","library");
backup_dir = File.join(library_dir,"original-native");
unpack_dir = File.join(library_dir,"unpack-amd64");
Dir.mkdir backup_dir unless File.exists?(backup_dir)
Dir.mkdir unpack_dir unless File.exists?(unpack_dir)

jars = Dir.glob(File.join(library_dir,"*.jar")).select {|f| f =~ /linux-amd64/ }
jars.each do |jar_file|
  system "unzip -o #{jar_file} -d #{unpack_dir}"
end  

libraries = Dir.glob(File.join(unpack_dir,"*.so"))
libraries.each do |so_file|
  src = File.join(library_dir,File.basename(so_file))
  unless File.exists?(File.join(backup_dir,File.basename(so_file)))
    FileUtils.mv(src, backup_dir)
  end
  FileUtils.cp(so_file, library_dir, :preserve => true)
end
 


Ruby-Processing Issue

Presently there is an unresolved opengl issue with sketch resizing with ruby-processing. In practice that means you can only run ruby-processing opengl sketches in full-screen mode on linux.
Adding the line at the beginning of the sketch
full_screen
is often all you need to do to get the sketch to run.

Followers

About Me

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