Browse Source

Merge pull request #6503 from repsac/6468

Blender exporter: parsing of face materials should ignore unused materials
Ricardo Cabello 10 years ago
parent
commit
b61e3bd74a

+ 1 - 0
utils/exporters/blender/addons/io_three/exceptions.py

@@ -3,6 +3,7 @@ class UnimplementedFeatureError(ThreeError): pass
 class ThreeValueError(ThreeError): pass
 class ThreeValueError(ThreeError): pass
 class UnsupportedObjectType(ThreeError): pass
 class UnsupportedObjectType(ThreeError): pass
 class GeometryError(ThreeError): pass
 class GeometryError(ThreeError): pass
+class MaterialError(ThreeError): pass
 class SelectionError(ThreeError): pass
 class SelectionError(ThreeError): pass
 class NGonError(ThreeError): pass
 class NGonError(ThreeError): pass
 class BufferGeometryError(ThreeError): pass
 class BufferGeometryError(ThreeError): pass

+ 20 - 4
utils/exporters/blender/addons/io_three/exporter/api/mesh.py

@@ -178,14 +178,18 @@ def buffer_uv(mesh):
 
 
 
 
 @_mesh
 @_mesh
-def faces(mesh, options):
+def faces(mesh, options, materials=None):
     """
     """
 
 
     :param mesh:
     :param mesh:
     :param options:
     :param options:
+    :param materials: (Default value = None)
 
 
     """
     """
-    logger.debug("mesh.faces(%s, %s)", mesh, options)
+    logger.debug("mesh.faces(%s, %s, materials=%s)",
+                 mesh, options, materials)
+
+    materials = materials or []
     vertex_uv = len(mesh.uv_textures) > 0
     vertex_uv = len(mesh.uv_textures) > 0
     has_colors = len(mesh.vertex_colors) > 0
     has_colors = len(mesh.vertex_colors) > 0
     logger.info("Has UVs = %s", vertex_uv)
     logger.info("Has UVs = %s", vertex_uv)
@@ -242,7 +246,14 @@ def faces(mesh, options):
         face_data.extend([v for v in face.vertices])
         face_data.extend([v for v in face.vertices])
 
 
         if mask[constants.MATERIALS]:
         if mask[constants.MATERIALS]:
-            face_data.append(face.material_index)
+            for mat_index, mat in enumerate(materials):
+                if mat[constants.DBG_INDEX] == face.material_index:
+                    face_data.append(mat_index)
+                    break
+            else:
+                error = ("Could not map the material index "
+                         "for face %d" % face.index)
+                raise exceptions.MaterialError(error)
 
 
         # @TODO: this needs the same optimization as what
         # @TODO: this needs the same optimization as what
         #        was done for colours and normals
         #        was done for colours and normals
@@ -339,7 +350,12 @@ def materials(mesh, options):
 
 
     """
     """
     logger.debug("mesh.materials(%s, %s)", mesh, options)
     logger.debug("mesh.materials(%s, %s)", mesh, options)
-    indices = set([face.material_index for face in mesh.tessfaces])
+
+    indices = []
+    for face in mesh.tessfaces:
+        if face.material_index not in indices:
+            indices.append(face.material_index)
+
     material_sets = [(mesh.materials[index], index) for index in indices]
     material_sets = [(mesh.materials[index], index) for index in indices]
     materials_ = []
     materials_ = []
 
 

+ 18 - 9
utils/exporters/blender/addons/io_three/exporter/geometry.py

@@ -15,8 +15,8 @@ class Geometry(base_classes.BaseNode):
     def __init__(self, node, parent=None):
     def __init__(self, node, parent=None):
         logger.debug("Geometry().__init__(%s)", node)
         logger.debug("Geometry().__init__(%s)", node)
 
 
-        #@TODO: maybe better to have `three` constants for
-        #       strings that are specific to `three` properties
+#       @TODO: maybe better to have `three` constants for
+#              strings that are specific to `three` properties
         geo_type = constants.GEOMETRY.title()
         geo_type = constants.GEOMETRY.title()
         if parent.options.get(constants.GEOMETRY_TYPE):
         if parent.options.get(constants.GEOMETRY_TYPE):
             opt_type = parent.options[constants.GEOMETRY_TYPE]
             opt_type = parent.options[constants.GEOMETRY_TYPE]
@@ -69,7 +69,16 @@ class Geometry(base_classes.BaseNode):
 
 
         length = len(faces)
         length = len(faces)
         offset = 0
         offset = 0
-        bitset = lambda x, y: x & (1 << y)
+
+        def bitset(bit, mask):
+            """
+
+            :type bit: int
+            :type mask: int
+
+            """
+            return bit & (1 << mask)
+
         face_count = 0
         face_count = 0
 
 
         masks = (constants.MASK[constants.UVS],
         masks = (constants.MASK[constants.UVS],
@@ -213,8 +222,8 @@ class Geometry(base_classes.BaseNode):
             io.dump(filepath, data, options=self.scene.options)
             io.dump(filepath, data, options=self.scene.options)
             return filepath
             return filepath
         else:
         else:
-            logger.warning("Could not determine a filepath for "\
-                "animation data. Nothing written to disk.")
+            logger.warning("Could not determine a filepath for "
+                           "animation data. Nothing written to disk.")
 
 
     def _component_data(self):
     def _component_data(self):
         """Query the component data only
         """Query the component data only
@@ -405,8 +414,9 @@ class Geometry(base_classes.BaseNode):
 
 
         if self.options.get(constants.FACES):
         if self.options.get(constants.FACES):
             logger.info("Parsing %s", constants.FACES)
             logger.info("Parsing %s", constants.FACES)
+            materials = self.get(constants.MATERIALS)
             self[constants.FACES] = api.mesh.faces(
             self[constants.FACES] = api.mesh.faces(
-                self.node, self.options) or []
+                self.node, self.options, materials=materials) or []
 
 
         no_anim = (None, False, constants.OFF)
         no_anim = (None, False, constants.OFF)
         if self.options.get(constants.ANIMATION) not in no_anim:
         if self.options.get(constants.ANIMATION) not in no_anim:
@@ -414,8 +424,8 @@ class Geometry(base_classes.BaseNode):
             self[constants.ANIMATION] = api.mesh.skeletal_animation(
             self[constants.ANIMATION] = api.mesh.skeletal_animation(
                 self.node, self.options) or []
                 self.node, self.options) or []
 
 
-        #@TODO: considering making bones data implied when
-        #       querying skinning data
+#       @TODO: considering making bones data implied when
+#              querying skinning data
 
 
         bone_map = {}
         bone_map = {}
         if self.options.get(constants.BONES):
         if self.options.get(constants.BONES):
@@ -438,4 +448,3 @@ class Geometry(base_classes.BaseNode):
             logger.info("Parsing %s", constants.MORPH_TARGETS)
             logger.info("Parsing %s", constants.MORPH_TARGETS)
             self[constants.MORPH_TARGETS] = api.mesh.morph_targets(
             self[constants.MORPH_TARGETS] = api.mesh.morph_targets(
                 self.node, self.options) or []
                 self.node, self.options) or []
-