Alternativa3Dでウォークスルー #1 JiglibFlash

2011年4月 6日
Alternativa3D(A3D7.7)でウォークスルーしてみようと思います。3Dな地形の中をキャラクターが歩き回るあれです。

昔PV3Dで作ろうとしていて記事もいくつか書いてたんですが、当たり判定難しいとか、PV3Dのポリゴンソート的に厳しいとかで、1年以上放置してました・・・。今回は当たり判定に物理エンジンライブラリを使ってみる事にします。

ここ最近は出来あがった作品をwonderflに投稿するだけだったので、久しぶりに制作過程をメモしていこうと思います。ただ、Alternativa3Dの基本的な使い方までは解説しないので、そっちを知りたい方はnarutohyperさんのサイトが詳しいのでそちらをお勧めします。
東京てらこ がっつり3D スライド資料 | Alternativa3D7 | 丸林商店

これから作っていくもののソースコードですが、ちょっとしたサンプルは公開できるかもしれないけど、作りこんでくると公開が難しくなるので、あまり期待しない方がいいかも。

JiglibFlash

ウォークスルーさせるには地形とキャラクターとの当たり判定を計算する必要があって、今回はJiglibFlashを利用しようと思います。JiglibFlashの存在は前から知っていたんですが、実際使った事はなかったので色々調べてみました。

JiglibFlashについて

  • AS3用の3D物理エンジンライブラリ
  • Jiglib本体は位置とか回転とかの見えないデータをもじゃもじゃしてる
  • Jiglibが計算したデータを3Dメッシュモデルに適用する必要がある
  • いくつかプラグインが用意されていて、PV3Dとかのモデルには簡単に適用できる
  • A3D用のプラグインは今のところ同封されていない
JiglibFlashで扱えるコリジョン(※確認できたもの)

  • 直方体(JBox)
  • 球(JSphere)
  • カプセル(JCapsule)
  • 無限に広がる平面(JPlane)
  • 地形(JTerrain)

primitives.png

カプセルは最初円柱と勘違いしてました。実際は円柱の両サイドに半球がくっついた感じです。JiglibFlash + PV3Dのサンプルに円柱がありますが、あれは見た目だけでコリジョンはカプセルになってました。地形は上下方向に頂点を移動させた凸凹な地形を作れる感じなのかな?

カプセルが円柱じゃないのはわかったけど、もしかして円柱は作れない?他にも三角錐とか円錐とか、複雑な形状のモデルとかは 無理なんでしょうか。地形が作れるのなら頑張ればどんな形状でもいけるんじゃ・・・と思って中を覗いたけど、よくわからなかった。。細長い棒とかならカプセルで代用できるけど、薄い円形の板とかはどうすればいいんだろう。

このままだと作れる地形が限定されてしまいそうで不安ですが、きっと誰かが他の形状にも対応させてくれてるはず・・・と他人任せにしつつ、とりあえず今は用意されてるものだけでなんとかしてみます。

A3DでJiglibFlashを使う

さっそくA3DでJiglibしたいところなんですが、A3D用メッシュとJiglibコリジョンをくっつける為のプラグインは同封されていないので用意 する必要があります。PV3D用プラグインを見る限りでは、基本的にスクリプトでメッシュとコリジョンを生成して2つを関連付けている感じでした。自分はモデリングソフトでステージを作って、そのモデルデータをFlashで使う事が多いので、スクリプトでメッシュとコリジョンを生成する機能だけだと困る事 があります。

例えばこんなステージを3dsMaxで作って、スクリプトでこのステージの形状に合わせたコリジョンを座標を調べつつ入力していくのはかなり骨が折れます。
teststage.jpg

そこで、こんな感じにコリジョン用モデルも一緒に用意しておいて、各モデルの位置・サイズ・回転を元にコリジョンを自動生成するようにできればよさそうです。
testcollision.jpg


つくってみた

PV3D用のプラグインを参考にしつつ、メッシュを渡すだけでコリジョンを生成して関連付けてくれるものを用意してみました。ボックス・球・カプセル・無限平面に対応しています。地形はまだ対応できてません。

