背景:
我目前正在 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 提供的任何其他内容,并阅读了以下资源,希望自己能找到答案:
加上通过谷歌搜索发现的各种其他小讨论(我只能发布 2 个链接)
共识是四元数在任何意义上都不编码“平移”或“位置”,并且似乎没有提供一种直观的方式来模拟它,因此纯四元数数学似乎不太可能成为一个可行的解决方案。
然而,在这里有一个明确的答案可能会很好。有谁知道“伪造”四元数的位置分量的任何方法,以某种方式保持四元数数学效率,或其他一些方法来“累积”围绕不同原点的旋转,这比仅仅计算矩阵更有效四元数,并为每个四元数做矩阵平移和旋转乘法?或者也许一些数学保证,不同的枢轴点实际上没有任何区别,实际上可以在以后应用(但我对此表示怀疑)。
或者在这种情况下使用四元数只是表面上的一个坏主意?