Canvas3D によるルービックキューブのその2です。
前回は話を簡単にするために、「クリックされた面さえ分かれば回転させるのは容易」と書きましたが、実際は少し問題がありました。
と、言うのも、ドラッグされた方向(2次元)と、3次元の各軸とのなす角を知る必要があるからです。
図をご覧下さい。細い矢印がX軸、太い矢印がドラッグ方向です。キューブの中心に原点があります。X軸は(3次元の)単位ベクトルで表すと(1,0,0)です。これを2次元に投射すると、カメラの位置によって様々な値を取り得るのですが、今回はその計算は省略して、とりあえず、図のように下向き45°で表示されているとしましょう。この場合、1/sqrt(2) = 0.707 ですから、X軸のベクトルは2次元で表すと(0.707, -0.707)です。
ドラッグ方向のベクトルは、開始点を (x1, y1)、終了点を(x2, y2)とすると、( x2 – x1, y2 – y1 )ですね。ここでは仮に(5,5)としておきましょう。
さて、この二つのベクトルのなす角を知るには「内積」を求めるのが一般的です。まずは、ドラッグ方向を単位ベクトルにしておきましょう。
a = sqrt( 5*5 + 5*5 )
= 7.07
xn = x / a
= 0.707
yn = y / a
= 0.707
ですから、(0.707, 0.707)ですね。
ベクトル A( xa, ya ) と B( xb, yb )のなす角は、
acos(〈A,B〉/ ||A||・||B||)
で求められます。acos はアークコサイン、逆余弦です。〈A,B〉が内積。
||A|| と ||B|| は、A と B のノルム、即ちベクトルの大きさであり、この場合はあらかじめ単位ベクトルに直しておきましたから必要ありません。
〈A,B〉 = xa * xb + ya * yb
= 0.707 * 0.707 + 0.707 * (-0.707)
= 0
この内積は二つのベクトルが平行なときに1、直交するときに0になりますので、この場合、ドラッグ方向はX軸に対して垂直、即ちX軸を中心に回転させようとしている、とめでたく判定できたわけです。
仮に内積が1に近い値ならば、X軸に対して水平、即ちZ軸を中心に回転させようとしているとわかります。
日本の教育
前回、この部分の説明を軽く流したのは、「内積」なんて高校で習うんだし、いちいち説明しなくても良いだろう、と思ったからです。
でも、よく考えてみると、こんなの忘れてますよね。実際私もこの間まで忘れてました。
なぜ忘れるのかというと、二つのベクトルのなす角を知ったからといって嬉しくも何ともないからです。「ふーん」としか思わない。
ですが、自分で3Dゲームを作ろうとすれば、嫌でも覚えざるを得ないし、たぶん、一生忘れません。
ですから、高校生にも、プログラミングさせたら良いのです。「数学なんて、何の役に立つの?」という子供の素朴な疑問に対する答えは、現代に於いて、「プログラミングに必要」というのが最も説得力があります。
日本の教育は詰め込み型だと批判されています。それに対して、詰め込みのどこが悪い? という再批判もあります。いずれにしろ最低限のことは詰め込まなければならないでしょう。かけ算九九を無理やり覚えさせるのはかわいそうなどといった議論は取り上げるまでもありません。
しかし、教育というものはある程度まで進むと、本人の自主性がなければ効果が上がらなくなります。殆どの人がベクトルの内積を忘れてしまうのも、何の役に立つか分からないからです。
資源の乏しい我が国に於いては、ITは今後最も有望な産業です。我が国を支える人材を育成するためにも、教育にプログラミングを取り入れるのは重要です。
ただ、先生方は苦労するかもしれません。歳を取ってからプログラミングをマスターするのは容易ではないからです。しかし、やって出来ないということはないはずです。聖職に身を捧げたならば、そのくらいの努力はして貰わなければなりません。