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

Thursday 27 December 2012

Bezier Patch in ruby-processing

This is getting to be a habit? Another sketch by Marius Watz translated to ruby-processing. The main reason is that I've been working on updating ruby-processing to processing-2.0, and in the course of that I'm including some sketches included with the processing-2.0 distribution and this is just another. Both these sketches benefit from taking a different approach building arrays in ruby cf java. This one has benefited from bit more tuning, as there no real need for an arrays of PVector once the math has been done. Further it is so easy to just splat array to the vertex coordinates, don't you just love ruby.
# bezier patch By Marius Watz:
# http://www.openprocessing.org/sketch/57709
# Normal calculation added by Andres Colubri
# Direct port of sample code by Paul Bourke.
# Original code: http://paulbourke.net/geometry/bezier/
#
# hit "spacebar" to generate a new shape and save current
#

NI=4
NJ=5
RESI=NI*10
RESJ=NJ*10

attr_accessor :outp, :inp, :normp, :auto_normals


def setup
  size(1024, 768, P3D)
  @auto_normals = false
  build
end

def draw
  background(255)
  translate(width/2,height/2)
  smooth(8)
  lights
  #scale(0.9)
  rotate_y(map(mouse_x, 0, width, -PI, PI))
  rotate_x(map(mouse_y, 0, height, -PI, PI))
  no_stroke
  fill(192, 192, 192)
  ambient_light(100, 100, 100)
  ambient(40)
  specular(30)
  (0 ... RESI - 1).each do |i|
    beginShape(QUAD_STRIP)
    (0 ... RESJ).each do |j|
      if (!auto_normals)
        normal(*normp[i][j])
      end
      vertex(*outp[i][j])
      vertex(*outp[i+1][j])
    end
    endShape
  end
end

def keyPressed
    if (key == ' ')
        save_frame("bezPatch.png")
        build
    end
end

def build
  @outp = []
  @normp = []
  @inp = []
  uitang = PVector.new
  ujtang = PVector.new

  (0 ... NI).each do |i|
    row = Array.new
    (0 ... NJ).each do |j|
      row << PVector.new(i, j, (rand * 6) - 3)
    end
    inp << row
  end

  (0 ... RESI).each do |i|
    mui = i.fdiv(RESI - 1)
    row = []
    row_n = []
    (0 ... RESJ).each do |j|
      muj = j.fdiv(RESJ - 1)
      vect = PVector.new
      uitang.set(0, 0, 0)
      ujtang.set(0, 0, 0)
      (0 ... NI).each do |ki|
        bi = bezier_blend(ki, mui, NI)
        dbi = d_bezier_blend(ki, mui, NI)
        (0 ... NJ).each do |kj|
          bj = bezier_blend(kj, muj, NJ)
          dbj = d_bezier_blend(kj, muj, NJ)
          vect.x += (inp[ki][kj].x * bi * bj)
          vect.y += (inp[ki][kj].y * bi * bj)
          vect.z += (inp[ki][kj].z * bi * bj)

          uitang.x += (inp[ki][kj].x * dbi * bj)
          uitang.y += (inp[ki][kj].y * dbi * bj)
          uitang.z += (inp[ki][kj].z * dbi * bj)

          ujtang.x += (inp[ki][kj].x * bi * dbj)
          ujtang.y += (inp[ki][kj].y * bi * dbj)
          ujtang.z += (inp[ki][kj].z * bi * dbj)
        end
      end
      vect.add(PVector.new(-NI/2,-NJ/2,0))
      vect.mult(100)
      row << vect.array()
      uitang.normalize
      ujtang.normalize
      row_n << uitang.cross(ujtang).array()
    end
    @outp << row
    @normp << row_n
  end
end

def bezier_blend( k, mu,  n)
    blend = 1.0
    nn = n
    kn = k
    nkn = n - k

    while (nn >= 1)
        blend *= nn
        nn -= 1
        if (kn > 1)
            blend = blend.fdiv(kn)
            kn -= 1
        end
        if (nkn > 1)
            blend = blend.fdiv(nkn)
            nkn -= 1
        end
    end
    blend *= pow(mu, k.to_f) if (k > 0)
    blend *= pow(1-mu, (n - k).to_f) if (n - k > 0)
    return(blend)
end

def d_bezier_blend( k, mu,  n)
  dblendf = 1.0

  nn = n
  kn = k
  nkn = n - k

  while (nn >= 1)
    dblendf *= nn
    nn -= 1
    if (kn > 1)
      dblendf  = dblendf.fdiv(kn)
      kn -= 1
    end
    if (nkn > 1)
      dblendf  = dblendf.fdiv(nkn)
      nkn -= 1
    end
  end

  fk = 1
  dk = 0
  fnk = 1
  dnk = 0
  if (k > 0)
    fk = pow(mu, k.to_f)
    dk = k * pow(mu, (k - 1).to_f)
  end
  if (n - k > 0)
    fnk = pow(1 - mu, (n - k).to_f)
    dnk = (k - n)*pow(1 - mu, (n - k - 1).to_f)
  end
  dblendf *= (dk * fnk + fk * dnk)

  return(dblendf)
end

No comments:

Post a Comment

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