瀏覽代碼

Merge pull request #10621 from phfatmonkey/Blender_Exporter_Object_Export_with_Skinned_Mesh

Blender exporter object export with skinned mesh
Mr.doob 8 年之前
父節點
當前提交
d047a71132

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

@@ -41,6 +41,7 @@ NUMERIC = {
     'SphericalReflectionMapping': 305,
 
     'RepeatWrapping': 1000,
+    'repeat': 1000,
     'ClampToEdgeWrapping': 1001,
     'MirroredRepeatWrapping': 1002,
 

+ 258 - 36
utils/exporters/blender/addons/io_three/exporter/api/mesh.py

@@ -12,6 +12,33 @@ from . import object as object_
 from .. import constants, utilities, logger, exceptions
 
 
+# flips vectors 
+
+#TODO: add these strings into constants.py
+
+XZ_Y = "XZ_Y"
+X_ZY = "X_ZY"
+XYZ = "XYZ"
+_XY_Z = "_XY_Z"
+
+
+def flip_axes (a, dir=XYZ):
+    """
+
+    :function to swap vectors:
+
+    """
+
+    if dir == XZ_Y:
+        a = (a[0], a[2], -a[1])
+    elif dir == X_ZY:
+        a = (a[0], -a[2], a[1])
+    elif dir == _XY_Z:
+        a = (-a[0], -a[1], a[2])
+
+    return (a[0], a[1], a[2])
+
+
 def _mesh(func):
     """
 
@@ -107,7 +134,7 @@ def bones(mesh, options):
 
 
 @_mesh
-def buffer_normal(mesh):
+def buffer_normal(mesh, options):
     """
 
     :param mesh:
@@ -122,16 +149,43 @@ def buffer_normal(mesh):
             msg = "Non-triangulated face detected"
             raise exceptions.BufferGeometryError(msg)
 
-        for vertex_index in face.vertices:
-            normal = mesh.vertices[vertex_index].normal
-            vector = (normal.x, normal.y, normal.z) if face.use_smooth else (face.normal.x, face.normal.y, face.normal.z)
-            normals_.extend(vector)
+        # using Object Loader with skinned mesh
+        if options.get(constants.SCENE, True) and _armature(mesh):
+        
+            for vertex_index in face.vertices:
+                normal = mesh.vertices[vertex_index].normal
+                vector = flip_axes(normal, XZ_Y) if face.use_smooth else flip_axes(face.normal, XZ_Y)
+                normals_.extend(vector)
+
+        # using Object Loader with static mesh
+        elif options.get(constants.SCENE, True) and not _armature(mesh):
+
+            for vertex_index in face.vertices:
+                normal = mesh.vertices[vertex_index].normal
+                vector = flip_axes(normal, _XY_Z) if face.use_smooth else flip_axes(face.normal, _XY_Z)
+                normals_.extend(vector)
+
+        # using JSON Loader with skinned mesh
+        elif not options.get(constants.SCENE, True) and _armature(mesh):
+
+            for vertex_index in face.vertices:
+                normal = mesh.vertices[vertex_index].normal
+                vector = flip_axes(normal) if face.use_smooth else flip_axes(face.normal)
+                normals_.extend(vector)
+
+        # using JSON Loader with static mesh
+        else:
+
+            for vertex_index in face.vertices:
+                normal = mesh.vertices[vertex_index].normal
+                vector = flip_axes(normal) if face.use_smooth else flip_axes(face.normal)
+                normals_.extend(vector)
 
     return normals_
 
 
 @_mesh
-def buffer_position(mesh):
+def buffer_position(mesh, options):
     """
 
     :param mesh:
@@ -146,10 +200,37 @@ def buffer_position(mesh):
             msg = "Non-triangulated face detected"
             raise exceptions.BufferGeometryError(msg)
 
-        for vertex_index in face.vertices:
-            vertex = mesh.vertices[vertex_index]
-            vector = (vertex.co.x, vertex.co.y, vertex.co.z)
-            position.extend(vector)
+        # using Object Loader with skinned mesh
+        if options.get(constants.SCENE, True) and _armature(mesh):
+
+            for vertex_index in face.vertices:
+                vertex = mesh.vertices[vertex_index]
+                vector = flip_axes(vertex.co, XZ_Y)
+                position.extend(vector)
+
+        # using Object Loader with static mesh
+        elif options.get(constants.SCENE, True) and not _armature(mesh):
+
+            for vertex_index in face.vertices:
+                vertex = mesh.vertices[vertex_index]
+                vector = flip_axes(vertex.co, _XY_Z)
+                position.extend(vector)
+
+        # using JSON Loader with skinned mesh
+        elif not options.get(constants.SCENE, True) and _armature(mesh):
+
+            for vertex_index in face.vertices:
+                vertex = mesh.vertices[vertex_index]
+                vector = flip_axes(vertex.co)
+                position.extend(vector)
+
+        # using JSON Loader with static mesh
+        else:
+
+            for vertex_index in face.vertices:
+                vertex = mesh.vertices[vertex_index]
+                vector = flip_axes(vertex.co)
+                position.extend(vector)
 
     return position
 
@@ -293,7 +374,7 @@ def faces(mesh, options, material_list=None):
     logger.debug("Normals enabled = %s", opt_normals)
 
     uv_indices = _uvs(mesh)[1] if opt_uvs else None
-    vertex_normals = _normals(mesh) if opt_normals else None
+    vertex_normals = _normals(mesh, options) if opt_normals else None
     vertex_colours = vertex_colors(mesh) if opt_colours else None
 
     faces_data = []
@@ -305,11 +386,37 @@ def faces(mesh, options, material_list=None):
             colour_indices[str(colour)] = index
 
     normal_indices = {}
+
     if vertex_normals:
         logger.debug("Indexing normals")
-        for index, normal in enumerate(vertex_normals):
-            normal = (normal[0], normal[2], -normal[1])
-            normal_indices[str(normal)] = index
+
+        # using Object Loader with skinned mesh
+        if options.get(constants.SCENE, True) and _armature(mesh):
+
+            for index, normal in enumerate(vertex_normals):
+                normal = flip_axes(normal, XYZ)
+                normal_indices[str(normal)] = index
+
+        # using Object Loader with static mesh
+        elif options.get(constants.SCENE, True) and not _armature(mesh):
+
+            for index, normal in enumerate(vertex_normals):
+                normal = flip_axes(normal, XYZ)
+                normal_indices[str(normal)] = index
+
+        # using JSON Loader with skinned mesh
+        elif not options.get(constants.SCENE, True) and _armature(mesh):
+
+            for index, normal in enumerate(vertex_normals):
+                normal = flip_axes(normal)
+                normal_indices[str(normal)] = index
+
+        # using JSON Loader with static mesh
+        else:
+
+            for index, normal in enumerate(vertex_normals):
+                normal = flip_axes(normal)
+                normal_indices[str(normal)] = index
 
     logger.info("Parsing %d faces", len(mesh.tessfaces))
     for face in mesh.tessfaces:
@@ -355,11 +462,43 @@ def faces(mesh, options, material_list=None):
                     mask[constants.UVS] = True
 
         if vertex_normals:
-            for vertex in face.vertices:
-                normal = mesh.vertices[vertex].normal
-                normal = (normal.x, normal.z, -normal.y) if face.use_smooth else (face.normal.x, face.normal.z, -face.normal.y)
-                face_data.append(normal_indices[str(normal)])
-                mask[constants.NORMALS] = True
+
+            # using Object Loader with skinned mesh
+            if options.get(constants.SCENE, True) and _armature(mesh):
+
+                for vertex in face.vertices:
+                    normal = mesh.vertices[vertex].normal
+                    normal = flip_axes(normal, XZ_Y) if face.use_smooth else flip_axes(face.normal, XZ_Y)
+                    face_data.append(normal_indices[str(normal)])
+                    mask[constants.NORMALS] = True
+
+            # using Object Loader with static mesh
+            elif options.get(constants.SCENE, True) and not _armature(mesh):
+
+                for vertex in face.vertices:
+                    normal = mesh.vertices[vertex].normal
+                    normal = flip_axes(normal, _XY_Z) if face.use_smooth else flip_axes(face.normal, _XY_Z)
+                    face_data.append(normal_indices[str(normal)])
+                    mask[constants.NORMALS] = True
+
+            # using JSON Loader with skinned mesh
+            elif not options.get(constants.SCENE, True) and _armature(mesh):
+
+                for vertex in face.vertices:
+                    normal = mesh.vertices[vertex].normal
+                    normal = flip_axes(normal) if face.use_smooth else flip_axes(face.normal)
+                    face_data.append(normal_indices[str(normal)])
+                    mask[constants.NORMALS] = True
+
+            # using JSON Loader with static mesh
+            else:
+
+                for vertex in face.vertices:
+                    normal = mesh.vertices[vertex].normal
+                    normal = flip_axes(normal) if face.use_smooth else flip_axes(face.normal)
+                    face_data.append(normal_indices[str(normal)])
+                    mask[constants.NORMALS] = True
+            
 
         if vertex_colours:
             colours = mesh.tessface_vertex_colors.active.data[face.index]
@@ -403,8 +542,29 @@ def morph_targets(mesh, options):
         morphs.append([])
         vertices_ = object_.extract_mesh(obj, options).vertices[:]
 
-        for vertex in vertices_:
-            morphs[-1].extend([vertex.co.x, vertex.co.y, vertex.co.z])
+        # using Object Loader with skinned mesh
+        if options.get(constants.SCENE, True) and _armature(mesh):
+
+            for vertex in vertices_:
+                morphs[-1].extend(flip_axes(vertex.co, XZ_Y))
+
+        # using Object Loader with static mesh
+        elif options.get(constants.SCENE, True) and not _armature(mesh):
+
+            for vertex in vertices_:
+                morphs[-1].extend(flip_axes(vertex.co, _XY_Z))
+
+        # using JSON Loader with skinned mesh
+        elif not options.get(constants.SCENE, True) and _armature(mesh):
+
+            for vertex in vertices_:
+                morphs[-1].extend(flip_axes(vertex.co))
+
+        # using JSON Loader with static mesh
+        else:
+
+            for vertex in vertices_:
+                morphs[-1].extend(flip_axes(vertex.co))
 
     context.scene.frame_set(original_frame, 0.0)
     morphs_detected = False
@@ -605,7 +765,7 @@ def materials(mesh, options):
 
 
 @_mesh
-def normals(mesh):
+def normals(mesh, options):
     """
 
     :param mesh:
@@ -615,7 +775,7 @@ def normals(mesh):
     logger.debug("mesh.normals(%s)", mesh)
     normal_vectors = []
 
-    for vector in _normals(mesh):
+    for vector in _normals(mesh, options):
         normal_vectors.extend(vector)
 
     return normal_vectors
@@ -752,7 +912,7 @@ def vertex_colors(mesh):
 
 
 @_mesh
-def vertices(mesh):
+def vertices(mesh, options):
     """
 
     :param mesh:
@@ -762,8 +922,29 @@ def vertices(mesh):
     logger.debug("mesh.vertices(%s)", mesh)
     vertices_ = []
 
-    for vertex in mesh.vertices:
-        vertices_.extend((vertex.co.x, vertex.co.y, vertex.co.z))
+    # using Object Loader with skinned mesh
+    if options.get(constants.SCENE, True) and _armature(mesh):
+
+        for vertex in mesh.vertices:
+            vertices_.extend(flip_axes(vertex.co, XZ_Y))
+
+    # using Object Loader with static mesh
+    elif options.get(constants.SCENE, True) and not _armature(mesh):
+
+        for vertex in mesh.vertices:
+            vertices_.extend(flip_axes(vertex.co, _XY_Z))
+
+    # using JSON Loader with skinned mesh
+    elif not options.get(constants.SCENE, True) and _armature(mesh):
+
+        for vertex in mesh.vertices:
+            vertices_.extend(flip_axes(vertex.co))
+
+    # using JSON Loader with static mesh
+    else:
+
+        for vertex in mesh.vertices:
+            vertices_.extend(flip_axes(vertex.co))
 
     return vertices_
 
@@ -892,7 +1073,7 @@ def _diffuse_map(mat):
     return diffuse
 
 
-def _normals(mesh):
+def _normals(mesh, options):
     """
 
     :param mesh:
@@ -904,16 +1085,57 @@ def _normals(mesh):
     vectors_ = {}
     for face in mesh.tessfaces:
 
-        for vertex_index in face.vertices:
-            normal = mesh.vertices[vertex_index].normal
-            vector = (normal.x, normal.y, normal.z) if face.use_smooth else (face.normal.x, face.normal.y, face.normal.z)
+        if options.get(constants.SCENE, True) and _armature(mesh):
+
+            for vertex_index in face.vertices:
+                normal = mesh.vertices[vertex_index].normal
+                vector = flip_axes(normal, XZ_Y) if face.use_smooth else flip_axes(face.normal, XZ_Y)
+
+                str_vec = str(vector)
+                try:
+                    vectors_[str_vec]
+                except KeyError:
+                    vectors.append(vector)
+                    vectors_[str_vec] = True
+                    
+        elif options.get(constants.SCENE, True) and not _armature(mesh):
+
+            for vertex_index in face.vertices:
+                normal = mesh.vertices[vertex_index].normal
+                vector = flip_axes(normal,_XY_Z) if face.use_smooth else flip_axes(face.normal,_XY_Z)
+
+                str_vec = str(vector)
+                try:
+                    vectors_[str_vec]
+                except KeyError:
+                    vectors.append(vector)
+                    vectors_[str_vec] = True
+
+        elif not options.get(constants.SCENE, True) and _armature(mesh):
+
+            for vertex_index in face.vertices:
+                normal = mesh.vertices[vertex_index].normal
+                vector = flip_axes(normal) if face.use_smooth else flip_axes(face.normal)
+
+                str_vec = str(vector)
+                try:
+                    vectors_[str_vec]
+                except KeyError:
+                    vectors.append(vector)
+                    vectors_[str_vec] = True
 
-            str_vec = str(vector)
-            try:
-                vectors_[str_vec]
-            except KeyError:
-                vectors.append(vector)
-                vectors_[str_vec] = True
+        else:
+
+            for vertex_index in face.vertices:
+                normal = mesh.vertices[vertex_index].normal
+                vector = flip_axes(normal) if face.use_smooth else flip_axes(face.normal)
+
+                str_vec = str(vector)
+                try:
+                    vectors_[str_vec]
+                except KeyError:
+                    vectors.append(vector)
+                    vectors_[str_vec] = True
 
     return vectors
 

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

@@ -373,13 +373,13 @@ class Geometry(base_classes.BaseNode):
         option_index_type = self.options.get(constants.INDEX_TYPE)
 
         pos_tuple = (constants.POSITION, options_vertices,
-                     api.mesh.buffer_position, 3)
+                     lambda m: api.mesh.buffer_position(m, self.options), 3)
         uvs_tuple = (constants.UV, option_uvs,
                      api.mesh.buffer_uv, 2)
         uvs2_tuple = (constants.UV2, option_uvs,
                      lambda m: api.mesh.buffer_uv(m, layer=1), 2)
         normals_tuple = (constants.NORMAL, option_normals,
-                         api.mesh.buffer_normal, 3)
+                         lambda m: api.mesh.buffer_normal(m, self.options), 3)
         dispatch = (pos_tuple, uvs_tuple, uvs2_tuple, normals_tuple)
 
         for key, option, func, size in dispatch:
@@ -500,11 +500,11 @@ class Geometry(base_classes.BaseNode):
         """Parse the geometry to Three.Geometry specs"""
         if self.options.get(constants.VERTICES):
             logger.info("Parsing %s", constants.VERTICES)
-            self[constants.VERTICES] = api.mesh.vertices(self.node) or []
+            self[constants.VERTICES] = api.mesh.vertices(self.node, self.options) or []
 
         if self.options.get(constants.NORMALS):
             logger.info("Parsing %s", constants.NORMALS)
-            self[constants.NORMALS] = api.mesh.normals(self.node) or []
+            self[constants.NORMALS] = api.mesh.normals(self.node, self.options) or []
 
         if self.options.get(constants.COLORS):
             logger.info("Parsing %s", constants.COLORS)