Posted at

[WebGL] Three.jsで、オブジェクトの「前方ベクトル」を取得する

More than 3 years have passed since last update.

UnityではGameObjectのtransformにforwardが定義されていて、ワールド空間上で「前方はどちらか」というのが取得できます。

ゲームに限らず、「オブジェクトの前方」を取得したいケースはあると思います。

ということで、Three.jsでこの「オブジェクトの前方」ベクトルを取得するメモです。

実際に動くサンプルをjsdo.itにあげてあります。

動画サンプル


つまりは「Z軸がどちらを向いているか」

実際やることはとても簡単です。

なにを持って前方か、というと、つまりは「Z軸が現在どこを向いているか」が分かれば求めたいベクトルが得られます。

よく参考にさせてもらっているサイト(その39 知っていると便利?ワールド変換行列から情報を抜き出そう)にその答えがあります。

ワールド変換行列が得られればあとは簡単な掛け算で求めることができます。

原理、概要については上記サイトを見てください。


4次元ベクトルと行列を掛けるだけ

やることは Z値のみが1の4次元ベクトルを掛ける だけです。

Three.jsでやるには以下のようにします。

var forward = new THREE.Vector4(0, 0, 1, 0);

forward.applyMatrix4(aMatrix).normalize();

こうすることで、該当のマトリクスから前方ベクトルが抽出されます。

あとはこのベクトルを必要に応じて加工してあげれば目的達成です。


実例

例えばとあるオブジェクトの前方に常に別のオブジェクトが追従する、みたいなことであれば以下のように書くことができます。

document.addEventListener('mousemove', function (e) {

if (!dragging) {
return;
}
var deltaX = e.pageX - prev.x;
var deltaY = e.pageY - prev.y;

box2.rotation.x += deltaY / 30;
box2.rotation.y += deltaX / 30;
// console.log(deltaX, deltaY);

box2.matrixWorld.decompose(box.position, box.quaternion, box.scale);

var forward = new THREE.Vector4(0, 0, 1, 0);
forward.applyMatrix4(box2.matrix).normalize();
forward.multiplyScalar(30);
box.position.add(forward);

prev.x = e.pageX;
prev.y = e.pageY;
}, false);

jsdo.itにあげたサンプルの該当部分を抜き出したものです。

やっていることは、ドラッグしたらbox2を回転させ、その前方のやや離れた位置にboxが追従する、というものです。

ちなみにdecomposeは行列から、「位置」「回転」「スケール」の値を抜き出してくれる便利なメソッドです。

これでまるっとbox2の位置と回転をコピーし、さらに位置を少しだけ前方に移動している、というわけです。