programming

SharpDX事始め
SharpDX事始め WPFとかDirectX11とかKinectあたりのAPIに慣れておきたいということで、 SharpDXの練習を始めた。 SharpDXのサンプルにDirect3D10/WPFHostというのがあるのだが、 Direct3D11版が無かったので練習がてら11で動くように改造してみた。 Direct3D10とDirect3D11の間の違いは少ないので変更箇所は少ないのだが、 ポイントがいくつかあるのでメモ。 Direct3D11でDeviceの一部の機能がDeviceContextに分けられた。DeviceからDeviceContextを取得するには、Device.ImmediateContextを使える。 Direct3D11でAPIからEffectが消滅した。SharpDXはこの機能をsharpdx_direct3d11_effects_x86.dllで提供しているのでこれを実行パスにコピーするべし。あとよくわからないが、CompileFromFileの第2引数には”fx_5_0”を指定するべし。”fx_4_0”だとエラーになる。適当にやってみたら動いたからよいものの謎。 とりあえずこれでWPF+DirectX11な開発を始められるで。 せっかくなので CodePlexにアップ。 https://wpfhost11.codeplex.com/ ちょっと、C#系のクンフーを高めて行こうかと。 追記 http://stackoverflow.com/questions/18912194/sharpdx-2-5-in-directx11-in-wpf SharpDXElement使えだと?

Unity開始
Unity開始 仕事の都合もあって、Unityの学習を開始。 だいぶ前にオライリーのUnity本が出たころに少し触っただけなので初見とあまり変わらない。 今奥付、を見たら2011年9月とか書いてあった。 とりあえずUnity4.3をインストールして、 秀和システムの「見てわかるUnityゲーム制作超入門 (Game Developer Books)」 にさらっと目を通した。 これからソフトバンクの「Unityではじめるゲームづくり(DVD付) (ゲープロシリーズ) 」 を読むところ。 MikuMikuDance for Unityではまった で、mmdモデルでもさくっと出してみようとしたところはまったのでそれについてメモ。 コンパイラ エラー CS0241 既定のパラメータ指定子は使用できません が出てしまうと言うもの。 調べたところ、パラメータの規定値は.Net4.0で導入されたものらしいのだが .Net3.5でコンパイルしようとしているのが原因とわかった。 で、手動で.Net4を使うようにしたら治った。 参考 http://ufcpp.net/study/csharp/sp4_optional.html http://vmem.jp/2012/02/16/monodevelop%E3%81%A7%E3%83%87%E3%83%95%E3%82%A9%E3%83%AB%E3%83%88%E3%81%AEtarget-framework%E3%82%92mono-net-4-0%E3%81%AB%E5%A4%89%E6%9B%B4%E3%81%99%E3%82%8B/ ところが別のマシンでやってみたら何事もなくできてしまった。 道理でググっても同じはまりが出てこないわけだ。 古いMonoDevelopの設定が残っているとかあったのか。 2冊目の方を読み始めた。 適当にTerrain書いただけだがわりとそれっぽい感じに。

右辺値の理解
右辺値の理解 そろそろ右辺値を抑えておきたい気がしたのでテストコードを書きながら実験してみた(VC2010 Express Edition)。 http://msdn.microsoft.com/ja-jp/library/vstudio/dd293665.aspx を参考に右辺値実験クラスRightKunを書いた。 コピーコンストラクタと同じくシグニチャは決まったものがあって 右辺値代入演算のオーバーロードとペアになるらしい。 各関数の呼び出しでメッセージを表示するように仕込んだ。 https://gist.github.com/ousttrue/7178535 #include <memory> #include <iostream> class RightKun { public: RightKun() { std::cout << this << ":default constructor" << std::endl; }; ~RightKun() { std::cout << this << ":destructor" << std::endl; } // 左辺値によるコピーコンストラクタ RightKun(const RightKun &src) { std::cout << this << ":copy constructor: "; *this=src; } RightKun &operator=(const RightKun &src) { std::cout << "left value operator= " << &src << std::endl; return *this; } // 右辺値によるムーブコンストラクタ RightKun(RightKun &&src) { std::cout << this << ":move constructor: "; *this=std::move(src); } RightKun &operator=(RightKun &&src) { std::cout << "right value operator= " << &src << std::endl; return *this; } }; とりあえず使ってみる { // default RightKun r1; // copy RightKun r2=r1; } 結果

