glTF importer/exporter: fix for material_index/material slots

This commit is contained in:
Julien Duroure 2020-10-08 20:25:22 +02:00
parent 6cef5e013e
commit 77aada8057
4 changed files with 38 additions and 31 deletions

View File

@ -15,7 +15,7 @@
bl_info = {
'name': 'glTF 2.0 format',
'author': 'Julien Duroure, Scurest, Norbert Nopper, Urs Hanselmann, Moritz Becher, Benjamin Schmithüsen, Jim Eckerlein, and many external contributors',
"version": (1, 4, 34),
"version": (1, 4, 35),
'blender': (2, 91, 0),
'location': 'File > Import-Export',
'description': 'Import-Export as glTF 2.0',

View File

@ -294,7 +294,8 @@ def __gather_mesh(blender_object, library, export_settings):
vertex_groups = None # Not needed if no armature, avoid a cache miss
modifiers = None
material_names = tuple([ms.material.name for ms in blender_object.material_slots if ms.material is not None])
materials = tuple(ms.material for ms in blender_object.material_slots)
material_names = tuple(None if mat is None else mat.name for mat in materials)
# retrieve armature
# Because mesh data will be transforms to skeleton space,

View File

@ -55,14 +55,17 @@ def gather_primitives(
material = None
if export_settings['gltf_materials'] == "EXPORT":
try:
blender_material = bpy.data.materials[material_names[material_idx]]
material = gltf2_blender_gather_materials.gather_material(blender_material,
export_settings)
except IndexError:
# no material at that index
pass
blender_material = None
if material_names:
i = material_idx if material_idx < len(material_names) else -1
material_name = material_names[i]
if material_name is not None:
blender_material = bpy.data.materials[material_name]
if blender_material is not None:
material = gltf2_blender_gather_materials.gather_material(
blender_material,
export_settings,
)
primitive = gltf2_io.MeshPrimitive(
attributes=internal_primitive['attributes'],

View File

@ -320,33 +320,36 @@ def do_primitives(gltf, mesh_idx, skin_idx, mesh, ob):
# ----
# Assign materials to faces
has_materials = any(prim.material is not None for prim in pymesh.primitives)
if has_materials:
material_indices = np.empty(num_faces, dtype=np.uint32)
empty_material_slot_index = None
f = 0
# Initialize to no-material, ie. an index guaranteed to be OOB for the
# material slots. A mesh obviously can't have more materials than it has
# primitives...
oob_material_idx = len(pymesh.primitives)
material_indices = np.full(num_faces, oob_material_idx)
for prim in pymesh.primitives:
if prim.material is not None:
# Get the material
pymaterial = gltf.data.materials[prim.material]
vertex_color = 'COLOR_0' if 'COLOR_0' in prim.attributes else None
if vertex_color not in pymaterial.blender_material:
BlenderMaterial.create(gltf, prim.material, vertex_color)
material_name = pymaterial.blender_material[vertex_color]
f = 0
for prim in pymesh.primitives:
if prim.material is not None:
# Get the material
pymaterial = gltf.data.materials[prim.material]
vertex_color = 'COLOR_0' if 'COLOR_0' in prim.attributes else None
if vertex_color not in pymaterial.blender_material:
BlenderMaterial.create(gltf, prim.material, vertex_color)
material_name = pymaterial.blender_material[vertex_color]
# Put material in slot (if not there)
if material_name not in mesh.materials:
mesh.materials.append(bpy.data.materials[material_name])
material_index = mesh.materials.find(material_name)
# Put material in slot (if not there)
if material_name not in mesh.materials:
mesh.materials.append(bpy.data.materials[material_name])
material_index = mesh.materials.find(material_name)
else:
if empty_material_slot_index is None:
mesh.materials.append(None)
empty_material_slot_index = len(mesh.materials) - 1
material_index = empty_material_slot_index
material_indices[f:f + prim.num_faces].fill(material_index)
f += prim.num_faces
f += prim.num_faces
mesh.polygons.foreach_set('material_index', material_indices)
mesh.polygons.foreach_set('material_index', material_indices)
# ----
# Normals