Ruby で OpenGL 遊びをしているうち、同じことを繰り返し書くのに飽きたので、せっかく 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に、もう少し例があるので、そちらを参照して下さい。
たぶん、そのうちもう少しごちゃごちゃとイジると思う。
クロージャはえらいですなあ。