Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions addons/io_scene_gltf2/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -659,6 +659,13 @@ class ExportGLTF2_Base(ConvertGLTF2_Base):
default=False
)

export_compare_meshes: BoolProperty(
name='Compare meshes',
description='Compare mesh objects after applying modifiers '
'(to avoid duplication of identical meshes in the exported file)',
default=False
)

export_shared_accessors: BoolProperty(
name='Shared Accessors',
description='Export Primitives using shared accessors for attributes',
Expand Down Expand Up @@ -1200,6 +1207,7 @@ def execute(self, context):
export_settings['gltf_extras'] = self.export_extras
export_settings['gltf_yup'] = self.export_yup
export_settings['gltf_apply'] = self.export_apply
export_settings['gltf_compare_meshes'] = self.export_compare_meshes
export_settings['gltf_shared_accessors'] = self.export_shared_accessors
export_settings['gltf_current_frame'] = self.export_current_frame
export_settings['gltf_animations'] = self.export_animations
Expand Down Expand Up @@ -1497,6 +1505,7 @@ def export_panel_data_mesh(layout, operator):
header.label(text="Mesh")
if body:
body.prop(operator, 'export_apply')
body.prop(operator, 'export_compare_meshes')
body.prop(operator, 'export_texcoords')
body.prop(operator, 'export_normals')
col = body.column()
Expand Down
3 changes: 3 additions & 0 deletions addons/io_scene_gltf2/blender/exp/gather.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ def __gather_scene(blender_scene, export_settings):
export_user_extensions('vtree_after_filter_hook', export_settings, vtree)

export_settings['vtree'] = vtree
export_settings['mesh_instances'] = {}

# If we don't remove armature object, we can't have bones directly at root of scene
# So looping only on root nodes, as they are all nodes, not bones
Expand Down Expand Up @@ -149,6 +150,8 @@ def __gather_scene(blender_scene, export_settings):

export_user_extensions('gather_scene_hook', export_settings, scene, blender_scene)

export_settings['mesh_instances'].clear()

return scene


Expand Down
35 changes: 28 additions & 7 deletions addons/io_scene_gltf2/blender/exp/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,8 @@ def __gather_matrix(blender_object, export_settings):


def __gather_mesh(vnode, blender_object, export_settings):
need_to_mesh_clear = False

if vnode.blender_type == VExportNode.COLLECTION:
return None
if blender_object and blender_object.type in ['CURVE', 'SURFACE', 'FONT']:
Expand Down Expand Up @@ -319,6 +321,8 @@ def __gather_mesh(vnode, blender_object, export_settings):
depsgraph = bpy.context.evaluated_depsgraph_get()
blender_mesh_owner = blender_object.evaluated_get(depsgraph)
blender_mesh = blender_mesh_owner.to_mesh(preserve_all_data_layers=True, depsgraph=depsgraph)
need_to_mesh_clear = True

# Seems now (from 4.2) the custom properties are Statically Typed
# so no need to copy them in that case, because overwriting them will crash
if len(blender_mesh.keys()) == 0:
Expand All @@ -332,6 +336,23 @@ def __gather_mesh(vnode, blender_object, export_settings):
# Store that this evaluated mesh has been created by the exporter, and is not a GN instance mesh
blender_mesh['gltf2_mesh_applied'] = True

# check if other object used the same origin mesh produced the same mesh after modifier applies, if yes use this mesh
if export_settings["gltf_compare_meshes"]:
if not blender_object.data in export_settings["mesh_instances"]:
# make own copy of mesh because result of `to_mesh` is temporary
# (and can be overwrite for example by call `to_mesh` on same object in other instance of collection)
blender_mesh = blender_mesh.copy()
export_settings["mesh_instances"][blender_object.data] = [blender_mesh]
else:
for other_mesh in export_settings["mesh_instances"][blender_object.data]:
compare = blender_mesh.unit_test_compare(mesh=other_mesh)
if compare == "Same":
blender_mesh = other_mesh
break
else:
blender_mesh = blender_mesh.copy()
export_settings["mesh_instances"][blender_object.data].append(blender_mesh)

if export_settings['gltf_skins']:
# restore Armature modifiers
for idx, show_viewport in armature_modifiers.items():
Expand All @@ -348,12 +369,6 @@ def __gather_mesh(vnode, blender_object, export_settings):

else:
blender_mesh = blender_object.data
if not export_settings['gltf_skins']:
modifiers = None
else:
# Check if there is an armature modidier
if len([mod for mod in blender_object.modifiers if mod.type == "ARMATURE"]) == 0:
modifiers = None

# Keep materials from object, as no modifiers are applied, so no risk that
# modifiers changed them
Expand All @@ -369,6 +384,12 @@ def __gather_mesh(vnode, blender_object, export_settings):
if modifier.type == 'ARMATURE':
uuid_for_skined_data = vnode.uuid

# no need keep modifiers if skins are not exported or object don't have an armature modifier
# (applying different set of modifiers results in different blender_mesh object)
# so set it to None to avoid unnecessary mesh duplication
if uuid_for_skined_data is None:
modifiers = None

result = gltf2_blender_gather_mesh.gather_mesh(blender_mesh,
uuid_for_skined_data,
blender_object.vertex_groups if blender_object else None,
Expand All @@ -377,7 +398,7 @@ def __gather_mesh(vnode, blender_object, export_settings):
None,
export_settings)

if export_settings['gltf_apply'] and modifiers is not None:
if need_to_mesh_clear:
blender_mesh_owner.to_mesh_clear()

return result
Expand Down