読者です 読者をやめる 読者になる 読者になる

OpenGL のラッパーモジュール Opal を書いた(Ruby)

RubyOpenGL 遊びをしているうち、同じことを繰り返し書くのに飽きたので、せっかく Ruby を使っているのだから少しだけ Ruby っぽくするラッパーモジュール「オパール Opal」を書いた。Gem 'OpenGL' は、C言語のコードを移植するには便利なのだが。なお、当然 Gem 'OpenGL', 'Glu', 'Glut' が必要です。

コードやサンプルなどはとりあえずHPのここにある。

なお、ただのラッパーモジュールなので、(使おうと思えば)'OpenGL', 'Glu', 'Glut' の全機能が使えます。ただ、典型的な処理をできるだけ楽にやろうという目的なので、面倒なことがやりたい人には(たぶん)向きません。怠惰な人向き。

ウインドウを表示させるのはたったこれだけ。以下 require './opal' は書かない。

require './opal'
 
Opal.app do |g|
  g.display = proc {glFlush}
end



頂点配列。

Opal.app title: "Polygon", width: 500, height: 500 do |g|
  g.display = proc do
    vertex = [-0.9, 0.9, 0.9, 0.9, 0, -0.9]
    g.color(0, 1, 0)
    glLineWidth(3)
    g.draw_vertex(GL_LINE_LOOP, 2, vertex)
    glFlush
  end
end




3次元表示。ぐるぐる回る。変数 gl は姑息な手段。すべて Opal.app のブロックの中に収めるならブロック変数 g だけで OK。

gl = nil
vertex = [[0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 1, 0],
     [1, 0, 1], [0, 0, 1], [0, 1, 1], [1, 1, 1]]
edge = [[0, 1], [1, 2], [2, 3], [3, 0], [4, 5], [5, 6],
     [6, 7], [7, 4], [0, 5], [1, 4], [2, 7], [3, 6]].flatten
vertex = vertex.map {|v| [v[0] - 0.5, v[1] - 0.5, v[2] - 0.5]}.flatten

timer = proc do
  gl.rotate(10)
  gl.redraw
  gl.timer(100, timer)
end

init = proc do
  glEnable(GL_BLEND)
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
  gl.clr_matrix
  gluLookAt(3, 4, 5, 0, 0, 0, 0, 1, 0)
end


Opal.app title: "3d" do |g|
  gl = g
  init.call
  g.rotate = [0, 1, 0]
  
  g.display = proc do
    g.color(0, 1, 0)
    g.draw_elements(GL_LINES, 3, vertex, edge)
    glFlush
  end
  g.reshape = proc {|w, h| gluPerspective(30, w / h.to_f, 3, 10)}
  g.timer(100, timer)
end




3次元表示。混合処理と隠面消去とダブルバッファリングとカリングを行っている。

gl = nil
A = Math.sqrt(3) / 2
vertex = [[0, A / 2, 0], [-0.5, -A / 2, 0], [0.5, -A / 2, 0], [0, 0, A]]
face = [[0, 1, 2], [0, 3, 2], [0, 1, 3], [1, 2, 3]]
color = [[1, 1, 1], [1, 0, 0], [0, 1, 0], [0, 0, 1]]
 
display = proc do
  gl.draw(GL_TRIANGLES) do
    face.each_with_index do |ar, j|
      gl.color(color[j][0], color[j][1], color[j][2])
      ar.each {|i| glVertex3dv(vertex[i])}
    end
  end
end
 
timer = proc do
  gl.rotate(15)
  gl.redraw
  gl.timer(100, timer)
end
 
init = proc do
  glEnable(GL_BLEND)      #混合処理を可能にする
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
  gl.color_alpha = 0.8    #アルファ値(透け具合)
  glEnable(GL_DEPTH_TEST) #深度テストを有効にする(隠面消去を有効にする)
  gl.clr_matrix
  gluLookAt(4, 0, 1, 0, 0, A / 2, 0, 0, 1)
end
 
 
Opal.app title: "3d", buffering: GLUT_DOUBLE, depth: GLUT_DEPTH, culling: true do |g|
  gl = g
  init.call
  g.rotate = [0, 0, 1]
   
  g.display = display
  g.reshape = proc {|w, h| gluPerspective(30, w / h.to_f, 3, 10)}
  g.timer(100, timer)
end

上にリンクしておいたHPに、もう少し例があるので、そちらを参照して下さい。
たぶん、そのうちもう少しごちゃごちゃとイジると思う。

クロージャはえらいですなあ。