サイトトップ

Director Flash 書籍 業務内容 プロフィール

Flash ActionScript 3.0 Reference

◎06 幾何

☆16 ★Vector3Dの3次元空間座標を2次元平面に投影したい

解説
Vector3Dクラスは3次元空間の座標を扱います。3次元座標をコンピュータディスプレイの2次元平面に投影することは、「透視投影」といいます。Vector3D.project()メソッドを用いると、Vector3Dインスタンスの座標を透視投影できます。そのためには、焦点距離にもとづく投影の比率を定めなければなりません。投影の比率は、簡単な比例計算により、つぎのように求められます(図06-16-01)。

投影像の大きさ/オリジナルの大きさ = 焦点距離/(焦点距離 + z方向距離)
投影像の大きさ = オリジナルの大きさ×焦点距離/(焦点距離 + z方向距離)

図06-16-01■焦点距離とz方向距離が投影像の大きさを決める【Fig09-002.png】

Vector3Dインスタンスは、実際には4次元のベクトルです。3次元のxyz座標に加え、オプションとしてベクトルの第4成分(要素)となるVector3D.wプロパティをもちます(図06-16-02)。透視投影の比率は、このVector3D.wプロパティに設定します。ただし、Vector3D.project()メソッドは、Vector3D.x/Vector3D.y/Vector3D.zプロパティの各値を、Vector3D.wプロパティ値で割り算します。したがって、Vector3D.wプロパティには、つぎの計算値を設定します。

Vector3D.wプロパティ = (焦点距離 + Vector3D.zプロパティ値)/焦点距離

図06-16-02■Vector3Dインスタンスが表すベクトル

[編集者向け注釈] 図は[ヘルプ]から引用したものなので、イラストもしくは表組などで再作成してください。

Vector3D.project()メソッドは、参照したインスタンスのxyz座標を直接書替えます。ですから、もとのインスタンスを保持するためには、Vector3D.clone()メソッドで予めVector3Dオブジェクトを複製します。また、Matrix3D.transformVector()メソッドを使うと、Matrix3Dオブジェクトの変換行列でVector3Dインスタンスの3次元座標を変換することができます。

→関連項目
インスタンスを3次元変換行列で伸縮・回転したい」「3次元変換行列でインスタンスに複数の変換を加えたい

Vector3Dクラス
パッケージ flash.geom
継承 Vector3D → Object
Vector3D()コンストラクタ ASタイプ M
ランタイムバージョン AIR 1.5/Flash Player 10
文法 Vector3D(x:Number = 0, y:Number = 0, z:Number = 0, w:Number = 0)
意味 Vector3Dインスタンスを生成します。
引数

x:Number ― インスタンスのx座標値。デフォルト値は0。/y:Number ― インスタンスのy座標値。デフォルト値は0。/z:Number ― インスタンスのz座標値。デフォルト値は0。/w:Number ― インスタンスのw値(オプション)。透視投影比率などを納める。デフォルト値は0。

wプロパティ ASタイプ P
ランタイムバージョン AIR 1.5/Flash Player 10
文法 matrix:Matrix
意味 Vector3Dインスタンスが表すベクトルの第4成分(要素)。Vector3D.project()メソッドにより、xyz座標値を除する値。
プロパティ値 Vector3Dインスタンスが表すベクトルの第4成分値。透視投影比率などを納める。
project()メソッド ASタイプ M
ランタイムバージョン AIR 1.5/Flash Player 10
文法 project():void
意味 Vector3Dインスタンスのxyzの各座標値をVector3D.wプロパティの値で除する。3次元空間から2次元平面への座標の透視投影変換などに用いられる。
引数 なし。
戻り値 なし。
clone()メソッド ASタイプ M
ランタイムバージョン AIR 1.5/Flash Player 10
文法 clone():Vector3D
意味 Vector3Dインスタンス複製して、新たなオブジェクトとして返す。
引数 xScale:Number…水平方向に拡大・縮小として乗じる比率。/yScale:Number…垂直方向に拡大・縮小として乗じる比率。/zScale:Number…垂直方向に拡大・縮小として乗じる比率。
戻り値 複製された新たなVector3Dインスタンス。

Matrix3Dクラス
パッケージ flash.geom
継承 Matrix3D → Object
transformVector()メソッド ASタイプ M
ランタイムバージョン AIR 1.5/Flash Player 10
文法 transformVector(targetVector3D:Vector3D):Vector3D
意味 Matrix3Dオブジェクトの変換行列を用いて、Vector3Dインスタンスの座標を変換し、新たなVector3Dオブジェクトとして返す。
引数 targetVector3D:Vector3D…座標を変換する対象のVector3Dインスタンス。
戻り値 座標変換された新たなVector3Dインスタンス。

