math - 结合不同轴心点的四元数

标签 math translation glsl quaternions vertex-shader

背景:

我目前正在 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 个链接)

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

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

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

    最佳答案

    事实上,没有四元数的位置分量这样的东西,所以你需要单独跟踪它。假设个人转换最终像

    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 (最后一个链接也指向一篇论文)。

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

    相关文章:

    javascript - 如何在多个元素之间分配百分比?

    opengl - OpenGL GLSL中的atan(y/x)和atan2(y,x)有什么区别

    objective-c - 两个例程,一个在 Objective-C 中,另一个在 Swift 中,相同的代码产生本质不同的结果

    java - LWJGL - 帧缓冲区纹理

    math - 内联汇编与数学库

    powershell - 如何在 PowerShell 中正确舍入数字

    Angular 2翻译在应用程序中更改语言

    translation - 他们如何非正式地将已编译的程序从一种人类语言翻译成另一种人类语言?

    java - 为什么此照明代码仅适用于单个灯光,而当我添加多个灯光时会中断?

    c++ - GLSL 日志返回未定义的结果