大きさ基準が必要だ
大きさ基準が必要だ pmdの読み込み時スケーリングを実装した。 とりあえずドワーフと同じくらいの大きさになるように2.5倍という適当な数値を選択したが、 mmdモデルを一切スケーリングしない(Mikuが20高さ)か実世界のメートル/cm等の単位系になっているかのどちらかにしたい。 現状だと立った状態のカメラの高さが50くらいという謎の単位系であり、 Irrlichtのmediaディレクトリ内のファイル群と大きさがだいたい合うこと以外にメリットが無い。 Oculus使っているので実単位に合わせた方がよいな。cm単位系がよさげな気がする。 しかし、bullet的には9.8Gの方が98Gよりわかりやすような気がする。 bullet界はメートル系でレンダリングはcm系にするという手もあるがはまりそうではある。 シェーダーに梃入れしてもっとMMD風味のトゥーンレンダリングにしよう。

FPSカメラにOculus回転を仕込んだ
FPSカメラにOculus回転を仕込んだ IrrlichtのCSceneNodeAnimatorCameraFPSにOculusを合体した。 Irrlichtのカメラが思ったよりいろいろやっていたのと ビュー行列を直接扱っていないのに手間取ったがとりあえず当初の目的を達成。 どうにも都合が悪かったので本体をちょっと拡張した。 class CSCameraSceneNode { core::marix4 LeftAffector; }; レンダリング直前にビュー行列に乗算する行列をセットできるのだが これが右からの乗算なので、 左からの乗算を追加してこれにOculusの回転を表す行列をセットできるようにした。 これを踏まえてCSceneNodeAnimatorCameraFPSをコピーしてCSceneNodeAnimatorCameraOculusOnFPSを作った。 こいつはFPSカメラのマウスの上下移動を無視するのとlibOVRからの回転値取得と左行列を追加する機能をもつ。 コードはこれなのだけど https://github.com/ousttrue/onibi/blob/master/irrlicht/examples/HMDIrrlicht/CSceneNodeAnimatorCameraOculusOnFPS.cpp 日記に全部書くには長いし、サンプルが改造版のIrrlichtに依存するので紹介し辛い感じだなぁ。 オフスクリーンレンダリングとシェーダーをサポートした今風のglutみたいなフレームワークがあるとよいのだけど。 今度はmmd表示周りに着手して表示途中までできた。 しかしIrrlicht界のスケーリングの基準がよくわからず。cmのような気もするがなんかもっと適当な値のような気もする。 画像右側の身切れているのはIrrlichtサイズのDwarfである。 mmd界はミクさんの身長20を基準とする統一単位なのだが何かしら基準を決めねばならぬ。 物理の挙動の都合上スケーリングしたくないなーという事情がありどうしたものか。 スカイボックスもOculusで見ると見違えるものがあるなー。 テクスチャとライティングを解決する。 あとpmx。

