また日記をとめてしまった。コードも日記もこまめにコミットしないと!
日曜あたりにBulletMLの実行エンジンを作ってみたり。ついに流行にのるのかとかなんで弾幕なんてと散々言われる。俺が弾幕エンジン作ったらダメなのか!
パースはRubyなので簡単。どう作ろうかなーとかいいつつキーを叩いてたら出来てた。 式のパースもあるんだがそこも簡単だしね。
あとは実行部分だけだ。というかここが本番なんですが。
実行もそんなに難しくはないんだけど、命令列を途中で切り上げるwaitが入ってるのでこれをどうしようかなぁ。Fiberなんかで作ってもいいんだけど、そこまで大仰なことする必要はないから普通にwaitにぶつかったら戻っていくようにすればいいんだけどね。
あと実行部分は何気にパラメータの管理でスタックとか必要になりそうで真面目に書かないといけないな。 難しいわけではないんだが。
やっぱりちゃんと見ていくといろいろ分かってくる。シンプルなのに表現力は高いよなぁ。パーティクルの勉強に実装を始めたんだがやって良かったわ。
デスクトップマスコットは動くかなぁとやってみたら案の定動かなかった。
アセンブリシェーダをラッピングして使ってるところがシェーダ周りの変更についていけなかったようだ。想定していた通りではある。
じゃあ新しいのに対応してあげましょうと思ったが意外にめんどいな。実装しないといけないメソッドが沢山。
ARBProgramShaderってのがアセンブリシェーダのクラスで、こいつのメンバを一部オーバーライドしてしまえば話が早い。しかしARBProgramShaderのメンバ関数はC++内部で呼ばれちゃって、オーバーライドされたからってわざわざRubyのメソッドを呼び出していない。なのでC++から呼ばれるメンバはオーバーライド禁止にしてあるのだ。
かわりに全部Ruby側に移譲するGenericShaderを継承して中でARBProgramShaderに移譲しなおすクラスを作らないといけなくてめんどい。めんどいって程でもないんだけど全部一旦Ruby経由になるので無駄くさいなぁ。
あれ。今気付いたけどメソッドのオーバーライドが検出できるんだから、メソッドがオーバーライドされてたらって条件でRubyのメソッド呼びに行くのもできるじゃん。あー。でもいまから変えるのはめんどいな。またそのうちね。
で、シェーダは動くようにできたんだが今度はRenderStateが上手くいかない。RenderStateの仕様変更があったのには対応したんだけどすぐにSEGVで落ちちゃう。gdbで見ると変なアドレスを実行しようとしてる模様。既にdeleteしちゃってるオブジェクトの仮想関数呼んでるっぽいなぁ。
いろいろ思い当たるところはあるんだが、それらを見ても全部問題無い作りになってた。もっとミスってるかと思ったのにちゃんと出来てるなんて逆に不安だぜ。
いやいや、ちゃんと出来てないから落ちてるんでしょうが。あちこちにトラップ仕掛けてみる*1。
C++オブジェクトのをラップするRubyオブジェクトを作ったら、C++オブジェクト側にもラッパRubyオブジェクトのVALUE値を保持させてあとでmarkとかに使うっていうことをしてるんだけど、そのVALUE値の保持が上手くいってないようだ。しかしコード上はちゃんと保持させてるようだし、保持させた直後にトラップしかけても当然ちゃんと値は入ってるんだが。
よくわからんのだがなぜかどこかで抜けているようだ。
とりあえず保持させるコードを書くのを忘れるとまずいのでallocの中でやってしまうことにした。そしたらちゃんと動いた。あっれー?まあ動いたんならいいや。けっきょくこれが原因だったんだろうし。
終了時にSEGVで落ちることがあったのもとりあえず放置してたんだが、それもついでに直った。同じ問題だったか。
それで一応今まで動いてた程度の描画は動くようになった。…いやなってないな。照明無しは普通に動くんだが、照明有りは真っ黒。アセンブリシェーダにちゃんとパラメータがわたってないね。めんどくせー!
*1 C++テンプレート使うとブレークポイント張れなくて困るわ
突然ですがRiko拡張ライブラリをswig使って書き直したい。
インターフェースは極力変えないようにして、拡張ライブラリ内部だけでの変更だったらそんなに問題無いかなぁと。
なんでswigにするかというと。まず一つにラッピングがめんどくなった。
以前はラッパというよりはRuby向けの関数の中に実装をごりごり書いていたのでそんなにめんどくも無かったんだが、最近の変更で内部はC++でそこそこちゃんと実装して、あとはRuby側に公開って形になった部分がだいぶある。そしたら想像以上にラッピングがめんどくなった。
今は一旦落ち着いたのでどうでもいいんだけど、またクラス追加とかやったらめんどいなぁと。描画部分もC++に持っていきたいものがもう少しあるし、パーティクルとか物理エンジンなんかの演算部分は今後もC++で書いていくと思う。それを手でラッピングするのもめんどいわ。
つぎにswigは実績がある。wxRubyなんかで使われててそれなりに実績がある。なんか複雑になると落ちたりするけど。wxRubyのコードも相当地雷踏みまくってるけど。あれ、だめじゃん?
まあwxRubyで使えるくらいには機能充実してるってことだけど。C++クラスのvirtual関数をRubyのクラスでオーバーライドってのもちゃんと出来るのが頼もしい。GC周りは混沌としてて危うげだが。
とはいえ超巨大なC++ライブラリのwxWidgetsと俺がRuby向けに意識してちょこっと作る物では半自動ラッピングの難易度は桁違いだろう。
wxRubyのコードはちょっとはいじったからswigがどんな感じのコード吐くかだいたい分かってるってのはあるね。結構オーバーヘッドはでかそうなんだけど、その程度はあまり気にしないことにする。
あとはJavaとC#用のラッパも吐ける。かもしれない。JRubyとIronRuby対応もできるといいなぁとか思ってたのでこれが上手くいくと楽だ。JNIとPInvoke使ってるので結局ネイティブコンパイルは必要で微妙ではあるんだが。本当はJOGLとかOpenTK使ってJavaとC#で書いちゃった方が上手い感じではあるんだけどねぇ。
swigの問題点は、どこまで上手くいけるかまだ信用しきれない所と、オーバーヘッドがでかそうなのと、インターフェースの書き方が結構難しいところだ。