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

Monday 22 July 2013

Clobbering archived files in a github repository

Now largely thanks to moumar, we are good guys on ruby-processing because we no longer use unnecessary binaries in the ruby-processing repo (they are downloaded directly during autobuild process) but whoa! the download was 70Mb. So after some research I found unused binaries "jruby-complete.jar" "core.jar" etc are archived in the .git/object directory. So what to do, well fortunately there is this BFG tool that makes it easy to clobber the offending commits, but the references all get re-written so any forks should made anew. To make sure I have created a new repo (not a fork) from a clobbered mirrored clone of ruby-processing. The repo is now ca 10.75Mb vs ca 70Mb.
A couple of useful commands that came in handy in checking and setting remote.

git remote -v

git remote set-url origin https://github.com/monkstone/remote.git

Friday 19 July 2013

Fibonacci Sphere in Ruby Processing

# fibonacci_sphere.rb
# After a vanilla processing sketch by Jim Bumgardner
# http://www.openprocessing.org/sketch/41142
#
# Controls:
# 1. drag mouse to rotate sphere (uses builtin arcball library)
# 2. click mouse to toggle add box to sphere surface
# 3. press x, y, or z to constrain arcball rotation to that axis
#

load_library :arcball
import "arcball"

X = 0
Y = 1
Z = 2

PHI = (sqrt(5)+1) / 2 - 1   # golden ratio
GA = PHI * TWO_PI           # golden angle

KMAX_POINTS = 100000

attr_reader :pts, :rotation_x, :rotation_y, :nbr_points, :radius, :add_points
attr_reader :my_ball # for arcball rotation

def setup
  size(1024, 768, P3D)
  @my_ball = ArcBall.new(width/2.0, height/2.0, min(width - 20, height - 20) * 0.5)
  @rotation_x = 0
  @rotation_y = 0
  @nbr_points = 2000
  @radius = 0.8 * height / 2
  @add_points = true
  @pts = Array.new(KMAX_POINTS)
  init_sphere(nbr_points)
  background(0)
end

def draw
  if add_points
    @nbr_points += 1
    @nbr_points = min(nbr_points, KMAX_POINTS)
    init_sphere(nbr_points)
  end

  background 0
  lights
  ambient(200, 10, 10)
  ambient_light(150, 150, 150)
  translate(width/2.0, height/2.0, 0)
  update  # for arcball rotation
  render_globe
end

# arcball functionality ##################
##########################################

def update
  theta, x, y, z = my_ball.update
  rotate(theta, x, y, z)
end

def mouse_pressed
  my_ball.mouse_pressed(mouse_x, mouse_y)
end

def mouse_dragged
  my_ball.mouse_dragged(mouse_x, mouse_y)
end

def key_pressed
  case(key)
  when 'x'
    my_ball.select_axis(X)
  when 'y'
    my_ball.select_axis(Y)
  when 'z'
    my_ball.select_axis(Z)
  end
end

def key_released
  my_ball.select_axis(-1)
end
###########################################
# For Fibonacci Sphere
##################################

def render_globe
  push_matrix
  (0 .. min(nbr_points, pts.length)).each do |i|
    lat = pts[i].lat
    lon = pts[i].lon
    push_matrix
    rotate_y(lon)
    rotate_z(-lat)
    fill(200, 10, 10)
    translate(radius, 0, 0)
    box(4, 7, 7)
    pop_matrix
  end
  pop_matrix
end

def mouse_clicked
  @add_points = !add_points
end

SpherePoint = Struct.new(:lat, :lon) do
end

def init_sphere(num)
  (0 .. num).each do |i|
    lon = GA * i
    lon /= TWO_PI
    lon -= lon.floor
    lon *= TWO_PI
    if (lon > PI)
      lon -= TWO_PI
    end
    # Convert dome height (which is proportional to surface area) to latitude
    # lat = asin(-1 + 2 * i / num.to_f)    
    pts[i] = SpherePoint.new(asin(-1 + 2 * i / num.to_f), lon)
  end
end

Here's a very equivalent sketch I published at openprocessing

Thursday 18 July 2013

A simple ruby-processing paint application

#
# Painting Application in Ruby-Processing
# 
# Click and drag the mouse to paint. 
#

load_library :control_panel

attr_reader :panel, :red, :alpha, :green, :erase, :brush, :blue, :sz

def setup
  size(640, 360)
  color_mode RGB, 1.0
  background(0.8)
  control_panel do |c|
    c.slider    :red, 0.0..1.0, 1.0
    c.slider    :green, 0.0..1.0, 0.0
    c.slider    :blue, 0.0..1.0, 0.0
    c.slider    :alpha,  0.0..1.0, 0.9
    c.menu(:brush, ['big', 'medium', 'fine', 'pencil'], 'medium') {|m| load_menu_item(m) }
    c.checkbox  :erase
    c.button    :print_color
    c.button    :clear!
    @panel = c
  end
end

def draw
  no_stroke
  erase ? fill(0.8) : fill(red, green, blue, alpha)
  panel.set_visible true if self.visible?
  if mouse_pressed?
    ellipse(mouse_x, mouse_y, sz, sz)
  end
end

def clear!
  background(0.8)
end

def load_menu_item m
  chosen = brush[m]
  @sz = {'big' => 20, 'medium' => 10, 'fine' => 5, 'pencil' => 2}[chosen]
  return chosen
end

def print_color
  puts "red=#{(red*255).to_i}, blue=#{(blue*255).to_i}, green=#{(green*255).to_i}, alpha=#{(alpha*255).to_i}"
end

Monday 15 July 2013

Using Threads in Ruby-Processing

It has taken a bit of time but finally I got round to rubifying vanilla processing threads example. Avoids nasty reflection nonsense use by processing convenience method thread(some_method). Which I have just overridden, which now like fork and Thread.new in ruby, takes a block (my method is actually just a convenience wrapper for Thread.new, so it is not really useful, apart from providing a method that people coming from vanilla processing might expect.
# 
# Thread function example
# by Martin Prout (after a Dan Schiffman vanilla processing version).  
# 
# This example demonstrates how to use Thread.new to spawn
# a process that happens outside of the main animation thread.
#
# When Thread.new is called, the draw() loop will continue while
# the code inside the block passed to the thread will operate
# in the background.
#
# For more about threads, see: http://wiki.processing.org/w/Threading
#

# This sketch will load data from all of these URLs in a separate thread
URLS = [
"http://processing.org",
"http://www.processing.org/exhibition/",
"http://www.processing.org/reference/",
"http://www.processing.org/reference/libraries",
"http://www.processing.org/reference/tools",
"http://www.processing.org/reference/environment",
"http://www.processing.org/learning/",
"http://www.processing.org/learning/basics/",
"http://www.processing.org/learning/topics/",
"http://www.processing.org/learning/gettingstarted/",
"http://www.processing.org/download/",
"http://www.processing.org/shop/",
"http://www.processing.org/about/"
]


attr_reader :finished, :percent

def setup
  size(640, 360)
  # Spawn the thread!
  # This will keep track of whether the thread is finished
  load_data
end

def draw
  background(0)

  # If we're not finished draw a "loading bar"
  # This is so that we can see the progress of the thread
  # This would not be necessary in a sketch where you wanted to load data in the background
  # and hide this from the user, allowing the draw() loop to simply continue
  if (!finished)
    stroke(255)
    no_fill()
    rect(width/2-150, height/2, 300, 10)
    fill(255)
    # The size of the rectangle is mapped to the percentage completed
    w = map(percent, 0, 1, 0, 300)
    rect(width/2-150, height/2, w, 10)
    text_size(16)
    text_align(CENTER)
    fill(255)
    text("Loading", width/2, height/2+30)
  else
    # The thread is complete!
    text_align(CENTER)
    text_size(24)
    fill(255)
    text("Finished loading. Click the mouse to load again.", width/2, height/2)
  end
end

def load_data
  Thread.new {
    # The thread is not completed
    @finished = false
    @percent = 0
    # Reset the data to empty
    @all_data = ""
    URLS.each_with_index do |url, i|
      lines = load_strings(url)
      all_txt = lines.join(' ')
      words = all_txt.scan(/\w+/)
      words.each do |word|
        word.strip!
        word.downcase!
      end
      words.sort!
      @all_data << words.join(' ')
      @percent = i.to_f / URLS.length
    end
    @finished = true
  }
end

def mouse_pressed
  load_data
end

Saturday 13 July 2013

Yet Another 10 PRINT sketch in ruby-processing

Added some tweaks for smoother operation ie key_pressed/key_released to sequence action. See at open processing here.
# 
# Inspired by:
# 10 PRINT CHR$(205.5+RND(1)) : GOTO 10
# 
# Sketch by:
# Jacob Joaquin
# jacobjoaquin@gmail.com
# twitter @jacobjoaquin
# 

ODDS = 0.618

attr_reader :num_tiles_x, :num_tiles_y, :tile_size, :c1, :c2

def setup
  size 800, 800
  @tile_size = 50
  @num_tiles_x = width / tile_size
  @num_tiles_y = height / tile_size
  @c2 = color(235, 70, 47)
  @c1 = color(255)
  background c2
  fill c1
  no_stroke
  no_loop
end

def draw
  do_maze
end

def key_pressed
  case key
  when 'q'
    resize_tile 2
  when 'w'
    resize_tile 0.5
  when 's'
    save "maze_sketch.png"
  end
end

def key_released
  case key
  when 'q', 'w'
    background c2
    redraw
  end
end

def resize_tile v
  @tile_size *= v
  @tile_size *= v
  @num_tiles_x = width / tile_size
  @num_tiles_y = height / tile_size
end

def do_maze
  (-1 .. num_tiles_x).each do |i|
    (-1 .. num_tiles_y).each do |j|
      x1, y1 = i * tile_size, j * tile_size
      x2, y2 = x1, y1 + tile_size
      d = height / (tile_size / 2)
      n = y1 / d
      x = y2 / d

      if (rand > ODDS)
        x1 += tile_size
        quad(x1, y1 - n, x1 + n, y1, x2, y2 + x, x2 - x, y2)
      else
        x2 += tile_size
        quad(x1 - n, y1, x1, y1 - n, x2 + x, y2, x2, y2 + x)
      end
    end
  end
end

Another 10 PRINT sketch translated to ruby-processing

Catch the live version here.
#####################
#                                      #
#    10 PRINT - Stacked 3D Version     #
#                                      #
#####################

# original by bit.craft

W = 400   # canvas size
N = 10    # number of grid cells
D = W/N   # diameter of a grid cell
DPT = 0.5 # relative cell depth

def setup
  size W, W, P3D
  rect_mode CENTER
  background 255
  stroke_weight 3
end

def draw
  # get coordinates
  xy = frame_count % (N*N)
  # shift image in z-direction
  if (xy == 0)
    img = get
    background 255
    push_matrix
    translate 0, 0, -D * DPT
    fill 204
    no_stroke
    image img, 0, 0
    pop_matrix
  end

  # scale and rotate the square
  scale D
  translate (xy % N) + 0.5, (xy/N).to_i + 0.5, - DPT * 0.5
  rotate_z QUARTER_PI - HALF_PI * rand(2)
  rotate_x HALF_PI

  # draw the square
  stroke 0
  fill 255
  rect 0, 0, sqrt(2), DPT
end

Minimalist Perlin noise sketch in ruby-processing

In response to a Casey Reas challenge, R Brauer published a vanilla processing sketch which I've re-coded in ruby:-
S, V, D = 400, [], 0.02

def draw
  S.times { |a| V << [a, rand * S]; g = noise(V[a][0] * D, V[a][1] * D) * 6; point(V[a][0] += sin(g), V[a][1] += cos(g))}
end

Friday 5 July 2013

Setting texture sampling ruby-processing-2.0

Here is a little pixel manipulation sketch that uses and off screen image for efficiency:-
# Taken from processing discussion board, a little sketch by Amnon Owed
# Illustrates use of offscreen image, texture sampling, mouse_pressed?,
# load_pixels, displayWidth and displayHeight (do not snake case the last two)

SCALE = 5
attr_reader :grid
COLOR_RANGE = 16581375 # 255 * 255 * 255

def setup
  size(displayWidth, displayHeight, P2D)
  @grid = create_image(width/SCALE, height/SCALE, RGB)
  g.texture_sampling(2)       # 2 = POINT mode sampling
end

def draw
  unless mouse_pressed?
    grid.load_pixels
    grid.pixels.length.times do |i|
      grid.pixels[i] = rand(COLOR_RANGE)
    end
    grid.update_pixels
  end
  image(grid, 0, 0, width, height)
  frame.set_title("#{frame_rate.to_i}+ fps")
end

Followers

Blog Archive

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