######## # Soft Body by Ira Greenberg # Softbody dynamic simulation using curve_vertex # and curve_tightness (and new Vec2D to_curve_vertex) ######## require 'jruby_art' # SoftBody class wrapped JRubyArt sketch features Vec2D :to_curve_vertex class SoftBody < Processing::App attr_reader :accel, :center, :frequency, :radius, :rot_angle attr_reader :organic_constant, :nodes, :renderer, :angle, :node_start SPRINGING = 0.0009 DAMPING = 0.98 NODES = 5 def setup size 640, 360 @renderer = AppRender.new(self) init_node no_stroke frame_rate 30 end def init_node @accel = Vec2D.new @center = Vec2D.new(width / 2, height / 2) @radius = 45 @organic_constant = 1 @rot_angle = -90 @nodes = (0...NODES).map { Vec2D.new } @frequency = (0...NODES).map { rand(5..12) } @angle = Array.new(NODES, 0) end def draw fill(0, 100) rect(0, 0, width, height) update draw_shape move_shape end def draw_shape curve_tightness(organic_constant) fill 255 begin_shape nodes.each { |vec| vec.to_curve_vertex(renderer) } nodes.take(NODES - 1).each { |vec| vec.to_curve_vertex(renderer) } end_shape(Java::ProcessingCore::PConstants::CLOSE) end def update delta = Vec2D.new(mouse_x - center.x, mouse_y - center.y) delta *= SPRINGING @accel += delta @center += accel @accel *= DAMPING @organic_constant = 1 - (((accel.x).abs + (accel.y).abs) * 0.1) @node_start = create_start end def create_start (0...NODES).map do |n| Vec2D.new( center.x + DegLut.cos(n * (360 / NODES)) * radius, center.y + DegLut.sin(n * (360 / NODES)) * radius ) end end def move_shape (0...NODES).each do |i| nodes[i] = Vec2D.new( node_start[i].x + DegLut.sin(angle[i]) * (accel.x * 2), node_start[i].y + DegLut.sin(angle[i]) * (accel.y * 2) ) angle[i] = frequency[i] + angle[i] end end end SoftBody.new(title: 'Soft Body')
Experiments with ruby-processing (processing-2.2.1) and JRubyArt for processing-3.0
Showing posts with label Vec2D. Show all posts
Showing posts with label Vec2D. Show all posts
Saturday, 25 October 2014
Sketch featuring Vec2D to_curve_vertex (JRubyArt)
Labels:
curve_vertex,
dyamic sketch,
JRubyArt,
Vec2D
Wednesday, 17 September 2014
Using the Range class in ruby processing
Since ruby-processing-2.6.3 the processing constrain function is actually implemented using the clip function of Range (this method has been added to Range in ruby-processing). However in ruby processing we should probably prefer to use the clip method directly, as I have here in my World class:-
For the sketch using this code see my fork Dan Shiffmans The Nature of Code Examples.
# Class provides an OO way constraining a Mover in a 2D space # use # world = World.new((0..width), (0..height)) # world.constrain_mover(mover) class World attr_reader :xrange, :yrange def initialize(xrange, yrange) @xrange, @yrange = xrange, yrange end # @param mover is expected respond to loc, vel # that in turn respond to x and y getter/setters (Vec2D does this) def constrain_mover(mover) # Note clip functionality, extends Range in ruby-processing unless xrange.cover? mover.loc.x mover.vel.x *= -1 mover.loc.x = xrange.clip mover.loc.x end return if yrange.cover? mover.loc.y mover.vel.y *= -1 mover.loc.y = yrange.clip mover.loc.y end end
For the sketch using this code see my fork Dan Shiffmans The Nature of Code Examples.
Labels:
clip,
constrain,
Dan Shiffman,
range,
ruby-processing,
Vec2D
Thursday, 9 January 2014
Penrose tiling generator (after Shiffman)
Previously I have experimented with cfdg and lsystems to generate penrose tiling, this version by Dan Shiffman seems very similar to the cfdg version. Interestingly Dan ported this somewhat from python, and here we end with a ruby version. Dan unsurprisingly makes use of the PVector class to do the vector math here we use my Vec2D from the ruby-processing vecmath library, which is far more concise (designed to use arithmetic operators from the outset). Here is the sketch, somewhat drier than the original with choosable options via control panel (it is necessary to press "reset" to change seed/triangle type):-
Here is the tile library:-
Here is a screenshot, before I added second checkbox
# Penrose Tile Generator # Using a variant of the "ArrayList" recursion technique: http://natureofcode.com/book/chapter-8-fractals/chapter08_section4 # Penrose Algorithm from: http://preshing.com/20110831/penrose-tiling-explained # Daniel Shiffman May 2013 # Translated (and refactored) to ruby-processing Jan 2014 by Martin Prout load_libraries :vecmath, :tile, :control_panel attr_reader :tris, :s, :panel, :hide, :acute def setup size(1024, 576) control_panel do |c| c.title = "Tiler Control" c.look_feel "Nimbus" c.checkbox :seed c.checkbox :acute c.button :generate c.button :reset! @panel = c end @hide = false init false # defaults to regular penrose end def draw # only make control_panel visible once, or again when hide is false unless hide @hide = true panel.setVisible(hide) end background(255) translate(width/2, height/2) tris.each do |t| t.display end end def generate next_level = [] tris.each do |t| more = t.subdivide more.each do |m| next_level << m end end @tris = next_level end def reset! Tiler.acute(acute) # set the Tiler first init @seed java.lang.System.gc # but does it do any good? end def init alt_seed @tris = [] 10.times do |i| # create 36 degree segments a = Vec2D.new b = Vec2D.from_angle((2 * i - 1) * PI / 10) c = Vec2D.from_angle((2 * i + 1) * PI / 10) b *= 370 c *= 370 if alt_seed tile = (i % 2 == 0)? Tiler.tile(b, a, c) : Tiler.tile(c, a, b) tris << tile else tile = (i % 2 == 0)? Tiler.tile(a, b, c) : Tiler.tile(a, c, b) tris << tile end end end
Here is the tile library:-
module Tiler @@acute = false def self.acute(x) @@acute = x end # setup the initial tiling with all red tiles def self.tile(a, b, c) tile = (@@acute)? ATile.new(0, a, b, c) : Tile.new(0, a, b, c) end end class Tile include Processing::Proxy PHI = (1.0 + Math.sqrt(5)) / 2.0 # golden ratio RED = [255, 0, 0] BLUE = [0, 0, 255] COLORS = [RED, BLUE] attr_reader :a, :b, :c, :col def initialize(col, a, b, c) @col, @a, @b, @c = col, a, b, c end def display no_stroke fill(*COLORS[col]) triangle(a.x, a.y, b.x, b.y, c.x, c.y) #fill(0,0,255) #ellipse(a.x,a.y,4,4) #ellipse(b.x,b.y,4,4) #ellipse(c.x,c.y,4,4) end def subdivide result = [] if (col == 0) # Subdivide red triangle p = b - a p /= PHI p += a result << Tile.new(0, c, p, b) result << Tile.new(1, p, c, a) else # Subdivide blue triangle q = a - b q /= PHI q += b r = c - b r /= PHI r += b result << Tile.new(1, r, c, a) result << Tile.new(1, q, r, b) result << Tile.new(0, r, q, a) end return result end end class ATile < Tile def subdivide result = [] if (col == 0) # Subdivide red (half kite) triangle q = b - a q /= PHI q += a r = c - b r /= PHI r += b result << ATile.new(1, r, q, b) result << ATile.new(0, q, a, r) result << ATile.new(0, c, a, r) else # Subdivide blue (half dart) triangle p = a - c p /= PHI p += c result << ATile.new(1, b, p, a) result << ATile.new(0, p, c, b) end return result end end
Here is a screenshot, before I added second checkbox
Labels:
control panel,
penrose tiling,
ruby-processing,
Vec2D
Subscribe to:
Posts (Atom)
Followers
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

