三次元変換行列(5)
2008/05/09 22:48 - AS3.0
前回は、行列の実装を二次元配列でおこなうという話でした。
速度的に Array を使うのは果たしてどうなのか…… という今後の先行きに暗雲漂いまくりな情報を目にしちゃったんですが、とりあえず今は見ないふりして今後の課題ということで、何事もなかったかの如く進みます。
で、普通に使ってる分なら、三次元変換行列に対する操作は、平行移動・座標軸回転・拡大縮小だけで、せん断はまず用いない、そのため、おそらく行列の成分を個別に外部からアクセスする必要もないであろう、そういう前提で設計しよう、ということにしました。
そうすると、三次元変換行列のクラスオブジェクトを生成する際に、行列の成分を指定する必要もないわけで、コンストラクタは引数なしでいきます。
てなわけで、コンストラクタは以下のようにします。
public function Matrix3D() {}
次はメソッドのコード。
最低限必要なのは、拡大縮小(scale)、座標軸回転(rotateAxis)、平行移動(translate)、行列の連結(concat)。
あと、行列の連結に伴い、行列の複製(clone)も必要になります。それぞれ以下のようにコーディングします。
まず拡大縮小と回転について。
/** * 拡大縮小 * | sx 0 0 0 | * | 0 sy 0 0 | * | 0 0 sz 0 | * | 0 0 0 1 | */ public function scale( sx:Number, sy:Number, sz:Number ):void { var mat:Matrix3D = new Matrix3D(); mat.matrix[0][0] = sx; mat.matrix[1][1] = sy; mat.matrix[2][2] = sz; concat( mat ); }
/** * X軸回転 * | 1 0 0 0 | * | 0 cos -sin 0 | * | 0 sin cos 0 | * | 0 0 0 1 | */ public function rotateX( angle:Number ):void { var mat:Matrix3D = new Matrix3D(); var cos:Number = Math.cos( angle ); var sin:Number = Math.sin( angle ); mat.matrix[1][1] = mat.matrix[2][2] = cos; mat.matrix[1][2] = -sin; mat.matrix[2][1] = sin; concat( mat ); } /** * Y軸回転 * | cos 0 sin 0 | * | 0 1 0 0 | * | -sin 0 cos 0 | * | 0 0 0 1 | */ public function rotateY( angle:Number ):void { var mat:Matrix3D = new Matrix3D(); var cos:Number = Math.cos( angle ); var sin:Number = Math.sin( angle ); mat.matrix[0][0] = mat.matrix[2][2] = cos; mat.matrix[0][2] = sin; mat.matrix[2][0] = -sin; concat( mat ); } /** * Z軸回転 * | cos -sin 0 0 | * | sin cos 0 0 | * | 0 0 1 0 | * | 0 0 0 1 | */ public function rotateZ( angle:Number ):void { var mat:Matrix3D = new Matrix3D(); var cos:Number = Math.cos( angle ); var sin:Number = Math.sin( angle ); mat.matrix[0][0] = mat.matrix[1][1] = cos; mat.matrix[0][1] = -sin; mat.matrix[1][0] = sin; concat( mat ); }
これらのメソッドは極めて単純。 新規に単位行列を生成し、参考書のとおりにその行列の当該成分に当該値を代入。 そして現在使用している行列との連結をおこなう。そんだけ。
flash.geom.Matrix にあわせて、回転メソッドの引数は、度(degree)ではなくラジアン(radian)を使用しました。
続く。