Here is a 3D Hilbert in ruby-processing, you can see the basic shape if you set the number of repeats to 1. For me the best look was 3 iterations (starts to look a bit fuzzy with 4 repeats).
I used this application to test my grammar (and lsystem vanilla processing) library on 32 bit Windows (XP). Which worked OK for me, because linux has a bit of an issue about OPENGL with ruby-processing unless fullscreen (vanilla processing works s fine) I have used P3D here.
I'm sure it could work a bit better using opengl. It would be cool to use my vanilla library with ruby-processing but I can't find an interface for the java char in ruby....
########################################################
# A 3D Hilbert fractal implemented using a
# Lindenmayer System in ruby-processing by Martin Prout
########################################################
require 'hilbert'
class Hilbert_Test < Processing::App
load_libraries :grammar, :control_panel
attr_reader :hilbert, :y, :x
attr_accessor :x_view, :y_view, :zoom, :repeat
def setup()
size(500, 500, P3D)
setup_panel
@x_view = 400.0;
@y_view = 0.0;
@zoom = 9.0;
@hilbert = Hilbert.new
hilbert.create_grammar(3)
no_stroke()
camera(x_view, y_view, zoom, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0)
translate(width / 2, height / 2)
end
def setup_panel
control_panel do |c|
c.title = "Control:"
c.menu(:repeat, ['1', '2', '3', '4'], '3') {|m| load_menu_item(m) }
c.slider(:zoom, -100..400, zoom)
c.slider(:x_view, 300..700, x_view)
c.slider(:y_view, -400..400, y_view)
c.button :reset!
end
end
def reset!
x_view = 0.0
y_view = 0.0
zoom = 5
@hilbert = Hilbert.new
hilbert.create_grammar(repeat.to_i)
end
def load_menu_item(item)
repeat = item
end
def draw()
background(0)
hilbert.render()
ambient_light(0, 255, 0)
directional_light(0, 255, 0, 0.0, -1.0, 0.0)
camera(x_view, y_view, zoom, # eyeX, eyeY, eyeZ
0.0, 0.0, 0.0, # centerX, centerY, centerZ
0.0, 1.0, 0.0)
end
end
############################
# hilbert.rb
###########################
class Hilbert
include Processing::Proxy
attr_reader :grammar, :axiom, :production, :premis, :rule,
:theta, :scale_factor, :distance, :phi
def initialize()
@axiom = "X"
@grammar = Grammar.new(axiom)
@production = axiom
@premis = "X"
@rule = "^<XF^<XFX-F^>>XFX&F+>>XFX-F>X->"
@distance = 160
@theta = Math::PI/180 * 90
@phi = Math::PI/180 * 90
grammar.add_rule(premis, rule)
no_stroke()
end
def render()
production.scan(/./) do |ch|
case(ch)
when "F"
fill(0, 200, 0)
translate(0, distance/-2, 0)
box(distance/9 , distance, distance/9)
translate(0, distance/-2, 0)
when "+"
rotateX(-theta)
when "-"
rotateX(theta)
when ">"
rotateY(theta)
when "<"
rotateY(-theta)
when "&"
rotateZ(-phi)
when "^"
rotateZ(phi)
when "X"
else
puts("character '#{ch}' not in grammar")
end
end
end
##############################
# create grammar from axiom and
# rules (adjust scale)
##############################
def create_grammar(gen)
@distance *= 0.5**gen
@production = @grammar.generate gen
end
end
No comments:
Post a Comment