# ***** BEGIN GPL LICENSE BLOCK ***** # # Copyright (C) 2021-2024 Robossembler LLC # # Created by Ilia Kurochkin (brothermechanic) # contact: brothermechanic@yandex.com # # This file is part of Robossembler Framework # project repo: https://gitlab.com/robossembler/framework # # Robossembler Framework 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. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # ***** END GPL LICENSE BLOCK ***** # # coding: utf-8 ''' DESCRIPTION. Blender material generation functions. ''' __version__ = '1.0' import configparser import logging import os import bpy from bpy_extras.node_shader_utils import PrincipledBSDFWrapper from .utils.shininess_to_roughness import shiny_to_rough logger = logging.getLogger(__name__) def black_material(obj): ''' Generate absolute black body shader ''' mat_name = 'Robossembler_Black_Body' if mat_name in bpy.data.materials: # assign material to object if len(obj.material_slots) < 1: obj.data.materials.append(bpy.data.materials[mat_name]) else: obj.material_slots[0].material = bpy.data.materials[mat_name] else: bmat = bpy.data.materials.new(name=mat_name) bmat.use_nodes = True bmat.diffuse_color = (0, 0, 0, 1) principled = bmat.node_tree.nodes['Principled BSDF'] principled.inputs['Base Color'].default_value = (0, 0, 0, 1) principled.inputs['Specular IOR Level'].default_value = 0.0 principled.inputs['Roughness'].default_value = 1.0 # assign material to object if len(obj.material_slots) < 1: obj.data.materials.append(bmat) else: obj.material_slots[0].material = bmat logger.debug('Material was assigned to object: %s -> %s', bmat.name, obj.name) return bmat def material_generator(obj, material_path): ''' Generate shader from FreeCAD's FEM material ''' material = configparser.ConfigParser() with open(material_path, encoding='utf-8') as data: material.read_file(data) mat_name = os.path.splitext(os.path.basename(material_path))[0] if mat_name != material['General']['Name']: logger.warning( 'Material %s is not supported! ' 'For Robossembler CG Pipeline material should have ' 'a same Name and FCMat filename!', mat_name) return black_material(obj) if mat_name in bpy.data.materials: # assign material to object if len(obj.material_slots) < 1: obj.data.materials.append(bpy.data.materials[mat_name]) else: obj.material_slots[0].material = bpy.data.materials[mat_name] logger.debug('Material was assigned to object: %s -> %s', mat_name, obj.name) return obj if 'Rendering' not in material: logger.warning( 'Material %s is not supported! ' 'For Robossembler CG Pipeline material should have ' 'Rendering category with shading parameters!', mat_name) return black_material(obj) rendering = material['Rendering'] if rendering.get('DiffuseColor'): d_col_str = rendering['DiffuseColor'] d_col4 = tuple(map(float, d_col_str[1:-1].split(', '))) d_col = d_col4[:-1] else: logger.warning( 'DiffuseColor not found for %s %s.', mat_name, obj.name) d_col = (1.0, 0.0, 0.0) if rendering.get('Father'): if rendering['Father'] == 'Metal': me = 1 else: me = 0 else: me = 0 if rendering.get('Shininess'): shiny = float(rendering['Shininess']) if shiny == 0: rg = 0.5 else: rg = shiny_to_rough(shiny) else: rg = 0.5 if rendering.get('EmissiveColor'): e_col_str = rendering['EmissiveColor'] e_col4 = tuple(map(float, e_col_str[1:-1].split(', '))) e_col = e_col4[:-1] else: e_col = (0.0, 0.0, 0.0) if rendering.get('Transparency'): tr_str = rendering['Transparency'] alpha = 1.0 - float(tr_str) else: alpha = 1.0 bmat = bpy.data.materials.new(name=mat_name) bmat.use_nodes = True principled = PrincipledBSDFWrapper(bmat, is_readonly=False) principled.base_color = d_col principled.metallic = me principled.roughness = rg principled.emission_color = e_col principled.alpha = alpha bevel = bmat.node_tree.nodes.new(type="ShaderNodeBevel") bevel.location = -300, -300 bevel.samples = 32 bevel.inputs[0].default_value = 0.001 principled_node = bmat.node_tree.nodes["Principled BSDF"] bmat.node_tree.links.new(bevel.outputs['Normal'], principled_node.inputs['Normal']) # assign material to object if len(obj.material_slots) < 1: obj.data.materials.append(bmat) else: obj.material_slots[0].material = bmat logger.debug('Material was assigned to object: %s -> %s', bmat.name, obj.name) return bmat