ActionScript 3.0で始めるオブジェクト指向スクリプティング

第42回 Vector3Dクラスの3次元空間座標とインスタンスへの描画

この記事を読むのに必要な時間:およそ 7 分

今回からまた3次元空間の話に戻る。新たに学ぶクラスはVector3Dだ。名前が示すとおり,3次元空間座標(位置ベクトル)を扱う。初めのお題は例によって,四角形を3次元空間で水平に回してみる。第35回「Matrix3Dクラスによる座標変換」スクリプト1と同じく,マウスポインタの水平位置に応じてアニメーションさせたい第35回図3再掲)⁠

第35回図3 インスタンスの基準点から見たマウスポインタの水平位置に応じてインスタンスが水平回転(再掲)

第35回図3 インスタンスの基準点から見たマウスポインタの水平位置に応じてインスタンスが水平回転(再掲)

Vector3DインスタンスをMatrix3Dオブジェクトで座標変換する

まず,Vector3Dオブジェクトは,xyzの3次元座標をそれぞれVector3D.x/Vector3D.y/Vector3D.zプロパティとしてもつ。2次元平面の座標については,第22回MovieClipシンボルにクラスを定義するでPointクラスを学んだ。Vector3Dクラスは,その3次元版といえる。コンストラクタメソッドVector3D()でインスタンスをつくるとき,xyz座標値は引数として渡せばよい※1)⁠引数がなければ,初期値0として扱われる。

new Vector3D(x座標, y座標, z座標)

Vector3Dインスタンスも,Matrix3Dクラスを使って座標変換できる。メソッドは,Matrix3D.transformVector()だ。引数にVector3Dインスタンスを渡すと,変換の加えられた新たなVector3Dオブジェクトが返される。

Matrix3Dオブジェクト.transformVector(Vector3Dオブジェクト)

たとえば,3次元空間座標(100, 0, 0)をy軸で90度回してみよう。新しい(デフォルトの)Matrix3Dオブジェクトに加える回転なので,Matrix3D.prependRotation()メソッドで足りるだろう。

var myVector3D:Vector3D = new Vector3D(100, 0, 0);
var myMatrix3D:Matrix3D = new Matrix3D();
myMatrix3D.prependRotation(90, Vector3D.Y_AXIS);
trace(myMatrix3D.transformVector(myVector3D));

変換されたVector3Dインスタンスの座標情報が,以下のように[出力]される図1)⁠x軸上の座標(100, 0, 0)をy軸正方向に対して90度時計回りに変換すれば,z軸上負の方向つまり手前に移る。その座標は(0, 0, -100)となる。

Vector3D(6.12323420998628e-15, 0, -100)

なお,[出力]されたVector3Dインスタンスのx座標が「6.123…e-15」というのは,小数点以下0が14桁続く極めて小さな数値で,誤差を含んだ0と考えればよい※2)⁠

図1 変換されたVector3Dインスタンスの座標情報が[出力]される

図1 変換されたVector3Dインスタンスの座標情報が[出力]される

図1 変換されたVector3Dインスタンスの座標情報が[出力]される

さて,これで3次元座標が自由に変換できる。しかし,まだ大事なことが残っている。Vector3Dオブジェクトの座標を回しても,そのままでは見えない。xyz座標の値を[出力]しただけでは,回っているのかどうかがわからないだろう。

※1
オプションの第4引数(プロパティVector3D.w)については,後の回で扱う。
※2
「指数表記」と呼ばれ,大きな数や小さい数を表すのに用いられる。たとえば,⁠1.23e-4」は,つぎのように0.000123を意味する。
1.23e-4 = 1.23×10-4 = 0.000123

Spriteインスタンスに直線を描く

3次元空間座標を行列変換しただけでは,座標値は求められても,その振る舞いが目に見えない。座標に対して線を描いたり,塗ったりする作業が必要になる。そこで,複数の座標の間を線(ワイヤーフレーム)で結ぶことにする。使うのは第33回遠近法の投影でもご紹介したGraphicsクラスのメソッドだ。描画用のSpriteインスタンスをつくり,そのSprite.graphicsプロパティのGraphicsオブジェクトにベクターの線を描く。

直線の描き方は,[線ツール]と同じ要領だ図2)⁠線の太さやカラーといったスタイルを決めてから,始まりと終わりの位置を定める。線のスタイルを決めるメソッドはGraphics.lineStyle()始まりと終わりはGraphics.moveTo()およびGraphics.lineTo()で指定する。

