def _make_lamp_emissive(self, obj: MeshObject, light: list): """ Adds an emission shader to the object materials which are specified in the light list :param obj: The blender object. :param light: A list of two lists. The first list specifies all materials which should act as a lightbulb, the second one lists all materials corresponding to lampshades. """ for i, m in enumerate(obj.get_materials()): mat_name = m.get_name() if "." in mat_name: mat_name = mat_name[:mat_name.find(".")] if mat_name in light[0] or mat_name in light[1]: old_mat_name = m.get_name() if old_mat_name in self._collection_of_mats["lamp"]: # this material was used as a ceiling before use that one obj.set_material(i, self._collection_of_mats["lamp"][old_mat_name]) continue # copy the material if more than one users is using it if m.get_users() > 1: m = m.duplicate() obj.set_material(i, m) # rename the material m.set_name(m.get_name() + "_emission") emission = m.get_nodes_with_type("Emission") if not emission: if mat_name in light[0]: # If the material corresponds to light bulb emission_strength = self.config.get_float("lightbulb_emission_strength", 15) else: # If the material corresponds to a lampshade emission_strength = self.config.get_float("lampshade_emission_strength", 7) m.make_emissive(emission_strength, keep_using_base_color=False, emission_color=m.blender_obj.diffuse_color) self._collection_of_mats["lamp"][old_mat_name] = m
def _make_window_emissive(self, obj: MeshObject): """ Makes the given window object emissive. For each material with alpha < 1. Uses a light path node to make it emit light, but at the same time look like a principle material. Otherwise windows would be completely white. :param obj: A window object. """ for i, m in enumerate(obj.get_materials()): # All parameters imported from the .mtl file are stored inside the principled bsdf node principled_node = m.get_the_one_node_with_type("BsdfPrincipled") alpha = principled_node.inputs['Alpha'].default_value if alpha < 1: mat_name = m.get_name() if mat_name in self._collection_of_mats["window"]: # this material was used as a ceiling before use that one obj.set_material(i, self._collection_of_mats["window"][mat_name]) continue # copy the material if more than one users is using it if m.get_users() > 1: m = m.duplicate() obj.set_material(i, m) # rename the material m.set_name(m.get_name() + "_emission") if not m.get_nodes_with_type('Emission'): transparent_node = m.new_node('ShaderNodeBsdfDiffuse') transparent_node.inputs['Color'].default_value[:3] = (0.285, 0.5, 0.48) m.make_emissive(emission_strength=10, keep_using_base_color=False, emission_color=(1, 1, 1, 1), non_emissive_color_socket=transparent_node.outputs['BSDF']) self._collection_of_mats["window"][mat_name] = m
def _make_ceiling_emissive(obj: MeshObject, collection_of_mats: dict[dict[Material]], ceiling_emission_strength: float = 1.5): """ Makes the given ceiling object emissive, s.t. there is always a little bit ambient light. :param obj: The ceiling object. :param collection_of_mats: A dictionary that contains materials for lamps, windows and ceilings. :param ceiling_emission_strength: The emission strength that should be used for the ceiling. Default: 1.5 """ for i, m in enumerate(obj.get_materials()): mat_name = m.get_name() if mat_name in collection_of_mats["ceiling"]: # this material was used as a ceiling before use that one obj.set_material(i, collection_of_mats["ceiling"][mat_name]) continue # copy the material if more than one users is using it if m.get_users() > 1: m = m.duplicate() obj.set_material(i, m) # rename the material m.set_name(m.get_name() + "_emission") if not m.get_nodes_with_type("Emission") and m.get_nodes_with_type( "BsdfPrincipled"): m.make_emissive(emission_strength=ceiling_emission_strength, emission_color=(1, 1, 1, 1), keep_using_base_color=False) collection_of_mats["ceiling"][mat_name] = m
def _make_lamp_emissive(obj: MeshObject, light: dict[list[str], list[str]], collection_of_mats: dict[dict[Material]], lightbulb_emission_strength: float = 15, lampshade_emission_strength: float = 7): """ Adds an emission shader to the object materials which are specified in the light dictionary :param obj: The blender object. :param light: A dictionary of two lists. The first list specifies all materials which should act as a lightbulb, the second one lists all materials corresponding to lampshades. :param collection_of_mats: A dictionary that contains materials for lamps, windows and ceilings. :param lightbulb_emission_strength: The emission strength that should be used for light bulbs. Default: 15 :param lampshade_emission_strength: The emission strength that should be used for lamp shades. Default: 7 """ for i, m in enumerate(obj.get_materials()): mat_name = m.get_name() if "." in mat_name: mat_name = mat_name[:mat_name.find(".")] if mat_name in light[0] or mat_name in light[1]: old_mat_name = m.get_name() if old_mat_name in collection_of_mats["lamp"]: # this material was used as a ceiling before use that one obj.set_material(i, collection_of_mats["lamp"][old_mat_name]) continue # copy the material if more than one users is using it if m.get_users() > 1: m = m.duplicate() obj.set_material(i, m) # rename the material m.set_name(m.get_name() + "_emission") emission = m.get_nodes_with_type("Emission") if not emission: if mat_name in light[0]: # If the material corresponds to light bulb emission_strength = lightbulb_emission_strength else: # If the material corresponds to a lampshade emission_strength = lampshade_emission_strength m.make_emissive(emission_strength, keep_using_base_color=False, emission_color=m.blender_obj.diffuse_color) collection_of_mats["lamp"][old_mat_name] = m
def _transform_and_colorize_object(object: MeshObject, material_adjustments: list, transform: Matrix = None, parent: MeshObject = None): """ Applies the given transformation to the object and refactors its materials. Material is replaced with an existing material if possible or is changed according to the material_adjustments :param object: The object to use. :param material_adjustments: A list of adjustments to make. (Each element i corresponds to material_i) :param transform: The transformation matrix to apply :param parent: The parent object to which the object should be linked """ if parent is not None: object.set_parent(parent) if transform is not None: # Apply transformation object.apply_T(transform) for i, mat in enumerate(object.get_materials()): # the material name of an object contains a nr, which is mentioned in the material_adjustments index = mat.get_name()[mat.get_name().find("_") + 1:] if "." in index: index = index[:index.find(".")] index = int(index) # check if this index is mentioned in material_adjustments and if a texture is necessary force_texture = index < len( material_adjustments ) and "texture" in material_adjustments[index] SuncgLoader._recreate_material_nodes(mat, force_texture) if index < len(material_adjustments): SuncgLoader._adjust_material_nodes(mat, material_adjustments[index]) mat_type, value = SuncgLoader._get_type_and_value_from_mat(mat) current_mats = SuncgLoader._collection_of_loaded_mats[mat_type] if value in current_mats: object.set_material(i, current_mats[value]) else: # save the current material for later current_mats[value] = mat
def _make_ceiling_emissive(self, obj: MeshObject): """ Makes the given ceiling object emissive, s.t. there is always a little bit ambient light. :param obj: The ceiling object. """ for i, m in enumerate(obj.get_materials()): mat_name = m.get_name() if mat_name in self._collection_of_mats["ceiling"]: # this material was used as a ceiling before use that one obj.set_material(i, self._collection_of_mats["ceiling"][mat_name]) continue # copy the material if more than one users is using it if m.get_users() > 1: m = m.duplicate() obj.set_material(i, m) # rename the material m.set_name(m.get_name() + "_emission") if not m.get_nodes_with_type("Emission") and m.get_nodes_with_type("BsdfPrincipled"): m.make_emissive(emission_strength=self.config.get_float("ceiling_emission_strength", 1.5), emission_color=(1, 1, 1, 1), keep_using_base_color=False) self._collection_of_mats["ceiling"][mat_name] = m