11

背景:

我目前正在 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 提供的任何其他内容,并阅读了以下资源,希望自己能找到答案:

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

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

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

4

2 回答 2

3

实际上,没有四元数的位置分量这样的东西,因此您需要单独跟踪它。假设个别转换最终像

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等等)而无需显式构建旋转矩阵。

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

于 2012-10-27T05:12:11.063 回答
2

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

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

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

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

于 2012-10-27T17:46:45.960 回答