DZone Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

Snippets has posted 5883 posts at DZone. View Full User Profile

OpenGL Ruby Example

04.10.2006
| 17016 views |
  • submit to reddit
        From <a href="http://alterego.freeshell.org/gtk-gl.rb">http://alterego.freeshell.org/gtk-gl.rb</a>

#!/usr/bin/env ruby
require 'gtkglext'

## -----------------------------------------------------------------------------
## A generic class for OpenGL application functions.
## -----------------------------------------------------------------------------
class GLRender
  attr_reader :fov

  def initialize(fov = 90.0)
    @fov = fov
  end

  ## Initialise OpenGL state for 3D rendering.
  def init()
    GL.ShadeModel(GL::SMOOTH)
    GL.Enable(GL::DEPTH_TEST)
    GL.DepthFunc(GL::LEQUAL)
    GL.ClearColor(0.0, 0.0, 0.0, 0.0)
    GL.Hint(GL::PERSPECTIVE_CORRECTION_HINT, GL::NICEST)
    true
  end

  ## Resize OpenGL viewport.
  def resize(width, height)
    GL.Viewport(0, 0, width, height)

    GL.MatrixMode(GL::PROJECTION)
    GL.LoadIdentity()
    GLU.Perspective(@fov, width.to_f() / height.to_f(), 0.1, 1024.0)
    
    GL.MatrixMode(GL::MODELVIEW)
    GL.LoadIdentity()
  end

  ## Render OpenGL scene.
  def draw()
    GL.Clear(GL::COLOR_BUFFER_BIT | GL::DEPTH_BUFFER_BIT)
    GL.LoadIdentity()

    ## Scene view translation. ---------------------------------------------->>>
    GL.Translate(0.0, 0.0, -1.0)
    GL.Rotate(0.0, 0.0, 0.0, 0.0)
    ## -------------------------------------------------------------------------

    ## Scene Rendering Code ------------------------------------------------->>>
    GL.Begin(GL::TRIANGLES)
      GL.Color3f(0, 0, 1)
      GL.Vertex2f(-1, -1)
      GL.Color3f(0, 1, 0)
      GL.Vertex2f(1, 1)
      GL.Color3f(1, 0, 0)
      GL.Vertex2f(1, -1)
    GL.End()
    ## -------------------------------------------------------------------------

    GL.Flush()
  end
end

## -----------------------------------------------------------------------------
## A GtkDrawingArea widget with OpenGL rendering capabilities.
## -----------------------------------------------------------------------------
class GLDrawingArea < Gtk::DrawingArea
  def initialize(width, height, fov, gl_config)
    super()
    set_size_request(width, height)
    set_gl_capability(gl_config)

    ## Create an OpenGL renderer instance.
    @render = GLRender.new(fov)

    ## Signal handler for drawing area initialisation.
    signal_connect_after("realize") do
      gl_begin() { @render.init() }
    end

    ## Signal handler for drawing area reshapes.
    signal_connect_after("configure_event") do
      gl_begin() { @render.resize(allocation.width, allocation.height) }
    end

    ## Signal handler for drawing area expose events.
    signal_connect_after("expose_event") do
      gl_begin() do
        @render.draw()
      end

      gl_drawable.swap_buffers() if gl_drawable.double_buffered?
    end

    ## Add mouse button press/release signal event handlers
    add_events(Gdk::Event::BUTTON_PRESS_MASK |
               Gdk::Event::BUTTON_RELEASE_MASK)

    signal_connect_after("button_press_event") { button_press_event() }
    signal_connect_after("button_release_event") { button_release_event() }
  end

  def gl_begin()
    gl_drawable.gl_begin(gl_context) { yield }
  end

  def button_press_event()
    puts "button_press_event"
    true
  end

  def button_release_event()
    puts "button_release_event"
    true
  end
end

## -----------------------------------------------------------------------------
## Application GUI Main Window Class
## -----------------------------------------------------------------------------
class AppWindow < Gtk::Window
  attr_reader :gl_area

  def initialize(title, width, height, fov, gl_config)
    super(title)

    ## Connect signals to handle keyboard user input.
    signal_connect_after("key_press_event") { key_press_event() }
    signal_connect_after("key_release_event") { key_release_event() }

    ## Create our GL drawing area widget.
    @gl_area = GLDrawingArea.new(width, height, fov, gl_config)

    add(@gl_area)
    show_all()
  end

  def key_press_event()
    puts "key_press_event"
    true
  end

  def key_release_event()
    puts "key_release_event"
    true
  end
end

## -----------------------------------------------------------------------------
## Application Class
## -----------------------------------------------------------------------------
class GtkGLApp
  attr_reader :window

  def initialize(title, width, height, bpp)
    ## Initialise Gtk[GLExt] library.
    Gtk.init()
    Gtk::GL.init()

    ## Obtain a valid OpenGL context configuration.
    gl_config = Gdk::GLConfig.new(Gdk::GLConfig::MODE_DEPTH |
                                  Gdk::GLConfig::MODE_DOUBLE |
                                  Gdk::GLConfig::MODE_RGBA)

    ## Create application main interface window.
    @window = AppWindow.new(title, width, height, 90.0, gl_config)

    @window.signal_connect_after("delete_event") do
      puts "Closing application."
      @window.destroy()
      Gtk.main_quit()
    end
  end

  def main()
    Gtk.main()  ## Enter into Gtk's main event processing loop.
    true
  end
end

## -----------------------------------------------------------------------------
## Application Entry Point
## -----------------------------------------------------------------------------
if $0 == __FILE__
  ## Create new application context.
  context = GtkGLApp.new("Gtk GL Application", 256, 256, 16)
  context.main()  ## Enter into the main execution loop.
end