mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 17:31:45 +00:00
Generating IFC compatible shader graphs
Added new panel. in shader graph N-panel that allows you to create fully GLTF and IFC compatible shader graphs by just tweaking parameters from the panel. Note that it's still saved to IFC only when you hit "Save Current Style", before that it's still just stored in blender. https://imgur.com/a/vmkoLPH The premise is that if you want to have non-external style you'd be able to create it entirely from this panel - so there will no need to guess or to remember which parameters from the graph are supported by IFC and which are not. It's still work in progress, still need to polish it, add support for more reflectance methods and add suport for textures (need to be able to import/export it with .ifc and set them from this panel).
This commit is contained in:
@@ -45,6 +45,7 @@ classes = (
|
|||||||
ui.BIM_PT_style_attributes,
|
ui.BIM_PT_style_attributes,
|
||||||
ui.BIM_PT_external_style_attributes,
|
ui.BIM_PT_external_style_attributes,
|
||||||
ui.BIM_UL_styles,
|
ui.BIM_UL_styles,
|
||||||
|
ui.BIM_PT_STYLE_GRAPH,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -30,11 +30,26 @@ import os
|
|||||||
class UpdateStyleColours(bpy.types.Operator, tool.Ifc.Operator):
|
class UpdateStyleColours(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
bl_idname = "bim.update_style_colours"
|
bl_idname = "bim.update_style_colours"
|
||||||
bl_label = "Save Current Shading Style"
|
bl_label = "Save Current Shading Style"
|
||||||
bl_description = "Save current style values to IfcSurfaceStyleShading"
|
bl_description = (
|
||||||
|
"Save current style values to IfcSurfaceStyleShading.\n\n" + "ALT+CLICK to see saved values details"
|
||||||
|
)
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
|
verbose: bpy.props.BoolProperty(default=False, options={"SKIP_SAVE"})
|
||||||
|
|
||||||
|
def invoke(self, context, event):
|
||||||
|
# verobse print to console on alt+click
|
||||||
|
# make sure to use SKIP_SAVE on property, otherwise it might get stuck
|
||||||
|
if event.type == "LEFTMOUSE" and event.alt:
|
||||||
|
self.verbose = True
|
||||||
|
return self.execute(context)
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
core.update_style_colours(tool.Ifc, tool.Style, obj=context.active_object.active_material)
|
mat = context.active_object.active_material
|
||||||
|
core.update_style_colours(tool.Ifc, tool.Style, obj=mat, verbose=self.verbose)
|
||||||
|
if self.verbose:
|
||||||
|
self.report({"INFO"}, "Check the system console to see saved style properties")
|
||||||
|
tool.Style.set_surface_style_props(mat)
|
||||||
|
|
||||||
|
|
||||||
class UpdateStyleTextures(bpy.types.Operator, tool.Ifc.Operator):
|
class UpdateStyleTextures(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
|
|||||||
@@ -96,9 +96,41 @@ def update_shading_style(self, context):
|
|||||||
|
|
||||||
if rendering_style and texture_style:
|
if rendering_style and texture_style:
|
||||||
tool.Loader.create_surface_style_with_textures(blender_material, rendering_style, texture_style)
|
tool.Loader.create_surface_style_with_textures(blender_material, rendering_style, texture_style)
|
||||||
|
tool.Style.set_surface_style_props(blender_material)
|
||||||
tool.Style.record_shading(blender_material)
|
tool.Style.record_shading(blender_material)
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: support more more methods and also textures
|
||||||
|
REFLECTANCE_METHODS = [
|
||||||
|
("PHYSICAL", "PHYSICAL", ""),
|
||||||
|
("FLAT", "FLAT", ""),
|
||||||
|
# ("METAL", "METAL", ""),
|
||||||
|
# ("MATT", "MATT", ""),
|
||||||
|
# ("GLASS", "GLASS", ""),
|
||||||
|
# ("NOTDEFINED", "NOTDEFINED", ""),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def update_shader_graph(self, context):
|
||||||
|
if not self.update_graph:
|
||||||
|
return
|
||||||
|
|
||||||
|
material = self.id_data
|
||||||
|
style_data = tool.Style.get_surface_style_from_props(material)
|
||||||
|
tool.Loader.create_surface_style_rendering(material, style_data)
|
||||||
|
|
||||||
|
|
||||||
|
def update_graph_get(self):
|
||||||
|
return self.get("update_graph", True)
|
||||||
|
|
||||||
|
|
||||||
|
def update_graph_set(self, value):
|
||||||
|
self["update_graph"] = value
|
||||||
|
if value:
|
||||||
|
material = self.id_data
|
||||||
|
tool.Style.set_surface_style_props(material)
|
||||||
|
|
||||||
|
|
||||||
class BIMStyleProperties(PropertyGroup):
|
class BIMStyleProperties(PropertyGroup):
|
||||||
attributes: CollectionProperty(name="Attributes", type=Attribute)
|
attributes: CollectionProperty(name="Attributes", type=Attribute)
|
||||||
is_editing: BoolProperty(name="Is Editing")
|
is_editing: BoolProperty(name="Is Editing")
|
||||||
@@ -113,3 +145,42 @@ class BIMStyleProperties(PropertyGroup):
|
|||||||
default="Shading",
|
default="Shading",
|
||||||
update=update_shading_style,
|
update=update_shading_style,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# GLTF style properties
|
||||||
|
update_graph: BoolProperty(
|
||||||
|
name="Update Shade Graph on Prop Change",
|
||||||
|
description="Update shader graph in real time\nas you update style properties",
|
||||||
|
default=True,
|
||||||
|
get=update_graph_get,
|
||||||
|
set=update_graph_set,
|
||||||
|
)
|
||||||
|
reflectance_method: EnumProperty(
|
||||||
|
name="Reflectance Method",
|
||||||
|
description="Reflectance method to use for the material",
|
||||||
|
items=REFLECTANCE_METHODS,
|
||||||
|
default="PHYSICAL",
|
||||||
|
update=update_shader_graph,
|
||||||
|
)
|
||||||
|
surface_color: bpy.props.FloatVectorProperty(
|
||||||
|
name="Surface Color",
|
||||||
|
subtype="COLOR",
|
||||||
|
default=(1, 1, 1, 1),
|
||||||
|
min=0.0,
|
||||||
|
max=1.0,
|
||||||
|
size=4,
|
||||||
|
update=update_shader_graph,
|
||||||
|
)
|
||||||
|
diffuse_color: bpy.props.FloatVectorProperty(
|
||||||
|
name="Diffuse Color",
|
||||||
|
subtype="COLOR",
|
||||||
|
default=(1, 1, 1, 1),
|
||||||
|
min=0.0,
|
||||||
|
max=1.0,
|
||||||
|
size=4,
|
||||||
|
update=update_shader_graph,
|
||||||
|
)
|
||||||
|
transparency: bpy.props.FloatProperty(
|
||||||
|
name="Transparency", default=0.0, min=0.0, max=1.0, update=update_shader_graph
|
||||||
|
)
|
||||||
|
roughness: bpy.props.FloatProperty(name="Roughness", default=0.0, min=0.0, max=1.0, update=update_shader_graph)
|
||||||
|
metallic: bpy.props.FloatProperty(name="Metallic", default=0.0, min=0.0, max=1.0, update=update_shader_graph)
|
||||||
|
|||||||
@@ -65,6 +65,24 @@ class BIM_PT_styles(Panel):
|
|||||||
self.layout.template_list("BIM_UL_styles", "", self.props, "styles", self.props, "active_style_index")
|
self.layout.template_list("BIM_UL_styles", "", self.props, "styles", self.props, "active_style_index")
|
||||||
|
|
||||||
|
|
||||||
|
def draw_style_ui(self, context):
|
||||||
|
mat = context.material
|
||||||
|
props = mat.BIMMaterialProperties
|
||||||
|
style_props = mat.BIMStyleProperties
|
||||||
|
row = self.layout.row(align=True)
|
||||||
|
if not props.ifc_style_id:
|
||||||
|
row.operator("bim.add_style", icon="ADD")
|
||||||
|
return
|
||||||
|
|
||||||
|
row.prop(style_props, "active_style_type", icon="SHADING_RENDERED", text="")
|
||||||
|
row.operator("bim.update_current_style", icon="FILE_REFRESH", text="")
|
||||||
|
row = self.layout.row(align=True)
|
||||||
|
row.operator("bim.update_style_colours", icon="GREASEPENCIL")
|
||||||
|
row.operator("bim.update_style_textures", icon="TEXTURE", text="")
|
||||||
|
row.operator("bim.unlink_style", icon="UNLINKED", text="")
|
||||||
|
row.operator("bim.remove_style", icon="X", text="").style = props.ifc_style_id
|
||||||
|
|
||||||
|
|
||||||
class BIM_PT_style(MaterialButtonsPanel, Panel):
|
class BIM_PT_style(MaterialButtonsPanel, Panel):
|
||||||
bl_label = "IFC Style"
|
bl_label = "IFC Style"
|
||||||
bl_idname = "BIM_PT_style"
|
bl_idname = "BIM_PT_style"
|
||||||
@@ -81,22 +99,11 @@ class BIM_PT_style(MaterialButtonsPanel, Panel):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
props = context.active_object.active_material.BIMMaterialProperties
|
|
||||||
style_props = context.active_object.active_material.BIMStyleProperties
|
|
||||||
mat = context.material
|
mat = context.material
|
||||||
row = self.layout.row(align=True)
|
props = mat.BIMMaterialProperties
|
||||||
|
draw_style_ui(self, context)
|
||||||
if not props.ifc_style_id:
|
if not props.ifc_style_id:
|
||||||
row.operator("bim.add_style", icon="ADD")
|
|
||||||
return
|
return
|
||||||
|
|
||||||
row.prop(style_props, "active_style_type", icon="SHADING_RENDERED", text="")
|
|
||||||
row.operator("bim.update_current_style", icon="FILE_REFRESH", text="")
|
|
||||||
row = self.layout.row(align=True)
|
|
||||||
row.operator("bim.update_style_colours", icon="GREASEPENCIL")
|
|
||||||
row.operator("bim.update_style_textures", icon="TEXTURE", text="")
|
|
||||||
row.operator("bim.unlink_style", icon="UNLINKED", text="")
|
|
||||||
row.operator("bim.remove_style", icon="X", text="").style = props.ifc_style_id
|
|
||||||
|
|
||||||
row = self.layout.row(align=True)
|
row = self.layout.row(align=True)
|
||||||
row.prop(mat, "diffuse_color", text="Viewport Color" if mat.use_nodes else "Render Color")
|
row.prop(mat, "diffuse_color", text="Viewport Color" if mat.use_nodes else "Render Color")
|
||||||
|
|
||||||
@@ -212,3 +219,38 @@ class BIM_UL_styles(UIList):
|
|||||||
row2 = row.row()
|
row2 = row.row()
|
||||||
row2.alignment = "RIGHT"
|
row2.alignment = "RIGHT"
|
||||||
row2.label(text=str(item.total_elements))
|
row2.label(text=str(item.total_elements))
|
||||||
|
|
||||||
|
|
||||||
|
class BIM_PT_STYLE_GRAPH(Panel):
|
||||||
|
bl_idname = "BIM_PT_style_graph"
|
||||||
|
bl_space_type = "NODE_EDITOR"
|
||||||
|
bl_label = "IFC Style Graph Settings"
|
||||||
|
bl_region_type = "UI"
|
||||||
|
bl_category = "BBIM"
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
layout = self.layout
|
||||||
|
props = context.active_object.active_material.BIMStyleProperties
|
||||||
|
|
||||||
|
draw_style_ui(self, context)
|
||||||
|
layout.separator()
|
||||||
|
box = layout.box()
|
||||||
|
box.label(text="Creating shader from this panel")
|
||||||
|
box.label(text="ensures that shader is")
|
||||||
|
box.label(text="GLTF compatible")
|
||||||
|
box.label(text="and therefore will be ")
|
||||||
|
box.label(text="stored in IFC safely.")
|
||||||
|
layout.separator()
|
||||||
|
|
||||||
|
layout.prop(props, "update_graph", text="Graph Auto Update")
|
||||||
|
layout.label(text="Reflectance Method:")
|
||||||
|
layout.prop(props, "reflectance_method", text="")
|
||||||
|
layout.prop(props, "surface_color")
|
||||||
|
layout.prop(props, "transparency")
|
||||||
|
layout.prop(props, "diffuse_color")
|
||||||
|
|
||||||
|
if props.reflectance_method == "PHYSICAL":
|
||||||
|
layout.prop(props, "metallic")
|
||||||
|
|
||||||
|
if props.reflectance_method not in ("FLAT", "NOTDEFINED"):
|
||||||
|
layout.prop(props, "roughness")
|
||||||
|
|||||||
@@ -491,7 +491,7 @@ class BIM_OT_add_section_plane(bpy.types.Operator):
|
|||||||
continue
|
continue
|
||||||
material.blend_method = "HASHED"
|
material.blend_method = "HASHED"
|
||||||
material.shadow_method = "HASHED"
|
material.shadow_method = "HASHED"
|
||||||
material_output = self.get_node(material.node_tree.nodes, "OUTPUT_MATERIAL")
|
material_output = tool.Blender.get_material_node(material, "OUTPUT_MATERIAL", {"is_active_output": True})
|
||||||
if not material_output:
|
if not material_output:
|
||||||
continue
|
continue
|
||||||
from_socket = material_output.inputs[0].links[0].from_socket
|
from_socket = material_output.inputs[0].links[0].from_socket
|
||||||
@@ -501,11 +501,6 @@ class BIM_OT_add_section_plane(bpy.types.Operator):
|
|||||||
material.node_tree.links.new(from_socket, section_override.inputs[0])
|
material.node_tree.links.new(from_socket, section_override.inputs[0])
|
||||||
material.node_tree.links.new(section_override.outputs[0], material_output.inputs[0])
|
material.node_tree.links.new(section_override.outputs[0], material_output.inputs[0])
|
||||||
|
|
||||||
def get_node(self, nodes, node_type):
|
|
||||||
for node in nodes:
|
|
||||||
if node.type == node_type:
|
|
||||||
return node
|
|
||||||
|
|
||||||
|
|
||||||
class BIM_OT_remove_section_plane(bpy.types.Operator):
|
class BIM_OT_remove_section_plane(bpy.types.Operator):
|
||||||
"""Remove selected section plane. No effect if executed on a regular object"""
|
"""Remove selected section plane. No effect if executed on a regular object"""
|
||||||
|
|||||||
@@ -54,18 +54,28 @@ def remove_style(ifc, material, style_tool, style=None):
|
|||||||
style_tool.import_presentation_styles(style_tool.get_active_style_type())
|
style_tool.import_presentation_styles(style_tool.get_active_style_type())
|
||||||
|
|
||||||
|
|
||||||
def update_style_colours(ifc, style, obj=None):
|
def update_style_colours(ifc, style, obj=None, verbose=False):
|
||||||
element = style.get_style(obj)
|
element = style.get_style(obj)
|
||||||
|
|
||||||
if style.can_support_rendering_style(obj):
|
if style.can_support_rendering_style(obj):
|
||||||
rendering_style = style.get_surface_rendering_style(obj)
|
style_elements = style.get_style_elements(obj)
|
||||||
attributes = style.get_surface_rendering_attributes(obj)
|
rendering_style = style_elements.get("IfcSurfaceStyleRendering", None)
|
||||||
|
texture_style = style_elements.get("IfcSurfaceStyleWithTextures", None)
|
||||||
|
attributes = style.get_surface_rendering_attributes(obj, verbose)
|
||||||
if rendering_style:
|
if rendering_style:
|
||||||
ifc.run("style.edit_surface_style", style=rendering_style, attributes=attributes)
|
ifc.run("style.edit_surface_style", style=rendering_style, attributes=attributes)
|
||||||
else:
|
else:
|
||||||
ifc.run(
|
ifc.run(
|
||||||
"style.add_surface_style", style=element, ifc_class="IfcSurfaceStyleRendering", attributes=attributes
|
"style.add_surface_style", style=element, ifc_class="IfcSurfaceStyleRendering", attributes=attributes
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# # TODO: uncomment to support saving textures
|
||||||
|
# # TODO: uvs?
|
||||||
|
# textures = ifc.run("style.add_surface_textures", material=obj)
|
||||||
|
# if not texture_style and textures:
|
||||||
|
# texture_style = ifc.get().createIfcSurfaceStyleWithTextures()
|
||||||
|
# if texture_style:
|
||||||
|
# texture_style.Textures = textures
|
||||||
else:
|
else:
|
||||||
shading_style = style.get_surface_shading_style(obj)
|
shading_style = style.get_surface_shading_style(obj)
|
||||||
attributes = style.get_surface_shading_attributes(obj)
|
attributes = style.get_surface_shading_attributes(obj)
|
||||||
|
|||||||
@@ -107,6 +107,13 @@ class Blender:
|
|||||||
return False
|
return False
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def show_error_message(cls, text):
|
||||||
|
"""useful for showing error messages outside blender operators"""
|
||||||
|
def error(self, context):
|
||||||
|
self.layout.label(text=text)
|
||||||
|
bpy.context.window_manager.popup_menu(error, title="Error", icon="ERROR")
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_viewport_context(cls):
|
def get_viewport_context(cls):
|
||||||
"""Get viewport area context for context overriding.
|
"""Get viewport area context for context overriding.
|
||||||
@@ -170,13 +177,13 @@ class Blender:
|
|||||||
shader_editor.pin = previous_pin_setting
|
shader_editor.pin = previous_pin_setting
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_material_node(cls, blender_material, node_type):
|
def get_material_node(cls, blender_material, node_type, kwargs={}):
|
||||||
"""returns first node from the `blender_material` shader graph with type `node_type`"""
|
"""returns first node from the `blender_material` shader graph with type `node_type`"""
|
||||||
if not blender_material.use_nodes:
|
if not blender_material.use_nodes:
|
||||||
return
|
return
|
||||||
nodes = blender_material.node_tree.nodes
|
nodes = blender_material.node_tree.nodes
|
||||||
for node in nodes:
|
for node in nodes:
|
||||||
if node.type == node_type:
|
if node.type == node_type and all(getattr(node, a) == kwargs[a] for a in kwargs):
|
||||||
return node
|
return node
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import ifcopenshell.util.element
|
|||||||
import blenderbim.core.tool
|
import blenderbim.core.tool
|
||||||
import blenderbim.tool as tool
|
import blenderbim.tool as tool
|
||||||
import os
|
import os
|
||||||
import mathutils
|
from mathutils import Vector
|
||||||
|
|
||||||
|
|
||||||
# Progressively we'll refactor loading elements into Blender objects into this
|
# Progressively we'll refactor loading elements into Blender objects into this
|
||||||
@@ -58,16 +58,12 @@ class Loader(blenderbim.core.tool.Loader):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create_surface_style_shading(cls, blender_material, surface_style):
|
def create_surface_style_shading(cls, blender_material, surface_style):
|
||||||
|
surface_style = cls.surface_style_to_dict(surface_style)
|
||||||
alpha = 1.0
|
alpha = 1.0
|
||||||
# Transparency was added in IFC4
|
# Transparency was added in IFC4
|
||||||
if hasattr(surface_style, "Transparency") and surface_style.Transparency:
|
if transparency := surface_style.get("Transparency", None):
|
||||||
alpha = 1 - surface_style.Transparency
|
alpha = 1 - transparency
|
||||||
blender_material.diffuse_color = (
|
blender_material.diffuse_color = surface_style["SurfaceColour"][:3] + (alpha,)
|
||||||
surface_style.SurfaceColour.Red,
|
|
||||||
surface_style.SurfaceColour.Green,
|
|
||||||
surface_style.SurfaceColour.Blue,
|
|
||||||
alpha,
|
|
||||||
)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def restart_material_node_tree(cls, blender_material):
|
def restart_material_node_tree(cls, blender_material):
|
||||||
@@ -76,44 +72,75 @@ class Loader(blenderbim.core.tool.Loader):
|
|||||||
for n in nodes[:]:
|
for n in nodes[:]:
|
||||||
nodes.remove(n)
|
nodes.remove(n)
|
||||||
output = nodes.new("ShaderNodeOutputMaterial")
|
output = nodes.new("ShaderNodeOutputMaterial")
|
||||||
|
output.location = Vector((300, 300))
|
||||||
bsdf = nodes.new("ShaderNodeBsdfPrincipled")
|
bsdf = nodes.new("ShaderNodeBsdfPrincipled")
|
||||||
|
bsdf.location = Vector((10, 300))
|
||||||
links.new(bsdf.outputs["BSDF"], output.inputs["Surface"])
|
links.new(bsdf.outputs["BSDF"], output.inputs["Surface"])
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def surface_style_to_dict(cls, surface_style):
|
||||||
|
if isinstance(surface_style, dict):
|
||||||
|
return surface_style
|
||||||
|
surface_style = surface_style.get_info()
|
||||||
|
color_to_tuple = lambda x: (x.Red, x.Green, x.Blue, 1)
|
||||||
|
|
||||||
|
if surface_style["SurfaceColour"]:
|
||||||
|
surface_style["SurfaceColour"] = color_to_tuple(surface_style["SurfaceColour"])
|
||||||
|
|
||||||
|
if surface_style["DiffuseColour"] and surface_style["DiffuseColour"].is_a("IfcColourRgb"):
|
||||||
|
surface_style["DiffuseColour"] = ("IfcColourRgb", color_to_tuple(surface_style["DiffuseColour"]))
|
||||||
|
|
||||||
|
elif surface_style["DiffuseColour"] and surface_style["DiffuseColour"].is_a("IfcNormalisedRatioMeasure"):
|
||||||
|
diffuse_color_value = surface_style["DiffuseColour"].wrappedValue
|
||||||
|
diffuse_color = [v * diffuse_color_value for v in surface_style["SurfaceColor"][:3]] + [1]
|
||||||
|
surface_style["DiffuseColour"] = ("IfcNormalisedRatioMeasure", diffuse_color)
|
||||||
|
else:
|
||||||
|
surface_style["DiffuseColour"] = None
|
||||||
|
|
||||||
|
if surface_style["SpecularColour"] and surface_style["SpecularColour"].is_a("IfcNormalisedRatioMeasure"):
|
||||||
|
surface_style["SpecularColour"] = surface_style["SpecularColour"].wrappedValue
|
||||||
|
else:
|
||||||
|
surface_style["SpecularColour"] = None
|
||||||
|
|
||||||
|
if surface_style["SpecularHighlight"] and surface_style["SpecularHighlight"].is_a("IfcSpecularRoughness"):
|
||||||
|
surface_style["SpecularHighlight"] = surface_style["SpecularHighlight"].wrappedValue
|
||||||
|
else:
|
||||||
|
surface_style["SpecularHighlight"] = None
|
||||||
|
return surface_style
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create_surface_style_rendering(cls, blender_material, surface_style):
|
def create_surface_style_rendering(cls, blender_material, surface_style):
|
||||||
|
surface_style = cls.surface_style_to_dict(surface_style)
|
||||||
cls.create_surface_style_shading(blender_material, surface_style)
|
cls.create_surface_style_shading(blender_material, surface_style)
|
||||||
if surface_style.ReflectanceMethod in ["PHYSICAL", "NOTDEFINED"]:
|
|
||||||
|
reflectance_method = surface_style["ReflectanceMethod"]
|
||||||
|
if reflectance_method not in ("PHYSICAL", "NOTDEFINED", "FLAT"):
|
||||||
|
print(f'WARNING. Unsupported reflectance method "{reflectance_method}" on style {surface_style}')
|
||||||
|
return
|
||||||
|
|
||||||
|
if reflectance_method in ["PHYSICAL", "NOTDEFINED"]:
|
||||||
blender_material.use_nodes = True
|
blender_material.use_nodes = True
|
||||||
cls.restart_material_node_tree(blender_material)
|
cls.restart_material_node_tree(blender_material)
|
||||||
bsdf = tool.Blender.get_material_node(blender_material, "BSDF_PRINCIPLED")
|
bsdf = tool.Blender.get_material_node(blender_material, "BSDF_PRINCIPLED")
|
||||||
if surface_style.DiffuseColour:
|
if surface_style["DiffuseColour"]:
|
||||||
if surface_style.DiffuseColour.is_a("IfcColourRgb"):
|
color_type, color_value = surface_style["DiffuseColour"]
|
||||||
bsdf.inputs["Base Color"].default_value = (
|
if color_type == "IfcColourRgb":
|
||||||
surface_style.DiffuseColour.Red,
|
bsdf.inputs["Base Color"].default_value = color_value
|
||||||
surface_style.DiffuseColour.Green,
|
elif color_type == "IfcNormalisedRatioMeasure":
|
||||||
surface_style.DiffuseColour.Blue,
|
bsdf.inputs["Base Color"].default_value = color_value
|
||||||
1,
|
if surface_style["SpecularColour"]:
|
||||||
)
|
bsdf.inputs["Metallic"].default_value = surface_style["SpecularColour"]
|
||||||
elif surface_style.DiffuseColour.is_a("IfcNormalisedRatioMeasure"):
|
if surface_style["SpecularHighlight"]:
|
||||||
bsdf.inputs["Base Color"].default_value = (
|
bsdf.inputs["Roughness"].default_value = surface_style["SpecularHighlight"]
|
||||||
surface_style.SurfaceColour.Red * surface_style.DiffuseColour.wrappedValue,
|
if transparency := surface_style.get("Transparency", None):
|
||||||
surface_style.SurfaceColour.Green * surface_style.DiffuseColour.wrappedValue,
|
bsdf.inputs["Alpha"].default_value = 1 - transparency
|
||||||
surface_style.SurfaceColour.Blue * surface_style.DiffuseColour.wrappedValue,
|
|
||||||
1,
|
|
||||||
)
|
|
||||||
if surface_style.SpecularColour and surface_style.SpecularColour.is_a("IfcNormalisedRatioMeasure"):
|
|
||||||
bsdf.inputs["Metallic"].default_value = surface_style.SpecularColour.wrappedValue
|
|
||||||
if surface_style.SpecularHighlight and surface_style.SpecularHighlight.is_a("IfcSpecularRoughness"):
|
|
||||||
bsdf.inputs["Roughness"].default_value = surface_style.SpecularHighlight.wrappedValue
|
|
||||||
if hasattr(surface_style, "Transparency") and surface_style.Transparency:
|
|
||||||
bsdf.inputs["Alpha"].default_value = 1 - surface_style.Transparency
|
|
||||||
blender_material.blend_method = "BLEND"
|
blender_material.blend_method = "BLEND"
|
||||||
|
|
||||||
elif surface_style.ReflectanceMethod == "FLAT":
|
elif reflectance_method == "FLAT":
|
||||||
blender_material.use_nodes = True
|
blender_material.use_nodes = True
|
||||||
cls.restart_material_node_tree(blender_material)
|
cls.restart_material_node_tree(blender_material)
|
||||||
|
|
||||||
output = {n.type: n for n in blender_material.node_tree.nodes}.get("OUTPUT_MATERIAL", None)
|
output = tool.Blender.get_material_node(blender_material, "OUTPUT_MATERIAL")
|
||||||
bsdf = tool.Blender.get_material_node(blender_material, "BSDF_PRINCIPLED")
|
bsdf = tool.Blender.get_material_node(blender_material, "BSDF_PRINCIPLED")
|
||||||
|
|
||||||
mix = blender_material.node_tree.nodes.new(type="ShaderNodeMixShader")
|
mix = blender_material.node_tree.nodes.new(type="ShaderNodeMixShader")
|
||||||
@@ -123,24 +150,21 @@ class Loader(blenderbim.core.tool.Loader):
|
|||||||
blender_material.node_tree.nodes.remove(bsdf)
|
blender_material.node_tree.nodes.remove(bsdf)
|
||||||
|
|
||||||
lightpath = blender_material.node_tree.nodes.new(type="ShaderNodeLightPath")
|
lightpath = blender_material.node_tree.nodes.new(type="ShaderNodeLightPath")
|
||||||
lightpath.location = mix.location - mathutils.Vector((200, -200))
|
lightpath.location = mix.location - Vector((200, -200))
|
||||||
blender_material.node_tree.links.new(lightpath.outputs[0], mix.inputs[0])
|
blender_material.node_tree.links.new(lightpath.outputs[0], mix.inputs[0])
|
||||||
|
|
||||||
bsdf = blender_material.node_tree.nodes.new(type="ShaderNodeBsdfTransparent")
|
bsdf = blender_material.node_tree.nodes.new(type="ShaderNodeBsdfTransparent")
|
||||||
bsdf.location = mix.location - mathutils.Vector((200, 0))
|
bsdf.location = mix.location - Vector((200, 150))
|
||||||
blender_material.node_tree.links.new(bsdf.outputs[0], mix.inputs[1])
|
blender_material.node_tree.links.new(bsdf.outputs[0], mix.inputs[1])
|
||||||
|
|
||||||
rgb = blender_material.node_tree.nodes.new(type="ShaderNodeRGB")
|
rgb = blender_material.node_tree.nodes.new(type="ShaderNodeRGB")
|
||||||
rgb.location = mix.location - mathutils.Vector((200, 200))
|
rgb.location = mix.location - Vector((200, 250))
|
||||||
blender_material.node_tree.links.new(rgb.outputs[0], mix.inputs[2])
|
blender_material.node_tree.links.new(rgb.outputs[0], mix.inputs[2])
|
||||||
|
|
||||||
if surface_style.DiffuseColour and surface_style.DiffuseColour.is_a("IfcColourRgb"):
|
if surface_style["DiffuseColour"]:
|
||||||
rgb.outputs[0].default_value = (
|
color_type, color_value = surface_style["DiffuseColour"]
|
||||||
surface_style.DiffuseColour.Red,
|
if color_type == "IfcColourRgb":
|
||||||
surface_style.DiffuseColour.Green,
|
rgb.outputs[0].default_value = color_value
|
||||||
surface_style.DiffuseColour.Blue,
|
|
||||||
1,
|
|
||||||
)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create_surface_style_with_textures(cls, blender_material, rendering_style, texture_style):
|
def create_surface_style_with_textures(cls, blender_material, rendering_style, texture_style):
|
||||||
@@ -153,73 +177,91 @@ class Loader(blenderbim.core.tool.Loader):
|
|||||||
if not os.path.abspath(texture.URLReference) and tool.Ifc.get_path():
|
if not os.path.abspath(texture.URLReference) and tool.Ifc.get_path():
|
||||||
image_url = os.path.join(os.path.dirname(tool.Ifc.get_path()), texture.URLReference)
|
image_url = os.path.join(os.path.dirname(tool.Ifc.get_path()), texture.URLReference)
|
||||||
|
|
||||||
|
reflectance_method = rendering_style.ReflectanceMethod
|
||||||
|
if reflectance_method not in ("PHYSICAL", "NOTDEFINED", "FLAT"):
|
||||||
|
print(f'WARNING. Unsupported reflectance method "{reflectance_method}" on style {rendering_style}')
|
||||||
|
return
|
||||||
|
|
||||||
if rendering_style.ReflectanceMethod in ["PHYSICAL", "NOTDEFINED"]:
|
if rendering_style.ReflectanceMethod in ["PHYSICAL", "NOTDEFINED"]:
|
||||||
bsdf = tool.Blender.get_material_node(blender_material, "BSDF_PRINCIPLED")
|
bsdf = tool.Blender.get_material_node(blender_material, "BSDF_PRINCIPLED")
|
||||||
if mode == "NORMAL":
|
if mode == "NORMAL":
|
||||||
|
# add normal map node
|
||||||
normalmap = blender_material.node_tree.nodes.new(type="ShaderNodeNormalMap")
|
normalmap = blender_material.node_tree.nodes.new(type="ShaderNodeNormalMap")
|
||||||
normalmap.location = bsdf.location - mathutils.Vector((200, 0))
|
normalmap.location = bsdf.location - Vector((200, 0))
|
||||||
blender_material.node_tree.links.new(normalmap.outputs[0], bsdf.inputs["Normal"])
|
blender_material.node_tree.links.new(normalmap.outputs[0], bsdf.inputs["Normal"])
|
||||||
|
|
||||||
|
# add normal map sampler
|
||||||
node = blender_material.node_tree.nodes.new(type="ShaderNodeTexImage")
|
node = blender_material.node_tree.nodes.new(type="ShaderNodeTexImage")
|
||||||
node.location = normalmap.location - mathutils.Vector((200, 0))
|
node.location = normalmap.location - Vector((200, 0))
|
||||||
image = bpy.data.images.load(image_url)
|
image = bpy.data.images.load(image_url)
|
||||||
image.colorspace_settings.name = "Non-Color"
|
image.colorspace_settings.name = "Non-Color"
|
||||||
node.image = image
|
node.image = image
|
||||||
blender_material.node_tree.links.new(node.outputs[0], normalmap.inputs["Color"])
|
blender_material.node_tree.links.new(node.outputs[0], normalmap.inputs["Color"])
|
||||||
elif mode == "EMISSIVE":
|
|
||||||
output = {n.type: n for n in blender_material.node_tree.nodes}.get("OUTPUT_MATERIAL", None)
|
|
||||||
|
|
||||||
|
elif mode == "EMISSIVE":
|
||||||
|
output = tool.Blender.get_material_node(blender_material, "OUTPUT_MATERIAL")
|
||||||
|
|
||||||
|
# add "Add Shader" node
|
||||||
add = blender_material.node_tree.nodes.new(type="ShaderNodeAddShader")
|
add = blender_material.node_tree.nodes.new(type="ShaderNodeAddShader")
|
||||||
add.location = bsdf.location + mathutils.Vector((200, 0))
|
add.location = bsdf.location + Vector((200, 0))
|
||||||
blender_material.node_tree.links.new(bsdf.outputs[0], add.inputs[1])
|
blender_material.node_tree.links.new(bsdf.outputs[0], add.inputs[1])
|
||||||
blender_material.node_tree.links.new(add.outputs[0], output.inputs[0])
|
blender_material.node_tree.links.new(add.outputs[0], output.inputs[0])
|
||||||
|
|
||||||
|
# add emssion shader node
|
||||||
emission = blender_material.node_tree.nodes.new(type="ShaderNodeEmission")
|
emission = blender_material.node_tree.nodes.new(type="ShaderNodeEmission")
|
||||||
emission.location = add.location - mathutils.Vector((200, 0))
|
emission.location = add.location - Vector((200, 0))
|
||||||
blender_material.node_tree.links.new(emission.outputs[0], add.inputs[0])
|
blender_material.node_tree.links.new(emission.outputs[0], add.inputs[0])
|
||||||
|
|
||||||
|
# add emission texture sampler
|
||||||
node = blender_material.node_tree.nodes.new(type="ShaderNodeTexImage")
|
node = blender_material.node_tree.nodes.new(type="ShaderNodeTexImage")
|
||||||
node.location = emission.location - mathutils.Vector((200, 0))
|
node.location = emission.location - Vector((200, 0))
|
||||||
image = bpy.data.images.load(image_url)
|
image = bpy.data.images.load(image_url)
|
||||||
node.image = image
|
node.image = image
|
||||||
blender_material.node_tree.links.new(node.outputs[0], emission.inputs[0])
|
blender_material.node_tree.links.new(node.outputs[0], emission.inputs[0])
|
||||||
|
|
||||||
elif mode == "METALLICROUGHNESS":
|
elif mode == "METALLICROUGHNESS":
|
||||||
separate = blender_material.node_tree.nodes.new(type="ShaderNodeSeparateRGB")
|
separate = blender_material.node_tree.nodes.new(type="ShaderNodeSeparateRGB")
|
||||||
separate.location = bsdf.location - mathutils.Vector((200, 0))
|
separate.location = bsdf.location - Vector((200, 0))
|
||||||
blender_material.node_tree.links.new(separate.outputs[1], bsdf.inputs["Roughness"])
|
blender_material.node_tree.links.new(separate.outputs[1], bsdf.inputs["Roughness"])
|
||||||
blender_material.node_tree.links.new(separate.outputs[2], bsdf.inputs["Metallic"])
|
blender_material.node_tree.links.new(separate.outputs[2], bsdf.inputs["Metallic"])
|
||||||
|
|
||||||
node = blender_material.node_tree.nodes.new(type="ShaderNodeTexImage")
|
node = blender_material.node_tree.nodes.new(type="ShaderNodeTexImage")
|
||||||
node.location = separate.location - mathutils.Vector((200, 0))
|
node.location = separate.location - Vector((200, 0))
|
||||||
image = bpy.data.images.load(image_url)
|
image = bpy.data.images.load(image_url)
|
||||||
image.colorspace_settings.name = "Non-Color"
|
image.colorspace_settings.name = "Non-Color"
|
||||||
node.image = image
|
node.image = image
|
||||||
blender_material.node_tree.links.new(node.outputs[0], separate.inputs[0])
|
blender_material.node_tree.links.new(node.outputs[0], separate.inputs[0])
|
||||||
|
|
||||||
elif mode == "OCCLUSION":
|
elif mode == "OCCLUSION":
|
||||||
# TODO work out how to implement glTF settings here
|
# TODO work out how to implement glTF settings here
|
||||||
# https://docs.blender.org/manual/en/dev/addons/import_export/scene_gltf2.html
|
# https://docs.blender.org/manual/en/dev/addons/import_export/scene_gltf2.html
|
||||||
pass
|
pass
|
||||||
|
|
||||||
elif mode == "DIFFUSE":
|
elif mode == "DIFFUSE":
|
||||||
node = blender_material.node_tree.nodes.new(type="ShaderNodeTexImage")
|
node = blender_material.node_tree.nodes.new(type="ShaderNodeTexImage")
|
||||||
node.location = bsdf.location - mathutils.Vector((400, 0))
|
node.location = bsdf.location - Vector((400, 0))
|
||||||
image = bpy.data.images.load(image_url)
|
image = bpy.data.images.load(image_url)
|
||||||
node.image = image
|
node.image = image
|
||||||
blender_material.node_tree.links.new(node.outputs[0], bsdf.inputs["Base Color"])
|
blender_material.node_tree.links.new(node.outputs[0], bsdf.inputs["Base Color"])
|
||||||
blender_material.node_tree.links.new(node.outputs[1], bsdf.inputs["Alpha"])
|
blender_material.node_tree.links.new(node.outputs[1], bsdf.inputs["Alpha"])
|
||||||
blender_material.blend_method = "BLEND"
|
blender_material.blend_method = "BLEND"
|
||||||
|
|
||||||
elif rendering_style.ReflectanceMethod == "FLAT":
|
elif rendering_style.ReflectanceMethod == "FLAT":
|
||||||
bsdf = tool.Blender.get_material_node(blender_material, "MIX_SHADER")
|
bsdf = tool.Blender.get_material_node(blender_material, "MIX_SHADER")
|
||||||
if mode == "EMISSIVE":
|
if mode != "EMISSIVE":
|
||||||
node = blender_material.node_tree.nodes.new(type="ShaderNodeTexImage")
|
continue
|
||||||
node.location = bsdf.location - mathutils.Vector((200, 0))
|
|
||||||
image = bpy.data.images.load(image_url)
|
node = blender_material.node_tree.nodes.new(type="ShaderNodeTexImage")
|
||||||
node.image = image
|
node.location = bsdf.location - Vector((200, 0))
|
||||||
blender_material.node_tree.links.new(node.outputs[0], bsdf.inputs[2])
|
image = bpy.data.images.load(image_url)
|
||||||
|
# TODO: orphaned textures after shader recreated?
|
||||||
|
node.image = image
|
||||||
|
blender_material.node_tree.links.new(node.outputs[0], bsdf.inputs[2])
|
||||||
|
|
||||||
if node and getattr(texture, "IsMappedBy", None):
|
if node and getattr(texture, "IsMappedBy", None):
|
||||||
coordinates = texture.IsMappedBy[0]
|
coordinates = texture.IsMappedBy[0]
|
||||||
coord = blender_material.node_tree.nodes.new(type="ShaderNodeTexCoord")
|
coord = blender_material.node_tree.nodes.new(type="ShaderNodeTexCoord")
|
||||||
coord.location = node.location - mathutils.Vector((200, 0))
|
coord.location = node.location - Vector((200, 0))
|
||||||
if coordinates.is_a("IfcTextureCoordinateGenerator") and coordinates.Mode == "COORD":
|
if coordinates.is_a("IfcTextureCoordinateGenerator") and coordinates.Mode == "COORD":
|
||||||
blender_material.node_tree.links.new(coord.outputs["Generated"], node.inputs["Vector"])
|
blender_material.node_tree.links.new(coord.outputs["Generated"], node.inputs["Vector"])
|
||||||
elif coordinates.is_a("IfcTextureCoordinateGenerator") and coordinates.Mode == "COORD-EYE":
|
elif coordinates.is_a("IfcTextureCoordinateGenerator") and coordinates.Mode == "COORD-EYE":
|
||||||
|
|||||||
@@ -24,6 +24,16 @@ import blenderbim.tool as tool
|
|||||||
import blenderbim.bim.helper
|
import blenderbim.bim.helper
|
||||||
|
|
||||||
|
|
||||||
|
STYLE_PROPS_MAP = {
|
||||||
|
"reflectance_method": "ReflectanceMethod",
|
||||||
|
"diffuse_color": "DiffuseColour",
|
||||||
|
"surface_color": "SurfaceColour",
|
||||||
|
"transparency": "Transparency",
|
||||||
|
"roughness": "SpecularHighlight",
|
||||||
|
"metallic": "SpecularColour",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class Style(blenderbim.core.tool.Style):
|
class Style(blenderbim.core.tool.Style):
|
||||||
@classmethod
|
@classmethod
|
||||||
def can_support_rendering_style(cls, obj):
|
def can_support_rendering_style(cls, obj):
|
||||||
@@ -87,6 +97,8 @@ class Style(blenderbim.core.tool.Style):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_style_elements(cls, blender_material):
|
def get_style_elements(cls, blender_material):
|
||||||
|
if not blender_material.BIMMaterialProperties.ifc_style_id:
|
||||||
|
return {}
|
||||||
style = tool.Ifc.get().by_id(blender_material.BIMMaterialProperties.ifc_style_id)
|
style = tool.Ifc.get().by_id(blender_material.BIMMaterialProperties.ifc_style_id)
|
||||||
style_elements = {}
|
style_elements = {}
|
||||||
for style in style.Styles:
|
for style in style.Styles:
|
||||||
@@ -94,52 +106,184 @@ class Style(blenderbim.core.tool.Style):
|
|||||||
return style_elements
|
return style_elements
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_surface_rendering_attributes(cls, obj):
|
def get_surface_style_from_props(cls, blender_material):
|
||||||
|
"""convert blender style props to ifc props"""
|
||||||
|
surface_style_data = dict()
|
||||||
|
props = blender_material.BIMStyleProperties
|
||||||
|
for prop_blender, prop_ifc in STYLE_PROPS_MAP.items():
|
||||||
|
surface_style_data[prop_ifc] = getattr(props, prop_blender)
|
||||||
|
if surface_style_data["ReflectanceMethod"] == "PHYSICAL" and tool.Ifc.get_schema() != "IFC4X3":
|
||||||
|
surface_style_data["ReflectanceMethod"] = "NOTDEFINED"
|
||||||
|
surface_style_data["DiffuseColour"] = ("IfcColourRgb", surface_style_data["DiffuseColour"])
|
||||||
|
return surface_style_data
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def set_surface_style_props(cls, blender_material):
|
||||||
|
"""set blender style props based on current surface material"""
|
||||||
|
props = blender_material.BIMStyleProperties
|
||||||
|
# make sure won't be updating while we changing it
|
||||||
|
prev_update_graph_value = props.update_graph
|
||||||
|
props["update_graph"] = False
|
||||||
|
|
||||||
|
style_elements = tool.Style.get_style_elements(blender_material)
|
||||||
|
surface_style = style_elements["IfcSurfaceStyleRendering"]
|
||||||
|
style_data = tool.Loader.surface_style_to_dict(surface_style)
|
||||||
|
if style_data["ReflectanceMethod"] == "NOTDEFINED":
|
||||||
|
style_data["ReflectanceMethod"] = "PHYSICAL"
|
||||||
|
style_data["DiffuseColour"] = style_data["DiffuseColour"][1]
|
||||||
|
|
||||||
|
for prop_blender, prop_ifc in STYLE_PROPS_MAP.items():
|
||||||
|
prop_value = style_data[prop_ifc]
|
||||||
|
# TODO: set to default?
|
||||||
|
if prop_value is None:
|
||||||
|
continue
|
||||||
|
setattr(props, prop_blender, prop_value)
|
||||||
|
|
||||||
|
props["update_graph"] = prev_update_graph_value
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_surface_rendering_attributes(cls, obj, verbose=True):
|
||||||
transparency = 1 - obj.diffuse_color[3]
|
transparency = 1 - obj.diffuse_color[3]
|
||||||
diffuse_color = obj.diffuse_color
|
diffuse_color = obj.diffuse_color
|
||||||
|
|
||||||
|
report = (lambda *x: print(*x)) if verbose else (lambda *x: None)
|
||||||
|
|
||||||
|
viewport_color = {
|
||||||
|
"Name": None,
|
||||||
|
"Red": obj.diffuse_color[0],
|
||||||
|
"Green": obj.diffuse_color[1],
|
||||||
|
"Blue": obj.diffuse_color[2],
|
||||||
|
}
|
||||||
attributes = {
|
attributes = {
|
||||||
"SurfaceColour": {
|
"SurfaceColour": viewport_color,
|
||||||
"Name": None,
|
|
||||||
"Red": obj.diffuse_color[0],
|
|
||||||
"Green": obj.diffuse_color[1],
|
|
||||||
"Blue": obj.diffuse_color[2],
|
|
||||||
},
|
|
||||||
"Transparency": transparency,
|
"Transparency": transparency,
|
||||||
}
|
}
|
||||||
|
GREEN = "\033[32m"
|
||||||
|
BLUE = "\033[1;34m"
|
||||||
|
R = "\033[0m" # RESET symbol
|
||||||
|
|
||||||
bsdfs = {n.type: n for n in obj.node_tree.nodes}
|
def get_input_node(node, input_name=None, of_type=None, input_index=None):
|
||||||
if "BSDF_GLOSSY" in bsdfs:
|
input_pin = node.inputs[input_name] if input_index is None else node.inputs[input_index]
|
||||||
attributes["ReflectanceMethod"] = "METAL"
|
if of_type:
|
||||||
bsdf = bsdfs["BSDF_GLOSSY"]
|
return next((l.from_node for l in input_pin.links if l.from_node.type == of_type), None)
|
||||||
|
return next((l.from_node for l in input_pin.links), None)
|
||||||
|
|
||||||
|
report("--------------------")
|
||||||
|
report("Verbose method of getting surface rendering attributes enabled.")
|
||||||
|
report("If some attribute is not mentioned below, then it won't be saved to IFC.")
|
||||||
|
report("--------------------")
|
||||||
|
report(f"{GREEN}Viewport color{R} saved as {GREEN}SurfaceColour{R}")
|
||||||
|
|
||||||
|
# TODO: make sure bsdf is connected to the output?
|
||||||
|
bsdfs = {n.type: n for n in obj.node_tree.nodes if n.outputs and n.outputs[0].is_linked}
|
||||||
|
if "BSDF_PRINCIPLED" not in bsdfs:
|
||||||
|
report(f"{GREEN}Viewport color alpha{R} saved as {GREEN}Transparency{R}")
|
||||||
|
|
||||||
|
# TODO: should escape referring to pins by their name to support different languages
|
||||||
|
material_output = tool.Blender.get_material_node(obj, "OUTPUT_MATERIAL", {"is_active_output": True})
|
||||||
|
surface_output = get_input_node(material_output, "Surface")
|
||||||
|
|
||||||
|
if surface_output and surface_output.type == "MIX_SHADER":
|
||||||
|
mix_shader = surface_output
|
||||||
|
if (
|
||||||
|
get_input_node(mix_shader, "Fac", "LIGHT_PATH")
|
||||||
|
and get_input_node(mix_shader, input_index=1, of_type="BSDF_TRANSPARENT")
|
||||||
|
and (rgb := get_input_node(mix_shader, input_index=2, of_type="RGB"))
|
||||||
|
):
|
||||||
|
report(
|
||||||
|
f"Because of {BLUE}MIX_SHADER + LIGHT_PATH + BSDF_TRANSPARENT + RGB{R} node setup reflectance method identified as {BLUE}FLAT{R}"
|
||||||
|
)
|
||||||
|
attributes["ReflectanceMethod"] = "FLAT"
|
||||||
|
attributes["SpecularHighlight"] = None
|
||||||
|
report(f"RGB {GREEN}Color{R} saved as {GREEN}DiffuseColour{R}")
|
||||||
|
diffuse_color = rgb.outputs[0].default_value
|
||||||
|
|
||||||
|
elif surface_output and surface_output.type == "BSDF_PRINCIPLED":
|
||||||
|
report(f"Because of {BLUE}BSDF_PRINCIPLED{R} node reflectance method identified as {BLUE}PHYSICAL{R}")
|
||||||
|
attributes["ReflectanceMethod"] = "NOTDEFINED" if tool.Ifc.get_schema() != "IFC4X3" else "PHYSICAL"
|
||||||
|
bsdf = surface_output
|
||||||
|
|
||||||
|
report(f"BSDF {GREEN}Base Color{R} saved as {GREEN}DiffuseColour{R}")
|
||||||
|
diffuse_color = bsdf.inputs["Base Color"].default_value
|
||||||
|
|
||||||
|
report(f"BSDF {GREEN}Metallic{R} saved as {GREEN}SpecularColour{R}")
|
||||||
|
attributes["SpecularColour"] = round(bsdf.inputs["Metallic"].default_value, 3)
|
||||||
|
|
||||||
|
report(f"BSDF {GREEN}Roughness{R} saved as {GREEN}IfcSpecularRoughness{R}")
|
||||||
attributes["SpecularHighlight"] = {"IfcSpecularRoughness": round(bsdf.inputs["Roughness"].default_value, 3)}
|
attributes["SpecularHighlight"] = {"IfcSpecularRoughness": round(bsdf.inputs["Roughness"].default_value, 3)}
|
||||||
|
|
||||||
|
report(f"BSDF {GREEN}Alpha{R} saved as {GREEN}Transparency{R}")
|
||||||
|
attributes["Transparency"] = 1 - bsdf.inputs["Alpha"].default_value
|
||||||
|
|
||||||
|
elif "BSDF_GLOSSY" in bsdfs:
|
||||||
|
attributes["ReflectanceMethod"] = "METAL"
|
||||||
|
report(f"Because of {BLUE}BSDF_GLOSSY{R} node reflectance method identified as {BLUE}METAL{R}")
|
||||||
|
bsdf = bsdfs["BSDF_GLOSSY"]
|
||||||
|
|
||||||
|
report(f"BSDF {GREEN}Roughness{R} saved as {GREEN}IfcSpecularRoughness{R}")
|
||||||
|
attributes["SpecularHighlight"] = {"IfcSpecularRoughness": round(bsdf.inputs["Roughness"].default_value, 3)}
|
||||||
|
|
||||||
|
report(f"BSDF {GREEN}Color{R} saved as {GREEN}DiffuseColour{R}")
|
||||||
diffuse_color = bsdf.inputs["Color"].default_value
|
diffuse_color = bsdf.inputs["Color"].default_value
|
||||||
|
|
||||||
elif "BSDF_DIFFUSE" in bsdfs:
|
elif "BSDF_DIFFUSE" in bsdfs:
|
||||||
|
report(f"Because of {BLUE}BSDF_DIFFUSE{R} node reflectance method identified as {BLUE}MATT{R}")
|
||||||
attributes["ReflectanceMethod"] = "MATT"
|
attributes["ReflectanceMethod"] = "MATT"
|
||||||
bsdf = bsdfs["BSDF_DIFFUSE"]
|
bsdf = bsdfs["BSDF_DIFFUSE"]
|
||||||
|
|
||||||
|
report(f"BSDF {GREEN}Roughness{R} saved as {GREEN}IfcSpecularRoughness{R}")
|
||||||
attributes["SpecularHighlight"] = {"IfcSpecularRoughness": round(bsdf.inputs["Roughness"].default_value, 3)}
|
attributes["SpecularHighlight"] = {"IfcSpecularRoughness": round(bsdf.inputs["Roughness"].default_value, 3)}
|
||||||
|
|
||||||
|
report(f"BSDF {GREEN}Color{R} saved as {GREEN}DiffuseColour{R}")
|
||||||
diffuse_color = bsdf.inputs["Color"].default_value
|
diffuse_color = bsdf.inputs["Color"].default_value
|
||||||
|
|
||||||
elif "BSDF_GLASS" in bsdfs:
|
elif "BSDF_GLASS" in bsdfs:
|
||||||
|
report(f"Because of {BLUE}BSDF_GLASS{R} node reflectance method identified as {BLUE}GLASS{R}")
|
||||||
attributes["ReflectanceMethod"] = "GLASS"
|
attributes["ReflectanceMethod"] = "GLASS"
|
||||||
bsdf = bsdfs["BSDF_GLASS"]
|
bsdf = bsdfs["BSDF_GLASS"]
|
||||||
|
|
||||||
|
report(f"BSDF {GREEN}Roughness{R} saved as {GREEN}IfcSpecularRoughness{R}")
|
||||||
attributes["SpecularHighlight"] = {"IfcSpecularRoughness": round(bsdf.inputs["Roughness"].default_value, 3)}
|
attributes["SpecularHighlight"] = {"IfcSpecularRoughness": round(bsdf.inputs["Roughness"].default_value, 3)}
|
||||||
|
|
||||||
|
report(f"BSDF {GREEN}Color{R} saved as {GREEN}DiffuseColour{R}")
|
||||||
diffuse_color = bsdf.inputs["Color"].default_value
|
diffuse_color = bsdf.inputs["Color"].default_value
|
||||||
|
|
||||||
|
# TODO: remove?
|
||||||
elif "EMISSION" in bsdfs:
|
elif "EMISSION" in bsdfs:
|
||||||
|
report(f"Because of {BLUE}EMISSION{R} node reflectance method identified as {BLUE}FLAT{R}")
|
||||||
attributes["ReflectanceMethod"] = "FLAT"
|
attributes["ReflectanceMethod"] = "FLAT"
|
||||||
bsdf = bsdfs["EMISSION"]
|
bsdf = bsdfs["EMISSION"]
|
||||||
|
|
||||||
attributes["SpecularHighlight"] = None
|
attributes["SpecularHighlight"] = None
|
||||||
|
report(f"BSDF {GREEN}Color{R} saved as {GREEN}DiffuseColour{R}")
|
||||||
|
|
||||||
diffuse_color = bsdf.inputs["Color"].default_value
|
diffuse_color = bsdf.inputs["Color"].default_value
|
||||||
|
|
||||||
|
# TODO: remove?
|
||||||
elif "BSDF_PRINCIPLED" in bsdfs:
|
elif "BSDF_PRINCIPLED" in bsdfs:
|
||||||
attributes["ReflectanceMethod"] = "NOTDEFINED"
|
report(f"Because of {BLUE}BSDF_PRINCIPLED{R} node reflectance method identified as {BLUE}PHYSICAL{R}")
|
||||||
|
attributes["ReflectanceMethod"] = "NOTDEFINED" if tool.Ifc.get_schema() != "IFC4X3" else "PHYSICAL"
|
||||||
bsdf = bsdfs["BSDF_PRINCIPLED"]
|
bsdf = bsdfs["BSDF_PRINCIPLED"]
|
||||||
attributes["SpecularColour"] = round(bsdf.inputs["Metallic"].default_value, 3)
|
|
||||||
attributes["SpecularHighlight"] = {"IfcSpecularRoughness": round(bsdf.inputs["Roughness"].default_value, 3)}
|
report(f"BSDF {GREEN}Base Color{R} saved as {GREEN}DiffuseColour{R}")
|
||||||
diffuse_color = bsdf.inputs["Base Color"].default_value
|
diffuse_color = bsdf.inputs["Base Color"].default_value
|
||||||
|
|
||||||
|
report(f"BSDF {GREEN}Metallic{R} saved as {GREEN}SpecularColour{R}")
|
||||||
|
attributes["SpecularColour"] = round(bsdf.inputs["Metallic"].default_value, 3)
|
||||||
|
|
||||||
|
report(f"BSDF {GREEN}Roughness{R} saved as {GREEN}IfcSpecularRoughness{R}")
|
||||||
|
attributes["SpecularHighlight"] = {"IfcSpecularRoughness": round(bsdf.inputs["Roughness"].default_value, 3)}
|
||||||
|
|
||||||
|
report(f"BSDF {GREEN}Alpha{R} saved as {GREEN}Transparency{R}")
|
||||||
attributes["Transparency"] = 1 - bsdf.inputs["Alpha"].default_value
|
attributes["Transparency"] = 1 - bsdf.inputs["Alpha"].default_value
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
report(f"No supported bsdfs found - reflectance method identified as {BLUE}NOTDEFINED{R}")
|
||||||
attributes["ReflectanceMethod"] = "NOTDEFINED"
|
attributes["ReflectanceMethod"] = "NOTDEFINED"
|
||||||
|
|
||||||
attributes["SpecularHighlight"] = None
|
attributes["SpecularHighlight"] = None
|
||||||
attributes["DiffuseColour"] = attributes["SurfaceColour"]
|
report(f"{GREEN}Viewport color{R} saved as {GREEN}DiffuseColour{R}")
|
||||||
|
attributes["DiffuseColour"] = viewport_color
|
||||||
return attributes
|
return attributes
|
||||||
|
|
||||||
attributes["DiffuseColour"] = {
|
attributes["DiffuseColour"] = {
|
||||||
@@ -148,16 +292,12 @@ class Style(blenderbim.core.tool.Style):
|
|||||||
"Green": diffuse_color[1],
|
"Green": diffuse_color[1],
|
||||||
"Blue": diffuse_color[2],
|
"Blue": diffuse_color[2],
|
||||||
}
|
}
|
||||||
|
|
||||||
return attributes
|
return attributes
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_surface_rendering_style(cls, obj):
|
def get_surface_rendering_style(cls, obj):
|
||||||
if obj.BIMMaterialProperties.ifc_style_id:
|
style_elements = cls.get_style_elements(obj)
|
||||||
style = tool.Ifc.get().by_id(obj.BIMMaterialProperties.ifc_style_id)
|
return style_elements.get("IfcSurfaceStyleRendering", None)
|
||||||
items = [s for s in style.Styles if s.is_a("IfcSurfaceStyleRendering")]
|
|
||||||
if items:
|
|
||||||
return items[0]
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_surface_shading_attributes(cls, obj):
|
def get_surface_shading_attributes(cls, obj):
|
||||||
|
|||||||
Reference in New Issue
Block a user