2007.12 Monthly archives

[Papervision3D2.0] Camera

2007.12.26

あまりに忙しすぎてblog更新サボってたら随分間が開いちゃったけど、引き続きPV3D2.0を勉強中。今回はカメラ。

PV3D2.0には、

  • Camera3D
  • FreeCamera3D
  • FrustumCamera3D

と、3種類のカメラがある。
※リビジョン639以降Camera3Dに一本化されました。FrustumCamera3Dの特性はCamera3Dが引き継いでいます。

Camera3DとFreeCamera3Dについては、これまでと変わりない(Camera3Dを原点に置くとマズいのも相変わらず)みたいなので、新規追加されたFrustumCamera3Dを使ってみた。ASColladaの作者でもあるTim Knip氏によるもので、以前はブランチで開発されてたものが2.0でめでたくマージされた。

標準のカメラとの決定的な違いは、nearClippingとfarClippingが実装されている点。カメラからの距離に応じて自動的にポリゴンの表示・非表示を処理してくれる。これで、特にテクニックを駆使しなくてもバカでかい地形の上を歩き回るようなものが比較的簡単に作れるようになったかも。

FrustumCamera3Dのコンストラクタ定義

FrustumCamera3D(
    viewport3D:Viewport3D,
    fov:Number = 90,
    near:Number = 10,
    far:Number = 2000
)
  • viewport3D:ViewPort3Dオブジェクトの指定
  • fov:カメラの視角
  • near:手前側のクリッピング平面位置
  • far:奥側のクリッピング平面位置

以下わりといい加減なサンプル。

e_frustumcamera.jpg

FrustumCameraTest.swf(要:FlashPlayer9)※ちょっと読み込みに時間かかります。
カーソルキーでカメラが移動

地形データは、206の時と同じくTORCSのデータを拝借。テクスチャを手抜きしたので、スゲー判りづらいサンプルになっちゃったけど、下記のようなオーバルのサーキット上を移動できるようになってる。

e_oval.jpg

衝突判定はよくわかんないので、バリバリにメリ込むヒドいサンプルだけど、とりあえずfarClippingが効いてるおかげで△5700の地形上をなんとか動き回れるだけで妙にウレシイ。

[Papervision3D2.0] Render

2007.12.11

続いてRender。
PV3D1.7までは最終的なレンダリングをScene3DのrenderCamera()メソッドで処理してたのが、レンダリング専用のクラス(org.papervision3d.render.BasicRenderEngine)として実装されたので、レンダリング処理は以下のように記述方法が変わった。

PV3D 1.7まで

scene = new Scene3D( container );
private function onEnterFrame(event:Event):void
{
    scene.renderCamera( camera );
}

PV3D 2.0

var renderer:BasicRenderEngine = new BasicRenderEngine();
private function onEnterFrame(event:Event):void
{
    renderer.renderScene(scene,camera,viewport);
}

基本レンダーとして用意されてるBasicRenderEngineを使っとけば良さげ。(LazyRenderEngineってのもあるけど、これはBasicRenderEngineを継承して scene、camera、viewport を後から参照したり、変更できるようにしたものっぽい。状況によってはこっちも使えそう。)色んなレンダーが追加されそうな空気が漂いまくりなので期待しちゃう。

renderScene()メソッドにscene,camera,viewportを突っ込むと、scene内のオブジェクトをcamera視点で座標変換し、viewportに出力すると。なんか、
ローカル座標 → ワールド座標変換 → ビュー座標変換 → プロジェクション座標変換 → スクリーン座標変換
っていう、3Dの解説とかでよく出てくる座標変換の流れに行儀良く従うようになった感じ?よくわかんないけど。

追加になった Viewport3D と、Render を踏まえた、PV3D 2.0の基本的なドキュメントクラスは以下のように書けばよさそうだ。

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
package
{
    import flash.display.*;
    import flash.events.*;
 
    import org.papervision3d.cameras.Camera3D;
    import org.papervision3d.render.BasicRenderEngine;
    import org.papervision3d.scenes.Scene3D;
    import org.papervision3d.view.Viewport3D;
    import org.papervision3d.objects.primitives.Plane;
    import org.papervision3d.materials.*;
    import org.papervision3d.materials.special.CompositeMaterial;
 
    [SWF(backgroundColor=0x000000)]
 
    public class BasicDocument extends Sprite
    {
        private var scene:Scene3D;
        private var viewport:Viewport3D;
        private var camera:Camera3D;
        private var renderer:BasicRenderEngine;
        private var objPlane:Plane;
 
        public function BasicDocument()
        {
            stage.frameRate = 60;
            stage.align = StageAlign.TOP_LEFT;
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.quality = StageQuality.MEDIUM;
            init3D();
        }
 
        private function init3D():void
        {
            //ビューポート設定
            viewport = new Viewport3D(0,0,true);
            viewport.opaqueBackground = 0x000000;
            addChild(viewport);
 
            //レンダー設定
            renderer = new BasicRenderEngine();
 
            //カメラ設定
            camera = new Camera3D();
            camera.z = -800;
            camera.fov = 30;
 
            //シーン設定
            scene = new Scene3D();
 
            //マテリアル設定
            var colorMat:ColorMaterial = new ColorMaterial( 0x006699, 1 );
            var wireMat:WireframeMaterial = new WireframeMaterial( 0x0099cc );
            var compoMat:CompositeMaterial = new CompositeMaterial();
            compoMat.addMaterial(colorMat);
            compoMat.addMaterial(wireMat);
            compoMat.doubleSided = true;
 
            //Plane生成
            objPlane = new Plane(compoMat, 300, 300);
            scene.addChild(objPlane);
 
            addEventListener(Event.ENTER_FRAME, onEnterFrame);
        }
 
        private function onEnterFrame(event:Event):void
        {
            objPlane.rotationY += 2;
            renderer.renderScene(scene,camera,viewport);
        }
    }
}

