papervison3d基礎の基礎

最近、papervison3dを使って、flash上で3dのムービーを作ろうとしています。

Web Designing 2009年6月号で連載されている、papervision3dの記事を参考に、基礎の勉強中をしています。

連載自体は、1つ前の5月号より行っているようで、手元にあるのは2回目でした。




3DCG表示関連の用語


連載のサンプルソースを見て、大体は理解できましたが、シーンやビューポートの位置づけがよくわかりませんでした(説明は5月号にあるのかな)。

この件については、以下のサイトでわかりやすく説明してありました。

勉強部屋:Papervision入門


3Dシーン(3Dscene)

3Dモデルを配置する空間です。この3D空間に、3Dモデルを配置する事により、空間と物
が存在する3DCGの世界が作られます。

カメラ(Camera)

3Dモデルと3Dシーンで3DCGの世界を作成したら、それを見るためにカメラが必要です。
私達は作成した3DCGの世界をカメラの視点で見ることになります。


ビューポート(Viewport)

カメラで撮影した3DCGの世界は、何かに投影しないと私達は見ることができません。
例えばテレビ局でカメラが撮影した映像は、液晶ディスプレイやブラウン管に映し出さ
れる事により目にする事ができるのと一緒です。この例えで、ディスプレイやブラウン
管の役割をするのがビューポートです。

ざっくりいえば、

  • シーンにオブジェクトを配置して動かしたりする
  • モデルをカメラで撮影する
  • 撮影したのをビューポートで映して見る

という感じで、上記一連の処理を、レンダリングで行うというという理解です。

オブジェクト


オブジェクトの形状は、Planeや、Cubeなどがあり、これらをプリミティブオブジェクトといいます。

現在のところ、プリミティブオブジェクトは6種類あるようです。

  • Cone (円錐)
  • Cube (直方体)
  • Cylinder (円柱)
  • Plane (平面)
  • Sphere (球体)


プリミティブオブジェクトの表面に設定する属性(色や、画像など)を、マテリアルといいます。
マテリアルは、プリミティブのインスタンスを生成時に引数で与えます。

マテリアルは、色をつけるためのマテリアルや、ワイヤーフレーム、bitmapやMovieClipを貼り付けるものなど色々あります。

// カラーマテリアル
var coMaterial:ColorMaterial = new ColorMaterial(0x006699);


ひとつのプリミティブオブジェクトに複数のマテリアルを設定したい場合は、CompositeMaterialというオブジェクトを使用します。

他のマテリアルをCompositeMaterialに追加すれば、プリミティブオブジェクトに複数のマテリアルを設定できます。

// カラーマテリアル
var coMaterial:ColorMaterial = new ColorMaterial(0x006699);

// ワイヤーフレームマテリアル
var wiMaterial:WireframeMaterial = new WireframeMaterial(0x0099CC);

// CompositeMaterialに集約
var compMaterial:CompositeMaterial = new CompositeMaterial();
compMaterial.addMaterial(coMaterial);
compMaterial.addMaterial(wiMaterial);

サンプル


ざっと説明しましたが、連載を参考に作ったものを下に書いておきます。
迷路のようなものを作ってみました。

複雑なことは何一つやっていないので、上記説明程度で、今回書いたソースは理解できると思います。

import org.papervision3d.scenes.Scene3D;
import org.papervision3d.cameras.Camera3D;
import org.papervision3d.view.Viewport3D;
import org.papervision3d.render.BasicRenderEngine;
import org.papervision3d.objects.DisplayObject3D;
import org.papervision3d.objects.primitives.Cube;
import org.papervision3d.objects.primitives.Plane;
import org.papervision3d.materials.ColorMaterial;
import org.papervision3d.materials.WireframeMaterial;
import org.papervision3d.materials.utils.MaterialsList;
import org.papervision3d.materials.special.CompositeMaterial;
import org.papervision3d.events.InteractiveScene3DEvent;

/**
 * 3Dの表示
 */
// シーン
var scene:Scene3D = new Scene3D();

// カメラ
var camera:Camera3D = new Camera3D();
camera.fov = 45; // カメラの視野角
camera.x = 600;
camera.y = 2000;
camera.z = -600;
camera.rotationX = 90;
//camera.target = DisplayObject3D.ZERO; // シーンの原点を注視し続けるように指定

// ビューポート
var viewport:Viewport3D = new Viewport3D(0, 0, true, true);
//var viewport:Viewport3D = new Viewport3D(0, 0, true);
addChild(viewport);
viewport.opaqueBackground = 0x000000;
viewport.buttonMode = true;

/**
 * オブジェクトの設定
 */
// マテリアルの定義
// 通路用マテリアル
var coMaterial1:ColorMaterial = new ColorMaterial(0x006699);
var wiMaterial1:WireframeMaterial = new WireframeMaterial(0x0099CC);
var floorMatelial:CompositeMaterial = new CompositeMaterial();
floorMatelial.addMaterial(coMaterial1);
floorMatelial.addMaterial(wiMaterial1);