jiglibtest.png
ソース

3dsMaxで適当に配置したプリミティブをCOLLADA形式で書き出して、A3D7.7で読み込んでJiglibのコリジョンを半自動で設定しています。せっかくなので新機能のライトとかも使ってみました。使い方があってるかは自信ないです。

今回作ったJiglib関係のクラスは
  • net.morocoshi.jiglib.a3d.A3dPhysics.as
  • net.morocoshi.jiglib.a3d.A3dMesh.as
の2つだけです。net.morocoshiパッケージ以下に上記以外のクラスも入ってるけど、A3Dのカメラやコンテナをまとめたクラスと、カメラをぐるぐるするのに必要なクラスなのでJiglibとは関係ないです。

使い方を簡単に説明すると、
_sim = new A3dPhysics(5, 0, 0, -20);
まず最初にA3dPhysicsクラスをnewします。第一引数は速度で、それ以降は重力の大きさ(XYZ成分)
_sim.addBox(mesh1, true);
_sim.addSphere(mesh2, true);
_sim.addCapsule(mesh3, "z", true);
_sim.addPlane(mesh4, true);
次に、A3dPhysicsオブジェクトでadd~()します。第一引数はコリジョンを生成したいメッシュです。addBox()すれば渡したメッシュでボックスコリジョンが生成されて、addSphere()すれば球のコリジョンが生成されます。コリジョンの大きさはメッシュから自動判別されます。カプセルを生成する時だけ、第二引数でカプセルがどの軸に沿って伸びているかをxyzから指定する必要があります。

ただ、どのメッシュがどんな形なのかまでは判別してくれないので、どの形状のコリジョンにするかはモデル名で形が分かるようにしておくなどの工夫が必要になります。サンプルではメッシュモデルの名前に_RB_がついていたらボックス、_RS_なら球という感じで判別しています。(Max側では[RB]ってつけてるんだけど、書き出すとアンダースコアになっちゃうから)
_sim.step();
後は毎フレームstep()してシミュレーションを進めるだけ。A3dPhysics.step()はフレーム経過にかかった時間を元にシミュレーション速度を調節していて、フレームレートに依存しないようになっているみたいです。これはこれで便利なんですが、FPSが極端に落ちてしまうと計算がアバウトになるせいか壁をすり抜けたり衝突判定がおかしくなってしまう事があります。その場合はstep()は使わずに、
_sim.engine.integrate(0.2);
こうするとシミュレーション速度がFPSに依存するようになります。(integrateの引数はシミュレーション速度)ちなみにA3dPhysicsクラスのコンストラクタで設定した速度はstep()の方にしか影響しません。

コリジョンの自動判定について

メッシュを渡した時のコリジョンの判定方法は形状によって違うんですが、ボックスとカプセルは、バウンディングボックスとXYZスケールと回転の情報だけで判定しています。例えばモデリングソフトでボックスを生成した後に適当に回転させて、ローカルXYZ軸に沿ってスケーリングした後、内部の全頂点を平行移動・・・までなら問題ないのですが、まずいのが内部の全頂点を回転してしまう事で、見た目のボックスとバウンディングボックスがずれてしまうので正しい判定ができなくなります。

それとJiglibでメッシュとコリジョンをくっつける際に、メッシュの基点がオブジェクトの中央である必要があるので、メッシュの基点が中央にない場合は自動で全頂点を平行移動させて合わせるようにしています。コリジョン適用前と適用後で座標が変化している場合があるのはそのためです。頂点を動かした分、モデルを逆にずらしているから見た目は変わらないはずだけど。

A3D7.7のCOLLADAパーサ

A3D7.7のCOLLADAパーサには現時点で一部不具合があるようで、モデリングソフト側でスケーリングや回転を組み合わせているとうまくパースできずに位置がずれてしまうケースがあるようなので、Jiglibを適用する前に表示がおかしくないかチェックした方がいいと思います。


では今回はこのくらいで。続きはそのうち・・・

トラックバック(0)

トラックバックURL: http://www.morocoshi.net/mt/mt-tb.cgi/36

コメントする