2017-03-01 68 views
5

说另一点我有两个载体:查找角度旋转点,使得它面对在3D空间

V1 = {X:3.296372727813439,Y:-14.497928014719344,Z:12.004105246875968}

V2 = {X :2.3652551657790695,y:-16.732085083053185,z:8.945905454164146}

我该如何计算出v1需要旋转到什么角度才能直接看到v2?

把英文写成:说我确切知道我在太空中的位置,以及在哪里另一个人在太空其他地方....在数学上,我怎么能够弄清楚什么角度把我的手指指向他们?

Here's what my axis looks like

我的电流(不正确的)式

v2.x -= v1.x; // move v2 (vector 2) relative to the new origin 
v2.y -= v1.y; 
v2.z -= v1.z; 

v1.x = 0; // set v1 (vector 1) as the origin 
v1.y = 0; 
v1.z = 0; 

var r = Math.sqrt(Math.pow(v2.x,2) + Math.pow(v2.y,2) + Math.pow(v2.z,2)); 
var θ = Math.acos((Math.pow(v2.x,2) + Math.pow(v2.z,2))/(r*Math.sqrt(Math.pow(v2.x,2) + Math.pow(v2.z,2)))); 
var ϕ = Math.acos(v2.x/Math.sqrt(Math.pow(v2.x,2) + Math.pow(v2.z,2))); 

然后我与旋转的θ和phi V1。

v1.rotation.y = θ; 
v2.rotation.x = ϕ; 

但是这给了我错误的轮换。

θ= 0.6099683401012933

φ= 1.8663452274936656

但是,如果使用three.js所和使用的lookAt功能,它吐出这些旋转取而代之的是,做工精美:

Y /θ: -0.24106818240525682

X /φ:2.5106584861123644

感谢所有帮助提前!我不能在我的最终结果中使用THREE.js,我试图去纯香草JS,以便将它移植到另一种语言。

+0

你可以看看如何在THREE.js中实现'lookAt'来获取想法? –

+0

我已经看过它了,但是它确实没有关于它是如何工作的任何文档,它依赖于深深地绑在库中的函数...... –

+0

您能否指定以后如何使用这些天使?这可能是@Zich和我不明白你需要哪个特定的天使。 – SergGr

回答

2

正确的公式是:

var dx = v2.x-v1.x; //-0.93 
var dy = v2.y-v1.y; //-31.22 
var dz = v2.z-v1.z; 
var rxy = Math.sqrt(Math.pow(dx,2) + Math.pow(dy,2)); 
var lambda = Math.atan(dy/dx); 
var phi = Math.atan(dz/rxy) 

philambda需要上述公式在此基础上季度的矢量位于调整我让你很容易:

//if you do the calculations in degrees, you need to add 180 instead of PI 
if (dx < 0) phi = phi + Math.PI; 
if (dz < 0) lambda = -1 * lambda; 
+0

我假设在第二个代码块x和z是从V2?如果是这样,对于上面提到的位置,它正在吐出这些角度:landa = -1.1759217695199877和phi = 2.2403038274064055 ....哪些不是y和x旋转的正确角度。 :/ –

+0

@DarrylHuffman我认为v2是v2- = v1之后的差分向量,所以我编辑了答案再次检查出来并告诉我结果。 – Zich

0

如何使用矩阵?我认为v1是你的观点,并期待v2。矩阵是展示定位的好方法。欧拉角是对方向的另一种解释。

我的想法是建立从对象空间转换矩阵世界空间,你想要做有三个步骤翻译的内容:

  1. 之初,相机在世界空间的原点,相机世界空间旋转为(0,0,0)与对象空间相同。 v1'(0,0,0)
  2. 我们将相机转换为v1(3.296372727813439,-14.497928014719344,12.004105246875968),物体空间与世界空间有偏移,但物体空间轴与世界空间轴平行,相机旋转依然为(0,0,0)。
  3. 我们让相机看看v2,正如你所看到的那样,相机的旋转会发生变化。

