Different BSDFs are now recognised for different reflectance methods.

This commit is contained in:
Dion Moult
2022-02-02 17:49:57 +11:00
parent 72397f3aff
commit 8c0b06b36e
5 changed files with 576 additions and 57 deletions
+47 -14
View File
@@ -20,12 +20,22 @@
def add_style(ifc, style, obj=None):
element = ifc.run("style.add_style", name=style.get_name(obj))
ifc.link(element, obj)
ifc.run(
"style.add_surface_style",
style=element,
ifc_class="IfcSurfaceStyleRendering",
attributes=style.get_surface_rendering_attributes(obj),
)
if style.can_support_rendering_style(obj):
attributes = style.get_surface_rendering_attributes(obj)
ifc.run("style.add_surface_style", style=element, ifc_class="IfcSurfaceStyleRendering", attributes=attributes)
else:
attributes = style.get_surface_shading_attributes(obj)
ifc.run("style.add_surface_style", style=element, ifc_class="IfcSurfaceStyleShading", attributes=attributes)
if style.can_support_texture_style(obj):
textures = ifc.run("style.add_surface_textures", textures=style.get_surface_textures(obj))
ifc.run(
"style.add_surface_style",
style=element,
ifc_class="IfcSurfaceStyleWithTextures",
attributes={"Textures": textures},
)
material = ifc.get_entity(obj)
if material:
ifc.run("style.assign_material_style", material=material, style=element, context=style.get_context(obj))
@@ -39,16 +49,39 @@ def remove_style(ifc, style, obj=None):
def update_style_colours(ifc, style, obj=None):
rendering_style = style.get_surface_rendering_style(obj)
if rendering_style:
attributes = style.get_surface_rendering_attributes(obj)
ifc.run("style.edit_surface_style", style=rendering_style, attributes=attributes)
return
element = ifc.get_entity(obj)
shading_style = style.get_surface_shading_style(obj)
if shading_style:
if style.can_support_rendering_style(obj):
rendering_style = style.get_surface_rendering_style(obj)
attributes = style.get_surface_rendering_attributes(obj)
if rendering_style:
ifc.run("style.edit_surface_style", style=rendering_style, attributes=attributes)
else:
ifc.run(
"style.add_surface_style", style=element, ifc_class="IfcSurfaceStyleRendering", attributes=attributes
)
else:
shading_style = style.get_surface_shading_style(obj)
attributes = style.get_surface_shading_attributes(obj)
ifc.run("style.edit_surface_style", style=shading_style, attributes=attributes)
if shading_style:
ifc.run("style.edit_surface_style", style=shading_style, attributes=attributes)
else:
ifc.run("style.add_surface_style", style=element, ifc_class="IfcSurfaceStyleShading", attributes=attributes)
texture_style = style.get_surface_texture_style(obj)
if style.can_support_texture_style(obj):
textures = ifc.run("style.add_surface_textures", textures=style.get_surface_textures(obj))
if texture_style:
ifc.run("style.edit_surface_style", style=texture_style, attributes={"Textures": textures})
else:
ifc.run(
"style.add_surface_style",
style=element,
ifc_class="IfcSurfaceStyleWithTextures",
attributes={"Textures": textures},
)
elif texture_style:
ifc.run("style.remove_style", style=texture_style)
def unlink_style(ifc, style, obj=None):
+4
View File
@@ -360,6 +360,8 @@ class Structural:
@interface
class Style:
def can_support_rendering_style(cls, obj): pass
def can_support_texture_style(cls, obj): pass
def disable_editing(cls, obj): pass
def enable_editing(cls, obj): pass
def export_surface_attributes(cls, obj): pass
@@ -370,6 +372,8 @@ class Style:
def get_surface_rendering_style(cls, obj): pass
def get_surface_shading_attributes(cls, obj): pass
def get_surface_shading_style(cls, obj): pass
def get_surface_texture_style(cls, obj): pass
def get_surface_textures(cls, obj): pass
def import_surface_attributes(cls, style, obj): pass
+134 -12
View File
@@ -23,6 +23,45 @@ import blenderbim.bim.helper
class Style(blenderbim.core.tool.Style):
@classmethod
def can_support_rendering_style(cls, obj):
return obj.use_nodes and hasattr(obj.node_tree, "nodes")
@classmethod
def can_support_texture_style(cls, obj):
if not obj.node_tree:
return False
output = {n.type: n for n in obj.node_tree.nodes}.get("OUTPUT_MATERIAL", None)
if not output:
return False
# For now, we assume only a single BSDF is allowed in our node tree.
try:
bsdf = output.inputs["Surface"].links[0].from_node
except:
return False
# For a quick check whether we have a compatible node tree, we check
# whether or not we have at least one image texture node that has a
# texture assigned and outputs to the bsdf.
textures = [n for n in obj.node_tree.nodes if n.type == "TEX_IMAGE" and n.image]
def does_texture_connect_to(node, target):
if node == target:
return True
try:
output = node.outputs[0].links[0].to_node
return does_texture_connect_to(output, target)
except:
return False
for texture in textures:
if does_texture_connect_to(texture, bsdf):
return True
return False
@classmethod
def disable_editing(cls, obj):
obj.BIMStyleProperties.is_editing = False
@@ -55,12 +94,8 @@ class Style(blenderbim.core.tool.Style):
def get_surface_rendering_attributes(cls, obj):
transparency = obj.diffuse_color[3]
diffuse_color = obj.diffuse_color
if obj.use_nodes and hasattr(obj.node_tree, "nodes") and "Principled BSDF" in obj.node_tree.nodes:
bsdf = obj.node_tree.nodes["Principled BSDF"]
transparency = bsdf.inputs["Alpha"].default_value
diffuse_color = bsdf.inputs["Base Color"].default_value
transparency = 1 - transparency
return {
attributes = {
"SurfaceColour": {
"Name": None,
"Red": obj.diffuse_color[0],
@@ -68,14 +103,50 @@ class Style(blenderbim.core.tool.Style):
"Blue": obj.diffuse_color[2],
},
"Transparency": transparency,
"DiffuseColour": {
"Name": None,
"Red": diffuse_color[0],
"Green": diffuse_color[1],
"Blue": diffuse_color[2],
},
}
bsdfs = {n.type: n for n in obj.node_tree.nodes}
if "BSDF_GLOSSY" in bsdfs:
attributes["ReflectanceMethod"] = "METAL"
bsdf = bsdfs["BSDF_GLOSSY"]
attributes["SpecularHighlight"] = {"IfcSpecularRoughness": round(bsdf.inputs["Roughness"].default_value, 3)}
diffuse_color = bsdf.inputs["Color"].default_value
elif "BSDF_DIFFUSE" in bsdfs:
attributes["ReflectanceMethod"] = "MATT"
bsdf = bsdfs["BSDF_DIFFUSE"]
attributes["SpecularHighlight"] = {"IfcSpecularRoughness": round(bsdf.inputs["Roughness"].default_value, 3)}
diffuse_color = bsdf.inputs["Color"].default_value
elif "BSDF_GLASS" in bsdfs:
attributes["ReflectanceMethod"] = "GLASS"
bsdf = bsdfs["BSDF_GLASS"]
attributes["SpecularHighlight"] = {"IfcSpecularRoughness": round(bsdf.inputs["Roughness"].default_value, 3)}
diffuse_color = bsdf.inputs["Color"].default_value
elif "EMISSION" in bsdfs:
attributes["ReflectanceMethod"] = "FLAT"
bsdf = bsdfs["EMISSION"]
attributes["SpecularHighlight"] = None
diffuse_color = bsdf.inputs["Color"].default_value
elif "BSDF_PRINCIPLED" in bsdfs:
attributes["ReflectanceMethod"] = "NOTDEFINED"
bsdf = bsdfs["BSDF_PRINCIPLED"]
attributes["SpecularHighlight"] = {"IfcSpecularRoughness": round(bsdf.inputs["Roughness"].default_value, 3)}
diffuse_color = bsdf.inputs["Base Color"].default_value
attributes["Transparency"] = 1 - bsdf.inputs["Alpha"].default_value
else:
attributes["ReflectanceMethod"] = "NOTDEFINED"
attributes["SpecularHighlight"] = None
attributes["DiffuseColour"] = attributes["SurfaceColour"]
return attributes
attributes["DiffuseColour"] = {
"Name": None,
"Red": diffuse_color[0],
"Green": diffuse_color[1],
"Blue": diffuse_color[2],
}
return attributes
@classmethod
def get_surface_rendering_style(cls, obj):
if obj.BIMMaterialProperties.ifc_style_id:
@@ -107,6 +178,57 @@ class Style(blenderbim.core.tool.Style):
if items:
return items[0]
@classmethod
def get_surface_texture_style(cls, obj):
if obj.BIMMaterialProperties.ifc_style_id:
style = tool.Ifc.get().by_id(obj.BIMMaterialProperties.ifc_style_id)
items = [s for s in style.Styles if s.is_a("IfcSurfaceStyleWithTextures")]
if items:
return items[0]
@classmethod
def get_surface_textures(cls, obj):
output = {n.type: n for n in obj.node_tree.nodes}.get("OUTPUT_MATERIAL", None)
bsdf = output.inputs["Surface"].links[0].from_node
node_mappings = {
"BSDF_GLOSSY": {
"DIFFUSE": "Color",
"SHININESS": "Roughness",
"NORMAL": "Normal",
},
"BSDF_DIFFUSE": {
"DIFFUSE": "Color",
"SHININESS": "Roughness",
"NORMAL": "Normal",
},
"BSDF_GLASS": {
"DIFFUSE": "Color",
"SHININESS": "Roughness",
"NORMAL": "Normal",
},
"EMISSION": {
"DIFFUSE": "Color",
},
"BSDF_PRINCIPLED": {
"DIFFUSE": "Base Color",
"SHININESS": "Roughness",
"NORMAL": "Normal",
"SPECULAR": "Specular",
"SELFILLUMINATION": "Emission Strength",
"OPACITY": "Alpha",
},
}
maps = {}
if bsdf.type not in node_mappings:
return maps
for map_type, input_name in node_mappings[bsdf.type].items():
if bsdf.inputs[input_name].links:
maps[map_type] = bsdf.inputs[input_name].links[0].from_node
return maps
@classmethod
def import_surface_attributes(cls, style, obj):
obj.BIMStyleProperties.attributes.clear()
+94 -11
View File
@@ -21,28 +21,35 @@ from test.core.bootstrap import ifc, style
class TestAddStyle:
def predict(self, ifc, style, obj="obj"):
style.get_name(obj).should_be_called().will_return("name")
def test_it_adds_a_style_with_rendering_attributes(self, ifc, style):
style.get_name("obj").should_be_called().will_return("name")
ifc.run("style.add_style", name="name").should_be_called().will_return("style")
ifc.link("style", obj).should_be_called()
style.get_surface_rendering_attributes(obj).should_be_called().will_return("attributes")
ifc.link("style", "obj").should_be_called()
style.can_support_rendering_style("obj").should_be_called().will_return(True)
style.get_surface_rendering_attributes("obj").should_be_called().will_return("attributes")
ifc.run(
"style.add_surface_style", style="style", ifc_class="IfcSurfaceStyleRendering", attributes="attributes"
).should_be_called()
ifc.get_entity(obj).should_be_called().will_return(None)
def test_it_adds_a_style_with_rendering_attributes(self, ifc, style):
self.predict(ifc, style)
style.can_support_texture_style("obj").should_be_called().will_return(False)
ifc.get_entity("obj").should_be_called().will_return(None)
assert subject.add_style(ifc, style, obj="obj") == "style"
def test_adding_a_style_linked_to_a_material(self, ifc, style):
style.get_name("obj").should_be_called().will_return("name")
ifc.run("style.add_style", name="name").should_be_called().will_return("style")
ifc.link("style", "obj").should_be_called()
style.get_surface_rendering_attributes("obj").should_be_called().will_return("attributes")
style.can_support_rendering_style("obj").should_be_called().will_return(False)
style.get_surface_shading_attributes("obj").should_be_called().will_return("attributes")
ifc.run(
"style.add_surface_style", style="style", ifc_class="IfcSurfaceStyleRendering", attributes="attributes"
"style.add_surface_style", style="style", ifc_class="IfcSurfaceStyleShading", attributes="attributes"
).should_be_called()
style.can_support_texture_style("obj").should_be_called().will_return(False)
ifc.get_entity("obj").should_be_called().will_return("material")
style.get_context("obj").should_be_called().will_return("context")
ifc.run("style.assign_material_style", material="material", style="style", context="context").should_be_called()
@@ -58,17 +65,93 @@ class TestRemoveStyle:
class TestUpdateStyleColours:
def test_updating_rendering_colours_if_available(self, ifc, style):
def test_updating_rendering_style_if_available(self, ifc, style):
ifc.get_entity("obj").should_be_called().will_return("element")
style.can_support_rendering_style("obj").should_be_called().will_return(True)
style.get_surface_rendering_style("obj").should_be_called().will_return("style")
style.get_surface_rendering_attributes("obj").should_be_called().will_return("attributes")
ifc.run("style.edit_surface_style", style="style", attributes="attributes").should_be_called()
style.get_surface_texture_style("obj").should_be_called().will_return(None)
style.can_support_texture_style("obj").should_be_called().will_return(False)
subject.update_style_colours(ifc, style, obj="obj")
def test_updating_shading_colours_as_a_fallback_if_available(self, ifc, style):
def test_adding_a_rendering_style_if_not_available(self, ifc, style):
ifc.get_entity("obj").should_be_called().will_return("element")
style.can_support_rendering_style("obj").should_be_called().will_return(True)
style.get_surface_rendering_style("obj").should_be_called().will_return(None)
style.get_surface_rendering_attributes("obj").should_be_called().will_return("attributes")
ifc.run(
"style.add_surface_style", style="element", ifc_class="IfcSurfaceStyleRendering", attributes="attributes"
).should_be_called()
style.get_surface_texture_style("obj").should_be_called().will_return(None)
style.can_support_texture_style("obj").should_be_called().will_return(False)
subject.update_style_colours(ifc, style, obj="obj")
def test_updating_shading_style_as_a_fallback_if_available(self, ifc, style):
ifc.get_entity("obj").should_be_called().will_return("element")
style.can_support_rendering_style("obj").should_be_called().will_return(False)
style.get_surface_shading_style("obj").should_be_called().will_return("style")
style.get_surface_shading_attributes("obj").should_be_called().will_return("attributes")
ifc.run("style.edit_surface_style", style="style", attributes="attributes").should_be_called()
style.get_surface_texture_style("obj").should_be_called().will_return(None)
style.can_support_texture_style("obj").should_be_called().will_return(False)
subject.update_style_colours(ifc, style, obj="obj")
def test_adding_a_shading_style_as_a_fallback_if_not_available(self, ifc, style):
ifc.get_entity("obj").should_be_called().will_return("element")
style.can_support_rendering_style("obj").should_be_called().will_return(False)
style.get_surface_shading_style("obj").should_be_called().will_return(None)
style.get_surface_shading_attributes("obj").should_be_called().will_return("attributes")
ifc.run(
"style.add_surface_style", style="element", ifc_class="IfcSurfaceStyleShading", attributes="attributes"
).should_be_called()
style.get_surface_texture_style("obj").should_be_called().will_return(None)
style.can_support_texture_style("obj").should_be_called().will_return(False)
subject.update_style_colours(ifc, style, obj="obj")
def test_updating_texture_style_if_available(self, ifc, style):
ifc.get_entity("obj").should_be_called().will_return("element")
style.can_support_rendering_style("obj").should_be_called().will_return(False)
style.get_surface_shading_style("obj").should_be_called().will_return("style")
style.get_surface_shading_attributes("obj").should_be_called().will_return("attributes")
ifc.run("style.edit_surface_style", style="style", attributes="attributes").should_be_called()
style.get_surface_texture_style("obj").should_be_called().will_return("style")
style.can_support_texture_style("obj").should_be_called().will_return(True)
style.get_surface_textures("obj").should_be_called().will_return("textures")
ifc.run("style.add_surface_textures", textures="textures").should_be_called().will_return("ifc_textures")
ifc.run("style.edit_surface_style", style="style", attributes={"Textures": "ifc_textures"}).should_be_called()
subject.update_style_colours(ifc, style, obj="obj")
def test_adding_texture_style_if_not_available(self, ifc, style):
ifc.get_entity("obj").should_be_called().will_return("element")
style.can_support_rendering_style("obj").should_be_called().will_return(False)
style.get_surface_shading_style("obj").should_be_called().will_return("style")
style.get_surface_shading_attributes("obj").should_be_called().will_return("attributes")
ifc.run("style.edit_surface_style", style="style", attributes="attributes").should_be_called()
style.get_surface_texture_style("obj").should_be_called().will_return(None)
style.can_support_texture_style("obj").should_be_called().will_return(True)
style.get_surface_textures("obj").should_be_called().will_return("textures")
ifc.run("style.add_surface_textures", textures="textures").should_be_called().will_return("ifc_textures")
ifc.run(
"style.add_surface_style",
style="element",
ifc_class="IfcSurfaceStyleWithTextures",
attributes={"Textures": "ifc_textures"},
).should_be_called()
subject.update_style_colours(ifc, style, obj="obj")
def test_removing_a_texture_style_if_no_longer_available(self, ifc, style):
ifc.get_entity("obj").should_be_called().will_return("element")
style.can_support_rendering_style("obj").should_be_called().will_return(False)
style.get_surface_shading_style("obj").should_be_called().will_return("style")
style.get_surface_shading_attributes("obj").should_be_called().will_return("attributes")
ifc.run("style.edit_surface_style", style="style", attributes="attributes").should_be_called()
style.get_surface_texture_style("obj").should_be_called().will_return("style")
style.can_support_texture_style("obj").should_be_called().will_return(False)
ifc.run("style.remove_style", style="style").should_be_called()
subject.update_style_colours(ifc, style, obj="obj")
+297 -20
View File
@@ -16,6 +16,7 @@
# You should have received a copy of the GNU General Public License
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
import os
import bpy
import ifcopenshell
import blenderbim.core.tool
@@ -29,6 +30,54 @@ class TestImplementsTool(NewFile):
assert isinstance(subject(), blenderbim.core.tool.Style)
class TestCanSupportRenderingStyle(NewFile):
def test_anything_with_nodes_can_support_a_rendering_style(self):
obj = bpy.data.materials.new("Material")
obj.use_nodes = True
assert subject.can_support_rendering_style(obj) is True
def test_without_nodes_we_do_not_support_rendering(self):
obj = bpy.data.materials.new("Material")
obj.use_nodes = False
assert subject.can_support_rendering_style(obj) is False
class TestCanSupportTextureStyle(NewFile):
def test_without_nodes_we_do_not_support_textures(self):
obj = bpy.data.materials.new("Material")
obj.use_nodes = False
assert subject.can_support_texture_style(obj) is False
def test_we_need_at_least_one_image_connected_to_a_bsdf(self):
obj = bpy.data.materials.new("Material")
obj.use_nodes = True
bsdf = obj.node_tree.nodes["Principled BSDF"]
node = obj.node_tree.nodes.new(type="ShaderNodeTexImage")
cwd = os.path.dirname(os.path.realpath(__file__))
image_path = os.path.join(cwd, "..", "files", "image.jpg")
node.image = bpy.data.images.load(image_path)
obj.node_tree.links.new(bsdf.inputs["Base Color"], node.outputs["Color"])
assert subject.can_support_texture_style(obj) is True
def test_a_texture_without_an_image_filepath_is_not_supported(self):
obj = bpy.data.materials.new("Material")
obj.use_nodes = True
bsdf = obj.node_tree.nodes["Principled BSDF"]
node = obj.node_tree.nodes.new(type="ShaderNodeTexImage")
obj.node_tree.links.new(bsdf.inputs["Base Color"], node.outputs["Color"])
assert subject.can_support_texture_style(obj) is False
def test_the_texture_needs_to_connect_to_the_bsdf(self):
obj = bpy.data.materials.new("Material")
obj.use_nodes = True
bsdf = obj.node_tree.nodes["Principled BSDF"]
node = obj.node_tree.nodes.new(type="ShaderNodeTexImage")
cwd = os.path.dirname(os.path.realpath(__file__))
image_path = os.path.join(cwd, "..", "files", "image.jpg")
node.image = bpy.data.images.load(image_path)
assert subject.can_support_texture_style(obj) is False
class TestDisableEditing(NewFile):
def test_run(self):
obj = bpy.data.materials.new("Material")
@@ -81,32 +130,14 @@ class TestGetStyle(NewFile):
class TestGetSurfaceRenderingAttributes(NewFile):
def test_get_colours_from_a_basic_material(self):
obj = bpy.data.materials.new("Material")
obj.diffuse_color = [1, 1, 1, 1]
assert subject.get_surface_rendering_attributes(obj) == {
"SurfaceColour": {
"Name": None,
"Red": 1,
"Green": 1,
"Blue": 1,
},
"Transparency": 0,
"DiffuseColour": {
"Name": None,
"Red": 1,
"Green": 1,
"Blue": 1,
},
}
def test_get_different_surface_and_diffuse_colours_from_a_node_based_material(self):
def test_get_different_surface_and_diffuse_colours_from_a_principled_bsdf(self):
obj = bpy.data.materials.new("Material")
obj.diffuse_color = [1, 1, 1, 1]
obj.use_nodes = True
node = obj.node_tree.nodes["Principled BSDF"]
node.inputs["Alpha"].default_value = 0.8
node.inputs["Base Color"].default_value = [0.5, 0.5, 0.5, 0.5]
node.inputs["Roughness"].default_value = 0.2
assert subject.get_surface_rendering_attributes(obj) == {
"SurfaceColour": {
"Name": None,
@@ -121,6 +152,141 @@ class TestGetSurfaceRenderingAttributes(NewFile):
"Green": 0.5,
"Blue": 0.5,
},
"SpecularHighlight": {"IfcSpecularRoughness": 0.2},
"ReflectanceMethod": "NOTDEFINED",
}
def test_get_rendering_styles_from_a_glossy_bsdf(self):
obj = bpy.data.materials.new("Material")
obj.diffuse_color = [1, 1, 1, 1]
obj.use_nodes = True
node = obj.node_tree.nodes["Principled BSDF"]
obj.node_tree.nodes.remove(node)
node = obj.node_tree.nodes.new(type="ShaderNodeBsdfGlossy")
node.inputs["Color"].default_value = [0.5, 0.5, 0.5, 0.5]
node.inputs["Roughness"].default_value = 0.2
assert subject.get_surface_rendering_attributes(obj) == {
"SurfaceColour": {
"Name": None,
"Red": 1,
"Green": 1,
"Blue": 1,
},
"Transparency": 1,
"DiffuseColour": {
"Name": None,
"Red": 0.5,
"Green": 0.5,
"Blue": 0.5,
},
"SpecularHighlight": {"IfcSpecularRoughness": 0.2},
"ReflectanceMethod": "METAL",
}
def test_get_rendering_styles_from_a_diffuse_bsdf(self):
obj = bpy.data.materials.new("Material")
obj.diffuse_color = [1, 1, 1, 1]
obj.use_nodes = True
node = obj.node_tree.nodes["Principled BSDF"]
obj.node_tree.nodes.remove(node)
node = obj.node_tree.nodes.new(type="ShaderNodeBsdfDiffuse")
node.inputs["Color"].default_value = [0.5, 0.5, 0.5, 0.5]
node.inputs["Roughness"].default_value = 0.2
assert subject.get_surface_rendering_attributes(obj) == {
"SurfaceColour": {
"Name": None,
"Red": 1,
"Green": 1,
"Blue": 1,
},
"Transparency": 1,
"DiffuseColour": {
"Name": None,
"Red": 0.5,
"Green": 0.5,
"Blue": 0.5,
},
"SpecularHighlight": {"IfcSpecularRoughness": 0.2},
"ReflectanceMethod": "MATT",
}
def test_get_rendering_styles_from_a_glass_bsdf(self):
obj = bpy.data.materials.new("Material")
obj.diffuse_color = [1, 1, 1, 1]
obj.use_nodes = True
node = obj.node_tree.nodes["Principled BSDF"]
obj.node_tree.nodes.remove(node)
node = obj.node_tree.nodes.new(type="ShaderNodeBsdfGlass")
node.inputs["Color"].default_value = [0.5, 0.5, 0.5, 0.5]
node.inputs["Roughness"].default_value = 0.2
assert subject.get_surface_rendering_attributes(obj) == {
"SurfaceColour": {
"Name": None,
"Red": 1,
"Green": 1,
"Blue": 1,
},
"Transparency": 1,
"DiffuseColour": {
"Name": None,
"Red": 0.5,
"Green": 0.5,
"Blue": 0.5,
},
"SpecularHighlight": {"IfcSpecularRoughness": 0.2},
"ReflectanceMethod": "GLASS",
}
def test_get_rendering_styles_from_a_emission_bsdf(self):
obj = bpy.data.materials.new("Material")
obj.diffuse_color = [1, 1, 1, 1]
obj.use_nodes = True
node = obj.node_tree.nodes["Principled BSDF"]
obj.node_tree.nodes.remove(node)
node = obj.node_tree.nodes.new(type="ShaderNodeEmission")
node.inputs["Color"].default_value = [0.5, 0.5, 0.5, 0.5]
assert subject.get_surface_rendering_attributes(obj) == {
"SurfaceColour": {
"Name": None,
"Red": 1,
"Green": 1,
"Blue": 1,
},
"Transparency": 1,
"DiffuseColour": {
"Name": None,
"Red": 0.5,
"Green": 0.5,
"Blue": 0.5,
},
"SpecularHighlight": None,
"ReflectanceMethod": "FLAT",
}
def test_other_unsupported_bsdfs_copy_the_rendering_style_from_the_shading_colours_as_a_fallback(self):
obj = bpy.data.materials.new("Material")
obj.diffuse_color = [1, 1, 1, 1]
obj.use_nodes = True
node = obj.node_tree.nodes["Principled BSDF"]
obj.node_tree.nodes.remove(node)
node = obj.node_tree.nodes.new(type="ShaderNodeVolumePrincipled")
node.inputs["Color"].default_value = [0.5, 0.5, 0.5, 0.5]
assert subject.get_surface_rendering_attributes(obj) == {
"SurfaceColour": {
"Name": None,
"Red": 1,
"Green": 1,
"Blue": 1,
},
"Transparency": 1,
"DiffuseColour": {
"Name": None,
"Red": 1,
"Green": 1,
"Blue": 1,
},
"SpecularHighlight": None,
"ReflectanceMethod": "NOTDEFINED",
}
@@ -173,6 +339,117 @@ class TestGetSurfaceShadingStyle(NewFile):
assert subject.get_surface_shading_style(obj) == style_item
class TestGetSurfaceTextureStyle(NewFile):
def test_run(self):
tool.Ifc.set(ifcopenshell.file())
style_item = tool.Ifc.get().createIfcSurfaceStyleWithTextures()
style = tool.Ifc.get().createIfcSurfaceStyle(Styles=[style_item])
obj = bpy.data.materials.new("Material")
obj.BIMMaterialProperties.ifc_style_id = style.id()
assert subject.get_surface_texture_style(obj) == style_item
class TestGetSurfaceTextures(NewFile):
def test_get_the_leaf_node_of_each_map_in_a_glossy_bsdf(self):
obj = bpy.data.materials.new("Material")
obj.use_nodes = True
bsdf = obj.node_tree.nodes["Principled BSDF"]
obj.node_tree.nodes.remove(bsdf)
bsdf = obj.node_tree.nodes.new(type="ShaderNodeBsdfGlossy")
output = {n.type: n for n in obj.node_tree.nodes}.get("OUTPUT_MATERIAL", None)
obj.node_tree.links.new(output.inputs["Surface"], bsdf.outputs["BSDF"])
diffuse = obj.node_tree.nodes.new(type="ShaderNodeTexImage")
obj.node_tree.links.new(bsdf.inputs["Color"], diffuse.outputs["Color"])
shininess = obj.node_tree.nodes.new(type="ShaderNodeTexImage")
obj.node_tree.links.new(bsdf.inputs["Roughness"], shininess.outputs["Color"])
normal = obj.node_tree.nodes.new(type="ShaderNodeTexImage")
obj.node_tree.links.new(bsdf.inputs["Normal"], normal.outputs["Color"])
assert subject.get_surface_textures(obj) == {"DIFFUSE": diffuse, "SHININESS": shininess, "NORMAL": normal}
def test_get_the_leaf_node_of_each_map_in_a_diffuse_bsdf(self):
obj = bpy.data.materials.new("Material")
obj.use_nodes = True
bsdf = obj.node_tree.nodes["Principled BSDF"]
obj.node_tree.nodes.remove(bsdf)
bsdf = obj.node_tree.nodes.new(type="ShaderNodeBsdfDiffuse")
output = {n.type: n for n in obj.node_tree.nodes}.get("OUTPUT_MATERIAL", None)
obj.node_tree.links.new(output.inputs["Surface"], bsdf.outputs["BSDF"])
diffuse = obj.node_tree.nodes.new(type="ShaderNodeTexImage")
obj.node_tree.links.new(bsdf.inputs["Color"], diffuse.outputs["Color"])
shininess = obj.node_tree.nodes.new(type="ShaderNodeTexImage")
obj.node_tree.links.new(bsdf.inputs["Roughness"], shininess.outputs["Color"])
normal = obj.node_tree.nodes.new(type="ShaderNodeTexImage")
obj.node_tree.links.new(bsdf.inputs["Normal"], normal.outputs["Color"])
assert subject.get_surface_textures(obj) == {"DIFFUSE": diffuse, "SHININESS": shininess, "NORMAL": normal}
def test_get_the_leaf_node_of_each_map_in_a_glass_bsdf(self):
obj = bpy.data.materials.new("Material")
obj.use_nodes = True
bsdf = obj.node_tree.nodes["Principled BSDF"]
obj.node_tree.nodes.remove(bsdf)
bsdf = obj.node_tree.nodes.new(type="ShaderNodeBsdfGlass")
output = {n.type: n for n in obj.node_tree.nodes}.get("OUTPUT_MATERIAL", None)
obj.node_tree.links.new(output.inputs["Surface"], bsdf.outputs["BSDF"])
diffuse = obj.node_tree.nodes.new(type="ShaderNodeTexImage")
obj.node_tree.links.new(bsdf.inputs["Color"], diffuse.outputs["Color"])
shininess = obj.node_tree.nodes.new(type="ShaderNodeTexImage")
obj.node_tree.links.new(bsdf.inputs["Roughness"], shininess.outputs["Color"])
normal = obj.node_tree.nodes.new(type="ShaderNodeTexImage")
obj.node_tree.links.new(bsdf.inputs["Normal"], normal.outputs["Color"])
assert subject.get_surface_textures(obj) == {"DIFFUSE": diffuse, "SHININESS": shininess, "NORMAL": normal}
def test_get_the_leaf_node_of_each_map_in_a_emission_bsdf(self):
obj = bpy.data.materials.new("Material")
obj.use_nodes = True
bsdf = obj.node_tree.nodes["Principled BSDF"]
obj.node_tree.nodes.remove(bsdf)
bsdf = obj.node_tree.nodes.new(type="ShaderNodeEmission")
output = {n.type: n for n in obj.node_tree.nodes}.get("OUTPUT_MATERIAL", None)
obj.node_tree.links.new(output.inputs["Surface"], bsdf.outputs["Emission"])
diffuse = obj.node_tree.nodes.new(type="ShaderNodeTexImage")
obj.node_tree.links.new(bsdf.inputs["Color"], diffuse.outputs["Color"])
assert subject.get_surface_textures(obj) == {"DIFFUSE": diffuse}
def test_get_the_leaf_node_of_each_map_in_a_principled_bsdf(self):
obj = bpy.data.materials.new("Material")
obj.use_nodes = True
bsdf = obj.node_tree.nodes["Principled BSDF"]
diffuse = obj.node_tree.nodes.new(type="ShaderNodeTexImage")
obj.node_tree.links.new(bsdf.inputs["Base Color"], diffuse.outputs["Color"])
shininess = obj.node_tree.nodes.new(type="ShaderNodeTexImage")
obj.node_tree.links.new(bsdf.inputs["Roughness"], shininess.outputs["Color"])
normal = obj.node_tree.nodes.new(type="ShaderNodeTexImage")
obj.node_tree.links.new(bsdf.inputs["Normal"], normal.outputs["Color"])
specular = obj.node_tree.nodes.new(type="ShaderNodeTexImage")
obj.node_tree.links.new(bsdf.inputs["Specular"], specular.outputs["Color"])
emission = obj.node_tree.nodes.new(type="ShaderNodeTexImage")
obj.node_tree.links.new(bsdf.inputs["Emission Strength"], emission.outputs["Color"])
opacity = obj.node_tree.nodes.new(type="ShaderNodeTexImage")
obj.node_tree.links.new(bsdf.inputs["Alpha"], opacity.outputs["Color"])
assert subject.get_surface_textures(obj) == {
"DIFFUSE": diffuse,
"SHININESS": shininess,
"NORMAL": normal,
"SPECULAR": specular,
"SELFILLUMINATION": emission,
"OPACITY": opacity,
}
class TestImportSurfaceAttributes(NewFile):
def test_run(self):
ifc = ifcopenshell.file()