diff options
author | Julien Duroure <julien.duroure@gmail.com> | 2019-06-06 22:25:29 +0300 |
---|---|---|
committer | Julien Duroure <julien.duroure@gmail.com> | 2019-06-06 22:25:29 +0300 |
commit | 42493a36ed9b712e46965a30480f59af65a64b83 (patch) | |
tree | 163d7f9ad39a56fb63c797f163df8b4754797a68 | |
parent | ae500d28913b17248653f79842d038c75b353e86 (diff) |
glTF exporter: Manage material at object level: instances with different colors
5 files changed, 94 insertions, 52 deletions
diff --git a/io_scene_gltf2/__init__.py b/io_scene_gltf2/__init__.py index ba8b750e..ce044ab1 100755 --- a/io_scene_gltf2/__init__.py +++ b/io_scene_gltf2/__init__.py @@ -15,7 +15,7 @@ bl_info = { 'name': 'glTF 2.0 format', 'author': 'Julien Duroure, Norbert Nopper, Urs Hanselmann, Moritz Becher, Benjamin Schmithüsen, Jim Eckerlein, and many external contributors', - "version": (0, 9, 23), + "version": (0, 9, 24), 'blender': (2, 80, 0), 'location': 'File > Import-Export', 'description': 'Import-Export as glTF 2.0', diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_extract.py b/io_scene_gltf2/blender/exp/gltf2_blender_extract.py index 4c6d2555..b48b76ea 100755 --- a/io_scene_gltf2/blender/exp/gltf2_blender_extract.py +++ b/io_scene_gltf2/blender/exp/gltf2_blender_extract.py @@ -423,26 +423,23 @@ def extract_primitives(glTF, blender_mesh, blender_vertex_groups, modifiers, exp # Directory of materials with its primitive. # no_material_primitives = { - MATERIAL_ID: '', + MATERIAL_ID: 0, INDICES_ID: [], ATTRIBUTES_ID: no_material_attributes } - material_name_to_primitives = {'': no_material_primitives} + material_idx_to_primitives = {0: no_material_primitives} # vertex_index_to_new_indices = {} - material_map[''] = vertex_index_to_new_indices + material_map[0] = vertex_index_to_new_indices # # Create primitive for each material. # - for blender_material in blender_mesh.materials: - if blender_material is None: - continue - + for (mat_idx, _) in enumerate(blender_mesh.materials): attributes = { POSITION_ATTRIBUTE: [], NORMAL_ATTRIBUTE: [] @@ -452,18 +449,18 @@ def extract_primitives(glTF, blender_mesh, blender_vertex_groups, modifiers, exp attributes[TANGENT_ATTRIBUTE] = [] primitive = { - MATERIAL_ID: blender_material.name, + MATERIAL_ID: mat_idx, INDICES_ID: [], ATTRIBUTES_ID: attributes } - material_name_to_primitives[blender_material.name] = primitive + material_idx_to_primitives[mat_idx] = primitive # vertex_index_to_new_indices = {} - material_map[blender_material.name] = vertex_index_to_new_indices + material_map[mat_idx] = vertex_index_to_new_indices tex_coord_max = 0 if blender_mesh.uv_layers.active: @@ -519,13 +516,12 @@ def extract_primitives(glTF, blender_mesh, blender_vertex_groups, modifiers, exp # - if blender_polygon.material_index < 0 or blender_polygon.material_index >= len(blender_mesh.materials) or \ - blender_mesh.materials[blender_polygon.material_index] is None: - primitive = material_name_to_primitives[''] - vertex_index_to_new_indices = material_map[''] + if not blender_polygon.material_index in material_idx_to_primitives: + primitive = material_idx_to_primitives[0] + vertex_index_to_new_indices = material_map[0] else: - primitive = material_name_to_primitives[blender_mesh.materials[blender_polygon.material_index].name] - vertex_index_to_new_indices = material_map[blender_mesh.materials[blender_polygon.material_index].name] + primitive = material_idx_to_primitives[blender_polygon.material_index] + vertex_index_to_new_indices = material_map[blender_polygon.material_index] # attributes = primitive[ATTRIBUTES_ID] @@ -920,7 +916,7 @@ def extract_primitives(glTF, blender_mesh, blender_vertex_groups, modifiers, exp result_primitives = [] - for material_name, primitive in material_name_to_primitives.items(): + for material_idx, primitive in material_idx_to_primitives.items(): export_color = True # @@ -993,7 +989,7 @@ def extract_primitives(glTF, blender_mesh, blender_vertex_groups, modifiers, exp pending_attributes[TANGENT_ATTRIBUTE] = [] pending_primitive = { - MATERIAL_ID: material_name, + MATERIAL_ID: material_idx, INDICES_ID: [], ATTRIBUTES_ID: pending_attributes } diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_mesh.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_mesh.py index 7e24319f..c2202b9e 100755 --- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_mesh.py +++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_mesh.py @@ -13,7 +13,7 @@ # limitations under the License. import bpy -from typing import Optional, Dict, List, Any +from typing import Optional, Dict, List, Any, Tuple from .gltf2_blender_export_keys import MORPH from io_scene_gltf2.blender.exp.gltf2_blender_gather_cache import cached from io_scene_gltf2.io.com import gltf2_io @@ -23,21 +23,22 @@ from io_scene_gltf2.io.com.gltf2_io_debug import print_console @cached -def gather_mesh(blender_mesh: bpy.types.Mesh, +def gather_mesh(blender_mesh_name: str, vertex_groups: Optional[bpy.types.VertexGroups], modifiers: Optional[bpy.types.ObjectModifiers], skip_filter: bool, + material_names: Tuple[str], export_settings ) -> Optional[gltf2_io.Mesh]: - if not skip_filter and not __filter_mesh(blender_mesh, vertex_groups, modifiers, export_settings): + if not skip_filter and not __filter_mesh(blender_mesh_name, vertex_groups, modifiers, export_settings): return None mesh = gltf2_io.Mesh( - extensions=__gather_extensions(blender_mesh, vertex_groups, modifiers, export_settings), - extras=__gather_extras(blender_mesh, vertex_groups, modifiers, export_settings), - name=__gather_name(blender_mesh, vertex_groups, modifiers, export_settings), - primitives=__gather_primitives(blender_mesh, vertex_groups, modifiers, export_settings), - weights=__gather_weights(blender_mesh, vertex_groups, modifiers, export_settings) + extensions=__gather_extensions(blender_mesh_name, vertex_groups, modifiers, export_settings), + extras=__gather_extras(blender_mesh_name, vertex_groups, modifiers, export_settings), + name=__gather_name(blender_mesh_name, vertex_groups, modifiers, export_settings), + primitives=__gather_primitives(blender_mesh_name, vertex_groups, modifiers, material_names, export_settings), + weights=__gather_weights(blender_mesh_name, vertex_groups, modifiers, export_settings) ) if len(mesh.primitives) == 0: @@ -46,17 +47,18 @@ def gather_mesh(blender_mesh: bpy.types.Mesh, return mesh -def __filter_mesh(blender_mesh: bpy.types.Mesh, +def __filter_mesh(blender_mesh_name: str, vertex_groups: Optional[bpy.types.VertexGroups], modifiers: Optional[bpy.types.ObjectModifiers], export_settings ) -> bool: + blender_mesh = bpy.data.meshes[blender_mesh_name] if blender_mesh.users == 0: return False return True -def __gather_extensions(blender_mesh: bpy.types.Mesh, +def __gather_extensions(blender_mesh_name: str, vertex_groups: Optional[bpy.types.VertexGroups], modifiers: Optional[bpy.types.ObjectModifiers], export_settings @@ -64,11 +66,12 @@ def __gather_extensions(blender_mesh: bpy.types.Mesh, return None -def __gather_extras(blender_mesh: bpy.types.Mesh, +def __gather_extras(blender_mesh_name: str, vertex_groups: Optional[bpy.types.VertexGroups], modifiers: Optional[bpy.types.ObjectModifiers], export_settings ) -> Optional[Dict[Any, Any]]: + blender_mesh = bpy.data.meshes[blender_mesh_name] extras = {} if export_settings['gltf_extras']: @@ -89,28 +92,33 @@ def __gather_extras(blender_mesh: bpy.types.Mesh, return None -def __gather_name(blender_mesh: bpy.types.Mesh, +def __gather_name(blender_mesh_name: str, vertex_groups: Optional[bpy.types.VertexGroups], modifiers: Optional[bpy.types.ObjectModifiers], export_settings ) -> str: - return blender_mesh.name + return blender_mesh_name -def __gather_primitives(blender_mesh: bpy.types.Mesh, +def __gather_primitives(blender_mesh_name: str, vertex_groups: Optional[bpy.types.VertexGroups], modifiers: Optional[bpy.types.ObjectModifiers], + material_names: Tuple[str], export_settings ) -> List[gltf2_io.MeshPrimitive]: - return gltf2_blender_gather_primitives.gather_primitives(blender_mesh, vertex_groups, modifiers, export_settings) + return gltf2_blender_gather_primitives.gather_primitives(blender_mesh_name, + vertex_groups, + modifiers, + material_names, + export_settings) -def __gather_weights(blender_mesh: bpy.types.Mesh, +def __gather_weights(blender_mesh_name: str, vertex_groups: Optional[bpy.types.VertexGroups], modifiers: Optional[bpy.types.ObjectModifiers], export_settings ) -> Optional[List[float]]: - + blender_mesh = bpy.data.meshes[blender_mesh_name] if not export_settings[MORPH] or not blender_mesh.shape_keys: return None diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_nodes.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_nodes.py index 4af4f043..ba303c42 100755 --- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_nodes.py +++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_nodes.py @@ -241,7 +241,13 @@ def __gather_mesh(blender_object, export_settings): blender_mesh = blender_object.data skip_filter = False - result = gltf2_blender_gather_mesh.gather_mesh(blender_mesh, vertex_groups, modifiers, skip_filter, export_settings) + material_names = tuple([ms.material.name for ms in blender_object.material_slots]) + result = gltf2_blender_gather_mesh.gather_mesh(blender_mesh.name, + vertex_groups, + modifiers, + skip_filter, + material_names, + export_settings) if export_settings[gltf2_blender_export_keys.APPLY]: blender_mesh_owner.to_mesh_clear() diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives.py index e7c21276..403ca5eb 100755 --- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives.py +++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives.py @@ -13,7 +13,7 @@ # limitations under the License. import bpy -from typing import List, Optional +from typing import List, Optional, Tuple from .gltf2_blender_export_keys import NORMALS, MORPH_NORMAL, TANGENTS, MORPH_TANGENT, MORPH @@ -32,9 +32,10 @@ from io_scene_gltf2.io.com.gltf2_io_debug import print_console @cached def gather_primitives( - blender_mesh: bpy.types.Mesh, + blender_mesh_name: str, vertex_groups: Optional[bpy.types.VertexGroups], modifiers: Optional[bpy.types.ObjectModifiers], + material_names: Tuple[str], export_settings ) -> List[gltf2_io.MeshPrimitive]: """ @@ -43,33 +44,64 @@ def gather_primitives( :return: a list of glTF2 primitives """ primitives = [] - blender_primitives = gltf2_blender_extract.extract_primitives( - None, blender_mesh, vertex_groups, modifiers, export_settings) + + blender_primitives = __gather_cache_primitives(blender_mesh_name, + vertex_groups, modifiers, export_settings) for internal_primitive in blender_primitives: + material_idx = internal_primitive['material'] + double_sided = False + material = None + try: + blender_material = bpy.data.materials[material_names[material_idx]] + double_sided = not blender_material.use_backface_culling + material = gltf2_blender_gather_materials.gather_material(blender_material, + double_sided, + export_settings) + except IndexError: + # no material at that index + pass + primitive = gltf2_io.MeshPrimitive( - attributes=__gather_attributes(internal_primitive, blender_mesh, modifiers, export_settings), + attributes=internal_primitive['attributes'], extensions=None, extras=None, - indices=__gather_indices(internal_primitive, blender_mesh, modifiers, export_settings), - material=__gather_materials(internal_primitive, modifiers, export_settings), + indices=internal_primitive['indices'], + material=material, mode=None, - targets=__gather_targets(internal_primitive, blender_mesh, modifiers, export_settings) + targets=internal_primitive['targets'] ) primitives.append(primitive) return primitives +@cached +def __gather_cache_primitives( + blender_mesh_name: str, + vertex_groups: Optional[bpy.types.VertexGroups], + modifiers: Optional[bpy.types.ObjectModifiers], + export_settings +) -> List[dict]: + """ + Gather parts that are identical for instances, i.e. excluding materials + """ + blender_mesh = bpy.data.meshes[blender_mesh_name] + primitives = [] + + blender_primitives = gltf2_blender_extract.extract_primitives( + None, blender_mesh, vertex_groups, modifiers, export_settings) -def __gather_materials(blender_primitive, modifiers, export_settings): - if not blender_primitive['material']: - # TODO: fix 'extract_primitives' so that the value of 'material' is None and not empty string - return None - material = bpy.data.materials[blender_primitive['material']] - material_double_sided = not material.use_backface_culling - return gltf2_blender_gather_materials.gather_material(material, material_double_sided, export_settings) + for internal_primitive in blender_primitives: + primitive = { + "attributes": __gather_attributes(internal_primitive, blender_mesh, modifiers, export_settings), + "indices": __gather_indices(internal_primitive, blender_mesh, modifiers, export_settings), + "material": internal_primitive['material'], + "targets": __gather_targets(internal_primitive, blender_mesh, modifiers, export_settings) + } + primitives.append(primitive) + return primitives def __gather_indices(blender_primitive, blender_mesh, modifiers, export_settings): indices = blender_primitive['indices'] |