WebGL蒙皮矩阵正常,FBX SDK设置蒙皮矩阵遇阻求助
WebGL蒙皮矩阵导出FBX至Blender的旋转问题
我有一套模型和对应的蒙皮矩阵,在WebGL中动画与蒙皮变形均可正常工作,但尝试用FBX SDK导出为Blender可识别的骨骼时失败。曾尝试生成嵌套骨骼(考虑关节继承变换将对象空间转换为世界空间),但无效。也考虑过直接沿用WebGL的animationMatrix * inverseObjectSpaceTransformMatrix逻辑设置蒙皮矩阵,但不确定可行性,更不清楚如何导入Blender这类不支持该逻辑的软件。理想方案是将WebGL蒙皮矩阵系统导出为Blender可用的骨骼,目前仅以FBX SDK为例进行尝试。
核心参考数据
以下是各骨骼的逆对象空间变换数据:
b_pedestal: inverse_object_space_transform: r=[0.0, 0.0, 0.0, 1.0], t=[0.0, 0.0, 0.0] b_pelvis: inverse_object_space_transform: r=[0.5, 0.5, 0.5, 0.5], t=[-1.034437, -0.0118, -0.0] b_utility: inverse_object_space_transform: r=[0.0, 0.0, 0.0, 1.0], t=[0.0, 0.0, 0.0] b_l_thigh: inverse_object_space_transform: r=[-0.540589, 0.495971, -0.505714, 0.453904], t=[-0.992615, 0.051638, 0.184923] b_r_thigh: inverse_object_space_transform: r=[-0.505715, -0.453904, 0.540589, 0.495971], t=[0.992615, -0.051638, -0.184923] b_spine_1: inverse_object_space_transform: r=[0.5, 0.5, 0.5, 0.5], t=[-1.091035, -0.0118, -0.0] b_l_calf: inverse_object_space_transform: r=[-0.581244, 0.447637, -0.464801, 0.495718], t=[-0.540767, -0.041656, 0.184923] b_r_calf: inverse_object_space_transform: r=[-0.464801, -0.495718, 0.581244, 0.447637], t=[0.540767, 0.041655, -0.184923] b_spine_2: inverse_object_space_transform: r=[0.463693, 0.533844, 0.533844, 0.463693], t=[-1.177534, -0.178358, -0.0]
WebGL蒙皮矩阵生成逻辑
for (var nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) { var inverseObjectSpaceTransform = inverseObjectSpaceTransforms[nodeIndex]; var translationScale = inverseObjectSpaceTransform.ts; var scale = translationScale[3]; var rotation = inverseObjectSpaceTransform.r; var translation = [translationScale[0], translationScale[1], translationScale[2]]; var inverseObjectSpaceTransformSRT = new TransformSRT(scale, rotation, translation); var inverseObjectSpaceTransformMatrix = mat4.create(); inverseObjectSpaceTransformSRT.setMatrix(inverseObjectSpaceTransformMatrix); inverseObjectSpaceTransformMatrices.push(inverseObjectSpaceTransformMatrix); var node = nodes[nodeIndex]; var parentNodeIndex = node.parent_node_index; parentNodeIndices.push(parentNodeIndex); } for (var nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) { var frameMatrix = frameMatrices[nodeIndex]; var animationMatrix = animationMatrices[nodeIndex]; var inverseObjectSpaceTransformMatrix = inverseObjectSpaceTransformMatrices[nodeIndex]; var parentNodeIndex = parentNodeIndices[nodeIndex]; if (parentNodeIndex >= 0) { Spasm.assert(parentNodeIndex < nodeIndex); var parentAnimationMatrix = animationMatrices[parentNodeIndex]; mat4.multiply(animationMatrix, parentAnimationMatrix, frameMatrix); } else { mat4.copy(animationMatrix, frameMatrix); } mat4.multiply(tempMatrix0, animationMatrix, inverseObjectSpaceTransformMatrix); mat4.transpose(tempMatrix0, tempMatrix0); transformBuffer.set(tempMatrix0.subarray(0, 12), nodeIndex * 12); // collapsed skinning matrices }
顶点着色器蒙皮逻辑
mat4 get_bone_transform(int bone_index) { int stride_bone_index = bone_index * 3; vec4 i0 = u_skinning_matrices[stride_bone_index + 0]; vec4 i1 = u_skinning_matrices[stride_bone_index + 1]; vec4 i2 = u_skinning_matrices[stride_bone_index + 2]; vec4 i3 = vec4(0.0, 0.0, 0.0, 1.0); mat4 bone_transform = mat4( vec4(i0.x, i1.x, i2.x, i3.x), vec4(i0.y, i1.y, i2.y, i3.y), vec4(i0.z, i1.z, i2.z, i3.z), vec4(i0.w, i1.w, i2.w, i3.w) ); return bone_transform; } mat4 skinning_transform = (get_bone_transform(blend_indices[0]) * a_blendweight[0]); skinning_transform += (get_bone_transform(blend_indices[1]) * a_blendweight[1]); skinning_transform += (get_bone_transform(blend_indices[2]) * a_blendweight[2]); skinning_transform += (get_bone_transform(blend_indices[3]) * a_blendweight[3]); mat4 model_view_matrix = u_view_matrix;// * u_model_matrix; mat4 camera_matrix = u_projection_matrix * model_view_matrix; vec4 position_transformed = vec4( (a_position.x * u_position_scale.x) + u_position_offset.x, (a_position.y * u_position_scale.y) + u_position_offset.y, (a_position.z * u_position_scale.z) + u_position_offset.z, 1.0 ); vec4 position_skinned = vec4((skinning_transform * position_transformed).xyz, 1.0);
FBX SDK导出尝试代码(Python)
for nodeIndex in range(self.node_count): nodeatt = fbx.FbxSkeleton.Create(model.scene, f"skeleton_{nodeIndex}") nodeatt.SetSkeletonType(fbx.FbxSkeleton.eLimbNode) joint = fbx.FbxNode.Create(model.scene, f"{self.names[nodeIndex]}_{nodeIndex}") joint.SetNodeAttribute(nodeatt) bone_nodes.append(joint) parentNodeIndex = self.mParents[nodeIndex] if parentNodeIndex >= 0: bone_nodes[parentNodeIndex].AddChild(bone_nodes[nodeIndex]) else: # root is first bone always rootnodeatt = fbx.FbxSkeleton.Create(model.scene, 'rootSkeleton') rootnodeatt.SetSkeletonType(fbx.FbxSkeleton.eRoot) root = fbx.FbxNode.Create(model.scene, 'rootNode') root.AddChild(bone_nodes[0]) root.SetNodeAttribute(rootnodeatt) model.scene.GetRootNode().AddChild(root) egt = joint.EvaluateGlobalTransform() fbx_transform = fbx.FbxAMatrix() fbx_transform.SetIdentity() transform = self.mTransforms[nodeIndex] rotation = transform.get_euler_rotation() # already inverted to be non-inverted object space transform translation = transform.get_translation() fbx_transform.SetR(fbx.FbxVector4(rotation[0], rotation[1], rotation[2])) fbx_transform.SetT(fbx.FbxVector4(translation[0], translation[1], translation[2])) fix = egt.Inverse() * fbx_transform joint.LclTranslation.Set(fbx.FbxDouble3(fix.GetT()[0], fix.GetT()[1], fix.GetT()[2])) joint.LclRotation.Set(fbx.FbxDouble3(fix.GetR()[0], fix.GetR()[1], fix.GetR()[2]))
当前问题现象
导入Blender后,骨骼位置正确,但旋转错误。
内容的提问来源于stack exchange,提问作者Monteven
相关产品推荐
相关产品推荐

