Step 2 - 3次元にする
このステップでは3次元空間上に頂点を定義し、それを先ほどと同じように描く方法を考えます。
Vector3の定義と座標系
まず、3次元空間上の点を表すためのシンプルなクラスVector3
を「Vector3.as」で定義します。
package { public class Vector3 { public var x:Number; public var y:Number; public var z:Number; public function Vector3(x:Number = 0.0, y:Number = 0.0, z:Number = 0.0) { this.x = x; this.y = y; this.z = z; } } }
次に、このクラスを使って配列vertices
に三角形の頂点を定義します。vertices
は、頂点を意味する英単語vertex
の複数形です。
var vertices:Array = [ new Vector3(0, 0.5, 0), new Vector3(0.5, -0.5, 0), new Vector3(-0.5, -0.5, 0), ];
それぞれの頂点は、以下の図のように配置されています。
この図を見て、Z軸の方向が無いことに気づいたでしょうか。3次元空間を定義するときに大事なのは、このZ軸の方向です。一般にZ軸が手前を向いている座標系を右手系、奥を向いている座標系を左手系と呼びます。今回は右手系の座標系を用います。
右手系、左手系と呼ぶ理由については、下の図を見ると分かりやすいと思います。
親指、人差し指、中指を互いに垂直に(いわゆるフレミングの法則状に)してみてください。親指から順にX軸、Y軸、Z軸とすれば、右手系の方に右手が、左手系の方に左手が重なるのが分かると思います。右手系と左手系のどちらを使うかで計算式が違ってくるので、ここははっきりさせておかないといけないところです。ちなみに有名どころについてはDirect3Dが左手系、OpenGLが右手系を採用しています。
2次元平面への投影
さて、この頂点を結ぶ線を引けば三角形を描くことができますが、3次元空間上の座標のままでは2次元の画面上に線が描けません。そのため、頂点を2次元平面へ投影する必要があります。
ここではZ軸の正の方向からXY平面を垂直に見ている形となるような簡単な式で投影を実現します。
x' = (x + 1) * W / 2 y' = (-y + 1) * H / 2
ここで、(x, y, z)を3次元空間上の頂点、(x', y')を2次元平面上の点、Wを画面の幅、Hを画面の高さとします。左上の頂点(-1, 1, 0)は平面上の点(0, 0)に、右下の頂点(1, -1, 0)は平面上の点(W, H)にそれぞれ投影されます。
この処理を行うのがproject
メソッドです。引数の頂点v
を投影した座標をPoint
型で返します。
private static function project(v:Vector3):Point { return new Point( ( v.x + 1) * WIDTH / 2, (-v.y + 1) * HEIGHT / 2 ); }
実際にこれを使って線を引いているのが以下の処理です。
// 線を引く var point:Point = project(vertices[vertices.length - 1]); graphics.moveTo(point.x, point.y); for (var i:int = 0; i < vertices.length; ++i) { point = project(vertices[i]); graphics.lineTo(point.x, point.y); }
最後の頂点をスタート地点として、一周してまた最後の頂点に来る形で線を引いています。これで、最初の2次元のときと同じ三角形を描くことができました。見た目は同じですが、中身の処理は全然違います。
平行投影を使った理由は、単に手法がシンプルだからです。透視投影をしようとするといきなり複雑な計算が必要となるので、線を描くだけでも一苦労になってしまいます。もっとも、Papervision3Dなどのライブラリを使うのであれば、そういった苦労をすることなく実装できます。