FBX IO: Export normals with IndexToDirect reference mode #105020

Merged
Thomas Barlow merged 3 commits from Mysteryem/blender-addons:fbx_normals_IndexToDirect into main 2023-12-02 02:08:21 +01:00
3 changed files with 33 additions and 38 deletions

View File

@ -5,7 +5,7 @@
bl_info = {
"name": "FBX format",
"author": "Campbell Barton, Bastien Montagne, Jens Restemeier, @Mysteryem",
"version": (5, 10, 3),
"version": (5, 11, 0),
"blender": (4, 1, 0),
"location": "File > Import-Export",
"description": "FBX IO meshes, UVs, vertex colors, materials, textures, cameras, lamps and actions",

View File

@ -1155,10 +1155,6 @@ def fbx_data_mesh_elements(root, me_obj, scene_data, done_meshes):
# Loop normals.
tspacenumber = 0
if write_normals:
# NOTE: ByVertice-IndexToDirect is not supported by the importer currently.
# XXX Official docs says normals should use IndexToDirect,
# but this does not seem well supported by apps currently...
normal_bl_dtype = np.single
normal_fbx_dtype = np.float64
match me.normals_domain:
@ -1182,12 +1178,12 @@ def fbx_data_mesh_elements(root, me_obj, scene_data, done_meshes):
t_normal = np.empty(len(normal_source) * 3, dtype=normal_bl_dtype)
normal_source.foreach_get("vector", t_normal)
t_normal = nors_transformed(t_normal, geom_mat_no, normal_fbx_dtype)
if 0:
normal_idx_fbx_dtype = np.int32
lay_nor = elem_data_single_int32(geom, b"LayerElementNormal", 0)
elem_data_single_int32(lay_nor, b"Version", FBX_GEOMETRY_NORMAL_VERSION)
elem_data_single_string(lay_nor, b"Name", b"")
elem_data_single_string(lay_nor, b"MappingInformationType", normal_mapping)
# FBX SDK documentation says that normals should use IndexToDirect.
elem_data_single_string(lay_nor, b"ReferenceInformationType", b"IndexToDirect")
# Tuple of unique sorted normals and then the index in the unique sorted normals of each normal in t_normal.
@ -1207,16 +1203,6 @@ def fbx_data_mesh_elements(root, me_obj, scene_data, done_meshes):
del t_normal_idx
# del t_normal_w
else:
lay_nor = elem_data_single_int32(geom, b"LayerElementNormal", 0)
elem_data_single_int32(lay_nor, b"Version", FBX_GEOMETRY_NORMAL_VERSION)
elem_data_single_string(lay_nor, b"Name", b"")
elem_data_single_string(lay_nor, b"MappingInformationType", normal_mapping)
elem_data_single_string(lay_nor, b"ReferenceInformationType", b"Direct")
elem_data_single_float64_array(lay_nor, b"Normals", t_normal)
# Normal weights, no idea what it is.
# t_normal = np.zeros(len(me.loops), dtype=np.float64)
# elem_data_single_float64_array(lay_nor, b"NormalsW", t_normal)
del t_normal
# tspace

View File

@ -1398,7 +1398,18 @@ def blen_read_geom_array_mapped_vert(
xform=None, quiet=False,
):
if fbx_layer_mapping == b'ByVertice':
if fbx_layer_ref == b'Direct':
if fbx_layer_ref == b'IndexToDirect':
# XXX Looks like we often get no fbx_layer_index in this case, shall not happen but happens...
# We fallback to 'Direct' mapping in this case.
#~ assert(fbx_layer_index is not None)
if fbx_layer_index is None:
blen_read_geom_array_foreach_set_direct(blen_data, blen_attr, blen_dtype, fbx_layer_data, stride,
item_size, descr, xform)
else:
blen_read_geom_array_foreach_set_indexed(blen_data, blen_attr, blen_dtype, fbx_layer_data,
fbx_layer_index, stride, item_size, descr, xform)
return True
elif fbx_layer_ref == b'Direct':
assert(fbx_layer_index is None)
blen_read_geom_array_foreach_set_direct(blen_data, blen_attr, blen_dtype, fbx_layer_data, stride, item_size,
descr, xform)
@ -1754,8 +1765,6 @@ def blen_read_geom_layer_normal(fbx_obj, mesh, xform=None):
loop_normals = np.repeat(bdata, poly_loop_totals, axis=0)
mesh.attributes["temp_custom_normals"].data.foreach_set("vector", loop_normals.ravel())
elif blen_data_type == "Vertices":
# Note: Currently unreachable because `blen_read_geom_array_mapped_polyloop` covers all the supported
# import cases covered by `blen_read_geom_array_mapped_vert`.
# We have to copy vnors to lnors! Far from elegant, but simple.
loop_vertex_indices = MESH_ATTRIBUTE_CORNER_VERT.to_ndarray(mesh.attributes)
mesh.attributes["temp_custom_normals"].data.foreach_set("vector", bdata[loop_vertex_indices].ravel())