// スタート、ゴール用マテリアル
var coMaterial1Sg:ColorMaterial = new ColorMaterial(0x999900);
var wiMaterial1Sg:WireframeMaterial = new WireframeMaterial(0xCCCC00);
var floorMatelialSg:CompositeMaterial = new CompositeMaterial();
floorMatelialSg.addMaterial(coMaterial1Sg);
floorMatelialSg.addMaterial(wiMaterial1Sg);

// 壁用マテリアル
var coMaterialWl:ColorMaterial = new ColorMaterial(0x0099CC);
var wiMaterialWl:WireframeMaterial = new WireframeMaterial(0x00CCFF);
var compMaterialWl:CompositeMaterial = new CompositeMaterial();
compMaterialWl.addMaterial(coMaterialWl);
compMaterialWl.addMaterial(wiMaterialWl);

// Cube用マテリアル定義:壁

/*
 * Cubeのすべての面に同じマテリアルを設定する
 * 個別に設定する場合は、allの代わりに以下のキーワードを使用する
 * (front, back, left, right, top, bottom )
 */
var wallMaterials:MaterialsList = new MaterialsList({
        all:compMaterialWl // Cubeのすべての面に同じマテリアルを設定する
    });

// 宝箱用マテリアル
var coMaterialTb:ColorMaterial = new ColorMaterial(0x990066);
var wiMaterialTb:WireframeMaterial = new WireframeMaterial(0xCC0099);
var compMaterialTb:CompositeMaterial = new CompositeMaterial();
compMaterialTb.addMaterial(coMaterialTb);
compMaterialTb.addMaterial(wiMaterialTb);

// Cube用マテリアル定義:宝箱
var tboxMaterials:MaterialsList = new MaterialsList({
        all:compMaterialTb
    });

/**
 * オブジェクトの配置
 */

// 迷路データ
var mapArray:Array = [
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
    [1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 2],
    [1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1],
    [1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 3, 1],
    [1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1],
    [1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1],
    [1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1],
    [1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1],
    [1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1],
    [1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1],
    [1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1],
    [1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1],
];

// 迷路の描画
var BROCKSIZE:Number = 100; // 1ブロックの大きさ
var zLength:uint = mapArray.length;
for(var zAxis:uint = 0; zAxis < zLength; zAxis++) {
    var xLength:uint = mapArray[zAxis].length;
    for(var xAxis:uint = 0; xAxis < xLength; xAxis++) {
        switch(mapArray[zAxis][xAxis]) {
            case 0: // 通路
                var plane:Plane = new Plane(floorMatelial, BROCKSIZE, BROCKSIZE);
                scene.addChild(plane);
                plane.x = xAxis * BROCKSIZE;
                plane.z = -zAxis * BROCKSIZE;
                plane.rotationX = 90;
                plane.y = -50;
            break;
            
            case 1: // 壁
                var cube:Cube = new Cube(wallMaterials, BROCKSIZE, BROCKSIZE, BROCKSIZE);
                scene.addChild(cube);
                cube.x = xAxis * BROCKSIZE;
                cube.z = -zAxis * BROCKSIZE;
            break;
            
            case 2: // スタート、ゴール
                var planeSg:Plane = new Plane(floorMatelialSg, BROCKSIZE, BROCKSIZE);
                scene.addChild(planeSg);
                planeSg.x = xAxis * BROCKSIZE;
                planeSg.z = -zAxis * BROCKSIZE;
                planeSg.rotationX = 90;
                planeSg.y = -50;
            break;
            
            case 3: // お宝
                // 床
                var planeTb:Plane = new Plane(floorMatelial, BROCKSIZE, BROCKSIZE);
                scene.addChild(planeTb);
                planeTb.x = xAxis * BROCKSIZE;
                planeTb.z = -zAxis * BROCKSIZE;
                planeTb.rotationX = 90;
                planeTb.y = -50;

                // 宝箱
                var tbox:Cube = new Cube(tboxMaterials, BROCKSIZE/5, BROCKSIZE/5, BROCKSIZE/5);
                scene.addChild(tbox);
                tbox.x = xAxis * BROCKSIZE;
                tbox.z = -zAxis * BROCKSIZE;
                break;
        }
    }
}

// レンダリングの設定
var renderer:BasicRenderEngine = new BasicRenderEngine();

function onEnterFrame(event:Event):void {
    renderer.renderScene(scene, camera, viewport);
}
addEventListener(Event.ENTER_FRAME, onEnterFrame, false, 0, true);


黄色いところが、スタート・ゴールで、赤いのが宝箱的なものです。

で、以下のような感じになりました。

サンプル

動きはないです。

ということで、Papervision3Dについては、これから少しずつ掘り下げていこうと思います。