如果我可以构建一个变换矩阵代表上面所有的动作,我可以得到方向。

  1. 首先,计算翻译矩阵:因为翻译是仿射变换,所以我们需要使用4x4矩阵来表示翻译。我们可以很容易得到矩阵: translation matrix
  2. 我们用基轴来得到旋转矩阵。

    您可能需要将相机设置为向量。缺省值是(0,1,0)。在对象空间中,可以通过v1-v2来计算轴的基础z

    z = (v1.x-v2.x,v1.y-v2.y,v1.z-v2.z).normalize()

    基础X矢量:我们知道,基向量垂直于Z-了飞机,我们获得通过交叉产品X矢量并ž的向量。

    x = up.crossproduct(z)

    基础ÿ矢量,ÿ是prependicular到Z-X平面

    y = z.product(x)

    我们可以建立旋转矩阵为3×3的矩阵:

    rotation matrix

    然后,我们终于得到了变换矩阵:

    transformation matrix

    我们可以使用矩阵表示相机的方向。如果你需要欧拉角或四元数。有一些方法在它们之间转换。你可以在这本书中找到:3D Math Primer for Graphics and Game Developmen

    Three.js执行LookAt()功能与我的方式相同。

    这里是three.js所的源代码,并加了一些意见:

    function lookAt(eye, target, up) //eye : your camera position; target :  which point you want to look at; up : camera up vector 
    { 
    
        if (x === undefined) { 
    
         x = new Vector3(); 
         y = new Vector3(); 
         z = new Vector3(); 
    
        } 
    
        var te = this.elements; //this.elements is a 4 x 4 matrix stored in a list. 
    
        z.subVectors(eye, target).normalize(); // set z vector with the direction from your camera to target point. 
    
        if (z.lengthSq() === 0) { 
    
         z.z = 1; 
    
        } 
    
        x.crossVectors(up, z).normalize(); // set the x vector by cross product up and z vector, you know cross product would get a //vector which perpendicular with these two vectors. 
    
        if (x.lengthSq() === 0) { 
    
         z.z += 0.0001; // if z is ZERO vector, then, make a little addition to z.z 
         x.crossVectors(up, z).normalize(); 
    
        } 
    
        y.crossVectors(z, x); // set y by cross product z and x. 
    
        // using basic axises to set the matrix. 
        te[ 0 ] = x.x; te[ 4 ] = y.x; te[ 8 ] = z.x; 
        te[ 1 ] = x.y; te[ 5 ] = y.y; te[ 9 ] = z.y; 
        te[ 2 ] = x.z; te[ 6 ] = y.z; te[ 10 ] = z.z; 
    
        return this; 
    
    }; 
    // now you get the transformation matrix, you can set the rotation or orientation with this matrix. 
    

你可以用列表实现矩阵状three.js所一样。

我也有另外一个想法 - 球形极坐标系统。球形坐标总是被记录为(r,Θ,Φ),θ是航向角,而Φ是俯仰角。你需要做的是将v1和v2笛卡尔坐标转换为球坐标。因为球面中的第二和第三个元素是角度,我们可以计算v1和v2之间的角位移。然后,将这种位移作为摄像头旋转的补充。

这里是我的代码(假设你的相机是在世界坐标系原点(0,0,0)):

//convert v1 and v2 Cartesian coordinates to Spherical coordinates; 
var radiusV1 = Math.sqrt(Math.pow(v1.x) + Math.pow(v1.y) + Math.pow(v1.z)); 
var headingV1 = Math.atan2(v1.x , v1.z); 
var pitchV1 = Math.asin(-(v1.y)/radiusV1); 

var radiusV2 = Math.sqrt(Math.pow(v2.x) + Math.pow(v2.y) + Math.pow(v2.z)); 
var headingV2 = Math.atan2(v2.x , v2.z); 
var pitchV2 = Math.asin(-(v2.y)/radiusV2); 