Oculus来たー
Oculus来たー 6月10くらいにぽちってから2週間くらいで到着。いいタイミングに発注したらしい Oculusことはじめ oculus sdk downloadあたりで検索すると見つかるのでいただいてくる。 特にログインとかアカウントとかは必要ない。 SDKにはlibSDKとそれを使ったサンプルがvcプロジェクトで入っている。 oculusの組み込みには2段階あって、ひとつは両目向けに違うレンダリングをする作業、 2つめはOculusのジャイロセンサの値を受け取ってカメラの方向を対応させる作業となっている。 ひとつめのステレオレンダリングに関しては、左目用と右目用にオフスクリーンレンダリングして それを表示するときにシェーダーで歪ませるというものになる。 歪ませ方は、 RenderTiny_D3D1X_Device.cpp や Oculus_SDK_Overview.pdfに書いてある。 OpenCVとかのカメラ係数に似ているような気もするが同じものかは確認していない。 ふたつめの方は、LibOVRに任せると簡単でusbのHIDデバイスから値を随時取得して カメラ姿勢に適用するだけ。 LibOVRはこのジャイロの値取得とDXUT的な3Dフレームワークが混合しているので ジャイロの方だけを抽出して最小限にしたい。 あと自分のコードに混ぜて公開していいのかライセンス的によくわからん。 とりあえずglut化してみよう はじめに軽くTinyRoomをglutに移植しようと思ったらdxutみたいのがくっついていて途中で投げ出したw。 手持ちで、OpenGLシェーダーとかオフスクリーンレンダリングを扱うシステムが無いので そこから作るのが少し時間がかかるので後回しに。 IrrlichtのカメラをOculus化 方向転換して、ベースにlibOVRを合体した。 githubのものはoculusのステレオレンダリングは実装済みなのでgyroを合成する件のみ。 Irrlichtのカメラ行列の制御がよくわからぬが一応表示。 あとでICameraSceneNodeを継承して作り直そう。 mikuさんprprな感じになるにはもう少しかかるな・・・

IrrlichtにVRPNを合体する
IrrlichtにVRPNを合体する 遂にOculusが発送されたらしくHongKong Postから国内に入ったらしい。今日明日には来るで。 vrpnを仕込む Oculusが来たら遊ぶべくIrrlichにさらにvrpnを仕込むことにした。 外部入力はこれで一括して捌こうと構想している。 さしあたってはOculusの傾き情報(Quaternion)、マウス、コントローラの入力をvrpn経由にしようかと。 さらには、 Oculusは位置情報が無いのでKinectからスケルトン情報を受けて移動できるようにしたりWiiコン入力をとったりしたい。 WiiMote plusの内臓ジャイロの値を取れるソースも発見したのでキネクトで手の位置を取ってWiiコンの傾きと合体すればいい感じになるのではないかと妄想(hydraみたいに手が出てくるとこまでいけるのではないか)。 ゆくゆくはARToolKitやOpenCVのマーカー式やつもvrpn経由で合体しやすくなる。 <pre> oculus kinect wiimote A | | | rendering | | sensor | | | V | | irrlicht <-----+-----+ </pre> ということでvrpn作業開始。

IrrlichtにMsgPackRPCを仕込む
IrrlichtにMsgPackRPCを仕込む Oculusの通販ステータスが早くもProcessingに変わって届くのが楽しみな今日この頃。 レンダリングエンジンにはIrrlichtを選択したのであるが、 そのままだとシーンを構築するとか諸々の作業がC++直叩きになる。 これだとさすがに大変なのでMsgPackRPCでラップして外部のツールから 操作しようと構想しておったのだが始めてみると早速問題に突き当たった。 オブジェクトを生成してそのメソッドをコールするのにどうすればいいのか。 こういう場合だ。 IMesh *mesh=CreateMesh("miku.pmd"); mesh->SetPosition(0, 0, 5); MsgPackRPC経由だと以下のような感じか。 # pythonとかそういうの client=msgpac.rpc.client() mesh=client.call("CreateMesh", "miku.pmd") client.call("Mesh_SetPosition", mesh, 0, 0, 5) 1つめのCreateMeshはグローバル関数かシングルトン的オブジェクトのメソッド呼び出しになるので特に問題は無い。 2つめはSetPositionのthisとしてmeshを送ってやる必要がある。 ここでmsgpack的にはIMesh*をシリアライズ/デシリアライズすることが必要になる。 案1 ポインタを整数値としてキャストすればいいじゃない template <typename Stream> inline packer<Stream>& operator<< (packer<Stream>& o, IMesh *v) { // ポインタをintにキャスト o.pack((int)v); return o; } inline IMesh *v operator>> (object o, IMesh* v) { unsigned int p; o.convert(&p): // intをポインタにキャスト v=(IMesh*)p; return v; } さすがにワイルドすぎる。というかポインタが既に開放されている場合になすすべが無いので没

