Ruby + SDL + OpenGL 2

Posted by Chris Thu, 31 Jan 2008 08:27:00 GMT

I started playing around with Ruby, rubysdl and ruby-opengl tonight. I’m not really sure where the last 6 hours went…

In six hours I went from knowing almost no OpenGL, a basic understanding of Ruby, and absolutely nothing about SDL to having a full screen OpenGL app written in Ruby that shows the JPGs in the current directory in a coverlow-esque manner that you can flip through with the left and right arrow keys. I’m amazed. The whole thing is only like 200ish lines long, and I’ll attach it so if anyone finds it while looking up how to do OpenGL stuff in Ruby you can maybe benefit from my hours of digging through random documentation and websites. It’s really strange, but the only actual OpenGL/GLU documentation I could find was in PDF form…that’s nuts.

Sometime after I get some sleep I’ll try to write up some tutorials.

Edit: So, I can’t figure out how to attach things right now, I’ll get it up later.

Edit: Here’s a link to download: Source

Edit: Here’s a link to look at it online: Online Source

Trackbacks

Use the following link to trackback from your own site:
http://www.staticmethod.net/trackbacks?article_id=ruby-sdl-opengl&day=31&month=01&year=2008

Comments

Leave a comment

  1. Ranska 18 days later:

    Hi thank for this good source. To run it corectly i have fixe some bugs.

    1) dont write glBindTex… but GL::BindTex… (idem not glublabl but GLU::bla

    2) GL::LoadIdentity() but GL::LoadIdentity() 3) idem for GL::End but GL::End() 4) not GL::Translatef(a,b,c) but GL::Translate(a,b,c) 5) idem for Vertex Scale and Rotate

    6) lol but think that you need specifique texture dimention ex: 128128 256256 or 512*512 (but the last need lot-of memorie and slow_down your code)

    happy-ruby

    ranska

    here the code with bug fixed and tested in Linux Mandriva-2007/spring

    ps: I dont know why but in the prewiew some part of the text are bold? and new line not respercted:(

    #!/usr/bin/env ruby -rubygems
    # Name:  nehe_lesson02.rb
    # Purpose: An implementation of NeHe's OpenGL Lesson #02
    #          using ruby-opengl (http://nehe.gamedev.net/)
    # 
    
    #  some bug fixed by Ranska  
    #
    
    require "sdl"
    require "opengl"
    require "mathn"
    require "find"
    
    # Add GL and GLUT namespaces in to make porting easier
    #include Gl
    #include Glu        I have comment this because that didn't on my linux/mandriva
    #include Glut
    
    # Placeholder for the window object
    window = ""
    
    @objectsToDraw = Array.new
    
    class PictureCollection
        attr_accessor :current_picture
    
        def initialize
            @pictures = Array.new
            @current_picture = -1
        end
    
        def select_next_picture
            @current_picture += 1 if (@current_picture + 1) != @pictures.size
        end
    
        def select_previous_picture
            @current_picture -= 1 if (@current_picture - 1) >= 0
        end
    
        def num_prepictures
            if @current_picture > -1
                @current_picture
            else
                0
            end
        end
    
        def num_postpictures
            @pictures.size - @current_picture - 1
        end
    
        def get_picture(pos)
            @pictures[pos] if pos > -1
        end
    
        def add_picture(pic)
            @pictures.push pic
            @current_picture = 0 if(@current_picture == -1)
        end
    
        def each
            @pictures.each do |pic|
                yield pic
            end
        end
    
        def length
            @pictures.length
        end
    end
    
    class Picture 
      def initialize(filename, number)
        surface = SDL::Surface.load(filename)
        texture = GL::GenTextures(1)
        GL::BindTexture(GL::TEXTURE_2D, texture[0])
        GL::TexImage2D(GL::TEXTURE_2D, 0, 3, surface.w, surface.h, 0, GL::RGB, GL::UNSIGNED_BYTE, surface.pixels)
        GL::TexParameteri(GL::TEXTURE_2D, GL::TEXTURE_MIN_FILTER, GL::LINEAR)
        GL::TexParameteri(GL::TEXTURE_2D, GL::TEXTURE_MAG_FILTER, GL::LINEAR)
        surface = nil #hopefully this gets garbage collected
        @textureId = texture[0] # Store the Texture ID
      end
    
    def draw
        GL::BindTexture(GL::TEXTURE_2D, @textureId)
        GL::MatrixMode(GL::TEXTURE)
        GL::LoadIdentity()
        GL::Rotate(180,0,0,1)
        GL::Scale(-1,1,1)
        GL::MatrixMode(GL::MODELVIEW)
        # Draw a rectangle
        GL::Begin(GL::QUADS)
          GL::TexCoord(0,0)
          GL::Vertex(-1.0, -1.0, 0.0) # Bottom Left
          GL::TexCoord(1,0)
          GL::Vertex( 1.0, -1.0, 0.0) # Bottom Right
          GL::TexCoord(1,1)
          GL::Vertex( 1.0,  1.0, 0.0) # Top Right
          GL::TexCoord(0,1)
          GL::Vertex(-1.0,  1.0, 0.0) # Top Left
        GL::End()
      end
    end
    
    def init_gl_window(width = 640, height = 480)
            GL::Viewport(0,0, width, height)
        # Background color to black
        GL::ClearColor(0.0, 0.0, 0.0, 0)
        # Enables clearing of depth buffer
        GL::ClearDepth(1.0)
        # Set type of depth test
        GL::DepthFunc(GL::LEQUAL)
        # Enable Textures
       GL::Enable(GL::TEXTURE_2D)
        # Enable depth testing
        GL::Enable(GL::DEPTH_TEST)
        # Enable smooth color shading
        GL::ShadeModel(GL::SMOOTH)
        GL::MatrixMode(GL::PROJECTION)
        GL::LoadIdentity()
        # Calculate aspect ratio of the window
        GLU::Perspective(60.0, width / height, 0.1, 100.0)
        GL::MatrixMode(GL::MODELVIEW)
    
    end
    
    #draw_gl_scene = Proc.new do
    def draw_gl_scene
        # Clear the screen and depth buffer
        GL::Clear(GL::COLOR_BUFFER_BIT | GL::DEPTH_BUFFER_BIT)
        # Reset the view
        GL::MatrixMode(GL::MODELVIEW);
        GL::LoadIdentity();
            # Draw main picture
            GL::Translate(0,0,-4)
            @objectsToDraw.get_picture(@objectsToDraw.current_picture).draw ;
            GL::LoadIdentity();
            # Draw pre pictures
            if(@objectsToDraw.num_prepictures > 0)
                pos = @objectsToDraw.current_picture - 1
                GL::Translate(-3.0,0,-6.0) # Starting position
                GL::Rotate(45.0,0,1,0)
                while pos >= 0
                    @objectsToDraw.get_picture(pos).draw
                    pos -= 1
                    GL::Translate(-0.3,0,-1);
                end 
            end
            GL::LoadIdentity()
            # Draw post pictures
            if(@objectsToDraw.num_postpictures > 0)
                pos = @objectsToDraw.current_picture + 1
                GL::Translate(3.0,0,-6.0) # Starting position
                GL::Rotate(-45.0,0,1,0)
                while pos < @objectsToDraw.length
                    @objectsToDraw.get_picture(pos).draw
                    pos += 1
                    GL::Translate(0.3,0,-1);
                end 
            end
            # Swap buffers for display 
        SDL.GLSwapBuffers
    end
    
    
    # début du script
    #
    #
    #
    SDL.init(SDL::INIT_VIDEO)
    SDL.setGLAttr(SDL::GL_DOUBLEBUFFER,1)
    SDL.setVideoMode(1280, 800, 0, SDL::FULLSCREEN|SDL::OPENGL|SDL::HWSURFACE)
    init_gl_window(1280, 800)
    @objectsToDraw = PictureCollection.new
    pos = 0
    Find.find(".") do |path|
        if FileTest.directory?(path) && path != "."
            Find.prune
        elsif File.extname(path) == ".jpg"
            puts path
            @objectsToDraw.add_picture Picture.new(path, pos)
            pos += 1
        end
    end
    
    # Main Loop
    loop do
        event = SDL::Event2.poll
        if !event.nil?
            break if event.is_a?(SDL::Event2::Quit)
            if event.is_a?(SDL::Event2::KeyDown) # This means it's some kind of key press
                @objectsToDraw.select_next_picture if event.sym == SDL::Key::RIGHT
                @objectsToDraw.select_previous_picture if event.sym == SDL::Key::LEFT
                exit if event.sym == SDL::Key::ESCAPE
            end
        end
        draw_gl_scene
    end
  2. Chris 27 days later:

    Ranska, Thanks for the comments, I’ve actually done quite a bit of work since posting this. I’ll be pretty close to posting an update and providing a link to my SVN repository pretty soon hopefully.

    I’m not sure why doing the include GL, etc didn’t work for you. The gl* methods are part of the GL module. I think you might be using an older version of the ruby-opengl gem, their tutorial seems to indicate that what you provided is their old naming structure.

Comments