我正在编写一个自定义脚本,用于将Blender模型和动画导出到使用OpenGL运行的游戏中。
我知道Blender使用Z-up系统,而我的游戏中的OpenGL使用Y-up系统。我可以轻松绕X轴-π/ 2旋转固定模型的网格和骨骼位置,从而正确呈现模型。
但是在Blender中,角色腿上与地板平行的骨骼的euler X旋转为0,而与地板垂直的骨骼的euler X旋转为-π/ 2(或π/ 2) )。
在游戏中,与地板平行的角色的腿的欧拉X旋转为-π/ 2(或π/ 2),与地板垂直的骨骼的旋转为0。
在这里,模型的左腿与地板平行,并具有与Blender中的左腿相同的XYZ欧拉旋转角度(垂直于地板):
每帧骨骼旋转的Blender导出脚本为:
for f in range(scene.frame_start, scene.frame_end + 1):
bpy.context.scene.frame_set(f);
bpy.context.scene.update();
for i in range(len(arm.pose.bones)):
bone = arm.pose.bones[i]
out.write(str(boneIDs[bone.name]) + ","); # ID of the bone
out.write(VecToStringComma(bone.matrix.to_euler())) # bone rotation
out.write("\n")
并将其加载到C#中,用以下代码重新组成骨骼旋转矩阵:
for (int i = 0; i <= frameCount; i++)
{
Frame frame = new Frame();
var parts = r[read].Split(',');
read++;
for (int p = 0; p < parts.Length - 1; p += 4)
{
FrameDeform fd = new FrameDeform();
fd.DeformerID = int.Parse(parts[p]);
Vector3 rot = new Vector3(double.Parse(parts[p + 1]), double.Parse(parts[p + 2]), double.Parse(parts[p + 3]));
fd.Rotation = Matrix4.CreateRotationX(rot.X) * Matrix4.CreateRotationY(rot.Y) * Matrix4.CreateRotationZ(rot.Z);
frame.FrameDeforms.Add(fd);
}
anim.Frames.Add(frame);
}
Blender中的第0帧如下:
游戏中的第0帧如下:
我知道目前我没有对旋转值进行任何更改,但是我可以看到腿在游戏中沿着正确的运动路径,但是在错误的轴上。
由于X值保持不变,因此绕X轴旋转-π/ 2旋转值无济于事。
由于我在这个问题上苦苦挣扎了很长时间,所以任何帮助都会令人感激。
更新
在加载模型时,我不会绕X轴旋转。相反,在运行时,我绕着X轴应用了-π/ 2的旋转,该旋转发生在着色器中:
vec3 pos = (zMat * bones[id] * vec4(aPosition, 1.0)).xyz
但是,这给了我以下结果(仅在对躯干进行动画处理时):