结合具有不同枢轴点的四元数

Posted

技术标签:

【中文标题】结合具有不同枢轴点的四元数【英文标题】:Combining quaternions with different pivot point 【发布时间】:2012-10-17 07:26:37 【问题描述】:

背景:

我目前正在 GLSL 中实现骨骼动画着色器,为了节省空间和复杂性,我使用四元数进行骨骼旋转,使用加权四元数乘法(每个骨骼)为每个顶点累积“最终旋转”。

类似于:(伪代码,假设四元数数学按预期工作)

  float weights[5];
  int bones[5];
  vec4 position;

  uniform quaternion allBoneRotations[100];
  uniform vec3 allBonePositions[100];

  main()
  quaternion finalQuaternion;
  for(i=0;i<5;i++)finalQuaternion *= allBoneRotations[bones[i]]*weights[i];
  gl_position = position.rotateByQuaternion(finalQuaternion);
  

真正的代码很复杂,草率,并且按预期工作,但这应该给出一般的想法,因为无论如何这主要是一个数学问题,代码没有太大的影响,它只是为了清楚起见而提供。

问题:

当我意识到“最终四元数”不会占用组合四元数本身时要考虑不同的枢轴点。在这种情况下,每个骨骼旋转都将被视为围绕点 (0,0,0)。

鉴于四元数仅代表一个旋转,看来我需要向四元数“添加”一个位置(如果可能),或者简单地将所有四元数转换为矩阵,然后进行矩阵乘法以组合系列的平移和旋转。我真的希望后者不是必需的,因为它看起来效率相对较低。

我搜索了 mathoverflow、math.stackexchange 以及 Google 提供的任何其他内容,并阅读了以下资源,希望自己能找到答案:

http://shankel.best.vwh.net/QuatRot.html

http://mathworld.wolfram.com/Quaternion.html

加上通过谷歌搜索发现的各种其他小讨论(我只能发布 2 个链接)

共识是四元数不编码任何意义上的“平移”或“位置”,并且似乎没有提供一种直观的方式来模拟它,因此纯四元数数学似乎不太可能成为一个可行的解决方案。

但是,在这里有一个明确的答案可能会很好。有谁知道“伪造”四元数的位置分量的任何方法,以某种方式保持四元数数学效率,或其他一些方法来“累积”围绕不同原点的旋转,这比仅仅计算矩阵更有效四元数,并为每个四元数做矩阵平移和旋转乘法?或者也许是一些数学保证,即不同的枢轴点实际上没有任何区别,实际上可以在以后应用(但我对此表示怀疑)。

或者说在这种情况下使用四元数只是表面上的一个坏主意?

【问题讨论】:

粗略浏览您的问题后,我想到的第一个(也可能是最好的)答案是:使用双四元数!。它们易于使用(一旦您掌握了概念),易于转换为刚体矩阵/从刚体矩阵转换,并且在性能上与矩阵相似(如果使用得当,请勿在着色器内进行矩阵转换)。在谷歌上搜索“双四元数蒙皮” 应该会引导您访问 Ladislav Kavan 的网站和论文,其中非常详尽地描述了它们的用法。 非常感谢!经过几个小时的搜索,我最终也发现了双四元数,但没有注意到 Ladislav Kavan 网站。不过,这似乎非常有帮助,谢谢! 【参考方案1】:

确实,四元数不存在位置分量,因此您需要单独跟踪它。假设个别转换最终是这样的

x' = R(q)*(x-pivot)+pivot = R(q)*x + (pivot-R(q)*pivot) = R(q)*x+p,

q 是你的四元数,R(q) 是由它构建的旋转矩阵,p=pivot-R(q)*pivot 是位置/平移组件。如果你想组合两个这样的变换,你可以不用全矩阵乘法:

x'' = R(q2)*x'+p2 = R(q2)*R(q)*x + (R(q2)*p+p2) = R(q2*q)*x + (R(q2)*p+p2).

这样组合的四元数将为q2*q,组合的位置为R(q2)*p+p2。请注意,如果您想绝对避免使用四元数,甚至可以将四元数应用于向量(R(q2)*p 等)而无需显式构建旋转矩阵。

也就是说,还有一个“双四元数”的概念,事实上,它确实包含一个平移分量,并且可能更适合表示螺旋运动。查看on Wiki 和here(最后一个链接也指向一篇论文)。

【讨论】:

【参考方案2】:

经过广泛的额外搜索,以及比任何理智的人都阅读更多关于四元数的内容,我终于在这里找到了答案:

http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/other/dualQuaternion/index.htm

事实证明,对偶四元数的操作类似于实际四元数,其中许多数学运算都基于常规四元数数学,但它们同时提供方向和位移,并且可以组合用于所需的任何旋转平移序列,非常多类似于变换矩阵乘法,但没有剪切/缩放能力。

该页面还有一个部分,该部分通过使用双四元数乘法精确地导出了我需要的“围绕任意点旋转”功能。或许我应该在问之前多研究一下,但至少现在答案就在这里,以防其他人来找。

【讨论】:

以上是关于结合具有不同枢轴点的四元数的主要内容,如果未能解决你的问题,请参考以下文章

最短路径的四元数 slerp 不起作用

python中的四元数运算

龙格库塔(Runge-Kutta)法求四元数微分方程

龙格库塔(Runge-Kutta)法求四元数微分方程

C/C++ 中的四元数库 [关闭]

Unity复杂的旋转-欧拉角和四元数