glTF importer: fix material import / vertex color

Fixed a bug when a same material sometimes uses vertex color, sometimes doesn't
This commit is contained in:
Julien Duroure 2018-12-15 06:30:27 +01:00
parent b55002b7c3
commit 6d933c0e3a
7 changed files with 57 additions and 38 deletions

View File

@ -84,7 +84,7 @@ class BlenderGlTF():
# Blender material
if gltf.data.materials:
for material in gltf.data.materials:
material.blender_material = None
material.blender_material = {}
if material.pbr_metallic_roughness:
# Init

View File

@ -23,17 +23,17 @@ class BlenderEmissiveMap():
raise RuntimeError("%s should not be instantiated" % cls)
@staticmethod
def create(gltf, material_idx):
def create(gltf, material_idx, vertex_color):
"""Create emissive map."""
engine = bpy.context.scene.render.engine
if engine in ['CYCLES', 'BLENDER_EEVEE']:
BlenderEmissiveMap.create_nodetree(gltf, material_idx)
BlenderEmissiveMap.create_nodetree(gltf, material_idx, vertex_color)
def create_nodetree(gltf, material_idx):
def create_nodetree(gltf, material_idx, vertex_color):
"""Create node tree."""
pymaterial = gltf.data.materials[material_idx]
material = bpy.data.materials[pymaterial.blender_material]
material = bpy.data.materials[pymaterial.blender_material[vertex_color]]
node_tree = material.node_tree
BlenderTextureInfo.create(gltf, pymaterial.emissive_texture.index)

View File

@ -22,17 +22,17 @@ class BlenderNormalMap():
raise RuntimeError("%s should not be instantiated" % cls)
@staticmethod
def create(gltf, material_idx):
def create(gltf, material_idx, vertex_color):
"""Creation of Normal map."""
engine = bpy.context.scene.render.engine
if engine in ['CYCLES', 'BLENDER_EEVEE']:
BlenderNormalMap.create_nodetree(gltf, material_idx)
BlenderNormalMap.create_nodetree(gltf, material_idx, vertex_color)
def create_nodetree(gltf, material_idx):
def create_nodetree(gltf, material_idx, vertex_color):
"""Creation of Nodetree."""
pymaterial = gltf.data.materials[material_idx]
material = bpy.data.materials[pymaterial.blender_material]
material = bpy.data.materials[pymaterial.blender_material[vertex_color]]
node_tree = material.node_tree
BlenderTextureInfo.create(gltf, pymaterial.normal_texture.index)

View File

@ -22,13 +22,13 @@ class BlenderOcclusionMap():
raise RuntimeError("%s should not be instantiated" % cls)
@staticmethod
def create(gltf, material_idx):
def create(gltf, material_idx, vertex_color):
"""Occlusion map creation."""
engine = bpy.context.scene.render.engine
if engine in ['CYCLES', 'BLENDER_EEVEE']:
BlenderOcclusionMap.create_nodetree(gltf, material_idx)
BlenderOcclusionMap.create_nodetree(gltf, material_idx, vertex_color)
def create_nodetree(gltf, material_idx):
def create_nodetree(gltf, material_idx, vertex_color):
"""Nodetree creation."""
pymaterial = gltf.data.materials[material_idx]

View File