//calculate angular displacement. 
var displacementHeading = headingV2 - headingV1; 
var displacementPitch = pitchV2 - pitchV1; 

//make this displacement as an addition to camera rotation. 
camera.rotation.x += displacementPitch; 
camera.rotation.y += displacementHeading; 

顺便说一句,3D数学是非常有益的,值得你去学习,所有的公式或者我参考的概念可以在书中找到。

希望它能帮助你。

0

x /φ围绕x轴旋转,因此它等于y,z之间的角度,对于y /θ,我们必须找到x,z之间的角度。

V1 = { x: 3.296372727813439, y: -14.497928014719344, z: 12.004105246875968 } 
 
V2 = { x: 2.3652551657790695, y: -16.732085083053185, z: 8.945905454164146 } 
 
var v={dx:V2.x-V1.x, dy:V2.y-V1.y, dz:V2.z-V1.z} 
 
testVector(v); 
 
    
 
function testVector(vec){ 
 
    console.log(); 
 
    var angles=calcAngles(vec); 
 
    console.log("phi:"+angles.phi+" theta:"+angles.theta); 
 
} 
 
function calcAngles(vec){ 
 
    return { 
 
     theta:(Math.PI/2)+Math.atan2(vec.dz, vec.dx), 
 
     phi:(3*Math.PI/2)+Math.atan2(vec.dz, vec.dy) 
 
    }; 
 
}

0

我从提取three.js所(R84)的最新版本的相关代码。 我认为这是得到你想要的结果的最好方法。

