Advertisement
Thunder-Menu

blender_Extract_mesh_to_FBX_with_position_and_size_json.py

Aug 2nd, 2024
307
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.51 KB | Source Code | 0 0
  1. import bpy
  2. import os
  3. import json
  4.  
  5. bl_info = {
  6.     "name": "FBX Mesh Exporter with Accurate Details",
  7.     "author": "Your Name",
  8.     "version": (1, 0),
  9.     "blender": (3, 6, 0),
  10.     "location": "File > Export > Export FBX Mesh with Details",
  11.     "description": "Exports meshes to FBX files and records their texture space details.",
  12.     "warning": "",
  13.     "wiki_url": "",
  14.     "category": "Import-Export",
  15. }
  16.  
  17. class ExportMeshesToFBXWithDetails(bpy.types.Operator):
  18.     bl_idname = "export_meshes.to_fbx_with_details"
  19.     bl_label = "Export Meshes to FBX with Details"
  20.     bl_options = {'REGISTER', 'UNDO'}
  21.  
  22.     directory: bpy.props.StringProperty(subtype="DIR_PATH")
  23.  
  24.     def execute(self, context):
  25.         if not self.directory:
  26.             self.report({'ERROR'}, "Directory path not provided.")
  27.             return {'CANCELLED'}
  28.  
  29.         destination_folder = os.path.abspath(self.directory)
  30.         if not os.path.exists(destination_folder):
  31.             os.makedirs(destination_folder)
  32.  
  33.         # Exporter les objets en FBX
  34.         for obj in bpy.context.scene.objects:
  35.             if obj.type == 'MESH':
  36.                 base_name = obj.name.split('.')[0]  # Nettoyer le nom de l'objet
  37.  
  38.                 bpy.context.view_layer.objects.active = obj
  39.                 obj.select_set(True)
  40.  
  41.                 export_path = os.path.join(destination_folder, f"{base_name}.fbx")
  42.  
  43.                 # Assurez-vous que le fichier n'existe pas déjà
  44.                 if os.path.exists(export_path):
  45.                     self.report({'WARNING'}, f"File {base_name}.fbx already exists and will be overwritten.")
  46.  
  47.                 bpy.ops.export_scene.fbx(filepath=export_path, use_selection=True)
  48.                 obj.select_set(False)
  49.  
  50.         # Appeler la fonction d'extraction des détails après avoir exporté les FBX
  51.         self.export_texture_details(destination_folder)
  52.  
  53.         return {'FINISHED'}
  54.  
  55.     def export_texture_details(self, destination_folder):
  56.         mesh_details = {}
  57.  
  58.         for obj in bpy.context.scene.objects:
  59.             if obj.type == 'MESH':
  60.                 # Assurez-vous que nous sommes en mode Objet
  61.                 if bpy.context.object.mode != 'OBJECT':
  62.                     bpy.ops.object.mode_set(mode='OBJECT')
  63.  
  64.                 obj_name = obj.name
  65.  
  66.                 # Initialisation des valeurs de texture space location
  67.                 texture_space_location = {"x": 0.0, "y": 0.0, "z": 0.0}
  68.                 texture_space_size = {"x": 0.0, "y": 0.0, "z": 0.0}
  69.  
  70.                 # Assurez-vous que l'objet est visible pour éviter les problèmes de données cachées
  71.                 if obj.hide_get() or obj.hide_viewport:
  72.                     self.report({'WARNING'}, f"Object {obj_name} is hidden. Skipping.")
  73.                     continue
  74.  
  75.                 # Vérifiez si des UV maps existent et extrayez les coordonnées UV si disponibles
  76.                 if obj.data.uv_layers:
  77.                     uv_layer = obj.data.uv_layers.active
  78.                     if uv_layer.data:
  79.                         # Calcul des coordonnées UV
  80.                         min_x = float('inf')
  81.                         min_y = float('inf')
  82.                         max_x = float('-inf')
  83.                         max_y = float('-inf')
  84.                         min_z = float('inf')
  85.                         max_z = float('-inf')
  86.  
  87.                         for poly in obj.data.polygons:
  88.                             for loop_index in poly.loop_indices:
  89.                                 uv = uv_layer.data[loop_index].uv
  90.                                 min_x = min(min_x, uv[0])
  91.                                 min_y = min(min_y, uv[1])
  92.                                 max_x = max(max_x, uv[0])
  93.                                 max_y = max(max_y, uv[1])
  94.                                 # Nous n'avons pas de coordonnées Z dans UV, donc nous utilisons les coordonnées du sommet
  95.                                 min_z = float('inf')
  96.                                 max_z = float('-inf')
  97.                                 for vert in obj.data.vertices:
  98.                                     world_coord = obj.matrix_world @ vert.co
  99.                                     min_z = min(min_z, world_coord.z)
  100.                                     max_z = max(max_z, world_coord.z)
  101.  
  102.                         texture_space_location = {
  103.                             "x": min_x,
  104.                             "y": min_y,
  105.                             "z": (min_z + max_z) / 2.0
  106.                         }
  107.                         texture_space_size = {
  108.                             "x": max_x - min_x,
  109.                             "y": max_y - min_y,
  110.                             "z": max_z - min_z
  111.                         }
  112.                 else:
  113.                     # Utilisez les coordonnées de l'objet si UV maps ne sont pas disponibles
  114.                     if obj.data.vertices:
  115.                         min_x = min_y = min_z = float('inf')
  116.                         max_x = max_y = max_z = float('-inf')
  117.  
  118.                         for vert in obj.data.vertices:
  119.                             world_coord = obj.matrix_world @ vert.co
  120.                             min_x = min(min_x, world_coord.x)
  121.                             min_y = min(min_y, world_coord.y)
  122.                             min_z = min(min_z, world_coord.z)
  123.                             max_x = max(max_x, world_coord.x)
  124.                             max_y = max(max_y, world_coord.y)
  125.                             max_z = max(max_z, world_coord.z)
  126.  
  127.                         texture_space_location = {
  128.                             "x": (min_x + max_x) / 2.0,
  129.                             "y": (min_y + max_y) / 2.0,
  130.                             "z": (min_z + max_z) / 2.0
  131.                         }
  132.                         texture_space_size = {
  133.                             "x": max_x - min_x,
  134.                             "y": max_y - min_y,
  135.                             "z": max_z - min_z
  136.                         }
  137.                     else:
  138.                         # Si aucun sommet n'est trouvé, utiliser la position de l'objet comme dernier recours
  139.                         texture_space_location = {
  140.                             "x": obj.location.x,
  141.                             "y": obj.location.y,
  142.                             "z": obj.location.z
  143.                         }
  144.  
  145.                 mesh_details[obj_name] = {
  146.                     "texture_space": {
  147.                         "location": texture_space_location,
  148.                         "size": texture_space_size
  149.                     }
  150.                 }
  151.  
  152.         # Sauvegarder les détails dans un fichier JSON
  153.         details_path = os.path.join(destination_folder, "mesh_details.json")
  154.         try:
  155.             with open(details_path, "w") as f:
  156.                 json.dump(mesh_details, f, indent=4)
  157.             self.report({'INFO'}, f"Details saved to {details_path}")
  158.         except IOError as e:
  159.             self.report({'ERROR'}, f"Failed to write JSON file: {e}")
  160.  
  161.     def invoke(self, context, event):
  162.         context.window_manager.fileselect_add(self)
  163.         return {'RUNNING_MODAL'}
  164.  
  165. def menu_func_export(self, context):
  166.     self.layout.operator(ExportMeshesToFBXWithDetails.bl_idname, text="Export Meshes to FBX with Details")
  167.  
  168. def register():
  169.     bpy.utils.register_class(ExportMeshesToFBXWithDetails)
  170.     bpy.types.TOPBAR_MT_file_export.append(menu_func_export)
  171.  
  172. def unregister():
  173.     bpy.utils.unregister_class(ExportMeshesToFBXWithDetails)
  174.     bpy.types.TOPBAR_MT_file_export.remove(menu_func_export)
  175.  
  176. if __name__ == "__main__":
  177.     register()
  178.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement