Posts Tagged away3d

[Away3D] BSP-dev Branch

2010.04.09

Away3Dに BSP/PVS を実装しようとしてるブランチを見つけてニヤリ。
コミッターはFP10版Away3DにPixelbenderによるシェーディング実装した David Lenaerts
今どきのリアルタイムレンダリングシーンじゃ特に意識しないだろうし、Flash用エンジンに絞っても Alternativa3D とか infinity3d にはとっくに実装されてるし、これといったアドバンテージがあるわけじゃないけど、ライセンス的に緩めなAway3Dに組み込まれるのは本当にありがたい。

今のところObjectContainer3Dを継承したクラスとしてBSPTreeが実装されてて、空間分割されたコンテナをSceneに追加する形で使う。この辺はハナっからScene3DにBSPが組み込まれてる(と思われる)Alternativa3Dのほうがスマートだと頭の悪いオレでも思うので、今後の仕様変更でScene3Dに内包されるかも。そうなれば Zソート・クリッピング・カリング・ポリゴン交差時の分割処理に至るまでパイプラインの至る所で恩恵にあずかれるはず。あと、内部で持ってる物理演算や衝突判定の最適化にも取り入れようとしているみたいなので、ちょっぴり期待しておく。

まだまだガンガン仕様変更があると思うけど、どんな感じになるのか試したくて、以前作った迷路を使ってポータルシステムがどの程度カリングを最適化してくれるのかを見てみた。比較用にBSP/PVSを使わない場合も改めて作成。

BSPTreeとポータルの生成にはかなり時間がかかる。DoomやQuakeなんかだとレベルエディタを使って事前に作ったものを外部ファイルとして保存しておいて、実行時は読み込みだけで済むようにしてあるように、事前処理のがよさそう。Away3Dもこの辺は考えてあるようで、エクスポータークラスが用意されてる(PreFabにレベルエディタ的な機能が追加されたりして?)。今回は使い方がよくわかんねーのと、必要なデータ全部エクスポートするのこれ?って感じだったので諦めた。

Maze normal
Maze using BSP/PVS (BSP/PVS使用)

■操作方法
カーソルキー [CursorKey] … 移動 (move)
[Z], [X] Key … ティルト (Tilt)

※要:FlashPlayer10

BSP/PVS版は、スタンドアロンプレーヤーならかなりヌルヌル動く感じ。マシンパワーのある環境だと2つの違いが分かりにくいかもしれないけど、オレの環境(MacBookPro 2.33GHz Core2Duo)だと全然違う。クリッピングモードをRectangle Clippingにすると視覚的にも違いが見て取れる。Project stats の T-ELEMENTS と R-ELEMENTS を見ると処理対象のFaceが大幅に減ってるのが分かる。ワクワクしてまいりました。

ハードウェアの進化に伴って失われつつある先人達の技術を追体験しつつ手軽に勉強できるのが、ActionScriptで3Dをやる唯一のメリットだと思うので、こういうトピックは超アガる。ちゃんと自分のものにするには相当ハードル高いけど、とりあえず周辺をウロウロする。

参考:
BSP Trees(視覚的でわかりやすい)
バイナリ空間分割(Binary space partitioning)- Wikipedia
BSP trees in 3D worlds
ゲームプログラミングのためのリアルタイム衝突判定(Amazon)

[Away3D] Away3D 2.4 Feature – Explode

2009.08.21

ワーカーホリック野郎な日々を送ってる間にAway3Dがバージョンアップ。
Away3d: 2.4 & 3.4 released!

とりあえず地味な機能から試してみる。

ExplodeTest(要:FlashPlayer9)

Explodeクラスは、指定したObject3Dインスタンス内の全Faceを位置関係をそのままに、バラバラのMeshやFaceに分解してくれるジオメトリモディファイア。
Away3DはもともとFace単位でvisibleプロパティを持ってるので、表示/非表示をFace単位で行うことができていたけど、Face単位で大きさ変えたりすることはできなかった。その名のとおり、簡易的な爆発表現なんかに使えそうだし、演出面で結構使えるかもしれない。

具体的には以下のようにして使う。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import away3d.geom.Explode;
 
- 中略 -
 
//適当なメッシュを用意
var wcMat:WireColorMaterial = new WireColorMaterial(0x0099CC, {wirecolor:0x00CCFF});
var sphere:Sphere = new Sphere({material:wcMat, radius:100, segmentsW:8, segmentsH:6});
 
//Explodeでメッシュを分解
var _explode:Explode = new Explode(true, true);
var _explodedObj:ObjectContainer3D = _explode.apply(sphere) as ObjectContainer3D;
 
//分解されたメッシュが束ねられたObjectContainer3Dをシーンに追加
scene.addChild(_explodedObj);

Explodeのコンストラクタに渡す引数は以下のようになってる模様。

  • 第1引数:分解したFaceを個別のMeshとして定義するかどうか
    trueなら、Faceの数分Meshが生成される。falseなら、共有していた頂点をFaceの数だけ用意してそれぞれ単独の面として扱えるようにする。

  • 第2引数:再定義後のMeshの中心点をFaceの重心にもってくるかどうか
    falseなら、元になったObject3Dの原点が中心点のままになる

コンストラクタの第1引数をtrueにして、個別のMeshを生成した場合は、

for each(var item:Mesh in _explodedObj.children)
{
    item.scaleX = 0.5;
}

などとして、それぞれのMeshを制御する。

理屈では、Colladaメッシュにも適用できる。

dae Explode(要:FlashPlayer9)

ただ、現状のExplode.asには、元にしたメッシュがFace単位でマテリアル指定されているような場合、マテリアルが引き継がれないという問題があって、テクスチャが無効になってしまう。そこで、Explode.asを以下のように書き換えることで暫定的に対処した。ついでに「bothsides、backの要素が引き継がれない」という問題にも対処。

Explode.as 61行目

61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
for(i=0;i<loop;++i){
 
    face = obj.faces[i];
    mesh = new Mesh();
 
    va = new Vertex(face.v0.x, face.v0.y, face.v0.z);
    vb = new Vertex(face.v1.x, face.v1.y, face.v1.z);
    vc = new Vertex(face.v2.x, face.v2.y, face.v2.z);
    uva = new UV(face.uv0.u, face.uv0.v);
    uvb = new UV(face.uv1.u, face.uv1.v);
    uvc = new UV(face.uv2.u, face.uv2.v);
 
    mesh.addFace(new Face(va, vb, vc, obj.material as ITriangleMaterial, uva, uvb, uvc));
    _container.addChild(mesh);
}

これを、

61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
for(i=0;i<loop;++i){
 
    face = obj.faces[i];
    mesh = new Mesh();
 
    va = new Vertex(face.v0.x, face.v0.y, face.v0.z);
    vb = new Vertex(face.v1.x, face.v1.y, face.v1.z);
    vc = new Vertex(face.v2.x, face.v2.y, face.v2.z);
    uva = new UV(face.uv0.u, face.uv0.v);
    uvb = new UV(face.uv1.u, face.uv1.v);
    uvc = new UV(face.uv2.u, face.uv2.v);
 
    var setMaterial:ITriangleMaterial;
    if (obj.material) setMaterial = obj.material as ITriangleMaterial;
    else setMaterial = face.material as ITriangleMaterial;
 
    var fc:Face = new Face(va, vb, vc, setMaterial, uva, uvb, uvc);
    mesh.addFace(fc);
    _container.addChild(mesh);
    mesh.bothsides = obj.bothsides;
    fc.back = obj.back as ITriangleMaterial;
}

とする。

あとは、バラバラになった後のMeshが、もともとのFaceの法線方向をforwardベクトルにしてくれるといいのになぁと思ったけど面倒くさそうだったのでとりあえず保留。
また、Explodeコンストラクタの第1引数をtrueにして、FaceごとのMeshを生成すると当然負荷が増大するので、パフォーマンス重視の場合はMeshを生成せずに、Faceレベルでコントロールする方法を確立しないとダメっぽい。

Away3D – Studies #05

2009.05.10

Drive Test 04(要:FlashPlayer9)

[←] [→] キー … ハンドル
[z] キー … アクセル
[x] キー … ブレーキ
[↓] … バック

これまではトラクションの掛かり方がなんだか微妙で、ホイルスピンしっぱなしみたいだったのがようやく解消された感じ。旋回時にロールするようになったり、ブレーキングの時微妙にピッチングが発生したりするので、そこそこ感じが出てきた。

未だによくわかんないのが、JigLibFlashのJCarクラスのメソッド「setupWheel」で指定する wheelRestingFrac と、wheelDampingFrac の役割と関係性。コードを見る限り、それぞれサスペンションのバネレートとショックの強さに関係してるっぽいんだけど、頭の中のイメージと、実際に数値を指定してみた時の挙動がかみ合わない。ロールしたりする時にもっと「粘り」のようなものが欲しいんだけど、なんだかカクカクした感じになってる。物理演算のステップ数にも関係してそうだし、パフォーマンスの問題と拮抗しそうなので悩ましい感じ。

あと、JigLibFlashのvehiclesでモデル化されてる足回りのサスペンション形式がよくわからん。4輪それぞれにストローク幅が設定できてたりするし、ジオメトリ変更(トーとかキャンバーとか)が実装されてなさそうなので、なんちゃってストラットっぽい感じだけどもどうなんだろ。

正確なシミュレーションがしたいというよりは「感じを出したい」だけだし、このままだと「俺と足回り」とかいうテーマで一生を終えてしまいそうなので、このへんを深追いするのは一回やめにして駆動系に手を付けよう。JigLibFlashでモデル化されてる駆動系はCVTっていうか「駆動輪にモーター直結」なので、クラッチとミッションを追加することを次の目標にしてみるべ。

[Away3D] Away3D 2.3 Feature – BezierPatch

2009.04.23

BezierPatch Test(要:FlashPlayer9)

いわゆるサブサーフェス(Subdivision Surface)っぽく、いくつかのコントロールポイントの座標を元にメッシュを定義するクラス BezierPatch 。Away3DのコミッターGreg Caldwell氏のblogで、チュートリアルとデータ定義用簡易エディタ「Patch Explorer」が公開されてて、やっと使い方が解った。
Away3D Bezier Patch Tutorial

エディタ無しじゃ狙った形作るのキビしすぎだと思う。3Dアプリケーションでサブサーフェスをポリゴン化せずにインポートできるようにしようとしてるのかなぁ。

上記のデモは、16個のコントロールポイント(黄色い四角)でメッシュを定義して、それを鏡面コピーしたもので構成。コントロールポイントを適当に動かすことでメッシュが変形する。有機的に変形できるのが強みですな。

JigLibFlash Update

2009.04.08

PV3D専用だと思ってあんまりチェックしてなかったJigLibFlashが、PV3D以外のエンジンにも対応(現在、PV3D、Away3D、Sandyに対応)してくれたので、Away3Dでもそのまま使えるようになった。JigLib Flash for Away3D おつかれさま。

これまでのバージョンだと、表示用のメッシュにDisplayObject3Dをダイレクトに指定する形になっていたのが、ISkin3D っていうインターフェースをカマせることで、組み合わせたいエンジンのメッシュを指定できるようになった。
Away3Dを使うなら、

var box:JBox = new JBox(new Away3dMesh(daeobj),100,200,50);
※daeobjは、外部から読み込んだColladaモデルと仮定

って感じ。ちなみに、Away3dMeshクラスの実装は、Mesh オブジェクトを指定するようになってたけど、オレ的に不便なので、Object3D を指定するようにして使ってる。

あと、

var physics:Away3DPhysics = new Away3DPhysics(viewport, 1);
var sphere:RigidBody = physics.createSphere({radius:30, segmentsW:6, segmentsH:6});

なんて感じで、プリミティブ形状については表示用メッシュと物理演算用メッシュを一度に定義できるメソッドが用意された。引数の与え方がPV3DとAway3Dで異なる部分は吸収してくれないので、それぞれのエンジンのルールに従うと。

このあたり、ある程度の説明が google code のプロジェクトページ内Wikiに記載されているので参考になる。
New_API_Very_Short_Tutorial

また、svnリポジトリにもPV3D、Away3Dそれぞれのサンプルがある。これまでとシンタックスが大分異なる(physics.Integrate(0.1); → physics.step(); とか)ので、早めに乗り換えるが吉かと。
コリジョン用の形状にカプセル型が追加されたのがウレシげだなぁ。元祖C++用のJigLibには、trianglemesh や heightmap なんてのもあるので、だんだん移植されるのかも。

早速インチキドライブシミュレータもどきに組み込んでみたんだけど、パラメータ共通なのに挙動が同じにならない。けど、なんか新しいほうがパラメータが正しく反映されてるような気がする。