前回の第21回「水平に回す立方体の面を塗る」では、立方体四方の面をy軸で水平に回した。今回は6面を揃えてx軸の回転も加える。つまり、マウスポインタの位置に応じて、立方体を水平および垂直に回してみよう。
立方体に上面と底面を加える
前回は、立方体の四方の面しか塗らなかった。y軸で水平に回すだけなので、どうせ上面と底面は見えないからだ。今回はx軸で垂直にも回すので、上面と底面も加える。それに、ふたつの面を加えないと立方体の中が見えてしまって、裏返った面は塗らないという手が使えなくなる。立方体の8頂点にはインデックスをふっておいた(第20回図3再掲)。
そして、面はクラス(Face)に4頂点インデックスを与えて定めた。ただし、面の裏表を調べるため、頂点の順序はふたつのベクトルの外積が右ネジの位置になるように、時計回りに決めなければならなかった(第21回図4再掲)。そこで、面のオブジェクトの配列をつくって返す関数(getFacesVertices())に、以下のように上面と底面を加える。
x軸とy軸の回転を扱う準備
いきなりx軸で回す前に、xy両軸での回転が扱えるよう第21回コード2「水平に回す立方体の表向きの面だけを描く」に下ごしらえを施す。まだ、y軸で水平に回すという動きは変えない。まず、変数のもち方から取りかかろう。立方体の回転角はy軸にx軸周りが加わる。また、マウスポインタの位置を測る中心点もxy座標が要る。そこで、ふたつの変数(angleとstageCenter)は、以下のようにPointオブジェクトで与えることにした。それにともなって、変数との値のやり取りの仕方も変わってくる。
前述のとおり、まだ動きはこれまでと変わらない。立方体はマウスポインタの水平位置に応じてy軸で回る(図1)。新たに加えた上面も底面も見えない。けれど、これでx軸周りの扱いが加えられるようになった。立方体を回転する処理は、以下のコード1のように変わった。なお、クラスの定めには手を触れていないので省いている。
立方体をx軸でも回す
いよいよ、立方体の回転にx軸も加える。つまり、マウスポインタの位置に応じて、立方体が上下左右に回ることになる。さて、どうしたら3次元座標をx軸で回転できるか。実は、y軸で回すのと変わらない。2次元平面で座標を変換するMatrix2D.transformPoint()メソッドが使える。y軸で回転するときは、「視点」を変えて真上から見たxz平面で座標変換した(第16回「3次元空間で座標を回す」の「z座標を加えてy軸で回す」の項参照)。今度は、真横から見てzy平面で回せばよい(図2)。
3次元空間座標をxy両軸で回すなら、クラス(Point3D)のメソッドとして備えた方が使いやすいだろう。引数には、つぎのようにMatrix2Dオブジェクトと回転軸を渡す。回転軸は"x"か"y"かの文字列で示す。
例によって、メソッドはできたものとして、それを呼び出すコードから以下のように書き替えよう。回転するMatrix2Dオブジェクトは、x軸とy軸のふたつを分けて変数(matrixXとmatrixY)に定める。回転角を決めるStage.stagemousemoveイベントのリスナー関数(setAngle())は、マウスポインタのxy座標からy軸とx軸それぞれの回転角を変数(angle)のPointオブジェクトに与える。
立方体を回すTicker.tickイベントのリスナー関数(rotate())は、y軸とx軸のMatrix2Dオブジェクト(matrixXとmatrixY)をそれぞれ定められた角度回転する。そして8頂点座標は、できたことにしたクラス(Point3D)のメソッド(rotatePoint())にMatrix2Dオブジェクトと回転軸の引数を渡して回す。なお、クラスのメソッドで座標を変換するようにしたため、Matrix2D.transformPoint()メソッドで使い回すPointオブジェクトはクラスに定めることとし、変数(_point)からは除く。
改めて、クラス(Point3D)に座標回転のメソッド(rotatePoint())を加えよう。ふたつの引数はもう決めた。また、「視点」を変えることでMatrix2D.transformPoint()メソッドにより、y軸とx軸それぞれの回転ができるという考え方も確かめた。そこで、自身のプロパティである3次元座標を回転するメソッドはつぎのように定めた。
これらの手を加えれば、晴れて立方体がマウスポインタの位置に応じて、y軸およびx軸で上下左右に回るようになる(図3)。書上げたコードを以下にまとめよう。コード2は3つのクラスの定めだ。そして、これらのクラスを使ったインタラクティブな立方体のアニメーションがコード3のスクリプトである。
第20回から3回にわたって取り組んできたお題は、これで仕上がった。jsdo.itにコードを掲げておこう。3つのクラスは[HTML]の欄に分けて書いた。次回は2次元平面に戻ろう。マウスポインタの動きに合わせて滑らかな線が描かれては消えてゆくサンプルを考えている。