使用四元数时如何从three.js导出"标准"旋转?

J S*_*gue 8 rotation quaternions three.js

新手stackoverflow参与者,新手3D程序员,远离数学wiz ...所以我会尝试尽可能清楚地构建这个问题,希望它有意义,并希望得到一个不是一英里的答案.

我使用three.js编写了一个非常酷的应用程序,让用户可以飞过3D空间并探索太阳系.飞行模型松散地基于three.js包中的Fly.Controller示例/扩展,它教会我使用四元数来保持所有轴旋转相对于彼此合理.飞行部分都很棒.

这是我的困境:当使用四元数时,我如何推断出"正常"(我不知道还有什么称之为)旋转值来确定我面临的方向?使用四元数时,相机对象内的"旋转"结构保持为0,0,0.因此,虽然我可以在任何角度自由地飞越太空,但我无法弄清楚如何确定我实际面对的方向.是否有内置的three.js功能,或其他简单的方法来转换它?

我在网上发现了一些类似的,令人困惑的指针,但我无法解读并在三个.js中使用.谢谢.

Wes*_*ley 5

这是一个很好的问题。

当对象处于其默认方向时,可以认为它是在看其内部的正 z 轴方向。(相机除外,它正朝着其内部z 轴的方向看。)

因此,当对象旋转时,您可以通过将对象的四元数应用于指向正 z 轴方向(相机的负 z 轴)的单位向量来获得对象面向的方向。

var zVec = new THREE.Vector3( 0, 0, 1 );
zVec.applyQuaternion( object.quaternion );
Run Code Online (Sandbox Code Playgroud)

这将返回一个单位向量,指向对象“面向”的方向。

如果对象是另一个旋转对象的子对象,则情况会更复杂。

编辑:为 r.58 更新。谢谢@eshan。


J S*_*gue 0

感谢您的快速回复 - 这并不完全是我想要的,但我可能不知道如何清楚地提出问题。我的具体用例是,我想绘制一个 2D 地图来表示 3D 场景中所有对象的相对位置,但我想根据 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
}
Run Code Online (Sandbox Code Playgroud)