サイトトップ

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

Adobe Flash非公式テクニカルノート

Vector3D.project()メソッド

ID: FN0906001 Platform: All Version: CS4/ActionScript 3.0 Runtime: Flash Player 10/AIR 1.5

Vector3Dクラス
パッケージ flash.geom
継承 Vector3D → Object
project()メソッド
文法 public function project():void
概要 Vector3Dインスタンスのxyzの各座標値をVector3D.wプロパティの値で除する。3次元座標空間から2次元座標平面への透視投影変換などに用いられる。
引数 なし。
戻り値 なし。

説明
参照するVector3DインスタンスのプロパティVector3D.x/Vector3D.y/Vector3D.zの各値を、それぞれVector3D.wプロパティの値で除算した数値に置替えます[*1]

(x, y, z) → (x/w, y/w, z/w)

3次元空間の座標を遠近法が適用された2次元平面に描画する「透視投影」では、視点から投影面までの焦点距離と投影面から対象へのz方向の距離によって、xy座標がつぎのように変換されます(図001)。

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

図001■焦点距離とz方向距離が投影像の大きさを決める

z方向の距離として座標値Vector3D.zプロパティ値を使うと、Vector3D.wプロパティの値はVector3D.project()メソッドにより3次元べクトルの各座標値を除算しますので、透視投影のためには以下の式の値を設定します[*2]

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

Vector3D.wプロパティのデフォルト値は0です。ただし、演算によって値は変わることがありますので、ご注意ください。

var myVector3D:Vector3D = new Vector3D();
trace(myVector3D.w);   // 出力: 0

第1に、加減算では、参照されたVector3DインスタンスのVector3D.wプロパティの値は0にリセットされます。

var my0Vector3D:Vector3D = new Vector3D(1, 2, 3, 4);
trace(my0Vector3D, my0Vector3D.w);   // 出力: Vector3D(1, 2, 3) 4
var my1Vector3D:Vector3D = new Vector3D(7, 5, 3, 100);
trace(my1Vector3D, my1Vector3D.w);   // 出力: Vector3D(7, 5, 3) 100
var resultVector3D:Vector3D = my0Vector3D.add(my1Vector3D);
trace(resultVector3D, resultVector3D.w);   // 出力: Vector3D(8, 7, 6) 0

第2に、外積(Vector3D.dotProduct()メソッド)を計算すると、Vector3D.wプロパティの値は1に再設定されます。

var resultVector3D:Vector3D = my0Vector3D.crossProduct(my1Vector3D);
trace(resultVector3D.w);   // 出力: 1

第3に、Matrix3D.transformVector()メソッドによりMatrix3Dインスタンスの変換行列と乗算すると、掛合わせるVector3D.wプロパティの値を1に設定し直したうえで、行列演算が行われます(図002)[*3]

var myMatrix3D:Matrix3D = new Matrix3D();
var myRawData:Vector. = myMatrix3D.rawData;
var myVector3D:Vector3D = new Vector3D(4, 3, 2);
trace(myVector3D, myVector3D.w);   // 出力: Vector3D(4, 3, 2) 0
myRawData[3] = 4;
myRawData[7] = 3;
myRawData[11] = 2;
myRawData[15] = 5;
myMatrix3D.rawData = myRawData;
myVector3D = myMatrix3D.transformVector(myVector3D);
trace(myVector3D, myVector3D.w);   // 出力: Vector3D(4, 3, 2) 34

図002■Matrix3Dの変換行列とVector3Dのベクトルとの乗算

[*1] Vedtor3Dクラスについて詳しくは、「Vector3Dクラス」をご覧ください。Vector3Dインスタンスは、つぎの図003のような4次元ベクトルで表されます。

図003■Vector3Dインスタンスは4次元ベクトルを表す

* [ヘルプ] > [ActionScript 3.0 言語およびコンポーネントリファレンス] > [Vector3D]より引用

[*2] 透視投影については、「3次元画像の描画方法」および、てっく煮ブログ「AS3.0 で3Dプログラミングを1から勉強する(3) - 透視投影 -」をご参照ください。

[*3] 乗算結果のVector3D.wプロパティ値は34になります。この値は、Matrix3Dインスタンスの4行目とVector3Dインスタンス(ただし、Vector3D.wプロパティ値は1)との内積です(前掲図002)。変換行列とVector3Dオブジェクトの乗算については、「乗算時のVector3D.wプロパティ」をお読みください。

(4, 3, 2, 5)・(4, 3, 2, 1) = 4×4 + 3×3 + 2×2 + 5×1 = 34


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

図004■3次元空間における矩形の4隅の座標

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

図005■ワイヤーフレームの矩形がマウスポインタの位置に応じて水平回転する
*画像のクリックでSWFが開く。

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

スクリプト001■マウスポインタの位置に応じて水平回転させた3次元座標でワイヤーフレームを描く
(ソースFLAファイル: Vector3D_project_001.zip/Flash CS4形式/Zip圧縮約8KB)

// フレームアクション
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);
  }
}

参考
[ActionScript 3.0 Reference for the Adobe Flash Platform] > [Vector3D]「project() mehtod
[Adobe Flash Professional CS5用ActionScript 3.0リファレンスガイド] > [Vector3D]「project()メソッド


作成者: 野中文雄
更新日: 2011年2月28日「参考」のリンクをFlash Professional CS5のドキュメントに変更。
更新日: 2009年10月3日 スクリプト001のソースFLAファイルをアップロード。
更新日: 2009年7月5日「例」を追加。
作成日: 2009年6月30日


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