あと、org.papervision3d.view.BasicView を使うことで、

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
package
{
    import flash.display.*;
    import flash.events.*;
 
    import org.papervision3d.view.BasicView;
    import org.papervision3d.objects.primitives.Plane;
    import org.papervision3d.materials.*;
    import org.papervision3d.materials.special.CompositeMaterial;
 
    [SWF(backgroundColor=0x000000)]
 
    public class BasicViewTest extends BasicView
    {
        private var objPlane:Plane;
 
        public function BasicViewTest()
        {
            stage.frameRate = 60;
            stage.align = StageAlign.TOP_LEFT;
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.quality = StageQuality.MEDIUM;
 
            //viewportの定義とカメラタイプ定義
            super (0,0,true,false,"Target");
 
            //カメラ設定
            camera.z = -1600;
            camera.fov = 30;
 
            //マテリアル設定
            var colorMat:ColorMaterial = new ColorMaterial( 0x006699, 1 );
            var wireMat:WireframeMaterial = new WireframeMaterial( 0x0099cc );
            var compoMat:CompositeMaterial = new CompositeMaterial();
            compoMat.addMaterial(colorMat);
            compoMat.addMaterial(wireMat);
            compoMat.doubleSided = true;
 
            //Plane生成
            objPlane = new Plane(compoMat, 300, 300);
            scene.addChild(objPlane);
 
            //レンダリング開始
            startRendering();
        }
 
        override protected function onRenderTick(event:Event=null):void
        {
            objPlane.rotationY += 2;
            super.onRenderTick(event);
        }
 
    }
}

みたいな書き方も出来るってのを、Richard蒸しパン工場さんのエントリで知った。これを元に AbstractView を継承した独自のクラス作っておけば何かと便利っぽい。

07/12/26追記:
BasicViewを使った場合のコードを若干修正。

[Papervision3D2.0] Viewport3D

2007.12.08

Papervision3D 2.0 の解析をちょっとずつ始めてみる。
とりあえず Viewport3D から。

これまでのバージョンだと、

var container:Sprite = new Sprite();
addChild(this.container);
scene = new Scene3D( container );

てな感じでSpriteをビューポートに見立ててたのが、新たにViewport3Dとして実装されたと。
Viewport3DはSpriteを継承したクラスで、表示範囲のクリッピングと、表示範囲外ポリゴンのカリングを処理してくれる。Papervision3Dメモ#22で取り上げた、RectangleTriangleCullerの機能がここに結実といった感じ。

そんなこんなで、PV3D2.0からは、

var viewport:Viewport3D = new Viewport3D(0,0,true);
addChild(viewport);
scene = new Scene3D();

と、定義することになったらしい。(Scene3Dにviewportを突っ込む必要はナシ。)

Viewport3Dのコンストラクタ定義

Viewport3D(
    viewportWidth:Number = 640,
    viewportHeight:Number = 480,
    autoScaleToStage:Boolean = false,
    interactive:Boolean = false,
    autoClipping:Boolean = true,
    autoCulling:Boolean = true
)
  • viewportWidth:ビューポートの幅
  • viewportHeight:ビューポートの高さ
  • autoScaleToStage:ステージサイズにビューポートのサイズをフィット
  • interactive:インタラクティブモード?(未確認)
  • autoClipping:ビューポート矩形範囲外をクリッピング
  • autoCulling:ビューポート矩形範囲外ポリゴンをカリング

Spriteを継承してるので、ステージ上での位置指定や背景色指定は

viewport.x = 200;
viewport.y = 200;
viewport.opaqueBackground = 0xFF0000;

とかいう感じでできる。

widthとheightに関しては

viewport.width = 200;
viewport.height = 200;

だと、当然ながらビューポート内のオブジェクトごと大きさが変わるので、ビューポート矩形のみ幅と高さを変えたい場合は、

viewport.viewportWidth = 200;
viewport.viewportHeight = 200;

ってな具合で指定するとよろし。

また、ビューポートはいくつも定義できるので、以下のようなことが出来る。

Viewport3DTest.swf(要:FlashPlayer9)

ビューポートを4つ作ってマトリクス状に配置。
シーン内に、設置場所の異なるカメラを4つ配置して、

renderer.renderScene(scene,top_camera,top_view);
renderer.renderScene(scene,front_camera,front_view);
renderer.renderScene(scene,side_camera,side_view);
renderer.renderScene(scene,quarter_camera,quarter_view);

って感じで、renderer.renderScene()メソッド(これも変わったポイント)にそれぞれのカメラとビューポートを指定した。ちょっとした3Dアプリみたいだわ。

Viewport3Dはだいたいこんな感じかな。

[Papervision3D2.0] Papervision3D Public Alpha 2.0

2007.12.06

Papervision3DTest.swf(要:FlashPlayer9)

Papervision3D Public Alpha 2.0「GreatWhite」出た。
とりあえずは、MLで流れたサンプルをちょっとだけイジって動作確認してみた。新マテリアル「GouraudMaterial」と「PhongMaterial」だそうな。ライト追加になったし、shader系がいっぱい追加になってて、しばらくコレだけで盛り上がれそう。個人的にはFrustumCamera3Dがマージされたのがスゲー嬉しい。

とにかく相当な量の仕様変更っぷり。イベント関連なんか相当変わったっぽいなぁ。5つに分かれてたScene3D系は「Scene3D」に一本化したっぽいし、マテリアルもかなり整理されて全体的な構造がスッキリした印象。
調べたいことがてんこ盛りでウキウキ。