Oculusぽちった
Oculusぽちった 会社で見せてもらったOculusに感銘を受けて本家サイトでぽちった。 8月発送の見通しとのことなのでそれまでに開発環境を用意しておかねば。 ということで、Irrlicht + Oculusという方向性で環境を整備することにしようかと思う。 Irrlichtに関しては数年前からちょくちょく触ってはいてgithubに残骸が残っている。 irrmmd(IrrlichtMMDメッシュ) onibi(Irrlichtと一緒に使いそうなライブラリの詰め合わせ) どっちが新しいのかよくわからないが、両方ともなんか中途半端な状態である。 しかし、mmdを表示できるようにしてbulletを仕込むという路線にするのでonibiの続きからやるのがよさそうだ。 まずはmmdがちゃんと動くところまで修復するとしようか。 あと別プロセスのGUI向けのバックドアとしてmsgpack-rpcを仕込む。 そんな感じにしよう。 onibiの方をvc2010でビルドしてみたところ少し手直ししたらビルドできた。そういえばirrlichtとbulletのpythonラッパーを作ろうとしておったことを思い出してきた。 まぁしかしそれはおいておくとする。 で、pmdモデルの読み込みサンプルがあるので実行してみたら完全に作業が途中らしくモーションがまったくおかしい。 さらにbulletのものと思われる開放漏れが報告される。前は、MinGWでやっていたので開放漏れに気付いていなかったか。 いろいろ手直しが必要そうだ。 mikuさん ついでなのでirrmmdの方もビルドしてみる。 こっちはちゃんと物理付でモーション再生に成功した。 irrmmdの方がちゃんとしているらしい。終了時にbulletを正しく開放しない問題はこちらも同じようだが。 onibiに合体して整理すれば使えそうだ。

おれおれmsgpack-rpc-pythonを作る
おれおれmsgpack-rpc-pythonを作る MsgPackRPCのpythonバインディング(クライアント側)が必要になったのでmsgpack-rpc-pythonを使ってみたのだが、 GUI(pyqt)に載せて接続制御とエラーハンドリングを細やかに制御したいので俺俺で類似品を作ることにした。 tonado-msgpackと名付けて取り合えず作業開始。 https://github.com/ousttrue/tornado-msgpack msgpack-rpc-pythonのおかげでtornadoの存在を知ったのだがtornado.ioloopが見れば見るほどboost::asioっぽい。 ということで、c++で作成中のmsgpack-rpc-asioのpython版のような感じのAPIにしてみた。 以下の点を考慮している。 tornado.ioloopを隠さない tornado.ioloopをスレッドに乗せて回しっぱなしにする tornado.ioloopひとつで複数の接続を扱う dispatcherを乗せ換え易くする。 接続ステータスの変化をコールバックで受け取る 非同期リクエストのコールバックを早期にセットする TCP以外は考慮しない プロジェクト作成 tonado_msgpack/ setup.py sample/ sample.py tonado_msgpack setup.py from distutils.core import setup setup( name='tonado_msgpack', version='0.1', py_modules=['tonado_msgpack'], ) 作業開始 $ python setup.py develop --user sample/sample.py #!/usr/bin/env python import tornado_msgpack import tornado if __name__=="__main__": port=18080 # dispatcher dispatcher=tornado_msgpack.Dispatcher() def add(a, b): return a+b dispatcher.add_handler("add", add) # server server_loop=tornado.ioloop.IOLoop() def on_receive(msg, session): result=dispatcher.dispatch(msg) session.