Graphicsオブジェクト.lineStyle(太さ,カラー, アルファ)
Graphicsオブジェクト.moveTo(x座標, y座標)
Graphicsオブジェクト.lineTo(x座標, y座標)

図2 [線ツール]と[プロパティ]インスペクタ

図2 [線ツール]と[プロパティ]インスペクタ

ステージ中央に置いたSpriteインスタンスに,100ピクセル四方の正方形を描いてみよう。線の太さは2ポイント,カラーは青(0x0000FF)とする。Spriteインスタンスの基準点に対して,水平・垂直とも±50ピクセルの大きさで4辺を描けばよい。なお,Graphics.lineTo()メソッドを呼出すと,その引数の座標がつぎの描き始めの位置になる。したがって,連続した直線を描くなら,Graphics.moveTo()メソッドは初めに呼出すだけでよい。

var mySprite:Sprite = new Sprite();
// インスタンスから取出したGraphicsオブジェクトを変数に代入
var myGraphics:Graphics = mySprite.graphics;
mySprite.x = stage.stageWidth / 2;
mySprite.y = stage.stageHeight / 2;
addChild(mySprite);
// Graphicsクラスのメソッドで線描
myGraphics.lineStyle(2, 0x0000FF);
myGraphics.moveTo(-50, -50);
myGraphics.lineTo(50, -50);
myGraphics.lineTo(50, 50);
myGraphics.lineTo(-50, 50);
myGraphics.lineTo(-50, -50);

図3 ステージ中央に100ピクセル四方の正方形を青い線で描く

図3 ステージ中央に100ピクセル四方の正方形を青い線で描く

この座標を線で描く処理は,後々使いやすいような仕組みに整えておこう。空間を座標で扱い出すと,座標の数はあっという間に増えてしまう。数に惑わされないよう,ふたつ手を加える。第1に,座標はまとめておく。xy座標はPointオブジェクトとし,さらにそれら座標群を配列に納める。第2に,描画は関数として定義する。引数には,Pointがエレメントに納められた配列を渡す。

でき上がったフレームアクションが,以下のスクリプト1だ。配列(変数vertices)に4つのPointインスタンスを納めた。描画する関数(xDrawLines())は,配列からPointインスタンスを取出し,Graphicsクラスのメソッドにより順に直線を描いている。処理の結果は,前のフレームアクションと変わらない(前掲図3参照)⁠

スクリプト1 配列から取出したPointインスタンスの座標にしたがってSpriteに線を描く

// フレームアクション
var nUnit:Number = 100 / 2;
var mySprite:Sprite = new Sprite();
var vertices:Array = new Array();   // 座標のPointインスタンスを納める配列生成
var myGraphics:Graphics = mySprite.graphics;
mySprite.x = stage.stageWidth / 2;
mySprite.y = stage.stageHeight / 2;
// xy座標をPointインスタンスにして配列に納める
vertices.push(new Point(-nUnit, -nUnit));
vertices.push(new Point(nUnit, -nUnit));
vertices.push(new Point(nUnit, nUnit));
vertices.push(new Point(-nUnit, nUnit));
addChild(mySprite);
xDrawLines(vertices);
// 配列からPointインスタンスを取出して線描する関数
function xDrawLines(vertices:Array):void {
  var nLength:uint = vertices.length;
  var myPoint:Point = vertices[nLength - 1];
  myGraphics.lineStyle(2, 0x0000FF);
  myGraphics.moveTo(myPoint.x, myPoint.y);
  for (var i:uint = 0; i < nLength; i++) {
    myPoint = vertices[i];
    myGraphics.lineTo(myPoint.x, myPoint.y);
  }
}

著者プロフィール

野中文雄(のなかふみお)

ソフトウェアトレーナー,テクニカルライター,オーサリングエンジニア。上智大学法学部卒,慶応義塾大学大学院経営管理研究科修士課程修了(MBA)。独立系パソコン販売会社で,総務・人事,企画,外資系企業担当営業などに携わる。その後,マルチメディアコンテンツ制作会社に転職。ソフトウェアトレーニング,コンテンツ制作などの業務を担当する。2001年11月に独立。Web制作者に向けた情報発信プロジェクトF-siteにも参加する。株式会社ロクナナ取締役(非常勤)。

URLhttp://www.FumioNonaka.com/

著書

コメント

コメントの記入