背景:
我目前正在 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 提供的任何其他资源,并阅读了以下资源,希望自己能找到答案:
共识是四元数不会在任何意义上对“翻译”或“位置”进行编码,并且似乎没有提供一种直观的方式来模拟它,因此纯四元数数学似乎不太可能是一个可行的解决方案。
然而,在这里有一个明确的答案可能会很好。有谁知道有什么方法可以“伪造”四元数的位置分量,以某种方式保持四元数数学效率,或者其他一些方法来“累积”围绕不同原点的旋转,这比仅计算矩阵更有效四元数,并为每个四元数做矩阵平移和旋转乘法?或者也许有一些数学保证,即不同的枢轴点实际上没有任何区别,实际上可以在以后应用(但我对此表示怀疑)。
或者在这种情况下使用四元数只是一个坏主意?
最佳答案
事实上,没有四元数的位置分量这样的东西,所以你需要单独跟踪它。假设个人转换最终像
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/