Matrix 理解对偶四元数蒙皮

Matrix 理解对偶四元数蒙皮,matrix,quaternions,skinning,Matrix,Quaternions,Skinning,我正在尝试将动画代码从矩阵切换到双四元数。我读过Ladislav Kavan的论文,据我所知,他提供了一种技术,将动画矩阵转换为两个特殊的四元数。然后在GPU上重建原始矩阵。然而,我没能让它发挥作用。当我在我的应用程序中插入代码时,所有的动画都被完全扭曲了,这意味着重建的矩阵是不正确的 然后我编写了一个c#控制台应用程序来检查这一点,事实确实如此:转换前后矩阵完全不同。在分解之前,我对矩阵进行了规范化,但这并不重要,重构的矩阵从来都不一样。我错过什么了吗?也许输入矩阵应该是特定类型的 以下是我的

我正在尝试将动画代码从矩阵切换到双四元数。我读过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();
        }
    }
}

如果矩阵中填充了16个随机值(如果考虑4x3部分,甚至是12个,因为在
UDQToMatrix
函数中,最右边的列总是0,0,0,1),则创建的变换无法用双四元数表示

四元数(和双四元数)不能表示任意非正交轴


不是生成完全随机的值,而是通过平移和旋转的随机操作生成矩阵。然后你应该能够在矩阵和对偶四元数之间可靠地转换它们

哇,我刚刚意识到我问错了问题。。。如果版主能帮我把这个话题转到GameDev,我将不胜感激。谢谢你的回答。我已经想到,当我创建和乘以旋转矩阵时,一切都很好。但对我们来说,更大的问题是,我无法将现有的动画矩阵转换为四元数并返回——最终结果总是一团糟。动画软件应该创建具有正交轴的动画矩阵,对吗?我的动画矩阵可能有什么问题?你能找出其中一些矩阵看起来像什么吗?你说的“跟踪”是什么意思?就写在这里?如何追踪矩阵?