飴屋

Flash3D/Papervision3DとJiglibからAway3Dに移行することにしてみた

昔作ったコンテンツがPapervision3Dで作られてまして

Flashで3Dが動くという話を聞いて、2,3年ほど前にPapervision3Dを使ってみたことがありました。それはまだ運用中のコンテンツなのですが、JiglibFlashで物理演算機能を追加したり、音声合成エンジンを追加したり、いろんなことを盛り込んだ結果当時の一般的なPCではFPSがでない、アニメーションがガタガタのものができあがりました。自分のPC環境ではなんとかみれるものの、他のユーザーからはいろいろ不満の声が聞かれました。

そんなコンテンツから収益が上がってくるわけもなく、プロジェクト的にはフェードアウトしていったのですが、年月を経てFlashはGPUを叩いて3D描画ができるようになりました。ひょっとしたらこのコンテンツは甦るんじゃないかと淡い気持ちを抱きました。

Away3Dを使ってみよう。

さて、Stage3Dについては別のプロジェクトで利用するために学習していたので基本的なことはわかっているつもりですが、Papervision3Dのようなある程度汎用性を担保しているライブラリを置き換える場合、同程度のライブラリが要求されることは想像に難くありません。自分用のライブラリも製作しているところではありますが、ちょっと特殊な仕様になっていたり、多くの機能を省いている都合で簡単にはPapervision3Dの代理は勤まらなそうです。Papervision3D自身がStage3D対応に動いてくれるのが一番よかったのかもしれませんが、期待できそうにはありません。

というわけで、いくつか世の中に出回っているStage3D対応ライブラリからAway3Dをチョイスしてみました。もともとPapervision3Dとも親戚にあたるようなライブラリらしいし、早いうちからアルファ版が出回っていて、多くの人に使われて、関連情報が得やすそうだし、AwayPhysicsなんていう物理演算ライブラリもあるそうだし、ということでライブラリファイルをダウンロードしてみました。

Papervision3Dとあわせて使っていたJiglibFlashという物理演算エンジンは多くの3Dエンジンとの親和性を実現してくれていたのですが、まだバージョンが若かったので機能的に不完全な部分が多くて、自分でソースを改変しながらプログラムを組んでいたのを覚えています。これをAwayPhysicsに置き換える作業がやはり一番面倒くさそうで途中で断念する可能性も捨て切れません。しかし、Awayシリーズでまとめたらそれ以上に3Dエンジンと物理演算エンジンに親和性が生まれて、きれいに実装ができるのではないかという期待もあります。

作業の方針

あまりプランを練らずに作業を開始してしまったのですが、とりあえずPapervision3DのクラスとJiglibFlashのクラスをソース上から追い出して、同等の機能を持つAwayシリーズのクラスで置き換えられれば目的が達成されるはずです。

とりあえず、Papervision3DでBasicViewという面倒なことを一手に引き受けてくれていたViewのクラスをAway3DのView3Dというクラスに置き換えてみます。そして、JiglibFlashのPapervision3DPhysicsクラスをAwayPhysicsのAWPDynamicsWorldクラスに置き換えます。この状態でコンパイルしようとするといろいろエラーが出てくるので、エラーがなくなるまで一つずつ直していけばいつか出来上がるんじゃないかという方針でスタートしました。Papervision3DとAway3Dは同名で同機能のクラスがあることが多いので、ライブラリの構成を把握しておくと作業が捗りそうです。

Date: 2012/2/12

修正ケース

修正前修正後
RigidBody.material.frictionとRigidBody.material.restitutionAWPRigidBody.frictionとAWPRigidbody.restitutionへ
物理演算の衝突を検知するときは衝突情報の配列を一つずつ調べてたAWPEvent.COLLISION_ADDEDイベントのリスナーをAWPRigidBodyにつけておくと衝突時に呼び出される。AWPDynamicsWorld.collisionCallbackOnをtrueにする必要がある模様
JiglibFlashを勝手に拡張して衝突した物体を判別できるようにしていたAWPCollisionObject.skin.extraに識別情報を付加しておくことに
DisplayObject3Dのalphaプロパティを減衰するアニメーションがあったAway3Dだと多分Materialを操作するのだろうけど、とりあえずScaleX、ScaleY、ScaleZを0に近づけるアニメーションでごまかした(後の課題とした)
衝突すると物体の衝突する物体の角度の情報みたいなのを取得できたのができなくなった(dirToBody)衝突した二者の位置情報から計算した
カメラのターゲットにDisplayObject3Dを指定するとカメラが勝手に追いかけてくれた毎フレーム、カメラ位置を更新してターゲットを追いかける
addBody,removeBodyaddRigidBody,removeRigidBody
RigidBody.setVelocityAWPRigidBody.applyCentralForce
MovieMaterialとかGouraudMaterialとりあえずBitmapMaterialとかColorMaterialに置換
Cylinder形状の側面だけMaterialを変更していた
JMatrix3Dは各行列要素をダイレクトに書き換えられたMatrix3Dに置換してcopyRawDataTo
Cube形状のマテリアルについてMaterialListで各面を制御CubeMapというクラスを発見したけどよくわからず
Rigidbody.setActiveメソッド、setInactiveメソッドAWPRigidBody.isActiveを操作はreadonlyなので困った。
DAEクラスLoader3Dクラス
DAEインスタンスはPVMeshにしてバウンディング情報を取得できた
MovieClipMaterialはtiled,maxU,maxVプロパティでタイリングを制御できたBitmapMaterialのコンストラクタの三番目ぐらいの引数にrepeat設定があった
MovieClipMaterialはMovieClip中の座標範囲を指定して描画できたBitmapMaterialに渡すBitmapDataに適切にdrawすればよかった
JPlane.yawで板ポリゴンを回転していたAWPPlane.rotationXに回転角度を設定

Date: 2012/2/13-2012/2/29

調整

とりあえずコンパイル通りましたが、意図する絵がまだでてないです。
そして、ここでAway3D 4.0 Betaが2月17日に更新されていることに気づきました。いろいろ変更が入っているみたいで新たなエラーの原因が誕生しました。調整作業を断念し、再度、コンパイルを通すための修正作業に戻ります。

Data: 2012/3/28

修正ケース2

Data: 2012/3/29 -
(以下、未稿)

修正前修正後
プリミティブのクラスがなくなった!?PlaneはPlaneGeometryといったようにxxxGeometryクラスに移行
プリミティブのコンストラクタにマテリアルを指定できなくなった!?プリミティブのような形状データ(geometry)とマテリアルを引数とするMeshクラスをシーンに追加するようにする模様
BitmapMaterialは使うなとの警告4.0a版から非推奨でTextureMaterialを使えとのこと。BitmapTextureとあわせればこれまで通り。
直方体の各面に別個に画像を貼り付ける方法がよくわからなくなったCubeGeometry.tile6プロパティをtrueにするとテクスチャを2x3のグリッドに分割して貼り付けてくれるとのこと
DAE(Collada)のモデルデータを読み込めると思ってたのに読み込めないParsers.enableAllBundledを呼べと警告が出るも関係なし。Away3Dのフォーラムによると将来的にはcollada形式のモデルのパーサーも作るかもしれないけど、優先度は高くないから他のデータ形式にした方がいいとのこと。確かにColladaの仕様は複雑ですものね・・・
キャラクターのrotationYが-90丸いキャラクターですが天地があったのでrotationXとrotationZを毎フレーム、0に設定していたせいかも。rotationを軸別に動かないようにするには、AWPRigidbody.angularFactorを使えばいいらしい。
剛体のrotationYがまだ-90剛体の位置を記述する方法に3つのオイラー角で表現する方法と四元数を使う方法とがあり、AwayPhysicsは前者を利用している。その場合、gimbal lockという現象が起こり、剛体の姿勢の自由度が失われることがあるらしい。それでもよく理由が理解できなかったのですが、こちらを読んでいろいろ納得しました。Matrix3Dを操作しているのがAwayPhysicsのパッケージの中なので、きれいに書けませんでした。

Flash3D