diff options
author | Julien Duroure <julien.duroure@gmail.com> | 2020-02-23 13:55:32 +0300 |
---|---|---|
committer | Julien Duroure <julien.duroure@gmail.com> | 2020-02-23 13:55:32 +0300 |
commit | ee61a3a692d30bcb844901c87c9408db332f4265 (patch) | |
tree | 61e58774a4ce0285a5103ca5f32e5ff1e2c272ec | |
parent | b4fc9fbcf4e2d766143d6e88b57e892a12b6fe88 (diff) |
glTF importer: manage morph weights at node level
-rwxr-xr-x | io_scene_gltf2/__init__.py | 2 | ||||
-rwxr-xr-x | io_scene_gltf2/blender/imp/gltf2_blender_gltf.py | 16 | ||||
-rwxr-xr-x | io_scene_gltf2/blender/imp/gltf2_blender_mesh.py | 12 | ||||
-rwxr-xr-x | io_scene_gltf2/blender/imp/gltf2_blender_node.py | 59 |
4 files changed, 34 insertions, 55 deletions
diff --git a/io_scene_gltf2/__init__.py b/io_scene_gltf2/__init__.py index e13b4cfc..3b586598 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": (1, 2, 27), + "version": (1, 2, 28), 'blender': (2, 82, 7), 'location': 'File > Import-Export', 'description': 'Import-Export as glTF 2.0', diff --git a/io_scene_gltf2/blender/imp/gltf2_blender_gltf.py b/io_scene_gltf2/blender/imp/gltf2_blender_gltf.py index 33f3ff57..8e6c1950 100755 --- a/io_scene_gltf2/blender/imp/gltf2_blender_gltf.py +++ b/io_scene_gltf2/blender/imp/gltf2_blender_gltf.py @@ -96,21 +96,10 @@ class BlenderGlTF(): # Something is wrong in file, there is no nodes return - for node_idx, node in enumerate(gltf.data.nodes): - + for node in gltf.data.nodes: # Weight animation management node.weight_animation = False - # skin management - if node.skin is not None and node.mesh is not None: - if not hasattr(gltf.data.skins[node.skin], "node_ids"): - gltf.data.skins[node.skin].node_ids = [] - - gltf.data.skins[node.skin].node_ids.append(node_idx) - - # Lights management - node.correction_needed = False - # Dispatch animation if gltf.data.animations: for node_idx, node in enumerate(gltf.data.nodes): @@ -138,8 +127,7 @@ class BlenderGlTF(): # Meshes if gltf.data.meshes: for mesh in gltf.data.meshes: - mesh.blender_name = {} # cache Blender mesh (keyed by skin_idx) - mesh.is_weight_animated = False + mesh.blender_name = {} # caches Blender mesh name # Calculate names for each mesh's shapekeys for mesh in gltf.data.meshes or []: diff --git a/io_scene_gltf2/blender/imp/gltf2_blender_mesh.py b/io_scene_gltf2/blender/imp/gltf2_blender_mesh.py index 04af71b2..adf05281 100755 --- a/io_scene_gltf2/blender/imp/gltf2_blender_mesh.py +++ b/io_scene_gltf2/blender/imp/gltf2_blender_mesh.py @@ -75,24 +75,12 @@ class BlenderMesh(): set_extras(mesh, pymesh.extras, exclude=['targetNames']) - pymesh.blender_name[skin_idx] = mesh.name - # Clear accessor cache after all primitives are done gltf.accessor_cache = {} return mesh @staticmethod - def set_mesh(gltf, pymesh, obj): - """Sets mesh data after creation.""" - # set default weights for shape keys, and names, if not set by convention on extras data - if pymesh.weights is not None: - for i in range(len(pymesh.weights)): - if pymesh.shapekey_names[i] is None: # No default value if shapekeys was not created - continue - obj.data.shape_keys.key_blocks[pymesh.shapekey_names[i]].value = pymesh.weights[i] - - @staticmethod def bmesh_to_mesh(gltf, pymesh, bme, mesh): bme.to_mesh(mesh) diff --git a/io_scene_gltf2/blender/imp/gltf2_blender_node.py b/io_scene_gltf2/blender/imp/gltf2_blender_node.py index 590a4fa5..d1ffdbe9 100755 --- a/io_scene_gltf2/blender/imp/gltf2_blender_node.py +++ b/io_scene_gltf2/blender/imp/gltf2_blender_node.py @@ -174,39 +174,42 @@ class BlenderNode(): @staticmethod def create_mesh_object(gltf, pynode, name): - instance = False - if gltf.data.meshes[pynode.mesh].blender_name.get(pynode.skin) is not None: - # Mesh is already created, only create instance - # Except is current node is animated with path weight - # Or if previous instance is animation at node level - if pynode.weight_animation is True: - instance = False - else: - if gltf.data.meshes[pynode.mesh].is_weight_animated is True: - instance = False - else: - instance = True - mesh = bpy.data.meshes[gltf.data.meshes[pynode.mesh].blender_name[pynode.skin]] - - if instance is False: - if pynode.name: - gltf.log.info("Blender create Mesh node " + pynode.name) + pymesh = gltf.data.meshes[pynode.mesh] + name = pymesh.name or name + + # Key to cache the Blender mesh by. + # Same cache key = instances of the same Blender mesh. + cache_key = None + if not pymesh.shapekey_names: + cache_key = (pynode.skin,) + else: + # Unlike glTF, all instances of a Blender mesh share shapekeys. + # So two instances that might have different morph weights need + # different cache keys. + if pynode.weight_animation is False: + cache_key = (pynode.skin, tuple(pynode.weights or [])) else: - gltf.log.info("Blender create Mesh node") + cache_key = None # don't use the cache at all + if cache_key is not None and cache_key in pymesh.blender_name: + mesh = bpy.data.meshes[pymesh.blender_name[cache_key]] + else: + gltf.log.info("Blender create Mesh node %s", name) mesh = BlenderMesh.create(gltf, pynode.mesh, pynode.skin) - - if pynode.weight_animation is True: - # flag this mesh instance as created only for this node, because of weight animation - gltf.data.meshes[pynode.mesh].is_weight_animated = True - - mesh_name = gltf.data.meshes[pynode.mesh].name - if not name and mesh_name: - name = mesh_name + if cache_key is not None: + pymesh.blender_name[cache_key] = mesh.name obj = bpy.data.objects.new(name, mesh) - if instance == False: - BlenderMesh.set_mesh(gltf, gltf.data.meshes[pynode.mesh], obj) + if pymesh.shapekey_names: + BlenderNode.set_morph_weights(gltf, pynode, obj) return obj + + @staticmethod + def set_morph_weights(gltf, pynode, obj): + pymesh = gltf.data.meshes[pynode.mesh] + weights = pynode.weights or pymesh.weights or [] + for i, weight in enumerate(weights): + if pymesh.shapekey_names[i] is not None: + obj.data.shape_keys.key_blocks[pymesh.shapekey_names[i]].value = weight |