新手stackoverflow参与者,新手3D程序员,远离数学巫师...所以我会尝试尽可能清楚地构建这个问题,希望它有意义,并希望得到一个不是一英里的答案我的脑袋。
我使用three.js编写了一个非常酷的应用程序,让用户可以飞过3D空间并探索太阳系。飞行模型松散地基于three.js包中的Fly.Controller示例/扩展,它教会我使用四元数来保持所有轴旋转相对于彼此合理。飞行部分都很棒。
这是我的困境:当使用四元数时,我如何推断出“正常”(我不知道还有什么称之为)旋转值来确定我面临的方向?使用四元数时,相机对象内的“旋转”结构保持为0,0,0。因此,虽然我可以在任何角度自由地飞越太空,但我无法弄清楚如何确定我实际面对的方向。是否有内置的three.js函数,或其他简单的方法来转换它?
我在网上发现了一些类似的,令人困惑的指针,但我无法破译并在三个.js中使用。感谢。
答案 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
}