subassembly models setup from SDFormat file
This commit is contained in:
parent
6af0f188a7
commit
95437a4527
7 changed files with 145 additions and 14 deletions
42
cg/blender/export/collision.py
Normal file
42
cg/blender/export/collision.py
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
DESCRIPTION.
|
||||||
|
STL mesh exporter.
|
||||||
|
Exports all objects in scene.
|
||||||
|
You can set export path and subdir.
|
||||||
|
"""
|
||||||
|
__version__ = "0.1"
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import sys
|
||||||
|
import bpy
|
||||||
|
import os
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
|
||||||
|
|
||||||
|
def export_col_stl(path, subdir=""):
|
||||||
|
""" STL mesh exporter. Exports all objects in scene. """
|
||||||
|
for ob in bpy.context.scene.objects:
|
||||||
|
# deselect all but just one object and make it active
|
||||||
|
bpy.ops.object.select_all(action='DESELECT')
|
||||||
|
ob.select_set(state=True)
|
||||||
|
bpy.context.view_layer.objects.active = ob
|
||||||
|
filename = bpy.context.active_object.name
|
||||||
|
# create collision hull mesh
|
||||||
|
bpy.ops.object.mode_set(mode='EDIT')
|
||||||
|
bpy.ops.mesh.select_all(action='SELECT')
|
||||||
|
bpy.ops.mesh.convex_hull()
|
||||||
|
bpy.ops.object.mode_set(mode='OBJECT')
|
||||||
|
bpy.ops.object.modifier_add(type='DECIMATE')
|
||||||
|
bpy.context.object.modifiers["Decimate"].ratio = 0.2
|
||||||
|
|
||||||
|
# export stl
|
||||||
|
stl_path = os.path.join(path, subdir).replace('\\', '/')
|
||||||
|
if not os.path.isdir(stl_path):
|
||||||
|
os.makedirs(stl_path)
|
||||||
|
outpath = os.path.join(stl_path, filename+'.stl')
|
||||||
|
logger.debug('collision:', outpath)
|
||||||
|
|
||||||
|
bpy.ops.export_mesh.stl(filepath=outpath, check_existing=False, filter_glob='*.stl', use_selection=True, global_scale=1.0, use_scene_unit=False, ascii=False, use_mesh_modifiers=True, batch_mode='OFF', axis_forward='Y', axis_up='Z')
|
|
@ -16,7 +16,7 @@ logger = logging.getLogger(__name__)
|
||||||
logging.basicConfig(level=logging.INFO)
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
|
||||||
|
|
||||||
def export_dae(path, subdir="dae"):
|
def export_dae(path, subdir=""):
|
||||||
""" Collada mesh exporter. Exports all objects in scene. """
|
""" Collada mesh exporter. Exports all objects in scene. """
|
||||||
for ob in bpy.context.scene.objects:
|
for ob in bpy.context.scene.objects:
|
||||||
# deselect all but just one object and make it active
|
# deselect all but just one object and make it active
|
||||||
|
|
|
@ -16,7 +16,7 @@ logger = logging.getLogger(__name__)
|
||||||
logging.basicConfig(level=logging.INFO)
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
|
||||||
|
|
||||||
def export_obj(path, subdir="obj"):
|
def export_obj(path, subdir=""):
|
||||||
""" OBJ mesh exporter. Exports all objects in scene. """
|
""" OBJ mesh exporter. Exports all objects in scene. """
|
||||||
for ob in bpy.context.scene.objects:
|
for ob in bpy.context.scene.objects:
|
||||||
# deselect all but just one object and make it active
|
# deselect all but just one object and make it active
|
||||||
|
|
|
@ -16,7 +16,7 @@ logger = logging.getLogger(__name__)
|
||||||
logging.basicConfig(level=logging.INFO)
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
|
||||||
|
|
||||||
def export_stl(path, subdir="stl"):
|
def export_stl(path, subdir=""):
|
||||||
""" STL mesh exporter. Exports all objects in scene. """
|
""" STL mesh exporter. Exports all objects in scene. """
|
||||||
for ob in bpy.context.scene.objects:
|
for ob in bpy.context.scene.objects:
|
||||||
# deselect all but just one object and make it active
|
# deselect all but just one object and make it active
|
||||||
|
@ -24,14 +24,6 @@ def export_stl(path, subdir="stl"):
|
||||||
ob.select_set(state=True)
|
ob.select_set(state=True)
|
||||||
bpy.context.view_layer.objects.active = ob
|
bpy.context.view_layer.objects.active = ob
|
||||||
filename = bpy.context.active_object.name
|
filename = bpy.context.active_object.name
|
||||||
# create collision hull mesh
|
|
||||||
bpy.ops.object.mode_set(mode='EDIT')
|
|
||||||
bpy.ops.mesh.select_all(action='SELECT')
|
|
||||||
bpy.ops.mesh.convex_hull()
|
|
||||||
bpy.ops.object.mode_set(mode='OBJECT')
|
|
||||||
bpy.ops.object.modifier_add(type='DECIMATE')
|
|
||||||
bpy.context.object.modifiers["Decimate"].ratio = 0.2
|
|
||||||
|
|
||||||
# export stl
|
# export stl
|
||||||
stl_path = os.path.join(path, subdir).replace('\\', '/')
|
stl_path = os.path.join(path, subdir).replace('\\', '/')
|
||||||
if not os.path.isdir(stl_path):
|
if not os.path.isdir(stl_path):
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
## Пакетное производство 3д ассетов из объектов сцены Freecad
|
### freecad_to_asset.py
|
||||||
|
|
||||||
|
Пакетное производство 3д ассетов из объектов сцены Freecad
|
||||||
|
|
||||||
Поддерживается работа поверх Blender в качестве модуля!
|
Поддерживается работа поверх Blender в качестве модуля!
|
||||||
|
|
||||||
|
@ -10,3 +12,21 @@
|
||||||
- обработку mesh объектов для использования в качестве ассетов
|
- обработку mesh объектов для использования в качестве ассетов
|
||||||
- импорт FEM материалов и назначение их для mesh объектов
|
- импорт FEM материалов и назначение их для mesh объектов
|
||||||
- экспорт mesh объектов в требуемые форматы
|
- экспорт mesh объектов в требуемые форматы
|
||||||
|
|
||||||
|
### asp_sdf_to_asset.py
|
||||||
|
|
||||||
|
Пакетное производство 3д ассетов из объектов сцены Freecad по описанию Генератора подсборок ASP
|
||||||
|
|
||||||
|
Поддерживается работа поверх Blender в качестве модуля!
|
||||||
|
|
||||||
|
Сценарий производит:
|
||||||
|
- импорт solid объектов в Blender сцену
|
||||||
|
- имена solid объектов в mesh объекты
|
||||||
|
- тесселяцию solid объектов с заданным уровнем
|
||||||
|
- выбор состава подсборки из SDF файла описания
|
||||||
|
- позиция деталей подсборки из SDF файла описания
|
||||||
|
- ретопологию mesh объектов с заданным уровнем
|
||||||
|
- обработку mesh объектов для использования в качестве ассетов
|
||||||
|
- импорт FEM материалов и назначение их для mesh объектов
|
||||||
|
- экспорт mesh объектов в STL mesh
|
||||||
|
- экспорт ассета подсборки BLEND
|
||||||
|
|
77
cg/pipeline/asp_sdf_to_asset.py
Normal file
77
cg/pipeline/asp_sdf_to_asset.py
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
DESCRIPTION.
|
||||||
|
Subassembly models setup from SDFormat file.
|
||||||
|
Script selected, transform, exported subassembly models.
|
||||||
|
Support Blender compiled as a Python Module only!
|
||||||
|
"""
|
||||||
|
__version__ = "0.1"
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import sys
|
||||||
|
import xml.etree.ElementTree as ET
|
||||||
|
import os
|
||||||
|
sys.path.append('../blender/')
|
||||||
|
from import_fcstd.importer import importer
|
||||||
|
from utils.remove_collections import remove_collections
|
||||||
|
from utils.cleanup_orphan_data import cleanup_orphan_data
|
||||||
|
from remesh import asset_setup
|
||||||
|
from export.stl import export_stl
|
||||||
|
|
||||||
|
sys.path.append('/home/bm/bin/blender-git/blender_bin') # import blender module
|
||||||
|
import bpy
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
|
||||||
|
|
||||||
|
def sdf_to_subassembly(assembly_path):
|
||||||
|
""" Setup scene by SDFormat file description """
|
||||||
|
assembly_sdf = os.path.join(assembly_path, 'assembly.sdf').replace('\\', '/')
|
||||||
|
|
||||||
|
mytree = ET.parse(assembly_sdf)
|
||||||
|
myroot = mytree.getroot()
|
||||||
|
|
||||||
|
models_transforms = {}
|
||||||
|
for models in myroot.iter('model'):
|
||||||
|
for models_childs in models:
|
||||||
|
# if hasattr(models_childs.find('pose'), 'text'): is this better?
|
||||||
|
if models_childs.find('pose') is not None:
|
||||||
|
pose = models_childs.find('pose').text
|
||||||
|
logger.debug(models.attrib['name'], pose)
|
||||||
|
pose_vectors = [float(x) * 0.001 for x in pose.split()]
|
||||||
|
models_transforms[models.attrib['name']] = pose_vectors
|
||||||
|
|
||||||
|
# TODO add models <==> objects compare validation
|
||||||
|
|
||||||
|
for obj in bpy.context.scene.objects:
|
||||||
|
if obj.name in models_transforms:
|
||||||
|
obj_transforms = models_transforms[obj.name]
|
||||||
|
obj.location = obj_transforms[:3]
|
||||||
|
obj.rotation_mode = 'XYZ'
|
||||||
|
obj.rotation_euler = obj_transforms[3:] # may be TODO
|
||||||
|
else:
|
||||||
|
bpy.data.objects.remove(bpy.data.objects[obj.name], do_unlink=True)
|
||||||
|
logger.info(obj.name, '- is not in assemly objects. Deleted!')
|
||||||
|
|
||||||
|
|
||||||
|
def asp_asset_pipeline(fcstd_path, export_path, assembly_path, tessellation=20):
|
||||||
|
""" Setup FreeCAD scene to CG asset """
|
||||||
|
remove_collections()
|
||||||
|
cleanup_orphan_data()
|
||||||
|
importer(fcstd_path, tessellation)
|
||||||
|
sdf_to_subassembly(assembly_path)
|
||||||
|
asset_setup()
|
||||||
|
bpy.ops.wm.save_as_mainfile(filepath=blend_path)
|
||||||
|
export_stl(export_path)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
fcstd_path = '/media/disk/robossembler/project/pipeline/asp/1.FCStd'
|
||||||
|
blend_path = '/media/disk/robossembler/project/pipeline/asp/1.blend'
|
||||||
|
assembly_path = '/media/disk/robossembler/project/pipeline/asp/asp-generation'
|
||||||
|
assembly_meshes_path = os.path.join(assembly_path, 'meshes').replace('\\', '/')
|
||||||
|
export_path = assembly_meshes_path
|
||||||
|
|
||||||
|
asp_asset_pipeline(fcstd_path, export_path, assembly_path, tessellation=20)
|
||||||
|
logger.info("Assets setup finished without errors")
|
|
@ -14,7 +14,7 @@ from utils.remove_collections import remove_collections
|
||||||
from utils.cleanup_orphan_data import cleanup_orphan_data
|
from utils.cleanup_orphan_data import cleanup_orphan_data
|
||||||
from remesh import asset_setup
|
from remesh import asset_setup
|
||||||
from export.dae import export_dae
|
from export.dae import export_dae
|
||||||
from export.stl import export_stl
|
from export.collision import export_col_stl
|
||||||
|
|
||||||
sys.path.append('/home/bm/bin/blender-git/blender_bin') # import blender module
|
sys.path.append('/home/bm/bin/blender-git/blender_bin') # import blender module
|
||||||
import bpy
|
import bpy
|
||||||
|
@ -31,7 +31,7 @@ def freecad_asset_pipeline(fcstd_path, export_path, tessellation=20):
|
||||||
asset_setup()
|
asset_setup()
|
||||||
bpy.ops.wm.save_as_mainfile(filepath="/home/bm/test.blend")
|
bpy.ops.wm.save_as_mainfile(filepath="/home/bm/test.blend")
|
||||||
export_dae(export_path)
|
export_dae(export_path)
|
||||||
export_stl(export_path)
|
export_col_stl(export_path)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue