diff --git a/addons/io_scene_gltf2/__init__.py b/addons/io_scene_gltf2/__init__.py index 5264f8d4a..369298c93 100644 --- a/addons/io_scene_gltf2/__init__.py +++ b/addons/io_scene_gltf2/__init__.py @@ -638,10 +638,23 @@ class ExportGLTF2_Base(ConvertGLTF2_Base): ) # Not starting with "export_", as this is a collection only option - at_collection_center: BoolProperty( - name="Export at Collection Center", - description="Export at Collection center of mass of root objects of the collection", - default=False, + collection_center_mode: EnumProperty( + name="Collection Center", + description="Scene origin of exported collection", + items=( + ('WORLD_ORIGIN', 'World Origin', + 'Export at world origin as scene origin'), + ('CENTER_MASS', 'Center of Mass', + 'Export at Collection center of mass of root objects of the collection'), + ('OBJECT_POSITION', 'Object Position', + 'Export at object position as scene origin')), + default='WORLD_ORIGIN' + ) + + collection_center_object: StringProperty( + name="Center Object", + description="Object to use as exported scene origin", + default="" ) export_extras: BoolProperty( @@ -1195,7 +1208,9 @@ def execute(self, context): export_settings['gltf_active_collection_with_nested'] = False export_settings['gltf_active_scene'] = self.use_active_scene export_settings['gltf_collection'] = self.collection - export_settings['gltf_at_collection_center'] = self.at_collection_center + export_settings['gltf_collection_center_mode'] = self.collection_center_mode + if self.collection_center_mode == 'OBJECT_POSITION': + export_settings['gltf_collection_center_object'] = context.scene.objects.get(self.collection_center_object) export_settings['gltf_selected'] = self.use_selection export_settings['gltf_layers'] = True # self.export_layers @@ -1402,7 +1417,7 @@ def draw(self, context): is_file_browser = context.space_data.type == 'FILE_BROWSER' export_main(layout, operator, is_file_browser) - export_panel_collection(layout, operator, is_file_browser) + export_panel_collection(layout, operator, is_file_browser, context) export_panel_include(layout, operator, is_file_browser) export_panel_transform(layout, operator) export_panel_data(layout, operator) @@ -1432,14 +1447,16 @@ def export_main(layout, operator, is_file_browser): layout.prop(operator, 'will_save_settings') -def export_panel_collection(layout, operator, is_file_browser): +def export_panel_collection(layout, operator, is_file_browser, context): if is_file_browser: return header, body = layout.panel("GLTF_export_collection", default_closed=True) header.label(text="Collection") if body: - body.prop(operator, 'at_collection_center') + body.prop(operator, 'collection_center_mode') + if operator.collection_center_mode == 'OBJECT_POSITION': + body.prop_search(operator, 'collection_center_object', context.scene, 'objects') def export_panel_include(layout, operator, is_file_browser): diff --git a/addons/io_scene_gltf2/blender/exp/gather.py b/addons/io_scene_gltf2/blender/exp/gather.py index 13dfe0ca3..0fcc8b774 100644 --- a/addons/io_scene_gltf2/blender/exp/gather.py +++ b/addons/io_scene_gltf2/blender/exp/gather.py @@ -23,7 +23,7 @@ from . import tree as gltf2_blender_gather_tree from .animation.sampled.object.keyframes import get_cache_data from .animation.animations import gather_animations - +from mathutils import Vector def gather_gltf2(export_settings): """ @@ -103,9 +103,18 @@ def __gather_scene(blender_scene, export_settings): # We need to calculate the collection center, # In order to set the scene center to the collection center # Using object center barycenter for now (another option could be to use bounding box center) - if export_settings['gltf_collection'] and export_settings['gltf_at_collection_center']: - vtree.calculate_collection_center() - + if export_settings['gltf_collection']: + match export_settings['gltf_collection_center_mode']: + case 'WORLD_ORIGIN': + pass + case 'CENTER_MASS': + vtree.calculate_collection_center_barycenter() + case 'OBJECT_POSITION': + center_object = export_settings['gltf_collection_center_object'] + if center_object: + export_settings['gltf_collection_center'] = center_object.matrix_world.translation + else: + export_settings['gltf_collection_center'] = Vector((0.0, 0.0, 0.0)) vtree.variants_reset_to_original() export_user_extensions('vtree_after_filter_hook', export_settings, vtree) diff --git a/addons/io_scene_gltf2/blender/exp/nodes.py b/addons/io_scene_gltf2/blender/exp/nodes.py index f6a273ff5..106456a8b 100644 --- a/addons/io_scene_gltf2/blender/exp/nodes.py +++ b/addons/io_scene_gltf2/blender/exp/nodes.py @@ -458,14 +458,11 @@ def __init__(self, name): def __gather_trans_rot_scale(vnode, export_settings): if vnode.parent_uuid is None: - # No parent, so matrix is world matrix, except if we export a collection - if export_settings['gltf_collection'] and export_settings['gltf_at_collection_center']: + # No parent, so matrix is world matrix, except if we export a collection + trans, rot, sca = vnode.matrix_world.decompose() + if export_settings['gltf_collection'] and export_settings['gltf_collection_center_mode'] != 'WORLD_ORIGIN': # If collection, we need to take into account the collection offset - trans, rot, sca = vnode.matrix_world.decompose() trans -= export_settings['gltf_collection_center'] - else: - # No parent, so matrix is world matrix - trans, rot, sca = vnode.matrix_world.decompose() else: # calculate local matrix if export_settings['vtree'].nodes[vnode.parent_uuid].skin is None: diff --git a/addons/io_scene_gltf2/blender/exp/tree.py b/addons/io_scene_gltf2/blender/exp/tree.py index a94326dbd..f734c7236 100644 --- a/addons/io_scene_gltf2/blender/exp/tree.py +++ b/addons/io_scene_gltf2/blender/exp/tree.py @@ -1046,7 +1046,7 @@ def check_if_we_can_remove_armature(self): "We can't remove armature object because some armatures have multiple root bones.") break - def calculate_collection_center(self): + def calculate_collection_center_barycenter(self): # Because we already filtered the tree, we can use all objects # to calculate the center of the scene # Are taken into account all objects that are direct root in the exported collection