framework/cg/blender/import_cad/build_blender_scene.py
2023-09-12 09:07:30 +00:00

144 lines
5.1 KiB
Python

# -*- coding: utf-8 -*-
# Original code by (C) 2019 yorikvanhavre <yorik@uncreated.net>
# Copyright (C) 2023 Ilia Kurochkin <brothermechanic@gmail.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
'''
DESCRIPTION.
- Build Blender scene from JSON data.
- Setup hierarchy.
- Setup materials.
- Setup LCS points.
- Apply Bledner scene transforms.
'''
__version__ = '0.1'
import logging
import random
import bpy
from blender.utils.object_transforms import apply_transforms
from blender.import_cad.import_hierarchy import (fc_placement,
hierarchy)
from blender.import_cad.import_materials import (assign_materials,
assign_black)
logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO)
# COLLECTIONS NAMIG CONVENTION
part_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'
scene_scale = 0.001
blackbody_mat_name = 'Robossembler_Black_Body'
def json_to_blend(js_data):
''' Reads JSON data and creates Blender scene '''
part_collection = bpy.data.collections.new(part_col_name)
bpy.context.scene.collection.children.link(part_collection)
lcs_collection = bpy.data.collections.new(lcs_col_name)
bpy.context.scene.collection.children.link(lcs_collection)
hierarchy_collection = bpy.data.collections.new(hierarchy_col_name)
bpy.context.scene.collection.children.link(hierarchy_collection)
fc_file = list(js_data.keys())[0]
bobjs = []
bobjs_for_render = []
for js_obj in js_data[fc_file]:
bobj = None
if js_data[fc_file][js_obj]['type'] == 'LCS':
bobj = bpy.data.objects.new(js_obj, None)
bobj.empty_display_type = 'ARROWS'
bobj.empty_display_size = round(random.uniform(0.05, 0.15), 3)
bobj.show_in_front = True
lcs_collection.objects.link(bobj)
elif js_data[fc_file][js_obj]['type'] == 'PART':
if js_data[fc_file][js_obj].get('mesh'):
verts = js_data[fc_file][js_obj]['mesh'][0]
edges = []
faces = js_data[fc_file][js_obj]['mesh'][1]
# create blender object data
bmesh = bpy.data.meshes.new(name=js_obj)
bmesh.from_pydata(verts, edges, faces)
bmesh.update()
bobj = bpy.data.objects.new(js_obj, bmesh)
part_collection.objects.link(bobj)
if bobj:
fc_placement(bobj,
js_data[fc_file][js_obj]['fc_location'],
js_data[fc_file][js_obj]['fc_rotation'],
scene_scale)
if bobj.type == 'MESH':
bobj.scale = (scene_scale, scene_scale, scene_scale)
apply_transforms(bobj, scale=True)
# construct assembly hierarchy
hierarchy_objs = hierarchy(bobj,
js_data[fc_file][js_obj]['hierarchy'],
scene_scale)
for hierarchy_obj in hierarchy_objs:
hierarchy_collection.objects.link(hierarchy_obj)
# one material for the whole object
if bobj.type == 'MESH':
if js_data[fc_file][js_obj].get('material'):
fem_mat = js_data[fc_file][js_obj]['material']
assign_materials(bobj, fem_mat)
bobjs_for_render.append(bobj)
else:
assign_black(bobj)
bobjs.append(bobj)
# losted root lcs inlet workaround
lcs_objects = lcs_collection.objects
if lcs_objects:
root_lcs = [lcs for lcs in lcs_objects if lcs.name.endswith(root)]
if root_lcs:
root_lcs = root_lcs[0]
root_inlet_name = '{}{}'.format(root_lcs.name.split(root)[0], inlet)
if not bpy.data.objects.get(root_inlet_name):
root_inlet = bpy.data.objects.new(root_inlet_name, None)
root_inlet.empty_display_type = 'ARROWS'
root_inlet.empty_display_size = 0.1
root_inlet.show_in_front = True
root_inlet.location = root_lcs.location
root_inlet.rotation_euler = root_lcs.rotation_euler
root_inlet.parent = root_lcs.parent
lcs_collection.objects.link(root_inlet)
else:
logger.info('Lost root LCS object!')
# TODO
# update do not dork
logger.info('Generated %s objects without errors', len(bobjs))
return bobjs_for_render