@ -34,13 +34,19 @@ class BlenderMaterial():
"""Material creation."""
pymaterial = gltf.data.materials[material_idx]
if pymaterial.name is not None:
name = pymaterial.name
if vertex_color is None:
if pymaterial.name is not None:
name = pymaterial.name
else:
name = "Material_" + str(material_idx)
else:
name = "Material_" + str(material_idx)
if pymaterial.name is not None:
name = pymaterial.name + "_" + vertex_color
else:
name = "Material_" + str(material_idx) + "_" + vertex_color
mat = bpy.data.materials.new(name)
pymaterial.blender_material = mat.name
pymaterial.blender_material[vertex_color] = mat.name
if pymaterial.extensions is not None and 'KHR_materials_pbrSpecularGlossiness' in pymaterial.extensions.keys():
BlenderKHR_materials_pbrSpecularGlossiness.create(
@ -62,36 +68,36 @@ class BlenderMaterial():
# add emission map if needed
if pymaterial.emissive_texture is not None:
BlenderEmissiveMap.create(gltf, material_idx)
BlenderEmissiveMap.create(gltf, material_idx, vertex_color)
# add normal map if needed
if pymaterial.normal_texture is not None:
BlenderNormalMap.create(gltf, material_idx)
BlenderNormalMap.create(gltf, material_idx, vertex_color)
# add occlusion map if needed
# will be pack, but not used
if pymaterial.occlusion_texture is not None:
BlenderOcclusionMap.create(gltf, material_idx)
BlenderOcclusionMap.create(gltf, material_idx, vertex_color)
if pymaterial.alpha_mode is not None and pymaterial.alpha_mode != 'OPAQUE':
BlenderMaterial.blender_alpha(gltf, material_idx)
BlenderMaterial.blender_alpha(gltf, material_idx, vertex_color)
@staticmethod
def set_uvmap(gltf, material_idx, prim, obj):
def set_uvmap(gltf, material_idx, prim, obj, vertex_color):
"""Set UV Map."""
pymaterial = gltf.data.materials[material_idx]
node_tree = bpy.data.materials[pymaterial.blender_material].node_tree
node_tree = bpy.data.materials[pymaterial.blender_material[vertex_color]].node_tree
uvmap_nodes = [node for node in node_tree.nodes if node.type in ['UVMAP', 'NORMAL_MAP']]
for uvmap_node in uvmap_nodes:
if uvmap_node["gltf2_texcoord"] in prim.blender_texcoord.keys():
uvmap_node.uv_map = prim.blender_texcoord[uvmap_node["gltf2_texcoord"]]
@staticmethod
def blender_alpha(gltf, material_idx):
def blender_alpha(gltf, material_idx, vertex_color):
"""Set alpha."""
pymaterial = gltf.data.materials[material_idx]
material = bpy.data.materials[pymaterial.blender_material]
material = bpy.data.materials[pymaterial.blender_material[vertex_color]]
node_tree = material.node_tree
# Add nodes for basic transparency

View File

@ -79,7 +79,10 @@ class BlenderMesh():
# Object and UV are now created, we can set UVMap into material
for prim in pymesh.primitives:
BlenderPrimitive.set_UV_in_mat(gltf, prim, obj)
vertex_color = None
if 'COLOR_0' in prim.attributes.keys():
vertex_color = 'COLOR_0'
BlenderPrimitive.set_UV_in_mat(gltf, prim, obj, vertex_color)
# Assign materials to mesh
offset = 0

View File

@ -57,13 +57,18 @@ class BlenderPrimitive():
# manage material of primitive
if pyprimitive.material is not None:
# Create Blender material
# TODO, a same material can have difference COLOR_0 multiplicator
if gltf.data.materials[pyprimitive.material].blender_material is None:
vertex_color = None
if 'COLOR_0' in pyprimitive.attributes.keys():
vertex_color = pyprimitive.attributes['COLOR_0']
BlenderMaterial.create(gltf, pyprimitive.material, vertex_color)
vertex_color = None
if 'COLOR_0' in pyprimitive.attributes.keys():
vertex_color = 'COLOR_0'
# Create Blender material if needed
if vertex_color is None:
if None not in gltf.data.materials[pyprimitive.material].blender_material.keys():
BlenderMaterial.create(gltf, pyprimitive.material, vertex_color)
else:
if vertex_color not in gltf.data.materials[pyprimitive.material].blender_material.keys():
BlenderMaterial.create(gltf, pyprimitive.material, vertex_color)
return verts, edges, faces
@ -126,7 +131,7 @@ class BlenderPrimitive():
offset = offset + pyprimitive.vertices_length
return offset
def set_UV_in_mat(gltf, pyprimitive, obj):
def set_UV_in_mat(gltf, pyprimitive, obj, vertex_color):
"""After nodetree creation, set UVMap in nodes."""
if pyprimitive.material is None:
return
@ -137,29 +142,34 @@ class BlenderPrimitive():
and gltf.data.materials[pyprimitive.material].extensions[
'KHR_materials_pbrSpecularGlossiness'
]['diffuse_type'] in [gltf.TEXTURE, gltf.TEXTURE_FACTOR]:
BlenderMaterial.set_uvmap(gltf, pyprimitive.material, pyprimitive, obj)
BlenderMaterial.set_uvmap(gltf, pyprimitive.material, pyprimitive, obj, vertex_color)
else:
if pyprimitive.material is not None \
and gltf.data.materials[pyprimitive.material].extensions[
'KHR_materials_pbrSpecularGlossiness'
]['specgloss_type'] in [gltf.TEXTURE, gltf.TEXTURE_FACTOR]:
BlenderMaterial.set_uvmap(gltf, pyprimitive.material, pyprimitive, obj)
BlenderMaterial.set_uvmap(gltf, pyprimitive.material, pyprimitive, obj, vertex_color)
else:
if pyprimitive.material is not None \
and gltf.data.materials[pyprimitive.material].pbr_metallic_roughness.color_type in \
[gltf.TEXTURE, gltf.TEXTURE_FACTOR]:
BlenderMaterial.set_uvmap(gltf, pyprimitive.material, pyprimitive, obj)
BlenderMaterial.set_uvmap(gltf, pyprimitive.material, pyprimitive, obj, vertex_color)
else:
if pyprimitive.material is not None \
and gltf.data.materials[pyprimitive.material].pbr_metallic_roughness.metallic_type in \
[gltf.TEXTURE, gltf.TEXTURE_FACTOR]:
BlenderMaterial.set_uvmap(gltf, pyprimitive.material, pyprimitive, obj)
BlenderMaterial.set_uvmap(gltf, pyprimitive.material, pyprimitive, obj, vertex_color)
def assign_material(gltf, pyprimitive, obj, bm, offset, cpt_index_mat):
"""Assign material to faces of primitives."""
if pyprimitive.material is not None:
obj.data.materials.append(bpy.data.materials[gltf.data.materials[pyprimitive.material].blender_material])
vertex_color = None
if 'COLOR_0' in pyprimitive.attributes.keys():
vertex_color = 'COLOR_0'
obj.data.materials.append(bpy.data.materials[gltf.data.materials[pyprimitive.material].blender_material[vertex_color]])
for vert in bm.verts:
if vert.index in range(offset, offset + pyprimitive.vertices_length):
for loop in vert.link_loops: