Texture support is now compatible with glTF texture maps

This commit is contained in:
Dion Moult
2022-02-09 11:34:59 +11:00
parent 4eaf0e7a9c
commit dd7a47ab99
19 changed files with 380 additions and 336 deletions
+41 -50
View File
@@ -32,8 +32,6 @@ class TestAddStyle:
"style.add_surface_style", style="style", ifc_class="IfcSurfaceStyleRendering", 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(None)
assert subject.add_style(ifc, style, obj="obj") == "style"
@@ -48,8 +46,6 @@ class TestAddStyle:
"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()
@@ -66,93 +62,88 @@ class TestRemoveStyle:
class TestUpdateStyleColours:
def test_updating_rendering_style_if_available(self, ifc, style):
ifc.get_entity("obj").should_be_called().will_return("element")
style.get_style("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_adding_a_rendering_style_if_not_available(self, ifc, style):
ifc.get_entity("obj").should_be_called().will_return("element")
style.get_style("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.get_style("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.get_style("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()
class TestUpdateStyleTextures:
def test_updating_an_existing_texture_style(self, ifc, style):
style.get_style("obj").should_be_called().will_return("element")
style.get_uv_maps("representation").should_be_called().will_return("uv_maps")
ifc.run("style.add_surface_textures", material="obj", uv_maps="uv_maps").should_be_called().will_return(
"textures"
)
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.remove_surface_style", style="style").should_be_called()
ifc.run(
"style.add_surface_style",
style="element",
ifc_class="IfcSurfaceStyleWithTextures",
attributes={"Textures": "ifc_textures"},
attributes={"Textures": "textures"},
).should_be_called()
subject.update_style_colours(ifc, style, obj="obj")
subject.update_style_textures(ifc, style, obj="obj", representation="representation")
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()
def test_adding_a_fresh_texture_style(self, ifc, style):
style.get_style("obj").should_be_called().will_return("element")
style.get_uv_maps("representation").should_be_called().will_return("uv_maps")
ifc.run("style.add_surface_textures", material="obj", uv_maps="uv_maps").should_be_called().will_return(
"textures"
)
style.get_surface_texture_style("obj").should_be_called().will_return(None)
ifc.run(
"style.add_surface_style",
style="element",
ifc_class="IfcSurfaceStyleWithTextures",
attributes={"Textures": "textures"},
).should_be_called()
subject.update_style_textures(ifc, style, obj="obj", representation="representation")
def test_removing_an_texture_if_no_textures_can_be_added(self, ifc, style):
style.get_style("obj").should_be_called().will_return("element")
style.get_uv_maps("representation").should_be_called().will_return("uv_maps")
ifc.run("style.add_surface_textures", material="obj", uv_maps="uv_maps").should_be_called().will_return(None)
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")
ifc.run("style.remove_surface_style", style="style").should_be_called()
subject.update_style_textures(ifc, style, obj="obj", representation="representation")
def test_doing_nothing_if_no_existing_texture_and_we_cannot_add_a_new_texture(self, ifc, style):
style.get_style("obj").should_be_called().will_return("element")
style.get_uv_maps("representation").should_be_called().will_return("uv_maps")
ifc.run("style.add_surface_textures", material="obj", uv_maps="uv_maps").should_be_called().will_return(None)
style.get_surface_texture_style("obj").should_be_called().will_return(None)
subject.update_style_textures(ifc, style, obj="obj", representation="representation")
class TestUnlinkStyle:
@@ -464,10 +464,14 @@ class TestShouldForceTriangulation(NewFile):
class TestShouldGenerateUVs(NewFile):
def test_needs_mesh_data(self):
ifc = ifcopenshell.file()
tool.Ifc.set(ifc)
obj = bpy.data.objects.new("Object", None)
assert subject.should_generate_uvs(obj) is False
def test_needs_nodes(self):
ifc = ifcopenshell.file()
tool.Ifc.set(ifc)
obj = bpy.data.objects.new("Object", bpy.data.meshes.new("Mesh"))
material = bpy.data.materials.new("Material")
obj.data.materials.append(material)
@@ -475,6 +479,8 @@ class TestShouldGenerateUVs(NewFile):
assert subject.should_generate_uvs(obj) is False
def test_needs_texture_coordinates_with_a_uv_output(self):
ifc = ifcopenshell.file()
tool.Ifc.set(ifc)
obj = bpy.data.objects.new("Object", bpy.data.meshes.new("Mesh"))
material = bpy.data.materials.new("Material")
obj.data.materials.append(material)
@@ -489,6 +495,8 @@ class TestShouldGenerateUVs(NewFile):
assert subject.should_generate_uvs(obj) is True
def test_accepts_a_uv_map_node(self):
ifc = ifcopenshell.file()
tool.Ifc.set(ifc)
obj = bpy.data.objects.new("Object", bpy.data.meshes.new("Mesh"))
material = bpy.data.materials.new("Material")
obj.data.materials.append(material)
+15 -135
View File
@@ -42,42 +42,6 @@ class TestCanSupportRenderingStyle(NewFile):
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")
@@ -338,6 +302,14 @@ class TestGetSurfaceShadingStyle(NewFile):
obj.BIMMaterialProperties.ifc_style_id = style.id()
assert subject.get_surface_shading_style(obj) == style_item
def test_do_not_get_rendering_styles(self):
tool.Ifc.set(ifcopenshell.file())
style_item = tool.Ifc.get().createIfcSurfaceStyleRendering()
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_shading_style(obj) is None
class TestGetSurfaceTextureStyle(NewFile):
def test_run(self):
@@ -349,105 +321,13 @@ class TestGetSurfaceTextureStyle(NewFile):
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 TestGetUVMaps(NewFile):
def test_run(self):
ifc = ifcopenshell.file()
item = ifc.createIfcTriangulatedFaceSet()
uv_map = ifc.createIfcIndexedTriangleTextureMap(MappedTo=item)
representation = ifc.createIfcShapeRepresentation(Items=[item])
assert subject.get_uv_maps(representation) == [uv_map]
class TestImportSurfaceAttributes(NewFile):