今製作中のもので、丸影を地面に添わせて地面の法線方向に向かせる、というのをやりたかった。
法線自体はすぐに取れたのだけど、Planeをどうやってその法線方向に向かせるか、というのをこちらの記事を参考にして作ってみた。
テスト用に法線方向とオブジェクトの方向をテストするものを作ったので、それをベースにメモを残しておく。
##サンプル
サンプルはこんな感じで、頭を任意のベクトルに沿わせる、というもの。
x, y, zの軸の位置のスライダーをいじるとそれに応じてオブジェクトが回転します。
##フロー
先にフローを書くと、
- 向かせたいベクトルと「上」方向のベクトルを取得
- 上記2つのベクトルとの外積を取る(これが回転軸となる)
- 上記2つのベクトルの角度を、内積を使って取得
- これら情報を元に、回転用のクォータニオンを生成
- 生成したクォータニオンをオブジェクトに適用
という流れ。
「上」と書いたのは必ずしも空方向ではなく、オブジェクトの「上」となるベクトル。
Three.jsを用いたサンプルコードを抜粋すると以下になる。
##サンプルコード
Threejs-sample.js
//「上」方向のベクトルを生成。サンプルでは「空」方向。
var up = new THREE.Vector3(0, 1, 0);
//法線ベクトルを取得。サンプルではinput要素から取得。
var normalAxis = new THREE.Vector3(+xInp.value, +yInp.value, +zInp.value).normalize();
//回転軸用のベクトルを生成
var dir = new THREE.Vector3();
//「上」方向と法線ベクトルとの外積を計算。正規化。
dir.crossVectors(up, normalAxis).normalize();
//上記ベクトルとの内積(cosθ)
var dot = up.dot(normalAxis);// / (up.length() * normalAxis.length());
//acos関数を使ってラジアンに変換。
var rad = Math.acos(dot);
//クォータニオンオブジェクトを生成
var q = new THREE.Quaternion();
//計算した回転軸と角度を元にクォータニオンをセットアップ
q.setFromAxisAngle(dir, rad);
//適用したいオブジェクトに回転を適用
mesh.rotation.setFromQuaternion(q);
Three.jsを使うとクォータニオンとかその他もろもろのめんどくさい計算をやってくれるクラスがあるので、これくらいの行数で簡単にできちゃいます。