Skip to content

Instantly share code, notes, and snippets.

@monkstone
Created July 12, 2011 18:18
Show Gist options
  • Save monkstone/1078591 to your computer and use it in GitHub Desktop.
Save monkstone/1078591 to your computer and use it in GitHub Desktop.
A little ruby script to create Rod Hilbert
class Rod_Hilbert < Processing::App
#full_screen # NB: All distances are relative to screen height
load_libraries 'grammar', 'lut'
import 'lut'
attr_reader :grammar, :production, :distance, :depth, :centre_adjust
# some lsystem constants
CENTER_ADJUST = [0, 0.5, 1.5, 3.5, 7.5]
XPOS = 0
YPOS = 1
ANGLE = 2
BEN = Math::PI/720 # use BEN to create a bent Hilbert
THETA = Math::PI/2 # + BEN
PHI = Math::PI/2 #- BEN
AXIOM = "A"
def setup()
size 600, 600, P3D
#render_mode P3D
LUT.initialize
@grammar = Grammar.new(AXIOM)
@grammar.add_rule "A", "B>F<CFC<F>D+F-D>F<1+CFC<F<B1^"
@grammar.add_rule "B", "A+F-CFB-F-D1->F>D-1>F-B1>FC-F-A1^"
@grammar.add_rule "C", "1>D-1>F-B>F<C-F-A1+FA+F-C<F<B-F-D1^"
@grammar.add_rule "D", "1>CFB>F<B1>FA+F-A1+FB>F<B1>FC1^"
@depth = 2
reset(depth)
camera(width/2.0, height/2.0, 600, 0, 0, 0, 0, -1, 0)
noStroke()
end
def reset(depth)
@distance = 380
create_grammar(depth)
end
def create_grammar(gen)
if (gen > 0)
@distance *= 1.0/((2**gen) - 1.0)
@production = grammar.generate gen
end
end
def render(production)
"""
Render evaluates the production string and calls box primitive
uses processing affine transforms (translate/rotate)
"""
lightSpecular(30, 30, 30)
ambient(192, 192, 192)
ambientLight(80, 80, 80)
directionalLight(0, 0, 0, 80, 80, 80)
specular(40, 40, 40)
shininess(0.3)
fill(192, 192, 192)
sphere_detail(10)
sphere(distance/7) # first sphere end cap
repeat = 1
production.scan(/./) do |ch|
case(ch)
when "F"
draw_rod(distance) # NB: translation done in draw_rod
when '+'
rotate_x(THETA * repeat)
repeat = 1
when '-'
rotate_x(-THETA * repeat)
repeat = 1
when '>'
rotate_y(THETA * repeat)
repeat = 1
when '<'
rotate_y(-THETA * repeat)
when '^'
rotateZ(PHI * repeat)
repeat = 1
when '1'
repeat = 2
when 'A', 'B', 'C', 'D'
else
puts("character '#{ch}' not in grammar")
end
end
end
def draw_rod(distance)
sides = 10
radius = distance/7
angle = 0
angle_increment = 360 / sides
translate(0, 0, -distance / 2.0)
begin_shape(QUAD_STRIP)
for i in 0...sides+1
normal(LUT.cos(angle), LUT.sin(angle), 0)
vertex(radius*LUT.cos(angle), radius*LUT.sin(angle), -distance/2)
vertex(radius*LUT.cos(angle), radius*LUT.sin(angle), distance/2)
angle += angle_increment
end
end_shape()
translate(0, 0, -distance/2)
sphere(radius)
end
def draw()
background(10, 10, 200)
lights()
push_matrix()
rotate_x(LUT.sin(frame_count))
rotate_y(LUT.cos(frame_count))
push_matrix()
translate( distance * CENTER_ADJUST[depth], -distance * CENTER_ADJUST[depth], distance * CENTER_ADJUST[depth])
render(production)
pop_matrix()
pop_matrix()
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment