144 lines
5.1 KiB
Python
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
|