|  | 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.
 |