我正在尝试将动画代码从矩阵切换到双四元数。我已经阅读了Ladislav Kavan的论文,据我所知,他提供了一种技术,可以将动画矩阵转换为两个特殊的四元数。然后,您在GPU上重建原始矩阵。但是,我没能让它发挥作用。当我在我的应用程序中插入代码时,所有动画都完全扭曲,这意味着重建的矩阵是不正确的。
然后我编写了一个c#控制台应用来检查确实如此:矩阵在转换之前和之后完全不同。我在分解之前对矩阵进行了标准化,但没关系,重建的矩阵永远不会相同。我错过了什么吗?也许输入矩阵应该是特定类型的?
这是我的控制台应用代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Xna.Framework;
namespace DualQuaternionTest
{
class DualQuaternion
{
public Quaternion Ordinary;
public Quaternion Dual;
public static Matrix Normalize(Matrix m)
{
Vector3 v = new Vector3(m.M11, m.M21, m.M31);
v.Normalize();
m.M11 = v.X; m.M21 = v.Y; m.M31 = v.Z;
v = new Vector3(m.M12, m.M22, m.M32);
v.Normalize();
m.M12 = v.X; m.M22 = v.Y; m.M32 = v.Z;
v = new Vector3(m.M13, m.M23, m.M33);
v.Normalize();
m.M13 = v.X; m.M23 = v.Y; m.M33 = v.Z;
return m;
}
public static DualQuaternion QuatTrans2UDQ(Quaternion q0, Vector3 t)
{
DualQuaternion dq = new DualQuaternion();
dq.Ordinary = q0;
dq.Dual.W = -0.5f * (t.X * q0.X + t.Y * q0.Y + t.Z * q0.Z);
dq.Dual.X = 0.5f * (t.X * q0.W + t.Y * q0.Z - t.Z * q0.Y);
dq.Dual.Y = 0.5f * (-t.X * q0.Z + t.Y * q0.W + t.Z * q0.X);
dq.Dual.Z = 0.5f * (t.X * q0.Y - t.Y * q0.X + t.Z * q0.W);
return dq;
}
public static Matrix UDQToMatrix(DualQuaternion dq)
{
Matrix M;
float len2 = Quaternion.Dot(dq.Ordinary, dq.Ordinary);
float w = dq.Ordinary.W, x = dq.Ordinary.X, y = dq.Ordinary.Y, z = dq.Ordinary.Z;
float t0 = dq.Dual.W, t1 = dq.Dual.X, t2 = dq.Dual.Y, t3 = dq.Dual.Z;
M.M11 = w * w + x * x - y * y - z * z;
M.M21 = 2 * x * y - 2 * w * z;
M.M31 = 2 * x * z + 2 * w * y;
M.M12 = 2 * x * y + 2 * w * z;
M.M22 = w * w + y * y - x * x - z * z;
M.M32 = 2 * y * z - 2 * w * x;
M.M13 = 2 * x * z - 2 * w * y;
M.M23 = 2 * y * z + 2 * w * x;
M.M33 = w * w + z * z - x * x - y * y;
M.M41 = -2 * t0 * x + 2 * w * t1 - 2 * t2 * z + 2 * y * t3;
M.M42 = -2 * t0 * y + 2 * t1 * z - 2 * x * t3 + 2 * w * t2;
M.M43 = -2 * t0 * z + 2 * x * t2 + 2 * w * t3 - 2 * t1 * y;
M.M14 = 0;
M.M24 = 0;
M.M34 = 0;
M.M44 = len2;
M /= len2;
return M;
}
}
class Program
{
static void Main(string[] args)
{
Matrix BaseMatrix = Matrix.Identity;
Random random = new Random();
BaseMatrix.M11 = random.Next(-1000000, 1000000) * 0.001f;
BaseMatrix.M12 = random.Next(-1000000, 1000000) * 0.001f;
BaseMatrix.M13 = random.Next(-1000000, 1000000) * 0.001f;
BaseMatrix.M14 = random.Next(-1000000, 1000000) * 0.001f;
BaseMatrix.M21 = random.Next(-1000000, 1000000) * 0.001f;
BaseMatrix.M22 = random.Next(-1000000, 1000000) * 0.001f;
BaseMatrix.M23 = random.Next(-1000000, 1000000) * 0.001f;
BaseMatrix.M24 = random.Next(-1000000, 1000000) * 0.001f;
BaseMatrix.M31 = random.Next(-1000000, 1000000) * 0.001f;
BaseMatrix.M32 = random.Next(-1000000, 1000000) * 0.001f;
BaseMatrix.M33 = random.Next(-1000000, 1000000) * 0.001f;
BaseMatrix.M34 = random.Next(-1000000, 1000000) * 0.001f;
BaseMatrix.M41 = random.Next(-1000000, 1000000) * 0.001f;
BaseMatrix.M42 = random.Next(-1000000, 1000000) * 0.001f;
BaseMatrix.M43 = random.Next(-1000000, 1000000) * 0.001f;
BaseMatrix.M44 = random.Next(-1000000, 1000000) * 0.001f;
Matrix NormalizedBaseMatrix = DualQuaternion.Normalize(BaseMatrix);
Quaternion[] qq = new Quaternion[2];
DualQuaternion dualQuaternion = null;
dualQuaternion = DualQuaternion.QuatTrans2UDQ(
Quaternion.CreateFromRotationMatrix(NormalizedBaseMatrix),
NormalizedBaseMatrix.Translation);
ReconstructedMatrix = DualQuaternion.UDQToMatrix(dualQuaternion);
Console.WriteLine(BaseMatrix.ToString());
Console.WriteLine();
Console.WriteLine(NormalizedBaseMatrix.ToString());
Console.WriteLine();
Console.WriteLine(ReconstructedMatrix.ToString());
Console.ReadKey();
}
}
}
答案 0 :(得分:1)
当你有一个矩阵填充了16个随机值(如果考虑4x3部分,甚至12个,因为你的最右边的列总是在你的UDQToMatrix
函数中为0,0,0,1),您正在创建无法用双四元数表示的变换。
四元数(和双四元数)不能表示任意非正交轴。
不是生成完全随机的值,而是通过随机化平移和旋转操作来生成矩阵。那么你应该能够在矩阵和双四元数之间可靠地转换它们