背景:

我目前正在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
  • 以及通过Google搜索找到的其他各种小讨论(我只能发布2个链接)

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

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

    还是在这种情况下使用四元数只是一个坏主意?

    最佳答案

    确实,没有四元数的位置分量,因此您需要单独跟踪它。假设个体转变最终像

    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等)。

    也就是说,还有一个“双四元数”的概念,实际上确实包含一个平移分量,并且可能更好地表示了螺旋运动。将它们 check out on Wikihere(最后一个链接也指向论文)。

    关于math - 结合具有不同枢轴点的四元数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13096939/

    10-11 00:56