From a44a13f04c89eb12c044aea4ec3891d756368919 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Wed, 9 Feb 2022 16:40:23 +1100 Subject: [PATCH] Implement loading glTF style textures from IFC. --- src/blenderbim/blenderbim/bim/import_ifc.py | 95 +++++++++++++++++++-- src/blenderbim/blenderbim/tool/ifc.py | 4 + src/blenderbim/blenderbim/tool/style.py | 1 + 3 files changed, 92 insertions(+), 8 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/import_ifc.py b/src/blenderbim/blenderbim/bim/import_ifc.py index 0d2d11f993..17b771d3d3 100644 --- a/src/blenderbim/blenderbim/bim/import_ifc.py +++ b/src/blenderbim/blenderbim/bim/import_ifc.py @@ -16,6 +16,7 @@ # You should have received a copy of the GNU General Public License # along with BlenderBIM Add-on. If not, see . +import os import re import bpy import time @@ -1354,15 +1355,15 @@ class IfcImporter: blender_material.node_tree.nodes.remove(bsdf) lightpath = blender_material.node_tree.nodes.new(type="ShaderNodeLightPath") - lightpath.location = mix.location - Vector((200, -200)) + lightpath.location = mix.location - mathutils.Vector((200, -200)) blender_material.node_tree.links.new(lightpath.outputs[0], mix.inputs[0]) bsdf = blender_material.node_tree.nodes.new(type="ShaderNodeBsdfTransparent") - bsdf.location = mix.location - Vector((200, 0)) + bsdf.location = mix.location - mathutils.Vector((200, 0)) blender_material.node_tree.links.new(bsdf.outputs[0], mix.inputs[1]) rgb = blender_material.node_tree.nodes.new(type="ShaderNodeRGB") - rgb.location = mix.location - Vector((200, 200)) + rgb.location = mix.location - mathutils.Vector((200, 200)) blender_material.node_tree.links.new(rgb.outputs[0], mix.inputs[2]) if surface_style.DiffuseColour and surface_style.DiffuseColour.is_a("IfcColourRgb"): @@ -1373,11 +1374,89 @@ class IfcImporter: 1, ) - def create_surface_style_with_textures(blender_material, rendering_style, texture_style): - if rendering_style.ReflectanceMethod in ["PHYSICAL", "NOTDEFINED"]: - pass - elif rendering_style.ReflectanceMethod == "FLAT": - pass + def create_surface_style_with_textures(self, blender_material, rendering_style, texture_style): + for texture in texture_style.Textures: + mode = getattr(texture, "Mode", None) + node = None + + if texture.is_a("IfcImageTexture"): + image_url = texture.URLReference + 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) + + if rendering_style.ReflectanceMethod in ["PHYSICAL", "NOTDEFINED"]: + bsdf = blender_material.node_tree.nodes["Principled BSDF"] + if mode == "NORMAL": + normalmap = blender_material.node_tree.nodes.new(type="ShaderNodeNormalMap") + normalmap.location = bsdf.location - mathutils.Vector((200, 0)) + blender_material.node_tree.links.new(normalmap.outputs[0], bsdf.inputs["Normal"]) + + node = blender_material.node_tree.nodes.new(type="ShaderNodeTexImage") + node.location = normalmap.location - mathutils.Vector((200, 0)) + image = bpy.data.images.load(image_url) + image.colorspace_settings.name = "Non-Color" + node.image = image + 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) + + add = blender_material.node_tree.nodes.new(type="ShaderNodeAddShader") + add.location = bsdf.location + mathutils.Vector((200, 0)) + blender_material.node_tree.links.new(bsdf.outputs[0], add.inputs[1]) + blender_material.node_tree.links.new(add.outputs[0], output.inputs[0]) + + emission = blender_material.node_tree.nodes.new(type="ShaderNodeEmission") + emission.location = add.location - mathutils.Vector((200, 0)) + blender_material.node_tree.links.new(emission.outputs[0], add.inputs[0]) + + node = blender_material.node_tree.nodes.new(type="ShaderNodeTexImage") + node.location = emission.location - mathutils.Vector((200, 0)) + image = bpy.data.images.load(image_url) + node.image = image + blender_material.node_tree.links.new(node.outputs[0], emission.inputs[0]) + elif mode == "METALLICROUGHNESS": + separate = blender_material.node_tree.nodes.new(type="ShaderNodeSeparateRGB") + separate.location = bsdf.location - mathutils.Vector((200, 0)) + blender_material.node_tree.links.new(separate.outputs[1], bsdf.inputs["Roughness"]) + blender_material.node_tree.links.new(separate.outputs[2], bsdf.inputs["Metallic"]) + + node = blender_material.node_tree.nodes.new(type="ShaderNodeTexImage") + node.location = separate.location - mathutils.Vector((200, 0)) + image = bpy.data.images.load(image_url) + image.colorspace_settings.name = "Non-Color" + node.image = image + blender_material.node_tree.links.new(node.outputs[0], separate.inputs[0]) + elif mode == "OCCLUSION": + # TODO work out how to implement glTF settings here + # https://docs.blender.org/manual/en/dev/addons/import_export/scene_gltf2.html + pass + elif mode == "DIFFUSE": + node = blender_material.node_tree.nodes.new(type="ShaderNodeTexImage") + node.location = bsdf.location - mathutils.Vector((400, 0)) + image = bpy.data.images.load(image_url) + node.image = image + 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.blend_method = "BLEND" + elif rendering_style.ReflectanceMethod == "FLAT": + bsdf = blender_material.node_tree.nodes["Mix Shader"] + if mode == "EMISSIVE": + node = blender_material.node_tree.nodes.new(type="ShaderNodeTexImage") + node.location = bsdf.location - mathutils.Vector((200, 0)) + image = bpy.data.images.load(image_url) + node.image = image + blender_material.node_tree.links.new(node.outputs[0], bsdf.inputs[2]) + + if node and getattr(texture, "IsMappedBy", None): + coordinates = texture.IsMappedBy[0] + coord = blender_material.node_tree.nodes.new(type="ShaderNodeTexCoord") + coord.location = node.location - mathutils.Vector((200, 0)) + if coordinates.is_a("IfcTextureCoordinateGenerator") and coordinates.Mode == "COORD": + blender_material.node_tree.links.new(coord.outputs["Generated"], node.inputs["Vector"]) + elif coordinates.is_a("IfcTextureCoordinateGenerator") and coordinates.Mode == "COORD-EYE": + blender_material.node_tree.links.new(coord.outputs["Camera"], node.inputs["Vector"]) + else: + blender_material.node_tree.links.new(coord.outputs["UV"], node.inputs["Vector"]) def get_name(self, element): return "{}/{}".format(element.is_a(), element.Name) diff --git a/src/blenderbim/blenderbim/tool/ifc.py b/src/blenderbim/blenderbim/tool/ifc.py index 4651d04ab9..ad719f9c55 100644 --- a/src/blenderbim/blenderbim/tool/ifc.py +++ b/src/blenderbim/blenderbim/tool/ifc.py @@ -35,6 +35,10 @@ class Ifc(blenderbim.core.tool.Ifc): def get(cls): return IfcStore.get_file() + @classmethod + def get_path(cls): + return IfcStore.path + @classmethod def get_schema(cls): if IfcStore.get_file(): diff --git a/src/blenderbim/blenderbim/tool/style.py b/src/blenderbim/blenderbim/tool/style.py index 7e6fed32a0..80f7248d5d 100644 --- a/src/blenderbim/blenderbim/tool/style.py +++ b/src/blenderbim/blenderbim/tool/style.py @@ -94,6 +94,7 @@ class Style(blenderbim.core.tool.Style): elif "BSDF_PRINCIPLED" in bsdfs: attributes["ReflectanceMethod"] = "NOTDEFINED" bsdf = bsdfs["BSDF_PRINCIPLED"] + attributes["SpecularColour"] = round(bsdf.inputs["Metallic"].default_value, 3) 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