シェーダをいじれるようになったので、簡単なプログラミングをしてみます。
最初はアンビエント光を試してみましょう。
まずは骸骨さんの頭を描画します。
完全なディレクショナルライト(平行光源)のシェーダなので、まるで宇宙空間のようですね。
エフェクトコードを次のように書き換えます。
すると結果は次に示すとおりです。
環境光の効果が確認できました。
前回のオマケで示しましたが、オブジェクトに適用しているマテリアルカラーを変更できます。
顔が赤い…
本当はここからシェーダ編を書きながら勉強したいのだけど
物理ノードの情報がほったらかしになっているので、先に物理の方を片づけたいと思います。
(シェーダコーディング自体はそんなに難しいことではありませんしね。
理論がわかれば簡単な部類です。今回のようにコードを試す環境を作るのはそこそこ作業量がありますが…)
ということで、今度は BulletSharp を勉強します。
Bullet の基本は昨年の自分がまとめているので、C#でどう書くかだけ確認していきます。
ひとまず公式サイトから最新版を取ってきます。
デモをひと通り動かしてみました。
ソースコードを読んでみましたけど、随分わかりやすくなっていました。
腕のいい方が手がけているのでしょう。
さっそく DemoFramework を参考に BulletPhysicsFramework クラスを作ってみました。
コードを次に示します。
これを使った簡単なテストアプリを用意しました。
イメージを次に示します。
Start ボタンを押すとスライダーのつまみが落下し、地面がある0のポイントでバウンドします。
バインディングでスライダーと剛体のY座標を結びつけるだけですので、特に説明は不要かと思います。
テストはこれくらいにして、Kimberliteにて読み込んだオブジェクトごとに衝突形状を作成する部分を
情報を付け加えるだけでは確認のしようがないので、衝突形状の描画という機能も付けたいと思います。
<作業>
さて、オブジェクトノードからわかる形状データは頂点バッファですね。
オブジェクトにフィットするように衝突形状を作りたいと思います。
考えているのは BoxShape で、バウンディングボックスを作るというものです。
先に衝突形状を描画する仕組みを用意してみます。
はい、ColladaBinary ファイルを exe にリソースとして埋め込んで、これを描画できるようにしました。
続いて…
コンバータに機能追加を行い、ノードごとに物理ベース情報を追加するようにしました。
ほか、色々と気になっていた部分を修正しています。
ノードツリーが正しく親子関係を記述するようにしたとか、ノードの配置情報をいじると
そのノードが移動するとか…
<実装メモ>
まず、シェイプタイプの判別を行います。
collisonObject.CollisionShape.ShapeType
でタイプ判別可能、またタイプごとにシェイプをキャストします。
Box なら collisonObject.CollisionShape as BoxShape とすればOK。
で、形状は BulletSharp.Vector3 xyzHalfWidth = shape.HalfExtentsWithMargin; と取得可能です。
現在の姿勢は collisonObject.WorldTransform で取っれこれるので
さっそくエフェクト変数の該当箇所を毎フレーム更新するように書いてみて結果を見てみましょう。
色々と面倒なので Box だけ描画するようにして CollisionShape の描画をテスト。
Bullet Physics も進化していますね。 500 個デバッグ描画してもフレーム落ちしてないみたい。
では、どんどんできることを増やしていきます。
ひとまず Box の他に Cone, Cylinder, Sphere, Capsule, StaticPlane の描画ができるようにしてみました。
あとはノードツリーのアイテムの描画を行うかどうかのフラグを変更できるようにしたのと
FPS を表示するようにしました。
また、ピンク色はアクティブなシェイプで、青色はスリープ中のシェイプを表すようにしています。
続いて、再生、一時停止、コマ送り、停止ができるようにしてみます。
その次はオブジェクトを読み込んだ時点で、シェイプを割り当てる機能の追加です。
はい、再生、一時停止、2倍→4倍→8倍→1/2倍→1/4倍→1/8倍→等速の順番でモードが切り替わる
コマ送り機能を確認しました。この辺は特に悩むところはないですね。説明を飛ばします。
さて、ここから一工夫必要なオブジェクトを読み込んだ時にシェイプを割り当てるという機能について説明します。
まずオブジェクトが持つメッシュ情報より、メッシュの中心とバウンディングボックスの各辺の
半分の長さを計算します。そして、オブジェクト自体の回転と移動を使って衝突形状の初期位置を
決定します。テストした結果がコチラ↓
読み込んだモデルの描画結果
PhysicsCollisionObject の描画結果
初期位置の時点でお互いに重なった状態でスタートすると、爆発します。
読み込むオブジェクトを細かく切り分けることと、初期位置やシェイプの調整機能がほしいです。
あと、はやく物理オブジェクトに追従してモデルを描画できるようにしたいですね。
ひとまず今回はこのあたりで話を切りたいと思います。
思いっきりタイトルと外れたことをしてましたが、次回もこんな感じで
Bullet Physics 導入による機能追加を進めたいと思います。
2012/09/19 初記。
2012/09/30 更新。