framework/cg/pipeline/cg_pipeline.py

188 lines
5.2 KiB
Python
Raw Normal View History

2023-09-12 09:07:30 +00:00
# -*- coding: utf-8 -*-
#!/usr/bin/env python
'''
DESCRIPTION.
Convert and setup FreeCAD solid objects to 3d assets.
Support Blender compiled as a Python Module only!
'''
__version__ = '0.6'
import json
import logging
import os
from blender.utils.remove_collections import remove_collections
from blender.utils.cleanup_orphan_data import cleanup_orphan_data
from utils.cmd_proc import cmd_proc
from blender.import_cad.build_blender_scene import json_to_blend
from blender.processing.restruct_hierarchy_by_lcs import restruct_hierarchy
from blender.processing.highpoly_setup import setup_meshes
from blender.processing.lowpoly_setup import parts_to_shells
from blender.processing.uv_setup import uv_unwrap
import bpy
import mathutils
# from export.dae import export_dae
# from export.collision import export_col_stl
logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO)
'''
IMPORT COLLECTIONS NAMIG CONVENTION:
Parts - collection for mesh objects
LCS - collection for location points
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)
'''
# ENV
freecadcmd = 'freecadcmd'
fcstd_data_script = 'freecad_to_json.py'
# COLLECTIONS NAMIG CONVENTION
parts_col_name = 'Parts'
lcs_col_name = 'LCS'
hierarchy_col_name = 'Hierarchy'
lowpoly_col_name = 'Lowpoly'
# LCS POINT'S SUFFIXES CONVENTION
inlet = '_in'
outlet = '_out'
root = '_root'
# CG ASSETS SUFFIXES CONVENTION
hightpoly = '_hp'
lowpoly = '_lp'
render = '_render'
def cg_pipeline(**kwargs):
''' CG asset creation pipeline '''
# prepare blend file
remove_collections()
cleanup_orphan_data()
# convert FreeCAD scene to Blender scene
objs_for_render = json_to_blend(
json.loads(
cmd_proc(freecadcmd,
fcstd_data_script,
'--',
**kwargs
).split('FreeCAD ')[0]
)
)
# restructuring hierarchy by lcs points
lcs_objects = restruct_hierarchy()
# save blender scene
if kwargs['blend_path'] is not None:
if not os.path.isdir(os.path.dirname(kwargs['blend_path'])):
os.makedirs(os.path.dirname(kwargs['blend_path']))
bpy.ops.wm.save_as_mainfile(filepath=kwargs['blend_path'])
# prepare highpoly
setup_meshes(objs_for_render, sharpness=True, shading=True)
# prepare lowpoly
part_names = [p.name.split(inlet)[0] for p in lcs_objects if p.name.endswith(inlet)]
lowpoly_objs = parts_to_shells(part_names)
uv_unwrap(lowpoly_objs)
# save blender scene
if kwargs['blend_path'] is not None:
if not os.path.isdir(os.path.dirname(kwargs['blend_path'])):
os.makedirs(os.path.dirname(kwargs['blend_path']))
bpy.ops.wm.save_as_mainfile(filepath=kwargs['blend_path'])
# export all objects
if kwargs['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(kwargs['mesh_export_path'])
export_col_stl(kwargs['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(
'--tesselation_method',
type=str,
help='Select tesselation method: Standard or FEM.',
default='Standard',
required=False
)
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(
'--fem_size',
type=float,
help='For FEM method only! Finite element size in mm',
default=50.0,
required=False
)
parser.add_argument(
'--skiphidden',
type=bool,
help='Skip processing for hidden FreeCAD objects',
default=True,
required=False
)
parser.add_argument(
'--property_forse_nonsolid',
type=str,
help='FreeCAD property to enable processing for nonsolid objects',
default='Robossembler_NonSolid',
required=False
)
parser.add_argument(
'--mesh_export_path',
type=str, help='Path for export meshes',
required=False
)
parser.add_argument(
'--blend_path',
type=str,
help='Path for export blend assembly file',
required=False
)
args = parser.parse_args()
kwargs = {key: getattr(args, key) for key in dir(args) if not key.startswith('_')}
cg_pipeline(**kwargs)
logger.info('CG Pipeline Completed!')