Ruby-FFIでODEを動かす実験4

それっぽくなってきました。
細かいところでおかしなところありますが、当初イメージしていた形に近づいてきています。
とりあえず動いています。

require 'ffi-ode'
require 'ffi-draw_stuff'

ODE.dInitODE

@world = ODE::World.new do |w|
  w.gravity = [0,0,-9.8]
end
@space = ODE::Space.new :Hash
@collide = ODE::Collide.new @world, @space

ODE::Geom::Plane.new @space, [0.0, 0.0, 1.0, 0]

@shapes = []
@shapes << (ODE::Geom::Sphere.new @space do |g|
  g.radius = 1.0
  g.body = ODE::Body.new @world do |b|
    b.mass.sphere_total = [1.0, g.radius]
  end
  g.position = [0,0,10]
  g.instance_eval do
    def draw
      DrawStuff.set_color(1,0,0)
      DrawStuff.draw_sphere position, rotation, radius
    end
  end
end)

DrawStuff.simulation do |fn|
  fn.size = "600x400"
  fn.start = Proc.new { DrawStuff.set_viewpoint [5,0,3], [180,-20,0] }

  fn.step = Proc.new do |pause|
    @collide.check
    @world.step 0.01 if pause == 0

    @shapes.each {|shape| shape.draw}
  end
end

APIは元の関数名を変形しています。
たとえば、dBodyGetPosition なら、
第一引数のdBodyIDをクラスメンバーにしておいて、
メソッド名はdBodyを除いたget_positionもしくはaliasとしてpositionでアクセスできるようにしています。

collideは記述が面倒なので、デフォルトは隠しておいて、カスタマイズしたい時はオーバーライドのようにできるようにしたいと思っています。
ひつようなのは、
@collide = ODE::Collide.new @world, @space
@collide.check
だけです。checkは適当にメソッド名付けました。もう少し良いネーミングあれば。。

world,spaceをそれぞれのオブジェクトに渡さないといけないところなんとかなるかなぁ。
ただ、これ以上隠してしまうと使いにくくなりそうなので考えどころです。
あと、DrawStuff.simulationで実行してしまっているが、設定と実行を分けたほうが使いやすいかもしれないです。.simuation書いてから.runで実行とか。