Python FBX SDK导出立方体法线异常问题求助
Python FBX SDK导出立方体法线错乱的解决方法
你的代码存在两个核心问题,导致导出的模型法线完全混乱:
问题1:顶点齐次坐标w分量错误
设置控制点时,你将FbxVector4的第四个参数设为0.0,但在FBX坐标系统中,w=0.0表示该向量是方向向量而非空间位置,这会导致顶点坐标无法被正确解析,进而法线方向彻底错乱。顶点位置的w分量必须设为1.0。
问题2:法线图层绑定不明确
虽然你创建了法线元素,但部分FBX导入器(如Blender、FBX Review)需要明确将法线元素绑定到网格的图层上,才能正确识别法线数据。
修正后的完整代码
import fbx memory_manager = fbx.FbxManager.Create() scene = fbx.FbxScene.Create(memory_manager, '') mesh_node = fbx.FbxNode.Create(memory_manager, 'cube') scene.GetRootNode().AddChild(mesh_node) # -- mesh mesh_attribute: fbx.FbxMesh = fbx.FbxMesh.Create(memory_manager, '') mesh_node.AddNodeAttribute(mesh_attribute) # -- mesh -- vertices mesh_attribute.InitControlPoints(8) CUBE_VERTS = ( (0,0,0), (0,0,1), (0,1,0), (0,1,1), (1,0,0), (1,0,1), (1,1,0), (1,1,1) ) for i in range(0, 8): vert = CUBE_VERTS[i] # 修正:w分量设为1.0,表示这是空间位置点 mesh_attribute.SetControlPointAt(fbx.FbxVector4(vert[0], vert[1], vert[2], 1.0), i) # -- mesh -- faces CUBE_FACES = ( (0,1,3,2), (3,2,6,7), (4,5,7,6), (0,1,5,4), (1,3,7,5), (0,2,6,4) ) for i in range(0, len(CUBE_FACES)): mesh_attribute.BeginPolygon() mesh_attribute.AddPolygon(CUBE_FACES[i][0]) mesh_attribute.AddPolygon(CUBE_FACES[i][1]) mesh_attribute.AddPolygon(CUBE_FACES[i][2]) mesh_attribute.AddPolygon(CUBE_FACES[i][3]) mesh_attribute.EndPolygon() # -- mesh -- normals NORMALS = [ [-0.57735, -0.57735, -0.57735, 1.0], [-0.57735, -0.57735, 0.57735, 1.0], [-0.57735, 0.57735, -0.57735, 1.0], [-0.57735, 0.57735, 0.57735, 1.0], [0.57735, -0.57735, -0.57735, 1.0], [0.57735, -0.57735, 0.57735, 1.0], [0.57735, 0.57735, -0.57735, 1.0], [0.57735, 0.57735, 0.57735, 1.0] ] normal_element: fbx.FbxLayerElementNormal = mesh_attribute.CreateElementNormal() normal_element.SetMappingMode(fbx.FbxLayerElementNormal.eByControlPoint) normal_element.SetReferenceMode(fbx.FbxLayerElementNormal.eDirect) for i in range(0, 8): normal_element.GetDirectArray().Add(fbx.FbxVector4(NORMALS[i][0], NORMALS[i][1], NORMALS[i][2])) # 修正:明确将法线元素绑定到图层,确保导入器能识别 layer = mesh_attribute.GetLayer(0) if not layer: layer = mesh_attribute.CreateLayer() layer.SetNormals(normal_element) # EXPORT exporter = fbx.FbxExporter.Create(memory_manager, '') exporter.Initialize('cuby.fbx', -1, memory_manager.GetIOSettings()) result = exporter.Export(scene) if result: print('exported successfully') memory_manager.Destroy()
额外说明:如果需要硬边立方体效果
当前代码设置的是平滑法线(每个顶点的法线指向立方体对角线方向),如果你需要立方体每个面的法线垂直于面(硬边效果),需要修改法线的映射模式为eByPolygonVertex,为每个面的每个顶点单独设置对应面的法线,示例代码如下:
# 替换法线部分的代码 # 每个面的法线(垂直于面向外) FACE_NORMALS = [ (-1, 0, 0), # 左面 (0, 1, 0), # 顶面 (1, 0, 0), # 右面 (0, -1, 0), # 底面 (0, 0, 1), # 前面 (0, 0, -1) # 后面 ] normal_element: fbx.FbxLayerElementNormal = mesh_attribute.CreateElementNormal() # 按多边形顶点映射,每个顶点实例对应一个法线 normal_element.SetMappingMode(fbx.FbxLayerElementNormal.eByPolygonVertex) normal_element.SetReferenceMode(fbx.FbxLayerElementNormal.eDirect) # 为每个面的四个顶点添加对应面的法线 for face_idx in range(len(CUBE_FACES)): normal = FACE_NORMALS[face_idx] # 每个面有4个顶点,添加4次相同的法线 for _ in range(4): normal_element.GetDirectArray().Add(fbx.FbxVector4(normal[0], normal[1], normal[2])) # 绑定到图层 layer = mesh_attribute.GetLayer(0) if not layer: layer = mesh_attribute.CreateLayer() layer.SetNormals(normal_element)
内容的提问来源于stack exchange,提问作者Serhii
相关产品推荐
相关产品推荐

