8

初心者のstackoverflow参加者、初心者の3Dプログラマー、そして数学の専門家からはほど遠い...だから、私はこの質問をできるだけ明確に組み立て、それが理にかなっていることを願って、そして私の頭から1マイルも離れていない答えを望んでいます。

私はthree.jsを使用して、ユーザーが3D空間を飛び回り、太陽系を探索できる非常にクールなアプリを作成しました。飛行モデルは、three.jsパッケージのFly.Controllerの例/拡張機能に大まかに基づいています。これは、すべての軸の回転を相互に適切に保つためにクォータニオンを使用することを教えてくれました。飛行部分はすべてうまく機能します。

これが私のジレンマです。クォータニオンを使用する場合、どの方向を向いているかを判断するために、「通常の」(他に何と呼ぶか​​わかりません)回転値をどのように推測しますか?クォータニオンを使用する場合、カメラオブジェクト内の「回転」構造は0,0,0のままです。ですから、私はどの角度でも自由に宇宙を飛ぶことができますが、実際にどの方向を向いているのかを判断する方法がわかりません。組み込みのthree.js関数、またはこれを変換する他の簡単な方法はありますか?

ウェブ上で似たような紛らわしいポインタをいくつか見つけましたが、解読してthree.jsで使用できるものは何もありません。ありがとう。

4

2 に答える 2

6

これは良い質問です。

オブジェクトがデフォルトの方向にある場合、そのオブジェクトは内部の正のz軸の方向を向いていると見なすことができます。(例外は、内部ののz軸の方向を向いているカメラです。)

したがって、オブジェクトを回転させたときに、オブジェクトのクォータニオンを正のz軸(カメラの場合は負のz軸)の方向を指す単位ベクトルに適用することで、オブジェクトが向いている方向を取得できます。

var zVec = new THREE.Vector3( 0, 0, 1 );
zVec.applyQuaternion( object.quaternion );

これにより、オブジェクトが「向いている」方向を指す単位ベクトルが返されます。

オブジェクトが別の回転したオブジェクトの子である場合、状況はより複雑になります。

編集:r.58用に更新。@eshanに感謝します。

于 2013-01-05T04:18:33.167 に答える
0

迅速な対応に感謝します。それは私が探していたものではありませんでしたが、質問を明確に行う方法がわからなかった可能性があります。私の特定の使用例は、3Dシーン内のすべてのオブジェクトの相対位置を表す2Dマップを描画したいのですが、3Dシーン内のカメラのヨーに基づいてマップ内のオブジェクトを回転させたいというものでした-そのため、マップ上の2Dオブジェクトの回転をそれに応じてオフセットできるように、クォータニオンベースのカメラが向いている「角度」を知る必要がありました。かなりうまくいくようです。それほど多くの計算が必要でなかったらいいのにと思いますが、少なくともJavascriptは高速です。

// Pass the obj.quaternion that you want to convert here:
//*********************************************************
function quatToEuler (q1) {
    var pitchYawRoll = new THREE.Vector3();
     sqw = q1.w*q1.w;
     sqx = q1.x*q1.x;
     sqy = q1.y*q1.y;
     sqz = q1.z*q1.z;
     unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor
     test = q1.x*q1.y + q1.z*q1.w;
    if (test > 0.499*unit) { // singularity at north pole
        heading = 2 * Math.atan2(q1.x,q1.w);
        attitude = Math.PI/2;
        bank = 0;
        return;
    }
    if (test < -0.499*unit) { // singularity at south pole
        heading = -2 * Math.atan2(q1.x,q1.w);
        attitude = -Math.PI/2;
        bank = 0;
        return;
    }
    else {
        heading = Math.atan2(2*q1.y*q1.w-2*q1.x*q1.z , sqx - sqy - sqz + sqw);
        attitude = Math.asin(2*test/unit);
        bank = Math.atan2(2*q1.x*q1.w-2*q1.y*q1.z , -sqx + sqy - sqz + sqw)
    }
    pitchYawRoll.z = Math.floor(attitude * 1000) / 1000;
    pitchYawRoll.y = Math.floor(heading * 1000) / 1000;
    pitchYawRoll.x = Math.floor(bank * 1000) / 1000;

    return pitchYawRoll;
}        

// Then, if I want the specific yaw (rotation around y), I pass the results of
// pitchYawRoll.y into the following to get back the angle in radians which is
// what can be set to the object's rotation.

//*********************************************************
function eulerToAngle(rot) {
    var ca = 0;
    if (rot > 0)
        { ca = (Math.PI*2) - rot; } 
    else 
        { ca = -rot }

    return (ca / ((Math.PI*2)/360));  // camera angle radians converted to degrees
}
于 2013-01-10T23:45:15.593 に答える