記述例
3次元空間に矩形の4隅の座標をVector3Dインスタンスで指定し、回転の変換を加えたうえで、タイムライン上にワイヤーフレームで回る矩形を描いてみましょう。4隅の初期位置はz座標を0とし、原点(0, 0, 0)を中心に1辺の半分を変数(nUnit)に代入して、下図06-16-03のように設定します。

図06-16-03■3次元空間における矩形の4隅の座標【06_16_Vector3D_project_001.png】

以下のスクリプト06-16-01は、3次元空間で矩形の4隅の座標をマウスポインタの水平位置に応じてy軸で回転し、タイムラインに動的に配置したSpriteインスタンスに4辺をワイヤーフレームで描きます(図06-16-04)。4隅の座標はVector3Dオブジェクトで生成し、Vectorインスタンス(myVectors)に納めています。

図06-16-04■ワイヤーフレームの矩形がマウスポインタの位置に応じて水平回転する【06_16_Vector3D_project_002.png】

DisplayObject.enterFrameイベント(定数Event.ENTER_FRAME)のリスナー関数xRotate()では、マウスポインタの座標から計算した水平方向の回転をMatrix3D.prependRotation()メソッドによりMatrix3Dオブジェクトに加え、forループの処理でMatrix3D.transformVector()で4隅のVector3Dインスタンスの座標を変換しています。2次元平面に透視投影するために、Vector3D.wプロパティに変換比率を設定したうえで、Vector3D.project()メソッドを呼出します。なお、透視投影はVector3D.clone()メソッドにより複製したインスタンスに対して行っています。

→関連項目
3次元変換行列でインスタンスに複数の変換を加えたい

スクリプト06-16-01■マウスポインタの位置に応じて水平回転させた3次元座標でワイヤーフレームを描く

// フレームアクション
var nUnit:Number = 50;
var nSensitivity:Number = 0.2;
var nFocalLength:Number = nUnit * 2;
var mySprite:Sprite = new Sprite();
var myGraphics:Graphics = mySprite.graphics;
var myMatrix3D:Matrix3D = new Matrix3D();
var myVectors:Vector.<Vector3D> = new Vector.<Vector3D>();   // Vectorインスタンスの生成
mySprite.x = stage.stageWidth / 2;
mySprite.y = stage.stageHeight / 2;
// 4隅の座標をVector3DオブジェクトとしてVectorインスタンスに納める
myVectors.push(new Vector3D(nUnit, nUnit, 0));
myVectors.push(new Vector3D(nUnit, -nUnit, 0));
myVectors.push(new Vector3D(-nUnit, -nUnit, 0));
myVectors.push(new Vector3D(-nUnit, nUnit, 0));
addChild(mySprite);
addEventListener(Event.ENTER_FRAME, xRotate);
function xRotate(eventObject:Event):void {
  var i:uint;
  var myVector3D:Vector3D;
  var projectedVectors:Vector.<Vector3D> = new Vector.<Vector3D>();
  var nLength:uint = myVectors.length;
  myMatrix3D.prependRotation(mySprite.mouseX * nSensitivity, Vector3D.Y_AXIS);
  for (i = 0; i<nLength; i++) {   // 4隅のVector3Dインスタンスを取出して処理
    myVector3D = myVectors[i];
    myVector3D = myMatrix3D.transformVector(myVector3D);   // 回転の変換を適用
    myVector3D = myVector3D.clone();   // インスタンスを複製
    // 透視投影の変換比率をVector3D.wプロパティに設定
    myVector3D.w = (nFocalLength + myVector3D.z)/nFocalLength;
    myVector3D.project();   // 透視投影
    projectedVectors.push(myVector3D);
  }
  myGraphics.clear();
  myGraphics.lineStyle(2, 0);
  myGraphics.moveTo(projectedVectors[nLength -1].x, projectedVectors[nLength -1].y);
  for (i = 0; i<nLength; i++) {   // 透視投影されたVector3Dインスタンスから線描
    myVector3D = projectedVectors[i];
    myGraphics.lineTo(myVector3D.x, myVector3D.y);
  }
}

Spriteインスタンスへの線描については、前述「直線を描きたい」をお読みください。

→関連項目
直線を描きたい


作成者: 野中文雄
ドラフト作成: 2009年7月2日


Copyright © 2001-2009 Fumio Nonaka.  All rights reserved.