書籍内のサンプルコードをOpalで書き直したものです。書籍のコードと比べ、かなりシンプルに書けていると思います。
コード最上部の require './opal' は以下すべて省略してあります。実際にはこれを書き加えて下さい。
書籍内のサンプルコードをOpalで書き直したものです。書籍のコードと比べ、かなりシンプルに書けていると思います。
コード最上部の require './opal' は以下すべて省略してあります。実際にはこれを書き加えて下さい。
p.42. キーでアームの角度を変えることができます。
p3-robot.rb
gl = nil shoulder = elbow = 0 display = proc do gl.clr_matrix glTranslated(-2, 0, -5) gl.block do gl.rotate(shoulder) glTranslated(1, 0, 0) gl.block do glScaled(2, 0.4, 1) glutWireCube(1) end glTranslated(1, 0, 0) gl.rotate(elbow) glTranslated(1, 0, 0) gl.block do glScaled(2, 0.4, 1) glutWireCube(1) end end end keyboard = proc do |key| case key when "s" shoulder = (shoulder + 5) % 360 when "S" shoulder = (shoulder - 5) % 360 when "e" elbow = (elbow + 5) % 360 when "E" elbow = (elbow - 5) % 360 when " " exit end gl.redraw end Opal.app width: 500, height: 500, buffering: GLUT_DOUBLE do |g| gl = g g.rotate = [0, 0, 1] g.display = display g.reshape = proc {gluPerspective(60, 500 / 500, 0.1, 20)} g.keyboard = keyboard end
p.46. キーで惑星を、公転・自転させることができます。
p3-planet.rb
gl = nil year = day = 0 display = proc do gl.clr_matrix gluLookAt(0, 0, 5, 0, 0, 0, 0, 1, 0) gl.color(1, 1, 1) gl.block do glutWireSphere(1, 20, 16) #半径1、緯度方向の分割数20, 経度方向の分割数16の球 「太陽」 gl.rotate(year) glTranslated(2, 0, 0) gl.rotate(day) glutWireSphere(0.2, 10, 8) #「惑星」 end end keyboard = proc do |key| case key when "d" day = (day + 10) % 360 when "D" day = (day - 10) % 360 when "y" year = (year + 5) % 360 when "Y" year = (year - 5) % 360 when " " exit end gl.redraw end Opal.app width: 500, height: 500, buffering: GLUT_DOUBLE do |g| gl = g g.rotate = [0, 1, 0] g.display = display g.reshape = proc {gluPerspective(60, 500 / 500, 0.1, 20)} g.keyboard = keyboard end
p.57. 太陽系アニメーション。
p4-MovingPlanet.rb
gl = nil year = day = 0 sampling_time = 50 display = proc do gl.clr_matrix gluLookAt(0, 0, 5, 0, 0, 0, 0, 1, 0) gl.color(1, 1, 1) gl.block do glutWireSphere(1, 20, 16) gl.rotate(year) glTranslated(2, 0, 0) gl.rotate(day) glutWireSphere(0.4, 10, 8) end end Opal.app width: 500, height: 500, buffering: GLUT_DOUBLE do |g| gl = g g.perspective g.rotate = [0, 1, 0] g.display = display g.repeat(sampling_time) do year = (year + 1) % 360 day = (day + 5) % 360 g.redraw end g.keyboard = proc {|key| exit if key == " "} end
p.52. ティーポットが飛んできます。じつはティーポットは移動しておらず、視点が近づいている。
p4-FlyingTeaPot.rb
gl = nil theta = 0 dist = -10 display = proc do gl.block do gl.look_to = [0, 1, dist + 1] gl.look_at(0, 1, dist) gl.xyzAxis(length: 10) #座標軸の表示 gl.block do glTranslated(1, 2, 0) gl.rotate(theta) gl.color(1, 0, 0) glutWireTeapot(1) end gl.color(1, 1, 1) #床 -35.step(35, 2) do |i| gl.line(i, 0, -35, i, 0, 35) gl.line(-50, 0, i, 50, 0, i) end end end Opal.app width: 500, height: 500, buffering: GLUT_DOUBLE do |g| gl = g g.perspective(90, 500 / 500, 0.1, 20) g.clr_matrix g.rotate = [1, 1, 0] g.display = display g.idle = proc do dist += 0.03 g.idle = nil if dist >= -1 theta -= 360 if (theta += 0.5) >= 360 g.redraw end g.keyboard = proc {|key| exit if key == " "} end
p.66. 表示する倍率をメニューから選択します。画面下に倍率を表示します。
p5-menu.rb
gl = nil size_of_teapot = 1 getValueFromMenu = proc do |value| size_of_teapot = case value when 1 then 0.5 when 2 then 1 when 3 then 2 end end mySetMenu = proc do glutCreateMenu(getValueFromMenu) gl.add_menu("x 0.5", 1) gl.add_menu("x 1.0", 2) gl.add_menu("x 2.0", 3) glutAttachMenu(GLUT_RIGHT_BUTTON) #マウスの右ボタンでメニュー表示 end display = proc do gl.block do gl.clr_matrix glTranslated(0, 0, -3) gl.color(1, 0, 0) glutWireTeapot(size_of_teapot) gl.color(0, 1, 0) glRasterPos3d(-0.3, -1.5, 0) #文字の位置 str = "Size is " + sprintf("%4.1f", size_of_teapot) gl.print(str) #文字の表示 end end Opal.app width: 500, height: 500, buffering: GLUT_DOUBLE do |g| gl = g mySetMenu.call g.display = display g.reshape = proc {|w, h| gluPerspective(60, w / h.to_f, 0.1, 20)} g.idle = proc {g.redraw} g.keyboard = proc {|key| exit if key == " "} end
p6-Lights.rb
gl = nil mySetLight = proc do l0_position = [ 1, 1, 1, 1] l1_position = [-1, -1, 1, 1] l1_ambient = [0, 0, 0.5, 1] l1_diffuse = [0, 0, 1, 1] l1_specular = [0, 0, 1, 1] gl.light(0, GL_POSITION, l0_position) gl.light(1, GL_POSITION, l1_position) gl.light(1, GL_AMBIENT, l1_ambient) gl.light(1, GL_DIFFUSE, l1_diffuse) gl.light(1, GL_SPECULAR, l1_specular) gl.light_enable(0) gl.light_enable(1) end display = proc do mtrl_specular = [1, 1, 1, 1] mtrl_shininess = [50] glEnable(GL_DEPTH_TEST) glEnable(GL_LIGHTING) glMaterialfv(GL_FRONT, GL_SPECULAR, mtrl_specular) glMaterialfv(GL_FRONT, GL_SHININESS, mtrl_shininess) glutSolidSphere(1, 20, 16) glFlush end Opal.app width: 500, height: 500, depth: GLUT_DEPTH do |g| gl = g mySetLight.call glShadeModel(GL_SMOOTH) gluLookAt(0, 0, 3, 0, 0, 0, 0, 1, 0) g.display = display g.reshape = proc {|w, h| gluPerspective(60, w / h.to_f, 0.1, 20)} g.keyboard = proc {|key| exit if key == " "} end
箱が回転します。内側と外側で色がちがいます。
p6-LightModel.rb
gl = nil gPitch = 30 gYaw = 30 mySetLight = proc do l0_position = [1, 1, 1, 1] gl.light(0, GL_POSITION, l0_position) gl.light_enable glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, 1) #1はGL_TRUEの代わり end display = proc do gl.clr_matrix ambient = [0.7 , 0.7 , 0.7 , 1] diffuse = [0.75, 0.75, 0.75, 1] specular = [0.25, 0.25, 0.25, 1] insideface = [1, 0, 0, 1] glEnable(GL_DEPTH_TEST) glEnable(GL_LIGHTING) glMaterialfv(GL_FRONT, GL_AMBIENT, ambient) glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse) glMaterialfv(GL_FRONT, GL_SPECULAR, specular) glMaterialf(GL_FRONT, GL_SHININESS, 50) glMaterialfv(GL_BACK, GL_AMBIENT_AND_DIFFUSE, insideface) glMaterialf(GL_BACK, GL_SHININESS, 60) gl.block do glRotated(gPitch, 1, 0, 0) glRotated(gYaw , 0, 0, 1) gl.draw(GL_QUADS) do glNormal3d(0, 0, -1) gl.vtx3(-1, -1, -1) gl.vtx3(-1, 1, -1) gl.vtx3( 1, 1, -1) gl.vtx3( 1, -1, -1) glNormal3d(1, 0, 0) gl.vtx3( 1, -1, -1) gl.vtx3( 1, 1, -1) gl.vtx3( 1, 1, 1) gl.vtx3( 1, -1, 1) glNormal3d(-1, 0, 0) gl.vtx3(-1, -1, -1) gl.vtx3(-1, -1, 1) gl.vtx3(-1, 1, 1) gl.vtx3(-1, 1, -1) glNormal3d(0, 1, 0) gl.vtx3(-1, 1, -1) gl.vtx3(-1, 1, 1) gl.vtx3( 1, 1, 1) gl.vtx3( 1, 1, -1) glNormal3d(0, -1, 0) gl.vtx3(-1, -1, -1) gl.vtx3( 1, -1, -1) gl.vtx3( 1, -1, 1) gl.vtx3(-1, -1, 1) end end end reshape = proc do |w, h| a = 3 z = 20 if w <= h glOrtho(-a, a, -a * h.to_f / w, a * h.to_f / w, -z, z) else glOrtho(-a * w.to_f / h, a * w.to_f / h, -a, a, -z, z) end end Opal.app width: 500, height: 500, buffering: GLUT_DOUBLE, depth: GLUT_DEPTH do |g| gl = g g.clear_color = [0.2, 0, 0.3] g.clear_color_alpha = 1 mySetLight.call glShadeModel(GL_FLAT) gluLookAt(0, 0, 3, 0, 0, 0, 0, 1, 0) g.display = display g.reshape = reshape g.repeat(30) do gYaw = (gYaw + 1) % 360 gPitch = (gPitch + 1) % 360 g.redraw end g.keyboard = proc {|key| exit if key == " "} end