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

时间:2013-01-05 02:29:36

标签: rotation three.js quaternions

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

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

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

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

2 个答案:

答案 0 :(得分:4)

这是一个很好的问题。

当一个物体处于默认方向时,可以认为它是朝向内部正Z轴的方向。 (例外是摄像头,它正朝着内部 z轴的方向看。)

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

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

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

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

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

答案 1 :(得分: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
}