// Unless otherwise noted by comments, all functions originate from the latest version of THREE.js (r84) 
 
    // https://github.com/mrdoob/three.js/tree/master 
 
    // THREE.js is licensed under MIT (Copyright © 2010-2017 three.js authors) 
 
    // 
 
    // Some functions have been changed by K Scandrett to work within this setting, 
 
    // but not the calculations. 
 
    // Any mistakes are considered mine and not the authors of THREE.js. 
 
    // I provide no guarantees that I haven't created any bugs in reworking the original code 
 
    // so use at your own risk. Enjoy the pizza. 
 
    
 
    
 
    var v1 = {x: 3.296372727813439, y: -14.497928014719344, z: 12.004105246875968}; 
 
    var v2 = {x: 2.3652551657790695, y: -16.732085083053185,z: 8.945905454164146}; 
 
    
 
    var startVec = {x: v1.x, y: v1.y, z: v1.z, w: 0}; 
 
    var endVec = {x: v2.x, y: v2.y, z: v2.z, w: 0}; 
 
    
 
    var upVec = {x: 0, y: 1, z: 0}; // y up 
 
    
 
    var quat = lookAt(startVec, endVec, upVec); 
 
    var angles = eulerSetFromQuaternion(quat); 
 
    
 
    console.log(angles.x + " " + angles.y + " " + angles.z); 
 
    
 
    /* KS function */ 
 
    function magnitude(v) { 
 
     return Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z); 
 
    } 
 
    
 
    /* KS function */ 
 
    function normalize(v) { 
 
     var mag = magnitude(v); 
 
     return { 
 
     x: v.x/mag, 
 
     y: v.y/mag, 
 
     z: v.z/mag 
 
     }; 
 
    } 
 
    
 
    function subVectors(a, b) { 
 
     return { 
 
     x: a.x - b.x, 
 
     y: a.y - b.y, 
 
     z: a.z - b.z 
 
     }; 
 
    } 
 
    
 
    function crossVectors(a, b) { 
 
     var ax = a.x, 
 
     ay = a.y, 
 
     az = a.z; 
 
     var bx = b.x, 
 
     by = b.y, 
 
     bz = b.z; 
 
     return { 
 
     x: ay * bz - az * by, 
 
     y: az * bx - ax * bz, 
 
     z: ax * by - ay * bx 
 
     }; 
 
    } 
 
    
 
    function lengthSq(v) { 
 
     return v.x * v.x + v.y * v.y + v.z * v.z; 
 
    } 
 
    
 
    
 
    function makeRotationFromQuaternion(q) { 
 
    
 
     var matrix = new Float32Array([ 
 
    
 
     1, 0, 0, 0, 
 
     0, 1, 0, 0, 
 
     0, 0, 1, 0, 
 
     0, 0, 0, 1 
 
    
 
     ]); 
 
    
 
     var te = matrix; 
 
    
 
     var x = q.x, 
 
     y = q.y, 
 
     z = q.z, 
 
     w = q.w; 
 
     var x2 = x + x, 
 
     y2 = y + y, 
 
     z2 = z + z; 
 
     var xx = x * x2, 
 
     xy = x * y2, 
 
     xz = x * z2; 
 
     var yy = y * y2, 
 
     yz = y * z2, 
 
     zz = z * z2; 
 
     var wx = w * x2, 
 
     wy = w * y2, 
 
     wz = w * z2; 
 
    
 
     te[0] = 1 - (yy + zz); 
 
     te[4] = xy - wz; 
 
     te[8] = xz + wy; 
 
    
 
     te[1] = xy + wz; 
 
     te[5] = 1 - (xx + zz); 
 
     te[9] = yz - wx; 
 
    
 
     te[2] = xz - wy; 
 
     te[6] = yz + wx; 
 
     te[10] = 1 - (xx + yy); 
 
    
 
     // last column 
 
     te[3] = 0; 
 
     te[7] = 0; 
 
     te[11] = 0; 
 
    
 
     // bottom row 
 
     te[12] = 0; 
 
     te[13] = 0; 
 
     te[14] = 0; 
 
     te[15] = 1; 
 
    
 
     return te; 
 
    
 
    } 
 
    
 
    function RotationMatrix(m) { 
 
    
 
     // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm 
 
    
 
     // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) 
 
    
 
     var _w, _x, _y, _z; 
 
     var te = m, 
 
    
 
     m11 = te[0], 
 
     m12 = te[4], 
 
     m13 = te[8], 
 
     m21 = te[1], 
 
     m22 = te[5], 
 
     m23 = te[9], 
 
     m31 = te[2], 
 
     m32 = te[6], 
 
     m33 = te[10], 
 
    
 
     trace = m11 + m22 + m33, 
 
     s; 
 
    
 
     if (trace > 0) { 
 
    
 
     s = 0.5/Math.sqrt(trace + 1.0); 
 
    
 
     _w = 0.25/s; 
 
     _x = (m32 - m23) * s; 
 
     _y = (m13 - m31) * s; 
 
     _z = (m21 - m12) * s; 
 
    
 
     } else if (m11 > m22 && m11 > m33) { 
 
    
 
     s = 2.0 * Math.sqrt(1.0 + m11 - m22 - m33); 
 
    
 
     _w = (m32 - m23)/s; 
 
     _x = 0.25 * s; 
 
     _y = (m12 + m21)/s; 
 
     _z = (m13 + m31)/s; 
 
    
 
     } else if (m22 > m33) { 
 
    
 
     s = 2.0 * Math.sqrt(1.0 + m22 - m11 - m33); 
 
    
 
     _w = (m13 - m31)/s; 
 
     _x = (m12 + m21)/s; 
 
     _y = 0.25 * s; 
 
     _z = (m23 + m32)/s; 
 
    
 
     } else { 
 
    
 
     s = 2.0 * Math.sqrt(1.0 + m33 - m11 - m22); 
 
    
 
     _w = (m21 - m12)/s; 
 
     _x = (m13 + m31)/s; 
 
     _y = (m23 + m32)/s; 
 
     _z = 0.25 * s; 
 
    
 
     } 
 
    
 
     return { 
 
     w: _w, 
 
     x: _x, 
 
     y: _y, 
 
     z: _z 
 
     }; 
 
    } 
 
    
 
    function eulerSetFromQuaternion(q, order, update) { 
 
    
 
     var matrix; 
 
    
 
     matrix = makeRotationFromQuaternion(q); 
 
    
 
     return eulerSetFromRotationMatrix(matrix, order); 
 
    } 
 
    
 
    function eulerSetFromRotationMatrix(m, order, update) { 
 
    
 
     var _x, _y, _z; 
 
     var clamp = function(value, min, max) { 
 
     return Math.max(min, Math.min(max, value)); 
 
     }; 
 
    
 
     // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) 
 
    
 
     var te = m; 
 
     var m11 = te[0], 
 
     m12 = te[4], 
 
     m13 = te[8]; 
 
     var m21 = te[1], 
 
     m22 = te[5], 
 
     m23 = te[9]; 
 
     var m31 = te[2], 
 
     m32 = te[6], 
 
     m33 = te[10]; 
 
    
 
     //order = order || this._order; 
 
     order = order || 'XYZ'; // KS added. Other code sets the rotation order default 
 
    
 
     if (order === 'XYZ') { 
 
    
 
     _y = Math.asin(clamp(m13, -1, 1)); 
 
    
 
     if (Math.abs(m13) < 0.99999) { 
 
    
 
      _x = Math.atan2(-m23, m33); 
 
      _z = Math.atan2(-m12, m11); 
 
    
 
     } else { 
 
    
 
      _x = Math.atan2(m32, m22); 
 
      _z = 0; 
 
    
 
     } 
 
    
 
     } else if (order === 'YXZ') { 
 
    
 
     _x = Math.asin(-clamp(m23, -1, 1)); 
 
    
 
     if (Math.abs(m23) < 0.99999) { 
 
    
 
      _y = Math.atan2(m13, m33); 
 
      _z = Math.atan2(m21, m22); 
 
    
 
     } else { 
 
    
 
      _y = Math.atan2(-m31, m11); 
 
      _z = 0; 
 
    
 
     } 
 
    
 
     } else if (order === 'ZXY') { 
 
    
 
     _x = Math.asin(clamp(m32, -1, 1)); 
 
    
 
     if (Math.abs(m32) < 0.99999) { 
 
    
 
      _y = Math.atan2(-m31, m33); 
 
      _z = Math.atan2(-m12, m22); 
 
    
 
     } else { 
 
    
 
      _y = 0; 
 
      _z = Math.atan2(m21, m11); 
 
    
 
     } 
 
    
 
     } else if (order === 'ZYX') { 
 
    
 
     _y = Math.asin(-clamp(m31, -1, 1)); 
 
    
 
     if (Math.abs(m31) < 0.99999) { 
 
    
 
      _x = Math.atan2(m32, m33); 
 
      _z = Math.atan2(m21, m11); 
 
    
 
     } else { 
 
    
 
      _x = 0; 
 
      _z = Math.atan2(-m12, m22); 
 
    
 
     } 
 
    
 
     } else if (order === 'YZX') { 
 
    
 
     _z = Math.asin(clamp(m21, -1, 1)); 
 
    
 
     if (Math.abs(m21) < 0.99999) { 
 
    
 
      _x = Math.atan2(-m23, m22); 
 
      _y = Math.atan2(-m31, m11); 
 
    
 
     } else { 
 
    
 
      _x = 0; 
 
      _y = Math.atan2(m13, m33); 
 
    
 
     } 
 
    
 
     } else if (order === 'XZY') { 
 
    
 
     _z = Math.asin(-clamp(m12, -1, 1)); 
 
    
 
     if (Math.abs(m12) < 0.99999) { 
 
    
 
      _x = Math.atan2(m32, m22); 
 
      _y = Math.atan2(m13, m11); 
 
    
 
     } else { 
 
    
 
      _x = Math.atan2(-m23, m33); 
 
      _y = 0; 
 
    
 
     } 
 
    
 
     } else { 
 
    
 
     console.warn('THREE.Euler: .setFromRotationMatrix() given unsupported order: ' + order); 
 
    
 
     } 
 
    
 
     //_order = order; 
 
    
 
     //if (update !== false) this.onChangeCallback(); 
 
    
 
     return { 
 
     x: _x, 
 
     y: _y, 
 
     z: _z 
 
     }; 
 
    
 
    } 
 
    
 
    function setFromQuaternion(q, order, update) { 
 
    
 
     var matrix = makeRotationFromQuaternion(q); 
 
    
 
     return setFromRotationMatrix(matrix, order, update); 
 
    } 
 
    
 
    function setFromRotationMatrix(m) { 
 
    
 
     // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm 
 
    
 
     // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) 
 
    
 
     var _w, _x, _y, _z; 
 
     var te = m, 
 
    
 
     m11 = te[0], 
 
     m12 = te[4], 
 
     m13 = te[8], 
 
     m21 = te[1], 
 
     m22 = te[5], 
 
     m23 = te[9], 
 
     m31 = te[2], 
 
     m32 = te[6], 
 
     m33 = te[10], 
 
    
 
     trace = m11 + m22 + m33, 
 
     s; 
 
    
 
     if (trace > 0) { 
 
    
 
     s = 0.5/Math.sqrt(trace + 1.0); 
 
    
 
     _w = 0.25/s; 
 
     _x = (m32 - m23) * s; 
 
     _y = (m13 - m31) * s; 
 
     _z = (m21 - m12) * s; 
 
    
 
     } else if (m11 > m22 && m11 > m33) { 
 
    
 
     s = 2.0 * Math.sqrt(1.0 + m11 - m22 - m33); 
 
    
 
     _w = (m32 - m23)/s; 
 
     _x = 0.25 * s; 
 
     _y = (m12 + m21)/s; 
 
     _z = (m13 + m31)/s; 
 
    
 
     } else if (m22 > m33) { 
 
    
 
     s = 2.0 * Math.sqrt(1.0 + m22 - m11 - m33); 
 
    
 
     _w = (m13 - m31)/s; 
 
     _x = (m12 + m21)/s; 
 
     _y = 0.25 * s; 
 
     _z = (m23 + m32)/s; 
 
    
 
     } else { 
 
    
 
     s = 2.0 * Math.sqrt(1.0 + m33 - m11 - m22); 
 
    
 
     _w = (m21 - m12)/s; 
 
     _x = (m13 + m31)/s; 
 
     _y = (m23 + m32)/s; 
 
     _z = 0.25 * s; 
 
    
 
     } 
 
    
 
     return { 
 
     w: _w, 
 
     x: _x, 
 
     y: _y, 
 
     z: _z 
 
     }; 
 
    } 
 
    
 
    function lookAt(eye, target, up) { 
 
    
 
     // This routine does not support objects with rotated and/or translated parent(s) 
 
    
 
     var m1 = lookAt2(target, eye, up); 
 
    
 
     return setFromRotationMatrix(m1); 
 
    
 
    } 
 
    
 
    function lookAt2(eye, target, up) { 
 
    
 
     var elements = new Float32Array([ 
 
    
 
     1, 0, 0, 0, 
 
     0, 1, 0, 0, 
 
     0, 0, 1, 0, 
 
     0, 0, 0, 1 
 
    
 
     ]); 
 
    
 
    
 
     var x = { 
 
     x: 0, 
 
     y: 0, 
 
     z: 0 
 
     }; 
 
     var y = { 
 
     x: 0, 
 
     y: 0, 
 
     z: 0 
 
     }; 
 
     var z = { 
 
     x: 0, 
 
     y: 0, 
 
     z: 0 
 
     }; 
 
    
 
     var te = elements; 
 
    
 
     z = subVectors(eye, target); 
 
     z = normalize(z); 
 
    
 
     if (lengthSq(z) === 0) { 
 
    
 
     z.z = 1; 
 
    
 
     } 
 
    
 
     x = crossVectors(up, z); 
 
     x = normalize(x); 
 
    
 
     if (lengthSq(x) === 0) { 
 
    
 
     z.z += 0.0001; 
 
     x = crossVectors(up, z); 
 
     x = normalize(x); 
 
    
 
     } 
 
    
 
     y = crossVectors(z, x); 
 
    
 
    
 
     te[0] = x.x; 
 
     te[4] = y.x; 
 
     te[8] = z.x; 
 
     te[1] = x.y; 
 
     te[5] = y.y; 
 
     te[9] = z.y; 
 
     te[2] = x.z; 
 
     te[6] = y.z; 
 
     te[10] = z.z; 
 
    
 
     return te; 
 
    } 
 
    
 
    
 
    function lookatOld(vecstart, vecEnd, vecUp) { 
 
    
 
     var temp = new THREE.Matrix4(); 
 
     temp.lookAt(vecEnd, vecstart, vecUp); 
 
    
 
     var m00 = temp.elements[0], 
 
     m10 = temp.elements[1], 
 
     m20 = temp.elements[2], 
 
     m01 = temp.elements[4], 
 
     m11 = temp.elements[5], 
 
     m21 = temp.elements[6], 
 
     m02 = temp.elements[8], 
 
     m12 = temp.elements[9], 
 
     m22 = temp.elements[10]; 
 
    
 
     var t = m00 + m11 + m22, 
 
     s, x, y, z, w; 
 
    
 
     if (t > 0) { 
 
     s = Math.sqrt(t + 1) * 2; 
 
     w = 0.25 * s; 
 
     x = (m21 - m12)/s; 
 
     y = (m02 - m20)/s; 
 
     z = (m10 - m01)/s; 
 
     } else if ((m00 > m11) && (m00 > m22)) { 
 
     s = Math.sqrt(1.0 + m00 - m11 - m22) * 2; 
 
     x = s * 0.25; 
 
     y = (m10 + m01)/s; 
 
     z = (m02 + m20)/s; 
 
     w = (m21 - m12)/s; 
 
     } else if (m11 > m22) { 
 
     s = Math.sqrt(1.0 + m11 - m00 - m22) * 2; 
 
     y = s * 0.25; 
 
     x = (m10 + m01)/s; 
 
     z = (m21 + m12)/s; 
 
     w = (m02 - m20)/s; 
 
     } else { 
 
     s = Math.sqrt(1.0 + m22 - m00 - m11) * 2; 
 
     z = s * 0.25; 
 
     x = (m02 + m20)/s; 
 
     y = (m21 + m12)/s; 
 
     w = (m10 - m01)/s; 
 
     } 
 
    
 
     var rotation = new THREE.Quaternion(x, y, z, w); 
 
     rotation.normalize(); 
 
     return rotation; 
 
    }

这是同样的代码Plunker:http://plnkr.co/edit/vgNko1fJu9eYYCnJbYVo?p=preview

+0

注意THREE使用右手坐标系统。问题中的图片是左手的,因此您可能需要进行相应调整。 –

+0

以为我会注意到上面的代码没有引用THREE.js库 - 它是独立的JavaScript,因此您可以将这些函数翻译成另一种编程语言。 –

0

你的问题的确切/字面解释是一个坏/不道德的答案。不要尝试使用欧拉角。欧拉坐标系用于协调。做定向/旋转并不是一个好的系统。虽然易于阅读,但容易产生错误的结果Gimbal lock

有两种常见的定位系统:变换矩阵和四元数。 three.js lookAt()使用四元数,Crag.Li的answer使用变换矩阵。

我觉得有必要强调这一点,因为我曾经低估了3D转换,并试图用“简单的方法”来解决它,浪费了将近一个月的时间来做傻瓜的工作。 3D转换硬。有没有快速,肮脏的方式,你只能以正确的方式做到这一点。拿一本书(3D数学入门书是一个很好的书),花时间学习数学,如果你真的想这样做。