AS3Graphics#6.1 PerspectiveProjectionで3D視点操作

前回に引き続き、AS3の3D描画に関係する PerspectiveProjection クラスについて解説します。

3D表現の二つの要素

3D表現とは、対象物と視点の二つの要素があって初めて成立します。どの位置にどんな物があって、それをどこから見ているかによって、どのように見えるのかが決定します。前回の#6では、「どの位置にどんな物があるか」を、Matrix3D クラスを使用して定義する手順について解説しました。今回は、「どこから見ているか」にあたる、PerspectiveProjection クラスを取り上げます。

PerspectiveProjection クラス

PerspectiveProjection クラスは、視点位置に関する以下の三つの値のみを持つシンプルなクラスです。

  • fieldOfView : 視野角
  • focalLength : 距離
  • projectionCenter : 投影の中心点

fieldOfViewは、遠近感の強さに影響を与えます。値が大きい場合は、z座標による見かけ上の大きさの変化が激しくなります。逆に値が小さい場合、z座標は見かけ上の大きさにあまり影響を与えません。focalLength は、fieldOfView の値とステージのサイズから自動設定されます。変更することも可能ですが、fieldOfView の値を変更すると再計算されます。focalLength と fieldOfView の値をそれぞれ変更した時の見え方の変化はどちらも似ているので、通常は fieldOfView のみ設定すれば良い場合が多いと思います。projectionCenter は、遠近法の一点透視図法で言うところの消失点にあたります。

これらの値が実際の見え方にどのように影響を与えるのかは、実際にやってみないことにはイメージしにくいと思いますので、サンプルプログラムを作成しました。マウスポインタの位置がprojectionCenter になります。上下にドラッグすると、fieldOfView の値が増減します。

package { import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import flash.geom.Point;

/** * PerspectiveProjection操作のサンプルです。 * @author ishigami.shintaro * */ public class PerspectiveProjectionTest extends Sprite { /** 描画領域の幅です。 */ public static const WIDTH:int = 400;

/** 描画領域の高さです。 */ public static const HEIGHT:int = 400;

/** * コンストラクタです。 */ public function PerspectiveProjectionTest() { super(); stage.scaleMode = "noScale";

//背景を描画します。 graphics.beginFill(0); graphics.drawRect(0, 0, WIDTH, HEIGHT);

var square:Circle; const SPAN:int = 100; const SPAN_Z:int = 50;

//Circleを作成して配置します。 for (var i:uint = 50; i <= WIDTH; i += SPAN) { for (var j:uint = 50; j <= HEIGHT; j += SPAN) { for (var k:int = -200; k < 200; k += SPAN_Z) { square = new Circle(); addChild(square); square.x = i; square.y = j; square.z = k; square.alpha = 1 - (k + 200) / 400; } } } stage.addEventListener(MouseEvent.MOUSE_MOVE, stageMouseMoveHandler); } /** * 前回mouseMove時のマウスY座標です。 */ private var _mouseY:Number; /** * stageのmouseMoveイベントハンドラです。 * @param event * */ private function stageMouseMoveHandler(event:MouseEvent):void { //projectionCenterをマウス位置に移動します。 transform.perspectiveProjection.projectionCenter = new Point(event.stageX, event.stageY); if(event.buttonDown) { if(isNaN(_mouseY)) { _mouseY = event.stageY; } //上下にドラッグ時にfieldOfViewを増減します。 var fieldOfView:Number = transform.perspectiveProjection.fieldOfView + event.stageY - _mouseY; if (0 < fieldOfView && fieldOfView < 180) { transform.perspectiveProjection.fieldOfView = fieldOfView; } _mouseY = event.stageY; } else { _mouseY = NaN; } } } } import flash.display.Graphics; import flash.display.Shape; import flash.geom.ColorTransform; import flash.geom.Matrix3D; import flash.geom.Vector3D; /** * 円を描画するShapeです。 * @author ishigami.shintaro */ class Circle extends Shape { /** * 半径です。 */ public static const RADIUS:int = 45; /** * コンストラクタです。 */ public function Circle() { super(); //円を描画します。 var g:Graphics = graphics; g.lineStyle(2, 0xFFFFFF); g.drawCircle(0, 0, RADIUS); } } [/as3] [SWF]http://public-blog-dev.s3.amazonaws.com/wp-content/uploads/2011/10/PerspectiveProjectionTest.swf, 400, 400[/SWF]

このサンプルを見るにはFlash Playerがインストールされている必要があります。

PerspectiveProjection の設定は、3D表現を行うにあたって必須というわけではありません。projectionCenterはデフォルトでは自動的にstageの中心点が設定されますし、fieldOfView とfocalLength も無難な設定になります。しかし、これらの値を動的に変化させることで得られる視覚効果は、3D表示オブジェクトを Matrix3D で直接アニメーションさせたりするよりも簡単に実装できます。