# bezier bez_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 # load_library :vecmath NI=4 NJ=5 RESI=NI*10 RESJ=NJ*10 attr_accessor :outp, :inp, :normp, :auto_normals, :arcball, :bez_patch def setup size(1024, 768, P3D) @arcball = ArcBall.new(width/2.0, height/2.0, min(width - 20, height - 20) * 0.5) @auto_normals = false build_geometry @bez_patch = build_shape end def draw background(255) translate(width/2,height/2) smooth(8) lights define_lights #scale(0.9) update shape(bez_patch) end ####### # use bez patch geometry to # create a vbo object (PShape) ####### def build_shape no_stroke bez = create_shape(QUAD_STRIP) bez.fill(192, 192, 192) bez.ambient(20, 20, 20) (0 ... RESI - 1).each do |i| (0 ... RESJ).each do |j| if (!auto_normals) bez.normal(*normp[i][j]) end bez.vertex(*outp[i][j]) bez.vertex(*outp[i+1][j]) end end bez.end # end has unfortunate ruby highlighting in jedit, not in vim though return bez end ########## # build geometry # for bez patch ########## def build_geometry @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 ###################### # ArcBall control # and lighting + re-run ###################### def update theta, x, y, z = arcball.update rotate(theta, x, y, z) end def mouse_pressed arcball.mouse_pressed(mouse_x, mouse_y) end def mouse_dragged arcball.mouse_dragged(mouse_x, mouse_y) end def define_lights ambient_light(60, 60, 60) point_light(30, 30, 30, 0, 0, 0) directional_light(40, 40, 50, 1, 0, 0) spot_light(30, 30, 30, 0, 40, 200, 0, -0.5, 0.5, PI / 2, 2) end def key_pressed case(key) when ' ' save_frame("bezPatch.png") build_geometry @bez_patch = build_shape when 'x' arcball.select_axis(X) when 'y' arcball.select_axis(Y) when 'z' arcball.select_axis(Z) end end def key_released arcball.select_axis(-1) endUpdated 20 February 2014 (arcball library is now in vecmath).
Experiments with ruby-processing (processing-2.2.1) and JRubyArt for processing-3.0
Friday, 28 December 2012
Bezier Patch as a VBO (PShape)
Hardly needs introduction here is an alternative version of the bezier patch sketch, features ArcBall (arcball library is built in to my fork of ruby-processing, which is required to run a sketch with processing-2.0 functionality such as PShape) to rotate the patch and uses PShape object to store the geometry as a vbo.
Labels:
bezier patch,
Marius Watz,
Paul Burke,
ruby-processing,
vbo
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
Labels:
bezier,
ruby-processing
Monday, 24 December 2012
Rotating Arcs Sketch in Ruby Processing
Here is vanilla sketch that wasn't easy to translate to ruby, the more hacks there are, the harder it is to translate. However conversely it should make me a bit bit more sensitive to the same issue in reverse. The original sketch featured sincos look up tables which are a dubious benefit in java, especially when not optimised. It also featured a nasty ++ increment hack. The original sketch had quite lot of casting to int, I found there no casting required in ruby-processing, just a nifty built in deg to radian conversion using a patched Numeric class.
# # Geometry # by Marius Watz. # load_library 'pdf' include_package 'processing.pdf' attr_reader :num, :pt, :style, :dosave def setup size(1024, 768, P3D) background(255) @dosave = false @num = 150 @pt = [] @style = [] # Set up arc shapes index = 0 (0 ... num).each do |i| pt.push(rand(TWO_PI)) # Random X axis rotation pt.push(rand(TWO_PI)) # Random Y axis rotation pt.push(rand(60 .. 80)) # Short to quarter-circle arcs if (rand(100)>90) pt[pt.length - 1] = rand(8 .. 27) * 10 end pt.push(rand(2 .. 50) * 5) # Radius. Space them out nicely pt.push(rand(4 .. 32)) # Width of band if (rand(100) > 90) pt[pt.length - 1] = rand(40 .. 60) # Width of band end pt.push(rand(0.005 .. 0.0334))# Speed of rotation # get colors prob = rand(100) if (prob < 30) style[i*2] = color_blended(rand, 255,0,100, 255,0,0, 210) elsif(prob < 70) style[i*2] = color_blended(rand, 0,153,255, 170,225,255, 210) elsif(prob<90) style[i*2] = color_blended(rand, 200,255,0, 150,255,0, 210) else style[i*2] = color(255,255,255, 220) end if (prob < 50) style[i*2] = color_blended(rand, 200,255,0, 50,120,0, 210) elsif(prob < 90) style[i*2] = color_blended(rand, 255,100,0, 255,255,0, 210) else style[i*2] = color(255, 255, 255, 220) style[i*2+1] = rand(100) % 3 end end end def draw if(dosave) # set up PGraphicsPDF for use with beginRaw pdf = begin_raw(PDF, "pdf_complex_out.pdf") # set default Illustrator stroke styles and paint background rect. pdf.stroke_join(MITER) pdf.stroke_cap(SQUARE) pdf.fill(0) pdf.no_stroke pdf.rect(0,0, width,height) end background(0) index = 0 translate(width/2, height/2, 0) rotate_x(PI/6) rotate_y(PI/6) (0 ... num).each do |i| push_matrix rotate_x(pt[index]) rotate_y(pt[index + 1]) index += 2 if (style[i*2+1] == 0) stroke(style[i*2]) no_fill stroke_weight(1) arc_line(0,0, pt[index],pt[index + 1],pt[index + 2]) index += 3 elsif (style[i*2+1] == 1) fill(style[i*2]) no_stroke arc_line_bars(0,0, pt[index],pt[index + 1],pt[index + 2]) index += 3 else fill(style[i*2]) no_stroke arc(0,0, pt[index],pt[index + 1],pt[index + 2]) index += 3 end # increase rotation pt[index-5] += pt[index] / 10 pt[index-4] += pt[index] / 20 index += 1 pop_matrix end if (dosave) end_raw @dosave=false end end # Get blend of two colors def color_blended(fract, r, g, b, r2, g2, b2, a) r2 = (r2 - r) g2 = (g2 - g) b2 = (b2 - b) return color(r + r2 * fract, g + g2 * fract, b + b2 * fract, a) end # Draw arc line def arc_line(x, y, deg, rad, w) a=(deg < 360)? deg : 0 numlines = w/2 (0 ... numlines).each do begin_shape (0 ... a).each do |i| vertex(cos(i.radians)*rad+x,sin(i.radians)*rad+y) end end_shape rad += 2 end end # Draw arc line with bars def arc_line_bars(x, y, deg, rad, w) a=(deg < 360)? deg / 4 : 0 begin_shape(QUADS) (0 ... a).step(4) do |i| vertex(cos(i.radians)*(rad)+x,sin(i.radians)*(rad)+y) vertex(cos(i.radians)*(rad+w)+x,sin(i.radians)*(rad+w)+y) vertex(cos((i + 2).radians)*(rad+w)+x,sin((i + 2).radians)*(rad+w)+y) vertex(cos((i + 2).radians)*(rad)+x,sin((i + 2).radians)*(rad)+y) end end_shape end # Draw solid arc def arc(x,y,deg,rad,w) a = (deg < 360)? deg : 0 begin_shape(QUAD_STRIP) (0 ... a).each do |i| vertex(cos(i.radians)*(rad)+x,sin(i.radians)*(rad)+y) vertex(cos(i.radians)*(rad+w)+x,sin(i.radians)*(rad+w)+y) end end_shape end def mouse_pressed @dosave = true end
# # Geometry # by Marius Watz. # load_library 'pdf' include_package 'processing.pdf' attr_reader :num, :pt, :style, :dosave def setup size(1024, 768, P3D) background(255) @dosave = false @num = 150 @pt = [] @style = [] # Set up arc shapes index = 0 (0 ... num).each do |i| pt.push(rand(TWO_PI)) # Random X axis rotation pt.push(rand(TWO_PI)) # Random Y axis rotation pt.push(rand(60 .. 80)) # Short to quarter-circle arcs if (rand(100)>90) pt[pt.length - 1] = rand(8 .. 27) * 10 end pt.push(rand(2 .. 50) * 5) # Radius. Space them out nicely pt.push(rand(4 .. 32)) # Width of band if (rand(100) > 90) pt[pt.length - 1] = rand(40 .. 60) # Width of band end pt.push(radians(rand(5 .. 30)) / 5 )# Speed of rotation # get colors prob = rand(100) if (prob < 30) style[i*2] = color_blended(rand, 255,0,100, 255,0,0, 210) elsif(prob < 70) style[i*2] = color_blended(rand, 0,153,255, 170,225,255, 210) elsif(prob<90) style[i*2] = color_blended(rand, 200,255,0, 150,255,0, 210) else style[i*2] = color(255,255,255, 220) end if (prob < 50) style[i*2] = color_blended(rand, 200,255,0, 50,120,0, 210) elsif(prob < 90) style[i*2] = color_blended(rand, 255,100,0, 255,255,0, 210) else style[i*2] = color(255, 255, 255, 220) style[i*2+1] = rand(100).to_i % 3 end end end def draw if(dosave) # set up PGraphicsPDF for use with beginRaw pdf = begin_raw(PDF, "pdf_complex_out.pdf") # set default Illustrator stroke styles and paint background rect. pdf.stroke_join(MITER) pdf.stroke_cap(SQUARE) pdf.fill(0) pdf.no_stroke pdf.rect(0,0, width,height) end background(0) index = 0 translate(width/2, height/2, 0) rotate_x(PI/6) rotate_y(PI/6) (0 ... num).each do |i| push_matrix rotate_x(pt[index]) rotate_y(pt[index + 1]) index += 2 if (style[i*2+1] == 0) stroke(style[i*2]) no_fill stroke_weight(1) arc_line(0,0, pt[index],pt[index + 1],pt[index + 2]) index += 3 elsif (style[i*2+1] == 1) fill(style[i*2]) no_stroke arc_line_bars(0,0, pt[index],pt[index + 1],pt[index + 2]) index += 3 else fill(style[i*2]) no_stroke arc(0,0, pt[index],pt[index + 1],pt[index + 2]) index += 3 end # increase rotation pt[index-5] += pt[index] / 10 pt[index-4] += pt[index] / 20 index += 1 pop_matrix end if (dosave) end_raw @dosave=false end end # Get blend of two colors def color_blended(fract, r, g, b, r2, g2, b2, a) r2 = (r2 - r) g2 = (g2 - g) b2 = (b2 - b) return color(r + r2 * fract, g + g2 * fract, b + b2 * fract, a) end # Draw arc line def arc_line(x, y, deg, rad, w) a=(deg < 360)? deg : 0 numlines = w/2 (0 ... numlines).each do begin_shape (0 ... a).each do |i| vertex(cos(radians(i))*rad+x,sin(radians(i))*rad+y) end end_shape rad += 2 end end # Draw arc line with bars def arc_line_bars(x, y, deg, rad, w) a=(deg < 360)? deg / 4 : 0 begin_shape(QUADS) (0 ... a).step(4) do |i| vertex(cos(radians(i))*(rad)+x,sin(radians(i))*(rad)+y) vertex(cos(radians(i))*(rad+w)+x,sin(radians(i))*(rad+w)+y) vertex(cos(radians(i + 2))*(rad+w)+x,sin(radians(i + 2))*(rad+w)+y) vertex(cos(radians(i + 2))*(rad)+x,sin(radians(i + 2))*(rad)+y) end end_shape end # Draw solid arc def arc(x,y,deg,rad,w) a = (deg < 360)? deg : 0 begin_shape(QUAD_STRIP) (0 ... a).each do |i| vertex(cos(radians(i))*(rad)+x,sin(radians(i))*(rad)+y) vertex(cos(radians(i))*(rad+w)+x,sin(radians(i))*(rad+w)+y) end end_shape end def mouse_pressed @dosave = true end
Labels:
complex 3D,
Marius Watz,
rotating arcs,
ruby processing
Friday, 21 December 2012
Context free sketch in regular ruby processing
Sometimes it is not necessary to use the ruby-cf3 library. I was contemplating adding parametrized shape to cf3ruby, so I thought I would try a simple context free art sketch to experiment with. Turn out this pretty easy to implement in regular ruby-processing (now using ruby-1.9 syntax for random range):-
# Grapher is based on a context free art design # by ColorMeImpressed (takes a bit of time to run) # http://www.contextfreeart.org/gallery/view.php?id=2844 # CMIN = -2.0 # Important to specify float else get random int from range? CMAX = 2.0 FUZZ = 0.04 SZ = 5 def setup size 600, 600 no_stroke color_mode(HSB, 1.0) background(0) frame_rate(4000) end def draw translate(width/2, height/2) dot(rand(-PI .. PI), rand(-PI .. PI), rand(CMIN .. CMAX)) unless frame_count > 200000 end def dot(px, py, c) func = sin(px) + sin(py) + c # change function to change the graph eg. #func = sin(px) + tan(py) + c #func = cos(px) + sin(py) + c if abs(func) <= FUZZ fill(((CMIN - c) / (CMIN - CMAX)), 1, 1) ellipse px * width / TWO_PI, py * height / TWO_PI, SZ, SZ else dot(rand(-PI .. PI), rand(-PI .. PI), rand(CMIN .. CMAX)) end end
Labels:
context free art,
equations,
graph,
ruby-processing
Wednesday, 19 December 2012
Exporting cf3ruby directly to 'large' pdf
With the processing pdf export library it is easy to export processing sketches to pdf. This is also true for ruby-processing sketches, including those using the cf3ruby library see example below:-
# levy.rb ruby-processing NB: :alpha is now implemented ruby-processing require 'cf3', 'pdf' include_package 'processing.pdf' def setup_the_levy @levy = ContextFree.define do shape :start do levy brightness: 0.9 end shape :levy do square alpha: 0.1 split do levy size: 1/Math.sqrt(2), rotation: -45, x: 0.5, brightness: 0.9 rewind levy size: 1/Math.sqrt(2), rotation: 45, x: 0.5, brightness: 0.9 end end end end def setup size 2000, 2000, PDF, "levy.pdf" setup_the_levy smooth draw_it end def draw exit end def draw_it background 255 @levy.render :start, size: 250, stop_size: 2, start_x: width/4, start_y: height/2 end
Labels:
cf3,
context free DSL,
pdf,
ruby processing
Tuesday, 18 December 2012
Context Free Tree in cf3ruby
################################################################# # A non deterministic sketch run it until you get a result you like # uncomment "srand 5" to get a more deterministic result. It looked # pretty good on my linux box (however I'm not sure how universal the # random seeding is in jruby) ################################################################# require 'cf3' def setup_the_tree @tree = ContextFree.define do shape :trunk, 20 do # rule has a probability weighting of 20 circle size: 0.25, brightness: 0.5 # giving an actual probability = 0.952381 scraggle y: -0.1 # the minus is require by the upside down coordinate system end shape :trunk, 1 do # rule has a probability weighting of 1 branch size: 0.7 # giving an actual probability = 0.047619 end shape :trunk, 0.02 do # empty rule top stop early end shape :branch do split do # split is like a branch, rewind returns original context trunk rotation: 10 rewind trunk rotation: -10 end end shape :scraggle do # without an explicit weighting trunk rotation: 5 # probability of each scraggle rule end # is 0.5 shape :scraggle do trunk rotation: -5 end end end def setup size 600, 600 srand 5 smooth setup_the_tree background 255 # NB color mode here is "RGB 255", within context free definition draw_it # the color mode is "HSB 1.0", supports :hue, :saturation, :brightness save_frame "/home/tux/tree4.png" end def draw_it @tree.render :trunk, start_x: width/2, start_y: height * 0.9, stop_size: height/150, size: height/15 end
Labels:
context free DSL,
ruby-cf3,
ruby-processing,
tree
New context_free.rb (cf3ruby)
Here is my "y" window sketch using my modified ruby-processing library (features CF3 syntax, ie shape replaces rule, also ruby 1.9 hash syntax).
# y.rb ruby-processing require 'cf3' Y_TOP = -1 / Math.sqrt(3) Y_BOT = Math.sqrt(3) / 6 def setup_the_triangle @triangle = ContextFree.define do ######## shape :start do unit brightness: 1.0 end shape :unit do triangle size: 1.0 split do unit size: 0.5, x: 0, y: Y_TOP/2, brightness: 0.8 rewind unit size: 0.5, x: -0.25, y: -Y_TOP/4, brightness: 0.8 rewind unit size: 0.5, x: 0.25, y: -Y_TOP/4, brightness: 0.8 end end ######## end end def setup size 1024, 1024 setup_the_triangle no_stroke color_mode RGB, 1 smooth draw_it save_frame("y.png") end def draw # Do nothing. end def draw_it background 225, 225, 0 @triangle.render :start, size: height, stop_size: 0.5, start_x: width/2, start_y: height * 0.6 end
Labels:
cf3,
context free DSL,
ruby-1.9,
ruby-processing
Friday, 14 December 2012
MeshToVBO conversion ruby-processing
Since processing-2.0 there is the possibility of converting 3D meshes to vertical buffer objects (vbo) as instances of PShape. Here I explore a toxiclibs example sketch that instead of using toxis gfx package to render the shapes converts the shapes to vbo using a ruby library (albeit with a Processing::Proxy mixin. Here is the library:-
Here is the example sketch:-
############################################ # mesh_to_vbo.rb # a ruby library to convert toxi.mesh object # to vbo (PShape) written by Martin Prout # make use of Processing::Proxy mixin ############################################ class MeshToVBO include Processing::Proxy attr_reader :parent def initialize(parent) @parent = parent end def meshToVBO(mesh, smth) retained = parent.createShape(PShape::TRIANGLES) retained.enableStyle() retained.fill(222, 222, 222) retained.ambient(50) retained.shininess(10) retained.specular(50) if (smth) mesh.computeVertexNormals() mesh.getFaces.each do |f| retained.normal(f.a.normal.x, f.a.normal.y, f.a.normal.z) retained.vertex(f.a.x, f.a.y, f.a.z) retained.normal(f.b.normal.x, f.b.normal.y, f.b.normal.z) retained.vertex(f.b.x, f.b.y, f.b.z) retained.normal(f.c.normal.x, f.c.normal.y, f.c.normal.z) retained.vertex(f.c.x, f.c.y, f.c.z) end else mesh.getFaces.each do |f| retained.normal(f.normal.x, f.normal.y, f.normal.z) retained.vertex(f.a.x, f.a.y, f.a.z) retained.vertex(f.b.x, f.b.y, f.b.z) retained.vertex(f.c.x, f.c.y, f.c.z) end end retained.end() return retained end # variant # input array of meshes, output an array of shapes def meshToRetained(mesh, smth) rshapes = [] (0 ... mesh.length).each do |i| rshapes.push(meshToVBO(mesh[i], smth)) end return rshapes end end
Here is the example sketch:-
# This example demonstrates how to rotate a number of meshes # so that each points towards a common & user controlled focal point. # # Requires toxiclibs-0020 or newer # # (c) 2012 Karsten Schmidt / LGPL2 licensed # load_libraries 'toxiclibscore', 'vbo' include_package 'toxi.geom' include_package 'toxi.geom.mesh' # container for mesh positions attr_reader :positions, :vbo def setup size(640,480,P3D) @vbo = MeshToVBO.new(self) @positions = [] # compute mesh positions on circle in XZ plane (Circle.new(200).toPolygon2D(8)).each do |p| positions.push(p.to3DXZ) end end def draw background(51) lights no_stroke translate(width/2,height/2,0) rotate_x(-PI/6) # create manual focal point in XY plane focus = Vec3D.new((mouse_x - width/2), (mouse_y - height/2), 0) # create mesh prototype to draw at all generated positions # the mesh is a simple box placed at the world origin m = AABB.new(25).to_mesh # draw focus shape(vbo.meshToVBO(AABB.new(focus, 5).to_mesh, false)) positions.each do |p| # align the positive z-axis of mesh to point at focus # mesh needs to be located at world origin for it to work correctly # only once rotated, move it to actual position shape(vbo.meshToVBO(m.copy.pointTowards(focus.sub(p), Vec3D::Z_AXIS).translate(p), false)) end # draw connections from mesh centers to focal point stroke(0,255,255) positions.each do |p| line(p.x, p.y, p.z, focus.x, focus.y, focus.z) end end
Labels:
3D mesh,
processing-2.0,
retained shape,
toxiclibs,
vbo
Wednesday, 12 December 2012
Fix for ruby-processing context free
The adoption of jruby-1.7.0 for the latest version of processing has required changes to the context_free.rb script. See the change on my Pembrokeshire Branch. My dragon sketch and city sketches working fine, I haven't checked any other. Here is my dragon sketch updated to ruby-1.9 syntax (NB: continues work with 1.8 syntax)
Here's a sketch with a simple custom shape of an isosceles triangle
# contributed by monkstone load_library 'context_free' def setup_the_dragon @dragon = ContextFree.define do rule :start do dragon alpha: 1 end rule :dragon do square hue: 0, brightness: 0, saturation: 1, alpha: 0.02 split do dragon size: 1/Math.sqrt(2), rotation: -45, x: 0.25, y: 0.25 rewind dragon size: 1/Math.sqrt(2), rotation: 135, x: 0.25, y: 0.25 rewind end end end end def setup size 800, 500 setup_the_dragon smooth draw_it end def draw # Do nothing. end def draw_it background 255 @dragon.render :start, size: width*0.8, stop_size: 2, start_x: width/3, start_y: height/3.5 end
Here's a sketch with a simple custom shape of an isosceles triangle
load_library 'context_free' def setup_the_spiral @spiral= ContextFree.define do ############ Begin defining custom terminal, an isoceles triangle class << self define_method(:isoceles) do |some_options| # isoceles triangle size, options = *self.get_shape_values(some_options) rot = options[:rotation] rotate(rot) if rot $app.triangle(-0.5 * size, -0.5 * size, -0.5 * size, 0.5 * size, 0.5 * size, 0.5 * size) rotate(-rot) if rot end end ########### End definition of custom terminal 'isoceles' rule :spiral do isoceles brightness: -1, rotation: 90 spiral rotation: 135, size: 1/sqrt(2), x: 1/sqrt(2) end end end def setup size 800, 500 setup_the_spiral draw_it end def draw # Do nothing. end def draw_it background 255 @spiral.render :spiral, size: height, start_x: width/3, start_y: height/2 end
Labels:
context free DSL,
jruby-1.7.0,
processing-2.0,
ruby-1.9
Wednesday, 5 December 2012
What works what does not and may not
I have just forked ruby-processing and updated my fork to match work in progress on my linux box to get ruby-processing running with the latest jruby-1.7.1 and latest processing-2.0b7 release. https://github.com/monkstone/ruby-processing clone it if you like. All samples should work, with the exception of the peasycam sketch (does work with an unofficially updated version of peasycam). Examples that rely on external "contributed" libraries probably will not work with the probable exception of toxiclibs (which is implementation agnostic). I don't think control panel likes working the latest version of processing (it was ok with processing-2.0b6).
Since web applets are no-longer supported with vanilla processing I don't think there's much call for it in ruby processing. For web presence with processing you are encouraged to write processing.js sketches (there is even preliminary support for coffeescript in processing ide). I have requested that my modified fork is pulled into core, which will make it easier to use but in the meantime you can clone it from github or fork it if you've a burning desire to implement something new.
Since web applets are no-longer supported with vanilla processing I don't think there's much call for it in ruby processing. For web presence with processing you are encouraged to write processing.js sketches (there is even preliminary support for coffeescript in processing ide). I have requested that my modified fork is pulled into core, which will make it easier to use but in the meantime you can clone it from github or fork it if you've a burning desire to implement something new.
Labels:
fork,
github,
libraries,
processing-2.0,
ruby-processing.
Retained Shape (FBO) in Ruby Processing
Now we are cooking, this example demonstrated running ruby-processing compiled with a pre-released version of processing-2.0b7. Further it demonstrates the use of the FBO to vastly improve performance. All sketches run with this ruby-processing hack are very noisy (complaining about ambigous overloaded java methods eg background and fill).
BOX_SIZE = 20 MARGIN = BOX_SIZE * 2 DEPTH = 400 FINT = 3 attr_reader :box_fill, :grid, :fcount, :lastm, :frate def setup size(640, 360, P3D) frame_rate(60) @fcount = 0 @lastm = 0 no_smooth() no_stroke() @grid = create_shape(GROUP) # Build grid using multiple translations (-(DEPTH/2 + MARGIN) ... (DEPTH/2 - MARGIN)).step(BOX_SIZE) do |i| (-(height + MARGIN) ... (height - MARGIN)).step(BOX_SIZE) do |j| (-(width + MARGIN) ... (width - MARGIN)).step(BOX_SIZE) do |k| # Base fill color on counter values, abs function # ensures values stay within legal range @box_fill = color(i.abs.to_i, j.abs.to_i, k.abs.to_i, 50) cube = create_shape(BOX, BOX_SIZE.to_f, BOX_SIZE.to_f, BOX_SIZE.to_f) cube.fill(box_fill) cube.translate(k, j, i) grid.add_child(cube) end end end end def draw background(255) hint(DISABLE_DEPTH_TEST) # Center and spin grid push_matrix() translate(width/2, height/2, -DEPTH) rotate_y(frame_count * 0.01) rotate_x(frame_count * 0.01) shape(grid) pop_matrix() hint(ENABLE_DEPTH_TEST) @fcount += 1 m = millis() if (m - lastm > 1000 * FINT) @frate = fcount / FINT @fcount = 0 @lastm = m puts("fps: #{frate}") end fill(0) text("fps: #{frate}", 10, 20) end
Labels:
FBO,
processing-2.0,
retained shape,
ruby-processing
Creating a Mock Vanilla Processing Distribution
It is possible to create a distribution version of processing from the git version. I wanted a mock version to use in my development version of ruby-processing.
These are the steps for a linux64 distribution:-
Clone processing from github here:-
https://github.com/processing/processing
Updated 6 November 2013, to match github and most recent pre-version
These are the steps for a linux64 distribution:-
- Build the git version from the build folder
- cd linux/work
- mkdir processing-2.1.1
- mkdir processing-2.1.1/modes
- cp -rf modes/java processing-2.1.1/modes
- cp -rf core processing-2.1.1
- tar czvf processing-2.1.1-linux64.tgz processing-2.1.1
Clone processing from github here:-
https://github.com/processing/processing
Updated 6 November 2013, to match github and most recent pre-version
Labels:
distribution,
github,
processing,
vanilla processing
Tuesday, 4 December 2012
Landscape shader in ruby-processing
Feels like I'm on a roll, here is the processing-2.0 landscape shader example running with ruby-processing.
## # Landscape # Simple raymarching shader with camera, originally by Paulo Falcão # Ported from the webGL version in GLSL Sandbox: # http://glsl.heroku.com/e//3213.0 # ## attr_reader :landscape, :pg def setup size(640, 360, P2D) # This effect can be too demanding on older GPUs, # so we can render it on a smaller res offscreen surface # @pg = create_graphics(320, 180, P2D) @pg = create_graphics(640, 360, P2D) pg.no_stroke() @landscape = load_shader("landscape.glsl") landscape.set("resolution", width.to_f, height.to_f) end def draw landscape.set("time", millis() / 1000.0) landscape.set("mouse", mouse_x.to_f, height - mouse_y.to_f) # This kind of raymarching effects are entirely implemented in the # fragment shader, they only need a quad covering the entire view # area so every pixel is pushed through the shader. pg.begin_draw() pg.shader(landscape) pg.rect(0, 0, width, height) pg.end_draw() # Scaling up offscreen surface to cover entire screen (if reduced). image(pg, 0, 0, width, height) end
Labels:
landscape shader,
processing-2.0,
ruby-processing
Fish-eye shader revisited with ruby-processing and processing-2.0
Previously one of the most popular posts (700+ hits) on this blog was my glgraphics post with the fish eye shader. Andres has now incorporated some the shader stuff into processing-2.0, here is essentially the same sketch running in ruby-processing, built with processing-2.0 (which includes built in support for glsl shaders).
## # Fish Eye # # This fish-eye shader is useful for dome projection. ## attr_reader :fisheye, :canvas, :use_fish_eye def setup() size(640, 640, P3D) @canvas = create_graphics(width, height, P3D) @fisheye = load_shader("FishEye.glsl") @use_fish_eye = true fisheye.set("aperture", 180.0) end def draw() canvas.begin_draw() canvas.background(0) canvas.stroke(255, 0, 0) (0...width).step(10){ |i| canvas.line(i, 0, i, height)} (0...height).step(10){ |i| canvas.line(0, i, width, i)} canvas.lights() canvas.no_stroke() canvas.translate(mouse_x, mouse_y, 100) canvas.rotate_x(frameCount * 0.01) canvas.rotate_y(frameCount * 0.01) canvas.box(100) canvas.end_draw() shader(fisheye) unless !use_fish_eye image(canvas, 0, 0, width, height) end def mouse_pressed() if (use_fish_eye) @use_fish_eye = false resetShader() else @use_fish_eye = true end end
Labels:
GLSL shader,
processing-2.0,
ruby-processing
Subscribe to:
Posts (Atom)
Followers
Blog Archive
-
▼
2012
(26)
-
▼
December
(17)
- Bezier Patch as a VBO (PShape)
- Bezier Patch in ruby-processing
- Rotating Arcs Sketch in Ruby Processing
- Context free sketch in regular ruby processing
- Exporting cf3ruby directly to 'large' pdf
- Context Free Tree in cf3ruby
- New context_free.rb (cf3ruby)
- MeshToVBO conversion ruby-processing
- Fix for ruby-processing context free
- What works what does not and may not
- Retained Shape (FBO) in Ruby Processing
- Creating a Mock Vanilla Processing Distribution
- Landscape shader in ruby-processing
- Fish-eye shader revisited with ruby-processing and...
- PShader Example in ruby-processing
- A 3D-texture example with my hacked ruby-processing
- Testing ruby-processing with processing-2.0
-
▼
December
(17)
About Me
- monkstone
- I have developed JRubyArt and propane new versions of ruby-processing for JRuby-9.1.5.0 and processing-3.2.2