# -*- coding: utf-8 -*- ''' DESCRIPTION. Convert and setup FreeCAD solid objects to 3d assets mesh files. Support Blender compiled as a Python Module only! ''' __version__ = '0.4' import logging import os import sys sys.path.append('../blender/') from import_fcstd.import_cad_objects import obj_importer from import_fcstd.restruct_hierarchy_by_lcs import restruct_hierarchy from import_fcstd.import_coordinate_point import lcs_json_importer from utils.remove_collections import remove_collections from utils.cleanup_orphan_data import cleanup_orphan_data from utils.sdf_mesh_selector import sdf_mesh_selector from remesh.highpoly_setup import setup_meshes from remesh.lowpoly_setup import parts_to_shells from export.dae import export_dae from export.collision import export_col_stl import bpy import mathutils logger = logging.getLogger(__name__) logging.basicConfig(level=logging.INFO) ''' IMPORT COLLECTIONS NAMIG CONVENTION: Import Parts - collection for mesh objects Import LCS - collection for location points Import Hierarchy - collection for hierarchy locators LCS POINT'S SUFFIXES CONVENTION: '_in' - inlet suffix '_out' - outlet suffix '_root' - root suffix CG ASSETS SUFFIXES CONVENTION: '_hp' - hightpoly asset (reference baking source) '_lp' - lowpoly asset (prepared for game engines) '_render' - root suffix (prepared for render engines) ''' # COLLECTIONS NAMIG CONVENTION parts_col_name = 'Import Parts' lcs_col_name = 'Import LCS' hierarchy_col_name = 'Import Hierarchy' lowpoly_col_name = 'Lowpoly Parts' # LCS POINT'S SUFFIXES CONVENTION inlet = '_in' outlet = '_out' root = '_root' # CG ASSETS SUFFIXES CONVENTION hightpoly = '_hp' lowpoly = '_lp' render = '_render' def freecad_asset_pipeline(fcstd_path, linear_deflection, angular_deflection, mesh_export_path=None, json_path=None, blend_path=None, sdf_path=None): ''' Setup FreeCAD scene to CG asset ''' # prepare blend file remove_collections() cleanup_orphan_data() # import objects, tesselation method can be "Standard" by default with linear/angular deflection parameters and Mefisto with max edge length parameter objs_for_render = obj_importer(fcstd_path, tesselation_method, linear_deflection, angular_deflection, max_edge_length) # restructuring hierarchy by lcs points lcs_objects = restruct_hierarchy() # import lcs if not bpy.data.collections.get(lcs_col_name): if not bpy.data.collections[lcs_col_name].objects: if json_path is None: json_path = os.path.dirname(fcstd_path) for f in os.listdir(os.path.dirname(fcstd_path)): if f.endswith('.json'): json_file = os.path.join(json_path, f) lcs_json_importer(json_file) # sdf setup WIP if sdf_path is not None: sdf_mesh_selector(sdf_path) # save blender scene if blend_path is not None: if not os.path.isdir(os.path.dirname(blend_path)): os.makedirs(os.path.dirname(blend_path)) bpy.ops.wm.save_as_mainfile(filepath=blend_path) # retopo setup_meshes(objs_for_render, sharpness=True, shading=True) part_names = [p.name.split(inlet)[0] for p in lcs_objects if p.name.endswith(inlet)] parts_to_shells(part_names) # save blender scene if blend_path is not None: if not os.path.isdir(os.path.dirname(blend_path)): os.makedirs(os.path.dirname(blend_path)) bpy.ops.wm.save_as_mainfile(filepath=blend_path) # export all objects if mesh_export_path is not None: obs = bpy.context.selected_objects for ob in obs: ob.matrix_world = mathutils.Matrix() for ob in obs: ob.select_set(state=True) export_dae(mesh_export_path) export_col_stl(mesh_export_path) if __name__ == '__main__': import argparse parser = argparse.ArgumentParser( description='Convert and setup FreeCAD solid objects to 3d assets mesh files.') parser.add_argument( '--fcstd_path', type=str, help='Path to source FreeCAD scene', required=True) parser.add_argument( '--linear_deflection', type=float, help='Max linear distance error', default=0.1, required=False) parser.add_argument( '--angular_deflection', type=float, help='Max angular distance error', default=20.0, required=False) parser.add_argument( '--mesh_export_path', type=str, help='Path for export meshes', required=False) parser.add_argument( '--json_path', type=str, help='Path to DIR with coordinate points jsons', required=False) parser.add_argument( '--blend_path', type=str, help='Path for export blend assembly file', required=False) parser.add_argument( '--sdf_path', type=str, help='Path to source SDF assembly file', required=False) args = parser.parse_args() freecad_asset_pipeline(args.fcstd_path, args.linear_deflection, args.angular_deflection, args.mesh_export_path, args.json_path, args.blend_path, args.sdf_path) logger.info('Assets setup completed!')