note.x

Away3D 2.2出てた。
メジャーバージョンアップ時の恒例行事になったデモは、相変わらず完成度高し。

主なバージョンアップ内容は以下。

  • Collada のボーンをサポート
  • Triangle キャッシュ機能追加(よくわからんけど、△ポリの情報をキャッシュするんだろうか)
  • バウンディングボックスとバウンディングスフィアの演算機能追加(これもよくわかんねーけど、コリジョン関係かも)
  • PathExtrude, PathAnimator と PathDuplicatorの追加
  • Simple shadowsの追加
  • Object based renderers追加(よくわからん)
  • 「.Obj」形式でのエクスポート
  • ElevationModifierの追加
  • Elevationで作成した形状を AS3 コードでのエクスポート

詳細は、フォーラムの Robによるアナウンス Away3d 2.2: the Motherlode を参照。

一瞬だけsvnリポジトリに上がってた CellMaterial がいつの間にか消えとる。何か問題あったのかしら。

オフィシャルサイトから.zipアーカイブがダウンロードできる。また、同ページにて Flash IDE CS3/CS4向けのシンタックスハイライターが配布されとります。

08/10/11追記:
2.2、かなりパフォーマンスが改善されてる模様。
AS3Dmodのサンプルをビルドし直してみたところ、明らかに軽い。

AS3Dmod 追加モディファイア Away3D2.2ビルド版(要:FlashPlayer9)

比較用:
AS3Dmod 追加モディファイア Away3D2.1ビルド版


PV3Dは、(Away3Dも)ポリゴンがカメラに近づき過ぎると、ポリゴンを構成する頂点がカリングされて結果としてポリゴンが丸ごと消えてしまうという欠点があって、地面に見立てた板ポリなどの表示で結構苦労する。
これを解消するには、カメラのnearクリップ面と交差するポリゴンを毎フレームチェックして、nearクリップ面付近で切ってやり、頂点、uvを再設定する(これをシザリングと呼ぶらしい)必要があるのだけど、この機能が実装された模様(Away3Dはまだ)。Sandyや、Altanativa3Dにはすでに実装されていた機能だけど、PV3Dもようやく一歩踏み出したと。

詳しい話は実装者の Andy Zupko 氏のblog参照
zupko.info | Papervision3D – Now Featuring Frustum Clipping

簡単な使い方としては、下記のように

renderer.clipping = new FrustumClipping(FrustumClipping.ALL);

として、renderer.clipping プロパティに FrustumClipping オブジェクトを渡せばいいと。
FrustumClipping の引数には、

  • FrustumClipping.NEAR
  • FrustumClipping.RIGHT
  • FrustumClipping.LEFT
  • FrustumClipping.TOP
  • FrustumClipping.BOTTOM
  • FrustumClipping.ALL

が指定できる。
これは恐らくカメラの視錐台の各面を指していて、どの面との交差をチェックし、ポリゴンを切るかを設定できる模様。FrustumClipping.ALL なら、視錐台の全面がシザリング対象になる。個別に指定する場合は、

renderer.clipping = new FrustumClipping(FrustumClipping.NEAR + FrustumClipping.BOTTOM + FrustumClipping.TOP);

という指定も可能。

てことで、喜び勇んで 以前作ったコレ に使ってみたんだけど…

Frustum Clipping Test(要:FlashPlayer9)

確かに、nearPlane付近のポリゴン消失は解消されたけど、重い〜。
Andy Zupko 氏のデモみたいに、skyBoxのポリゴン欠けを防ぐような使い方が今のとこ妥当かも。どうもシザリング対象を総当たりでチェックしてるっぽいなぁ。FPS的一人称視点ゲームとかに使うには、Altanativa3DのようにBSPツリーでシザリング対象のチェックを最適化するとかしないと、かなりムリめ。
とはいえ、できなかったことが出来るようになったので、工夫次第で使いどころはありそうだ。

08/10/11追記:
Rev.752の修正で、Frustum Clippingが若干高速化。ギリギリ現実味のあるパフォーマンスになってきた。

Frustum Clipping Test Rev.752(要:FlashPlayer9)


気になってしょーがなかった Unity を試してみた。
Flashでのリアルタイム3D表現は引き続き勉強するとして、ちょっとレベルの高い環境にも触れておこうと思った次第。
Unity – Game Development Tool

.NET(Mono)ベースなのに、OSX専用という奇特なゲーム開発環境。
興味を持ったのは、OSX / Win 共にWebPlayerが提供されてて、作ったコンテンツがブラウザでも動かせること。
有償の製品だけど、機能制限版のIndieライセンスだと20,000円ちょっと、フルスペックのPro版でも175,000円と、かなりコストパフォーマンス高い。おまけに.blendがネイティブで読み込めるので、ShockWave3Dのように、Director + 3dsMAX揃えないと開発できないなんてこともない。

