I've never done OpenGL before. So after looking a some examples here's
what I came up with. I did this pretty quick so there are many things
that ought to be fixed (like the mess of global variables), but it gets
the job done. Like the curses submission, pressing enter repeatedly
will add the next iteration. I don't have automatic resizing yet so
after you press enter, to get it to look right you have to resize the
window. Maybe I'll think about that a bit later (suggestions are
welcome on how resizing should be done). Anyways thanks for the quiz!

-----Jay Anderson

require 'opengl'
require 'glut'

class Array
    def rotate!
        push shift
    end
    def rotate
        self.dup.rotate!
    end
end

key_func = lambda do |key,x,y|
    case key
    when ?Q, ?q
        exit 0
    when ?\r, ?\n
        side = $width>$height ? $width : $height
        sq_x, sq_y = $x, $y
        case $add_to.first
        when :right
            sq_x = $x + $width
            $width += side
        when :left
            sq_x = $x - side
            $x = sq_x
            $width += side
        when :top
            sq_y = $y + $height
            $height += side
        when :bottom
            sq_y = $y - side
            $y = sq_y
            $height += side
        end
        $squares << {
            :side => side,
            :x => sq_x,
            :y => sq_y,
            :color => [rand, rand, rand]
        }

        $add_to.rotate!
    end
    GLUT.PostRedisplay
end

reshape_func = lambda do |w,h|
    $screen_width = w
    $screen_height = h
    range = ($width>$height ? $width : $height)
    border = range * 0.05
    left, right = $x-border, $x+range+border
    bottom, top = $y-border, $y+range+border
    aspect = w.to_f/h.to_f
    if w <= h then
        bottom /= aspect
        top /= aspect
    else
        left *= aspect
        right *= aspect
    end
    GL.Viewport(0, 0, w, h)
    GL.MatrixMode GL::PROJECTION
    GL.LoadIdentity
    GLU::Ortho2D(left, right, bottom, top)
    GL.MatrixMode GL::MODELVIEW
end

display_func = lambda do
    GL.Clear GL::COLOR_BUFFER_BIT | GL::DEPTH_BUFFER_BIT

    $squares.each do |s|
        GL.Translate(s[:x], s[:y], 0.0)
        side = s[:side]
        GL.Begin(GL::QUADS)
        GL.Color(*s[:color])
        GL.Vertex(0.0, 0.0)
        GL.Vertex(side, 0.0)
        GL.Vertex(side, side)
        GL.Vertex(0.0, side)
        GL.End
        GL.Translate(-s[:x], -s[:y], 0.0)
    end

    GL.Flush
end

GLUT.Init
GLUT.InitDisplayMode GLUT::SINGLE | GLUT::RGB | GLUT::DEPTH
GLUT.CreateWindow "Fibonacci"
GL.FrontFace GL::CW
GL.Enable(GL::DEPTH_TEST)

$screen_width = GLUT.Get(GLUT::WINDOW_WIDTH)
$screen_height = GLUT.Get(GLUT::WINDOW_HEIGHT)
$squares = []
$squares << {
    :side => 1.0,
    :x => 0.0,
    :y => 0.0,
    :color => [rand, rand, rand]
}
$width = 1.0
$height = 1.0
$x = 0.0
$y = 0.0
$add_to = [:right, :bottom, :left, :top]

GLUT.KeyboardFunc key_func
GLUT.ReshapeFunc reshape_func
GLUT.DisplayFunc display_func

GLUT.MainLoop