2012-07-26 68 views
0

我有一個4x4矩陣(行 - 主)類和一個四元類,我試圖提供轉換兩種表示之間轉換的轉換方法。將矩陣結果轉換爲四元數,並將值反轉?

這是用於從四元數轉換成矩陣,其中_2是System.Math.Pow我的轉換功能:

/// <summary> 
/// Converts the quaternion to it's matrix representation. 
/// </summary> 
/// <returns>A matrix representing the quaternion.</returns> 
public Matrix ToMatrix() 
{ 
    return new Matrix(new double[,] { 
     { 
      _2(W) + _2(X) - _2(Y) - _2(Z), 
      (2 * X * Y) - (2 * W * Z), 
      (2 * X * Z) + (2 * W * Y), 
      0 
     }, 
     { 
      (2 * X * Y) + (2 * W * Z), 
      _2(W) - _2(X) + _2(Y) - _2(Z), 
      (2 * Y * Z) + (2 * W * X), 
      0 
     }, 
     { 
      (2 * X * Z) - (2 * W * Y), 
      (2 * Y * Z) - (2 * W * X), 
      _2(W) - _2(X) - _2(Y) + _2(Z), 
      0 
     }, 
     { 
      0, 
      0, 
      0, 
      1 
     } 
    }); 
} 

這些是從矩陣轉換成四元數我的兩個轉換函數。請注意,在考慮X旋轉時,它們都不起作用。

/// <summary> 
/// Converts the matrix to a quaternion assuming the matrix purely 
/// represents rotation (any translation or scaling information will 
/// result in an invalid quaternion). 
/// </summary> 
/// <returns>A quaternion representing the rotation.</returns> 
public Quaternion ToQuaternion() 
{ 
    /* http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm 
     */ 
    double tr = this.m_Data[0, 0] + this.m_Data[1, 1] + this.m_Data[2, 2]; 
    if (tr > 0) 
    { 
     double s = _N2(tr + 1) * 2; 
     return new Quaternion(
      (this.m_Data[2, 1] - this.m_Data[1, 2])/s, 
      (this.m_Data[0, 2] - this.m_Data[2, 0])/s, 
      (this.m_Data[1, 0] - this.m_Data[0, 1])/s, 
      0.25 * s 
     ); 
    } 
    else if ((this.m_Data[0, 0] > this.m_Data[1, 1]) && (this.m_Data[0, 0] > this.m_Data[2, 2])) 
    { 
     double s = _N2(1 + this.m_Data[0, 0] - this.m_Data[1, 1] - this.m_Data[2, 2]) * 2; 
     return new Quaternion(
      0.25 * s, 
      (this.m_Data[0, 1] + this.m_Data[1, 0])/s, 
      (this.m_Data[0, 2] + this.m_Data[2, 0])/s, 
      (this.m_Data[2, 1] - this.m_Data[1, 2])/s 
     ); 
    } 
    else if (this.m_Data[1, 1] > this.m_Data[2, 2]) 
    { 
     double s = _N2(1 + this.m_Data[1, 1] - this.m_Data[0, 0] - this.m_Data[2, 2]) * 2; 
     return new Quaternion(
      (this.m_Data[0, 1] + this.m_Data[1, 0])/s, 
      0.25 * s, 
      (this.m_Data[1, 2] + this.m_Data[2, 1])/s, 
      (this.m_Data[0, 2] - this.m_Data[2, 0])/s 
     ); 
    } 
    else 
    { 
     double s = _N2(1 + this.m_Data[2, 2] - this.m_Data[0, 0] - this.m_Data[1, 1]) * 2; 
     return new Quaternion(
      (this.m_Data[0, 2] + this.m_Data[2, 0])/s, 
      (this.m_Data[1, 2] + this.m_Data[2, 1])/s, 
      0.25 * s, 
      (this.m_Data[1, 0] - this.m_Data[0, 1])/s 
     ); 
    } 
} 

/// <summary> 
/// This is a simpler form than above, but doesn't work for all values. It exhibits the 
/// *same results* as ToQuaternion for X rotation however (i.e. both are invalid). 
/// </summary> 
public Quaternion ToQuaternionAlt() 
{ 
    double w = System.Math.Sqrt(1 + this.m_Data[0, 0] + this.m_Data[1, 1] + this.m_Data[2, 2])/2; 
    return new Quaternion(
     (this.m_Data[2, 1] - this.m_Data[1, 2])/(4 * w), 
     (this.m_Data[0, 2] - this.m_Data[2, 0])/(4 * w), 
     (this.m_Data[1, 0] - this.m_Data[0, 1])/(4 * w), 
     w 
    ); 
} 

現在我的測試套件有一個簡單的測試,像這樣:

[TestMethod] 
public void TestMatrixXA() 
{ 
    Matrix m = Matrix.CreateRotationX(45/(180/System.Math.PI)); 
    Assert.AreEqual<Matrix>(m, m.ToQuaternion().ToMatrix(), "Quaternion conversion was not completed successfully."); 
} 

這是結果我從測試套件獲得:

Expected: 
{ 1, 0, 0, 0 } 
{ 0, 0.707106781186548, -0.707106781186547, 0 } 
{ 0, 0.707106781186547, 0.707106781186548, 0 } 
{ 0, 0, 0, 1 } 

Actual: 
{ 1, 0, 0, 0 } 
{ 0, 0.707106781186547, 0.707106781186547, 0 } 
{ 0, -0.707106781186547, 0.707106781186547, 0 } 
{ 0, 0, 0, 1 } 

你會注意到,矩陣中的兩個值被倒置。我已經測試了它,並且在每次來回轉換(如.ToQuaternion()。ToMatrix())時,這些字段都是反轉的。即如果我做四元數/矩陣轉換兩次,我得到正確的矩陣。由於正確值和結果之間的差異非常簡單,我假設它是一個簡單的東西,就像一個負號出現在錯誤的地方,但由於我不是矩陣和四元數學的專家,我無法找到問題所在。

有人知道數學有什麼問題嗎?

回答

0

一爲四元數轉換成矩陣其他解決方案似乎工作:

/// <summary> 
/// Converts the quaternion to it's matrix representation. 
/// </summary> 
/// <returns>A matrix representing the quaternion.</returns> 
public Matrix ToMatrix() 
{ 
    if (!this.Normalized) 
     return this.Normalize().ToMatrix(); 

    double xx = X * X; 
    double xy = X * Y; 
    double xz = X * Z; 
    double xw = X * W; 

    double yy = Y * Y; 
    double yz = Y * Z; 
    double yw = Y * W; 

    double zz = Z * Z; 
    double zw = Z * W; 

    return new Matrix(new double[,] 
    { 
     { 1 - 2 * (yy + zz), 2 * (xy - zw), 2 * (xz + yw), 0 }, 
     { 2 * (xy + zw), 1 - 2 * (xx + zz), 2 * (yz - xw), 0 }, 
     { 2 * (xz - yw), 2 * (yz + xw), 1 - 2 * (xx + yy), 0 }, 
     { 0, 0, 0, 1 } 
    }); 
} 

我敢肯定那裏面有一個微妙的數學差大概可以發現,如果你重新排列每個值來把它變成第一種形式,但對我來說這是有效的,我對此感到滿意。