WebPlayerをダウンロードして、オフィシャルなデモを見て頂ければどんなことが出来るか解ると思う。

とりあえず、indieのデモ版がダウンロードできるので、これを使ってデモ作ってみた。
デモ版でも普通にWebPlayer用のビルドが出来るのはありがたい。
OpenGLに対応したビデオカード積んでれば動くと思うけど、動かなかったら御容赦ください。ハードウェアの恩恵が得られる反面、動作環境に色々左右されるのはちょっと不安。

Hello Unity(要:Unity WebPlayer)
※各キューブはマウスでドラッグできます。

Unity Maze(要:Unity WebPlayer)

  • マウスで視点移動
  • [W or ↑]キー:前進
  • [S or ↓]キー:後退
  • [A or ←]キー:左平行移動
  • [D or →]キー:右平行移動
  • [Space]キー:ジャンプ

触ってみた感じは、タイムラインが無くなった Director っていう印象で、それなりに使いやすい。付属のチュートリアル読むだけでそこそこのことが理解できるし、ドキュメントも親切で助かった。今回作ったデモは、どっちもスクリプト書かずに出来ちゃった。絵を書いたりモデリングするのが得意な人が使う環境としてはかなりイイ感じだと思う。

Flash系3Dエンジンじゃ到底出来ないような負荷のかかる処理もサラっとできてしまうので、アイディアやエレメントの作り込みがキチンとできてないとアラが浮き彫りになる。そういう訓練を積む意味でもAway3Dと平行してあれこれ試してみよっと。


AS3Dmod Test(要:FlashPlayer9)

AS3Dmod なんてのがあったので使ってみた。
PV3D、Away3D、Sandy、Alternativa3Dと、AS3用の主要な3Dエンジンに対応したモディファイアライブラリ。何故か「物理エンジン」とか「クロスシミュレーション」とかいう解釈で紹介されてたりするけど、物理演算ではなくて単純に頂点を制御してメッシュを変形させるもの。やってることはこれと同じ。物理エンジンじゃないんだぜ。

今のトコ、Bend、Noise、Perlin と、3つのモディファイアが実装されてる。上記サンプルだと Cylinder に Bend、Plane に Perlin、GeodesicSphere に Noise をそれぞれ適用してみた。これに zupko.info の Twistあたりを追加で移植すれば即席メガデモもどきが作れそうな感じ。とはいえ、ミエミエな使い方は実務だとイタいな。

配布されてるアーカイブ付属のサンプルが結構ややこしかったんで単純にしてみた。Away3D用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package
{
    import flash.display.*;
    import flash.events.*;
 
    import away3d.containers.View3D;
    import away3d.core.base.*;
    import away3d.containers.ObjectContainer3D;
    import away3d.cameras.TargetCamera3D;
    import away3d.primitives.*;
    import away3d.materials.*;
 
    import com.as3dmod.modifiers.*;
    import com.as3dmod.util.*;
    import com.as3dmod.ModifierStack;
    import com.as3dmod.plugins.away3d.LibraryAway3d;
 
    [SWF(backgroundColor="#FFFFFF")]
 
    public class as3dmodSample extends View3D
    {
        private var mod:ModifierStack;
        private var ben:Bend;
        private var benPhase:Phase;
 
        private var mod2:ModifierStack;
        private var noi:Noise;
 
        private var mod3:ModifierStack;
        private var per:Perlin;
 
        public function as3dmodSample()
        {
            stage.frameRate = 60;
            stage.align = StageAlign.TOP_LEFT;
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.quality = StageQuality.MEDIUM;
 
            //View3D init
            var targetCamera:TargetCamera3D = new TargetCamera3D();
            super({camera:targetCamera, x:stage.stageWidth/2, y:stage.stageHeight/2});
            init();
        }
 
        private function init():void
        {
            initAway3D();
            initObjects();
            initListeners();
        }
 
        private function initAway3D():void
        {
            //Camera Setting
            camera.y = 2000;
            camera.x = 1000;
            camera.z = 5200;
            camera.focus = 500;
            camera.zoom = 12;
        }
 
 
        private function initObjects():void
        {
            // Material Setting
            var wcMat:WireColorMaterial = new WireColorMaterial(0x0099CC, {wirecolor:0x00CCFF});
 
            // Object Setting
            var cylinder:Cylinder = new Cylinder({material:wcMat, radius:35, segmentsW:8, segmentsH:6, height:400});
            scene.addChild(cylinder);
            cylinder.x = -200;
            cylinder.z = 200
 
            var objPlane:Plane = new Plane({material:wcMat, width:300, height:300, segmentsW:6, segmentsH:6 });
            objPlane.bothsides = true;
            scene.addChild(objPlane);
            objPlane.x = 200;
            objPlane.z = 200;
 
            var geo:GeodesicSphere = new GeodesicSphere({material:wcMat, radius:60, fractures:2});
            scene.addChild(geo);
            geo.x = 0;
            geo.z = -200;
 
            // Modifier Setting
            mod = new ModifierStack(new LibraryAway3d(), cylinder);
            ben = new Bend(0, .3);
            ben.constraint = ModConstant.LEFT;
            benPhase = new Phase();
            mod.addModifier(ben);
 
            mod2 = new ModifierStack(new LibraryAway3d(), geo);
            noi = new Noise(8);
            mod2.addModifier(noi);
 
            mod3 = new ModifierStack(new LibraryAway3d(), objPlane);
            per = new Perlin(1);
            per.setFalloff(0.5, 0.5);
            mod3.addModifier(per);
        }
 
        //Render Loop
        private function loop3D(event:Event):void
        {
            benPhase.value += 0.05;
            ben.force = benPhase.phasedValue;
            mod.apply();
            mod2.apply();
            mod3.apply();
 
            //Rendering
            render();
        }
 
 
        private function initListeners():void
        {
            addEventListener(Event.ENTER_FRAME, loop3D);
            stage.addEventListener(Event.RESIZE, onStageResize);
        }
 
        private function onStageResize(event:Event):void
        {
            this.x = stage.stageWidth >> 1;
            this.y = stage.stageHeight >> 1;
        }
 
    }
}

実際にコンパイルする場合は、そのままだとエラーになるので次のような対処を。
※最近のリビジョンではこの問題が解決されております。

Arthropod で採用されてる com.carlcalderon.arthropod.Debug クラスが無いとエラーになるので、該当クラスをパスの通った場所に設置するか、

import com.carlcalderon.arthropod.Debug;

の行をコメントアウト。下記ファイルに該当箇所がある。

  • core/MeshProxy.as
  • modifiers/Bend.as
  • modifiers/Noise.as
  • modifiers/Perlin.as
  • plugins/alternativa3d/Alternativa3dMesh.as
  • plugins/away3d/Away3dVertex.as

あと、modifiers/Noise.as には

import alternativa.types.Matrix3D;

って部分があって、ここもコメントアウトした。Alternativa3D入れてないので。
そんな感じでコンパイルが通るようになると思うです。

08/09/22追記:
モディファイアが追加されてた。
追加になったのは Taper、Skew、Twist、Bloat の4つ。

AS3Dmod 追加モディファイア(要:FlashPlayer9)

Taper、TwistなんかはLightWaveで使ってた機能とほぼ一緒なのでなじみ深いですな。Skewは一見Bendと似てるけど、こっちはいわゆる「せん断」なのでちょっと違う。Bloat面白いな〜、膨らませる中心点をx, y, z座標で指定できるので「カーペットの下に潜り込んだジェリー」とか「雨どいの中を通過中のジェリー」っぽい表現(何)とかできそう。


simpleShadowTest(要:FlashPlayer9)

超簡易的に影を生成するクラス SimpleShadow 。正確には影を生成してるわけじゃなく、Y軸方向から見たオブジェクトの形をビットマップに描画してPlaneに貼り付けてるだけみたい。なのでライトとか一切無関係。けど、これでも充分効果はあると思う。Flash3Dはこういうフェイクがかなり重要かと。

下記のようにして使うっぽい。

import away3d.materials.utils.SimpleShadow;

- 中略 -

var sphere:Sphere = new Sphere({material:mat, radius:100, segmentsW:9, segmentsH:6});
addChild(sphere);
var simpleshadow:SimpleShadow = new SimpleShadow(sphere, 0x666666, 48, -200, 250);
simpleshadow.apply(scene);

sphere.x = 100;
sphere.y = 0;
sphere.z = 100;
simpleshadow.plane.x = sphere.x;
simpleshadow.plane.z = sphere.z;

simpleshadow.apply() すると、影生成の際に指定したオブジェクト(上記の場合 sphere)が、何故か原点に強制移動するので、simpleshadow.apply()した後で位置を指定。さらに、simpleshadow内に作成されてるplaneオブジェクトの位置をsphereの座標と合わせる形で指定した。sphere動かすだけで影も追従してほしいとこだけどもそこは Simple ってことでしょーがねーのかも。せめてsimpleshadow内PlaneがaddChildされるコンテナくらいは指定できると良かったんだけど。


vectorvisionTest(要:FlashPlayer9)

vectorvisionなんてのがあったのか。
ベクターエレメントの3D変形ができるようにPV3Dを拡張するクラス群で、labs.zavoo.comのsvg関連クラスを取り込んでるのでsvgを振り回すこともできるみたいだ。
あと、FIVe3Dのサイトで配布されてる Make a new typography file で作ったフォントデータ使えるので、まさに「PV3D meets FIVe3D」って感じでございましょうか。Astro正式公開されたらアレだけど、とりあえずは便利なんじゃないかと。