OpenGL でごく単純なフライトシミュレータ

OpenGL の Ruby ミニライブラリ - Marginalia


 

require './miniopengl'

L = 0.5
vertex = [[-L, -L, -L], [L, -L, -L], [L, L, -L], [-L, L, -L],
     [L, -L, L], [-L, -L, L], [-L, L, L], [L, L, L]]
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]]

Mesh = 20

v = View.new
v.r      = Vector[0, 10, 1]
v.toward = Vector[0, -1, 0]
v.up     = Vector[0, 0, -1]

MiniOpenGL.app width: 400, height: 400, buffering: :on do
  clear_color(0, 0, 0.3)
  
  draw do
    clear
    color(0.6, 0, 0)
    (-Mesh..Mesh).each do |i|
      line3(i, 0, Mesh, i, 0, -Mesh)
      line3(Mesh, 0, i, -Mesh, 0, i)
    end
    color(0, 1, 0)
    draw_elements(GL_LINES, 3, vertex.flatten, edge.flatten)
    swap_buffers
  end
  
  reshape do |w, h|
    clear
    viewport(0, 0, w, h)
    init_projection
    perspective(30, w / h.to_f, 0.1, 50)
  end
  
  repeat(100) do
    init_modelview
    look_at(v.r[0], v.r[1], v.r[2], v.target[0], v.target[1], v.target[2], v.up[0], v.up[1], v.up[2])
    redisplay
    v.next
  end
  
  key_in do |key|
    th = 0.9 * PI / 180
    case key
    when "u"    #上
      v.headup(th)
    when "d"    #下
      v.headup(-th)
    when "l"    #左
      v.turn(th)
    when "r"    #右
      v.turn(-th)
    when "z"    #左回転
      v.screw(th)
    when "x"    #右回転
      v.screw(-th)
    when " "    #原点方向を向く
      r = v.r
      v.toward = -r / r.norm
      l = v.toward.cross(Vector[0, 1, 0])
      v.laxs = l / l.norm
      v.up = v.laxs.cross(v.toward)
    when "\r"   #決まった位置から再スタート
      v.r = Vector[0, 0.3, 10]
      v.toward = Vector[0, 0, -1]
      v.up = Vector[0, 1, 0]
    end
  end
end

 
class View

class View
  def initialize
    @r = Vector[0, 0, 10.0]
    @up = Vector[0, 1.0, 0]
    
    @toward = Vector[0, 0, -1.0]
    @step = 0.1
    cal_target
    last_axis
  end
  attr_accessor :r, :up, :toward, :target, :to, :step, :lax
  
  def cal_target
    @target = @r + @toward
  end
  private :cal_target
  
  def next(step = nil)
    @step = step if step
    @step
    @r = @r + @toward * @step
    cal_target
  end
  
  def last_axis
    @laxs = @toward.cross(@up)
  end
  private :last_axis
  
  def screw(th)
    @up, @laxs = @up * cos(th) + @laxs * sin(th), -@up * sin(th) + @laxs * cos(th)
  end
  
  def headup(th)
    @toward, @up = @toward * cos(th) + @up * sin(th), -@toward * sin(th) + @up * cos(th)
    cal_target
    last_axis
  end
  
  def turn(th)
    @laxs, @toward = @laxs * cos(th) + @toward * sin(th), -@laxs * sin(th) + @toward * cos(th)
  end
end