我有一个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 :(得分: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 }
});
}
我确信在那里有一个微妙的数学差异,如果你重新排列每个值以使其进入第一个形式,可能会发现,但对我来说这是有效的,我对此很满意。