FBX IO: Export normals with IndexToDirect reference mode #105020
@ -1155,10 +1155,6 @@ def fbx_data_mesh_elements(root, me_obj, scene_data, done_meshes):
|
|||||||
# Loop normals.
|
# Loop normals.
|
||||||
tspacenumber = 0
|
tspacenumber = 0
|
||||||
if write_normals:
|
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_bl_dtype = np.single
|
||||||
normal_fbx_dtype = np.float64
|
normal_fbx_dtype = np.float64
|
||||||
match me.normals_domain:
|
match me.normals_domain:
|
||||||
@ -1182,41 +1178,31 @@ def fbx_data_mesh_elements(root, me_obj, scene_data, done_meshes):
|
|||||||
t_normal = np.empty(len(normal_source) * 3, dtype=normal_bl_dtype)
|
t_normal = np.empty(len(normal_source) * 3, dtype=normal_bl_dtype)
|
||||||
normal_source.foreach_get("vector", t_normal)
|
normal_source.foreach_get("vector", t_normal)
|
||||||
t_normal = nors_transformed(t_normal, geom_mat_no, normal_fbx_dtype)
|
t_normal = nors_transformed(t_normal, geom_mat_no, normal_fbx_dtype)
|
||||||
if 0:
|
normal_idx_fbx_dtype = np.int32
|
||||||
normal_idx_fbx_dtype = np.int32
|
lay_nor = elem_data_single_int32(geom, b"LayerElementNormal", 0)
|
||||||
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_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"Name", b"")
|
elem_data_single_string(lay_nor, b"MappingInformationType", normal_mapping)
|
||||||
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")
|
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.
|
# Tuple of unique sorted normals and then the index in the unique sorted normals of each normal in t_normal.
|
||||||
# Since we don't care about how the normals are sorted, only that they're unique, we can use the fast unique
|
# Since we don't care about how the normals are sorted, only that they're unique, we can use the fast unique
|
||||||
# helper function.
|
# helper function.
|
||||||
t_normal, t_normal_idx = fast_first_axis_unique(t_normal.reshape(-1, 3), return_inverse=True)
|
t_normal, t_normal_idx = fast_first_axis_unique(t_normal.reshape(-1, 3), return_inverse=True)
|
||||||
|
|
||||||
# Convert to the type for fbx
|
# Convert to the type for fbx
|
||||||
t_normal_idx = astype_view_signedness(t_normal_idx, normal_idx_fbx_dtype)
|
t_normal_idx = astype_view_signedness(t_normal_idx, normal_idx_fbx_dtype)
|
||||||
|
|
||||||
elem_data_single_float64_array(lay_nor, b"Normals", t_normal)
|
elem_data_single_float64_array(lay_nor, b"Normals", t_normal)
|
||||||
# Normal weights, no idea what it is.
|
# Normal weights, no idea what it is.
|
||||||
# t_normal_w = np.zeros(len(t_normal), dtype=np.float64)
|
# t_normal_w = np.zeros(len(t_normal), dtype=np.float64)
|
||||||
# elem_data_single_float64_array(lay_nor, b"NormalsW", t_normal_w)
|
# elem_data_single_float64_array(lay_nor, b"NormalsW", t_normal_w)
|
||||||
|
|
||||||
elem_data_single_int32_array(lay_nor, b"NormalsIndex", t_normal_idx)
|
elem_data_single_int32_array(lay_nor, b"NormalsIndex", t_normal_idx)
|
||||||
|
|
||||||
del t_normal_idx
|
del t_normal_idx
|
||||||
# del t_normal_w
|
# 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
|
del t_normal
|
||||||
|
|
||||||
# tspace
|
# tspace
|
||||||
|
@ -1392,7 +1392,18 @@ def blen_read_geom_array_mapped_vert(
|
|||||||
xform=None, quiet=False,
|
xform=None, quiet=False,
|
||||||
):
|
):
|
||||||
if fbx_layer_mapping == b'ByVertice':
|
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)
|
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,
|
blen_read_geom_array_foreach_set_direct(blen_data, blen_attr, blen_dtype, fbx_layer_data, stride, item_size,
|
||||||
descr, xform)
|
descr, xform)
|
||||||
@ -1748,8 +1759,6 @@ def blen_read_geom_layer_normal(fbx_obj, mesh, xform=None):
|
|||||||
loop_normals = np.repeat(bdata, poly_loop_totals, axis=0)
|
loop_normals = np.repeat(bdata, poly_loop_totals, axis=0)
|
||||||
mesh.attributes["temp_custom_normals"].data.foreach_set("vector", loop_normals.ravel())
|
mesh.attributes["temp_custom_normals"].data.foreach_set("vector", loop_normals.ravel())
|
||||||
elif blen_data_type == "Vertices":
|
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.
|
# We have to copy vnors to lnors! Far from elegant, but simple.
|
||||||
loop_vertex_indices = MESH_ATTRIBUTE_CORNER_VERT.to_ndarray(mesh.attributes)
|
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())
|
mesh.attributes["temp_custom_normals"].data.foreach_set("vector", bdata[loop_vertex_indices].ravel())
|
||||||
|
Loading…
Reference in New Issue
Block a user