前回の第7回「回り込むカメラの真ん中にオブジェクトを捉える」では、真ん中のオブジェクトが中心となる円周上に、等しい間隔で複数のオブジェクトを並べ、カメラはその外の円軌道から回り込ませた(第7回コード3)。今回は、オブジェクトの位置や大きさをランダムにしてみよう。
Matrix3Dクラスで座標を回転する
オブジェクトをランダムに変換する前に、第7回コード3で円周上の座標を求めた関数(getPolarPosition())は書き替える。座標の回転や伸縮、さらに移動まで一手に引受けるMatrix3Dクラスを使ってみたい。"matrix"というのは数学の「行列」を意味する(映画を思い浮かべてはいけない)。難しげに聞こえるかもしれないが、つまるところ数値をパラメータで変換する仕組みだ[1]。
たとえば、Photoshop CCやFireworks CS6のフィルタやカラー調整は、内部的に行列を用いて行われている(図1)。これらの機能は、画像のピクセルごとのカラー値を変換する。
Away3DのMatrix3Dクラスが変換するのは3次元座標だ。パラメータを変えることにより、回転や伸縮、あるいは移動ができる。あまり難しく考えすぎずに、つぎの図2のようなパネルを思い浮かべてもらえばよい。ただし、スライダではなく、もちろんJavaScriptコードを書いて変換しなければならない。
Matrix3Dクラスに備わる回転・伸縮・移動の座標変換メソッドは、つぎの表1のとおりだ。円周上の座標を求めるには、回転のappendRotation()メソッドを使う。引数には度数の角度と回転軸を与える。y軸で回したいので、回転軸はVector3D.Y_AXISとする。なお、今のところ前変換(prepend)と後変換(append)が何かは気にしなくてよい[2]。まずは、Matrix3Dクラスに慣れることを心がけよう。
表1 Matrix3Dクラスの回転・伸縮・移動の座標変換メソッド
座標変換 | 前変換 | 後変換 |
回転 |
prependRotation(degrees, axis) | appendRotation(degrees, axis) |
伸縮 | prependScale(xScale, yScale, zScale) | appendScale(xScale, yScale, zScale) |
移動 | prependTranslation(x, y, z) | appendTranslation(x, y, z) |
Matrix3Dクラスで、距離と角度から円周上の座標をどう求めるか。x軸上の点(距離, 0, 0)をその角度回せばよい。ただし、Matrix3Dオブジェクトは変換行列を表し、3次元座標ではない。Matrix3D.transformVector()メソッドに座標のVector3Dオブジェクトを渡せば、変換されたVector3Dオブジェクトが得られる。距離と角度から円周上の座標を返す関数(getPolarPosition())は、以下のようにほぼすべて書き替えた[3]。
これで、円軌道上に置くオブジェクトは、Matrix3Dオブジェクトの行列変換により位置が決まる。書き替えたスクリプト全体は、つぎのコード1のとおりだ。もちろん、動きの見た目は第7回コード3と変わらない。
オブジェクトの位置をランダムに定める
では、オブジェクトの位置をランダムに定めたい。そこで、引数に渡した最小値と最大値の範囲で、ランダムな数値が返される関数(getRandom())を以下のように定めた。
そして、距離と角度から位置を返す関数には、y軸だけでなくx軸回りの角度も引数に加えた。Matrix3Dクラスを使った行列変換は、このように複数の変換を組み合わせたり、複雑な変換が求められる場合も、面倒な計算そのものは行列に任せてしまえるのが助かる。
これだけの変更で、周囲に置くオブジェクトの位置がランダムに定まる(図3)。なお、x軸回りつまり垂直方向の角度の範囲は大きくなりすぎないように、±60度に抑えた。スクリプト全体は、つぎのコード2のとおりだ。ただ、距離に対して箱が大きすぎるため、互いにぶつかってめり込んでしまうことが多い。つぎに、大きさもランダムに変えよう。
Transformクラスでオブジェクトの大きさをランダムに定める
それでは、周囲のオブジェクトは少し小さめにして、ランダムなサイズにしよう。ここではTransformオブジェクトを用いる。表示オブジェクトは、DisplayObject.transformプロパティに自らの変換情報を備えている。変形であれば、Transformオブジェクトのつぎの表2のプロパティにVector3Dオブジェクトを与えれば、回転や伸縮、あるいは移動できる。
表2 Transformクラスの回転・伸縮・移動の変形プロパティ
変形 | プロパティ |
回転 | rotation |
伸縮 | scale |
移動 | position |
オブジェクトを複製する関数(cloneMesh())は、新たに定めるサイズ変更の関数(setScale())に複製したオブジェクト(clone)と伸縮率(scale)を引数に渡して呼び出す。すると、オブジェクトのDisplayObject.transformから得たTransformオブジェクトのTransform.scaleプロパティに、xyz方向とも同じ伸縮率を定めたVector3Dオブジェクトが与えられる。
これで、周囲に置かれるオブジェクトは位置だけでなく、サイズも小さめのランダムな値に定められた(図4)。ここまでのスクリプトをまとめたのが、以下のコード1だ。jsdo.itのコードも、サンプル1として掲げた。次回は、マウスインタラクションを加えよう。