クォータニオンによる回転
3Dプログラミングで回転状態を表現する方法には、「オイラー角」と「クォータニオン」(四元数)があります。「オイラー角」はXYZの3次元で向きを表す方法で、「クォータニオン」はその名のとおり、4つの値で向きを表す方法です。
オイラー角は、人間が直観的に分かりやすい3軸で回転状態を表します。しかし、ある回転状態から、別の回転状態に移行する際の計算が大変です。クォータニオンは、人間には理解しにくい表現ですが、同じような計算をする際に、簡単に計算を行うことができます。
また、オイラー角では、XYZの3軸が重なってしまった際に、回転の制御に難が生じる「ジンバルロック」という状態に陥ります。しかし、クォータニオンでは、そういった問題は生じません。
「three.js」のデフォルトの回転系はオイラー角です。しかし、3Dオブジェクトの「useQuaternion」属性を「true」にすることで、クォータニオンで回転制御を行えるようになります。この場合に注意が必要な点は、それ以降「rotation」属性を使用した回転の制御ができなくなってしまうことです。
「rotation」は、オイラー角で回転状態を表すための属性です。クォータニオンを利用する場合は「quaternion」属性を利用します。「quaternion」属性には、「x」「y」「z」「w」という4つの値が用意されています。
「three.js」では、このクォータニオンの計算を行ったり、オイラー角をクォータニオンに変換するための関数が用意されています。
以下、クォータニオンによる回転を行う「crocro.bc.useQuaternion.js」を掲載します。
//= サンプル:クォータニオンによる操作
//== クォータニオンによる操作
crocro.bc.useQuaternion = function() {
// 変数の初期化
var d3 = crocro.bc.d3; // 3D格納用
// 要素の作成と格納
var cube = crocro.bc.mkColCube();
d3.scene.add(cube);
// クォータニオンを使う(mesh.rotationは無視される)
cube.useQuaternion = true;
crocro.bc.render();
// マウス操作の作成
d3.tgt = cube;
crocro.bc.useQuaternion_setMouse();
// 終了処理
crocro.bc.setFinalize(function() {
crocro.bc.d3.tgt = null;
})
};
//== マウス操作の作成
crocro.bc.useQuaternion_setMouse = function() {
// 変数の初期化
var d3 = crocro.bc.d3; // 3D格納用
var cntnr = crocro.bc.cntnr; // コンテナー
var isAct = false;
var posX, posY;
var rttVec = new THREE.Vector3(0, 0, 0);
var rttQuat = new THREE.Quaternion();
// マウス操作
var msStrt = function(event) {
isAct = true; // 動作状態に移行
// 位置の取得
posX = event.pageX;
posY = event.pageY;
};
var msMv = function(event) {
// 動作状態でなければ終了
if (! isAct) {return;}
// 位置の取得
var newX = event.pageX;
var newY = event.pageY;
// 回転ベクトルの作成
var x = newY - posY;
var y = newX - posX;
var z = 0;
rttVec.set(
x * 2 * Math.PI / 360,
y * 2 * Math.PI / 360,
z * 2 * Math.PI / 360
);
// オイラー角からクォータニオンに変換
rttQuat.setFromEuler(rttVec);
// クォータニオンの合成
d3.tgt.quaternion.multiply(rttQuat); // 掛け算
// 位置の更新
posX = newX;
posY = newY;
// レンダリング
crocro.bc.render();
};
var msEnd = function() {
isAct = false; // 動作状態を解除
};
// マウス操作の登録
cntnr.mousedown(msStrt);
cntnr.mousemove(msMv);
cntnr.mouseup(msEnd);
$(window).blur(msEnd);
}
今回の記事は以上です。次回は応用編として、集中線やフキダシ、箱人形の作成、そしてそれらのオブジェクトや部品をまとめて、マウスで操作するサンプルを作成して解説します。
