FBX IO: Material index access with attributes #104646
@ -1423,11 +1423,13 @@ def fbx_data_mesh_elements(root, me_obj, scene_data, done_meshes):
|
|||||||
elem_data_single_int32(lay_ma, b"Version", FBX_GEOMETRY_MATERIAL_VERSION)
|
elem_data_single_int32(lay_ma, b"Version", FBX_GEOMETRY_MATERIAL_VERSION)
|
||||||
elem_data_single_string(lay_ma, b"Name", b"")
|
elem_data_single_string(lay_ma, b"Name", b"")
|
||||||
nbr_mats = len(me_fbxmaterials_idx)
|
nbr_mats = len(me_fbxmaterials_idx)
|
||||||
if nbr_mats > 1:
|
multiple_fbx_mats = nbr_mats > 1
|
||||||
bl_pm_dtype = np.uintc
|
# If a mesh does not have more than one material its material_index attribute can be ignored.
|
||||||
|
# If a mesh has multiple materials but all its polygons are assigned to the first material, its
|
||||||
|
# material_index attribute may not exist.
|
||||||
|
t_pm = None if not multiple_fbx_mats else MESH_ATTRIBUTE_MATERIAL_INDEX.get_ndarray(attributes)
|
||||||
|
if t_pm is not None:
|
||||||
fbx_pm_dtype = np.int32
|
fbx_pm_dtype = np.int32
|
||||||
t_pm = np.empty(len(me.polygons), dtype=bl_pm_dtype)
|
|
||||||
me.polygons.foreach_get("material_index", t_pm)
|
|
||||||
|
|
||||||
# We have to validate mat indices, and map them to FBX indices.
|
# We have to validate mat indices, and map them to FBX indices.
|
||||||
# Note a mat might not be in me_fbxmaterials_idx (e.g. node mats are ignored).
|
# Note a mat might not be in me_fbxmaterials_idx (e.g. node mats are ignored).
|
||||||
@ -1439,7 +1441,10 @@ def fbx_data_mesh_elements(root, me_obj, scene_data, done_meshes):
|
|||||||
|
|
||||||
# Set material indices that are out of bounds to the default material index
|
# Set material indices that are out of bounds to the default material index
|
||||||
mat_idx_limit = len(me_blmaterials)
|
mat_idx_limit = len(me_blmaterials)
|
||||||
t_pm[t_pm >= mat_idx_limit] = def_me_blmaterial_idx
|
# Material indices shouldn't be negative, but they technically could be. Viewing as unsigned before
|
||||||
|
# checking for indices that are too large means that a single >= check will pick up both negative
|
||||||
|
# indices and indices that are too large.
|
||||||
|
t_pm[t_pm.view("u%i" % t_pm.itemsize) >= mat_idx_limit] = def_me_blmaterial_idx
|
||||||
|
|
||||||
# Map to FBX indices. Materials not in me_fbxmaterials_idx will be set to the default material index.
|
# Map to FBX indices. Materials not in me_fbxmaterials_idx will be set to the default material index.
|
||||||
blmat_fbx_idx = np.fromiter((me_fbxmaterials_idx.get(m, def_ma) for m in me_blmaterials),
|
blmat_fbx_idx = np.fromiter((me_fbxmaterials_idx.get(m, def_ma) for m in me_blmaterials),
|
||||||
@ -1453,11 +1458,18 @@ def fbx_data_mesh_elements(root, me_obj, scene_data, done_meshes):
|
|||||||
# indices??? *sigh*).
|
# indices??? *sigh*).
|
||||||
elem_data_single_string(lay_ma, b"ReferenceInformationType", b"IndexToDirect")
|
elem_data_single_string(lay_ma, b"ReferenceInformationType", b"IndexToDirect")
|
||||||
elem_data_single_int32_array(lay_ma, b"Materials", t_pm)
|
elem_data_single_int32_array(lay_ma, b"Materials", t_pm)
|
||||||
del t_pm
|
|
||||||
else:
|
else:
|
||||||
elem_data_single_string(lay_ma, b"MappingInformationType", b"AllSame")
|
elem_data_single_string(lay_ma, b"MappingInformationType", b"AllSame")
|
||||||
elem_data_single_string(lay_ma, b"ReferenceInformationType", b"IndexToDirect")
|
elem_data_single_string(lay_ma, b"ReferenceInformationType", b"IndexToDirect")
|
||||||
elem_data_single_int32_array(lay_ma, b"Materials", [0])
|
if multiple_fbx_mats:
|
||||||
|
# There's no material_index attribute, so every material index is effectively zero.
|
||||||
|
# In the order of the mesh's materials, get the FBX index of the first material that is exported.
|
||||||
|
all_same_idx = next(me_fbxmaterials_idx[m] for m in me_blmaterials if m in me_fbxmaterials_idx)
|
||||||
|
else:
|
||||||
|
# There's only one fbx material, so the index will always be zero.
|
||||||
|
all_same_idx = 0
|
||||||
|
elem_data_single_int32_array(lay_ma, b"Materials", [all_same_idx])
|
||||||
|
del t_pm
|
||||||
|
|
||||||
# And the "layer TOC"...
|
# And the "layer TOC"...
|
||||||
|
|
||||||
|
@ -1205,12 +1205,14 @@ def blen_read_geom_layer_material(fbx_obj, mesh):
|
|||||||
layer_id = b'Materials'
|
layer_id = b'Materials'
|
||||||
fbx_layer_data = elem_prop_first(elem_find_first(fbx_layer, layer_id))
|
fbx_layer_data = elem_prop_first(elem_find_first(fbx_layer, layer_id))
|
||||||
|
|
||||||
blen_data = mesh.polygons
|
blen_data = MESH_ATTRIBUTE_MATERIAL_INDEX.ensure(mesh.attributes).data
|
||||||
|
fbx_item_size = 1
|
||||||
|
assert(fbx_item_size == MESH_ATTRIBUTE_MATERIAL_INDEX.item_size)
|
||||||
blen_read_geom_array_mapped_polygon(
|
blen_read_geom_array_mapped_polygon(
|
||||||
mesh, blen_data, "material_index", np.uintc,
|
mesh, blen_data, MESH_ATTRIBUTE_MATERIAL_INDEX.foreach_attribute, MESH_ATTRIBUTE_MATERIAL_INDEX.dtype,
|
||||||
fbx_layer_data, None,
|
fbx_layer_data, None,
|
||||||
fbx_layer_mapping, fbx_layer_ref,
|
fbx_layer_mapping, fbx_layer_ref,
|
||||||
1, 1, layer_id,
|
1, fbx_item_size, layer_id,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user