# coding: utf-8 # Copyright (C) 2023 Ilia Kurochkin # # 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.2' import collections import logging import random import bpy from blender.utils.object_transforms import apply_transforms from blender.import_cad.import_hierarchy import (fc_placement, hierarchy_list) from blender.import_cad.import_materials import (assign_materials, assign_black) logger = logging.getLogger(__name__) scene_scale = 0.001 blackbody_mat_name = 'Robossembler_Black_Body' def json_to_blend(js_data): ''' Reads JSON data and creates Blender scene ''' render_collection = bpy.data.collections.new('Render') bpy.context.scene.collection.children.link(render_collection) fc_file = list(js_data.keys())[0] imported_objects = collections.defaultdict(list) for js_obj in js_data[fc_file]: bobj = None if js_data[fc_file][js_obj]['type'] == 'LCS': if not js_data[fc_file][js_obj].get('Robossembler_SocketFlow'): # TODO test logger.info('LCS %s is not defined!', js_obj) continue 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 for attr in js_data[fc_file][js_obj].keys(): if 'Robossembler' not in attr: continue bobj[attr] = js_data[fc_file][js_obj][attr] render_collection.objects.link(bobj) imported_objects['objs_lcs'].append(bobj.name) 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) render_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_list( bobj, js_data[fc_file][js_obj]['hierarchy'], scene_scale) for hierarchy_obj in hierarchy_objs: render_collection.objects.link(hierarchy_obj) imported_objects['objs_hierarchy'].append(hierarchy_obj.name) # 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) imported_objects['objs_foreground'].append(bobj.name) else: assign_black(bobj) imported_objects['objs_background'].append(bobj.name) logger.info('Generated %s objects without errors', len(sum(list(imported_objects.values()), []))) return imported_objects