Noise examples with JRubyArt

I have just released a new version of JRubyArt, which uses OpenSimplexNoise2 to implement noise, I was partly persuaded to convert from processing noise implementation (not really Perlin noise) by the work of Etienne Jacob, who’s work is worth looking out. Here is one of his tutorial examples converted to JRubyArt.

# After a tutorial exmple by Etienne Jacob https://bleuje.github.io/tutorial4/

WEB = %w[#f7f7f7 #cceabb #3f3f44 #fdcb9e]

NUM_FRAMES = 70
K = 130
SCL = 120.0

attr_reader :palette

def settings
  size(500, 500)
end

def setup
  sketch_title 'Replacement Technique'
  @palette = web_to_color_array(WEB)
end

def random_value(p, seed)
  ((noise(SCL * p, seed) + 1) / 2.0)**2
end

def position(p)
  q = sqrt(p)
  theta = 7 * TWO_PI * q
  r = 0.4 * width * q
  Vec2D.new(r * cos(theta), r * sin(theta))
end

def draw_thing(p)
  v1 = random_value(p, 100)
  v2 = random_value(p, 200)
  v3 = random_value(p, 300)
  sumv = v1 + v2 + v3
  alpha = 10 * TWO_PI * p
  theta0 = alpha + 0
  theta1 = alpha + map1d(v1 / sumv, 0..1, 0..TWO_PI)
  theta2 = alpha + map1d((v1 + v2) / sumv, 0..1, 0..TWO_PI)
  theta3 = alpha + TWO_PI
  radius = 30 * sin(PI * p) # sin(PI*p) is 0 at p=0 and p=1 and 1 in the middle
  pos = position(p)
  no_stroke
  fill(palette[1])
  arc(pos.x, pos.y, radius, radius, theta0, theta1)
  fill(palette[2])
  arc(pos.x, pos.y, radius, radius, theta1, theta2)
  fill(palette[3])
  arc(pos.x, pos.y, radius, radius, theta2, theta3)
end

def draw
  background(palette[0])
  t = 1.0 * frame_count / NUM_FRAMES
  push_matrix
  translate(width / 2, height / 2)
  K.times do |i|
    p = 1.0 * (i + t) / K
    draw_thing(p)
  end
  pop_matrix
  save_frame(data_path('fr###.png')) if frame_count <= NUM_FRAMES
  return unless frame_count == NUM_FRAMES

  puts('All frames have been saved')
  stop
end

etienne

Here’s a 4D Noise example:-

Coord = Struct.new(:mx, :my, :mz, :az, :al)

attr_reader :half_w, :half_h, :radius, :spin_x, :spin, :coords

def settings
  size(480, 480, P3D)
end

def setup
  sketch_title '4D Simplex Noise Test'
  background(0)
  stroke(255)
  fill(32, 255, 64)
  @half_w = width * 0.5
  @half_h = height * 0.5
  @radius = height * 0.4
  @spin_x = 0.0
  @spin = 0.0
  @smth = false
  angle = ((1.0 + Math.sqrt(5)) / 2.0 - 1) * TAU # Fibonacci distribution
  @coords = (0..2_000).map do |i|
    inc = Math.asin(i / 1_000.0 - 1.0) # inclination
    az = angle * i # azimuth
    # Too lazy to do this the right way... precalculating both the angles and the coordinates
    Coord.new.tap do |coord|
      push_matrix
      rotate_y(az)
      rotate_z(inc)
      translate(radius, 0, 0)
      coord.mx = g.model_x(0, 0, 0) * 0.007
      coord.my = g.model_y(0, 0, 0) * 0.007
      coord.mz = g.model_z(0, 0, 0) * 0.007
      coord.az = az
      coord.al = inc
      pop_matrix
    end
  end
end

def draw
  background(0)
  @spin -= (mouse_x - pmouse_x) * 0.0001 if mouse_pressed?
  @spin_x += spin
  @spin *= 0.98
  push_matrix
  translate(half_w, half_h, -0)
  rotate_y(-spin_x)
  coords.each do |ci|
    push_matrix
    rotate_y(ci.az)
    rotate_z(ci.al)
    translate(radius, 0, 0)
    dst = (g.model_z(0, 0, 0) + half_h) / 2 + 32
    stroke(dst, dst * 0.5, dst * 0.25)
    #  4D Simplex noise(x, y, z, time)
    ang = noise(ci.mx, ci.my, ci.mz, frame_count * 0.007) * TAU
    rotate_x(ang)
    line(0, 0, 0, 0, 15, 0)
    translate(0, 15, 0)
    rotate_x(-10)
    line(0, 0, 0, 0, 4, 0)
    rotate_x(20)
    line(0, 0, 0, 0, 4, 0)
    pop_matrix
  end
  pop_matrix
end

4dnoise

7 Likes

Hi @monkstone ,

Really cool gifs! Specially the first one with the colors :yum:

I am definitely going to try Processing in Ruby at some point :wink:

@josephh Just looked at your resume, and seems you are already familiar with ruby and linux, so you could try either PiCrate (on RaspberryPI4 64 bit or at a push RapberryPi3B+ or 32 bit for either), or the similar propane as the simplest versions of ruby-processing (64bit Windows MacOS or Linux) just run the sketch script with jruby. But if you prefer something more like a DSL for processing, then there’s JRubyArt, which has its own executable k9. All are installable as gems, preferably using jgem.

1 Like

@monkstone

Yes that’s right, I’ve learned Ruby and it’s a beautiful and elegant language :wink:

However I remember that I was looking at your repos for Processing in ruby and in my opinion I felt lost among all the different libraries and tools you made : PiCrate, propane and JRubyArt (and it’s own command k9).

Why was it useful to have so many independent libraries rather that one for all platforms? (including raspberry pi) :thinking:

Well its partly historical, first I took over ruby-processing from Jashkenas, it’s a bit over complicated because there is a two stage process. You could use regular ruby to fire up the app and provide a ruby wrapper around a processing sketch, in the second stage the sketch was fired up using java (called from ruby using JRuby-Complete to provide the ruby runtime) or directly using jruby. There was the possibility of creating an exportable using JRubyComplete, even create a browser Applet. JRubyArt was very much based on ruby-processing, however it has since morphed away, but still has the DSL element. So like vanilla processing:-

background 200, 0, 0

Is a valid JRubyArt sketch (it just gets class wrapped under the hood). Propane was originally a bit of an experiment but all sketches need to be explicitly class wrapped. The idea of PiCrate was to create a specialised version for the Arm architecture (which doesn’t need a lot of crap that is required for MacOS and Windows compatibility), in some ways its easiest to develop for.

1 Like

Hi @monkstone ,

Thanks for the explanations! It’s more clear now :wink: