2017-03-01 63 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數學入門書是一個很好的書),花時間學習數學,如果你真的想這樣做。