2023-02-01 13:43:23 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
2023-06-24 13:54:49 +00:00
|
|
|
'''
|
2023-02-01 13:43:23 +00:00
|
|
|
DESCRIPTION.
|
|
|
|
Convert and setup FreeCAD solid objects to 3d assets mesh files.
|
|
|
|
Support Blender compiled as a Python Module only!
|
2023-06-24 13:54:49 +00:00
|
|
|
'''
|
2023-09-03 21:39:50 +00:00
|
|
|
__version__ = '0.5'
|
2023-02-01 13:43:23 +00:00
|
|
|
|
|
|
|
import logging
|
2023-04-05 11:26:09 +00:00
|
|
|
import os
|
2023-02-01 13:43:23 +00:00
|
|
|
import sys
|
2023-09-03 21:39:50 +00:00
|
|
|
sys.path.append('../')
|
|
|
|
from freecad.utils.export_freecad_scene import freecad_to_json
|
|
|
|
|
|
|
|
from blender.import_cad.build_blender_scene import json_to_blend
|
|
|
|
from blender.import_cad.restruct_hierarchy_by_lcs import restruct_hierarchy
|
|
|
|
from blender.import_cad.import_coordinate_point import lcs_json_importer
|
|
|
|
from blender.utils.remove_collections import remove_collections
|
|
|
|
from blender.utils.cleanup_orphan_data import cleanup_orphan_data
|
|
|
|
from blender.utils.sdf_mesh_selector import sdf_mesh_selector
|
|
|
|
from blender.remesh.highpoly_setup import setup_meshes
|
|
|
|
from blender.remesh.lowpoly_setup import parts_to_shells
|
2023-06-24 13:54:49 +00:00
|
|
|
|
2023-02-01 13:43:23 +00:00
|
|
|
from export.dae import export_dae
|
2023-02-08 10:47:54 +03:00
|
|
|
from export.collision import export_col_stl
|
2023-02-01 13:43:23 +00:00
|
|
|
import bpy
|
2023-04-05 11:26:09 +00:00
|
|
|
import mathutils
|
2023-02-01 13:43:23 +00:00
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
logging.basicConfig(level=logging.INFO)
|
|
|
|
|
2023-06-24 13:54:49 +00:00
|
|
|
'''
|
|
|
|
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'
|
2023-02-01 13:43:23 +00:00
|
|
|
|
2023-07-04 10:18:10 +03:00
|
|
|
|
2023-03-06 12:50:35 +00:00
|
|
|
def freecad_asset_pipeline(fcstd_path,
|
2023-07-04 10:18:10 +03:00
|
|
|
tesselation_method,
|
2023-05-19 18:35:03 +00:00
|
|
|
linear_deflection,
|
|
|
|
angular_deflection,
|
2023-07-04 10:18:10 +03:00
|
|
|
fem_size,
|
2023-04-05 11:26:09 +00:00
|
|
|
mesh_export_path=None,
|
|
|
|
json_path=None,
|
2023-03-06 12:50:35 +00:00
|
|
|
blend_path=None,
|
|
|
|
sdf_path=None):
|
2023-06-24 13:54:49 +00:00
|
|
|
''' Setup FreeCAD scene to CG asset '''
|
|
|
|
|
2023-04-12 09:19:17 +00:00
|
|
|
# prepare blend file
|
2023-02-01 13:43:23 +00:00
|
|
|
remove_collections()
|
|
|
|
cleanup_orphan_data()
|
2023-04-12 09:19:17 +00:00
|
|
|
|
2023-09-03 21:39:50 +00:00
|
|
|
## convert FreeCAD scene to Blender scene
|
|
|
|
# TODO
|
|
|
|
objs_for_render = json_to_blend(freecad_to_json(**kwargs))
|
2023-06-24 13:54:49 +00:00
|
|
|
|
|
|
|
# restructuring hierarchy by lcs points
|
|
|
|
lcs_objects = restruct_hierarchy()
|
2023-04-05 11:26:09 +00:00
|
|
|
|
2023-04-12 09:19:17 +00:00
|
|
|
# import lcs
|
2023-06-24 13:54:49 +00:00
|
|
|
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)
|
2023-04-05 11:26:09 +00:00
|
|
|
|
2023-04-12 09:19:17 +00:00
|
|
|
# sdf setup WIP
|
2023-03-06 12:50:35 +00:00
|
|
|
if sdf_path is not None:
|
|
|
|
sdf_mesh_selector(sdf_path)
|
2023-04-05 11:26:09 +00:00
|
|
|
|
2023-06-24 13:54:49 +00:00
|
|
|
# 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)
|
|
|
|
|
2023-04-12 09:19:17 +00:00
|
|
|
# retopo
|
2023-06-24 13:54:49 +00:00
|
|
|
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)
|
2023-04-05 11:26:09 +00:00
|
|
|
|
2023-04-12 09:19:17 +00:00
|
|
|
# save blender scene
|
2023-03-06 12:50:35 +00:00
|
|
|
if blend_path is not None:
|
2023-04-12 09:19:17 +00:00
|
|
|
if not os.path.isdir(os.path.dirname(blend_path)):
|
|
|
|
os.makedirs(os.path.dirname(blend_path))
|
2023-03-06 12:50:35 +00:00
|
|
|
bpy.ops.wm.save_as_mainfile(filepath=blend_path)
|
2023-04-05 11:26:09 +00:00
|
|
|
|
|
|
|
# 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)
|
2023-02-01 13:43:23 +00:00
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
2023-03-06 12:50:35 +00:00
|
|
|
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)
|
2023-07-04 10:18:10 +03:00
|
|
|
parser.add_argument(
|
|
|
|
'--tesselation_method', type=str, help='Select tesselation method: Standard or FEM.', default='Standard', required=False)
|
2023-03-06 12:50:35 +00:00
|
|
|
parser.add_argument(
|
2023-05-19 18:35:03 +00:00
|
|
|
'--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)
|
2023-07-04 10:18:10 +03:00
|
|
|
parser.add_argument(
|
|
|
|
'--fem_size', type=float, help='For FEM method only! Finite element size in mm', default=1.0, required=False)
|
2023-04-05 11:26:09 +00:00
|
|
|
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)
|
2023-03-06 12:50:35 +00:00
|
|
|
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,
|
2023-07-04 10:18:10 +03:00
|
|
|
args.tesselation_method,
|
2023-05-19 18:35:03 +00:00
|
|
|
args.linear_deflection,
|
|
|
|
args.angular_deflection,
|
2023-07-04 10:18:10 +03:00
|
|
|
args.fem_size,
|
2023-04-05 11:26:09 +00:00
|
|
|
args.mesh_export_path,
|
|
|
|
args.json_path,
|
2023-03-06 12:50:35 +00:00
|
|
|
args.blend_path,
|
|
|
|
args.sdf_path)
|
|
|
|
|
2023-06-24 13:54:49 +00:00
|
|
|
logger.info('Assets setup completed!')
|