Special geometry data on meshes are also loaded as geometry attributes.

No functional change apart from in dissolve_triangulated_edges where it will try to load the attribute if it can. I believe it will be easier in the long term to use the builtin Attributes system. Unfortunately Curves don't support Attributes yet. Also, attributes are more lightweight compared to custom properties.
This commit is contained in:
Gorgious56
2025-01-03 16:12:51 +01:00
parent fe6a6d1a0d
commit fd7a7d44c3
3 changed files with 45 additions and 16 deletions
+24
View File
@@ -1032,6 +1032,30 @@ class Blender(bonsai.core.tool.Blender):
if child_obj:
yield child_obj
class Attribute:
@classmethod
def fill_attribute(cls, data: bpy.types.ID, attribute_name: str, domain: str, data_type: str, values):
attribute = cls.ensure_attribute(data, attribute_name, domain, data_type)
attribute.data.foreach_set(cls.get_data_name(data_type), values)
@classmethod
def ensure_attribute(cls, data: bpy.types.ID, attribute_name: str, domain: str, data_type: str):
attribute = data.attributes.get(attribute_name)
if not attribute:
attribute = data.attributes.new(attribute_name, domain=domain, type=data_type)
return attribute
@classmethod
def get_data_name(cls, data_type: str):
if data_type in ("FLOAT", "INT", "BOOLEAN", "STRING"):
return "value"
if data_type.endswith("VECTOR"):
return "vector"
elif data_type.endswith("COLOR"):
return "color"
else:
raise NotImplementedError(f"Attribute data type `{data_type}` not implemented yet")
@classmethod
def get_last_commit_hash(cls) -> Union[str, None]:
"""Get 8 symbols of last commit hash if it's present or return None otherwise."""
+10 -2
View File
@@ -261,9 +261,17 @@ class Geometry(bonsai.core.tool.Geometry):
mesh_element.is_a("IfcShapeRepresentation")
and ifcopenshell.util.representation.resolve_representation(mesh_element).RepresentationType
== "AdvancedBrep"
) or mesh_element.is_a("IfcAdvancedBrep"):
) or mesh_element.is_a("IfcAdvancedBrep") or not obj.data:
return
if obj.data and "ios_edges" in obj.data:
if hasattr(obj.data, "attributes") and (ios_edges_attribute := obj.data.attributes.get("ios_edges")):
# Edges from a forced triangulation are stored as True in a boolean attribute on the mesh
bm = bmesh.new()
bm.from_mesh(obj.data)
edges_to_dissolve = [e for i, e in enumerate(bm.edges) if not ios_edges_attribute.data[i].value]
bmesh.ops.dissolve_edges(bm, edges=edges_to_dissolve)
bm.to_mesh(obj.data)
bm.free()
elif "ios_edges" in obj.data:
bm = bmesh.new()
bm.from_mesh(obj.data)
edges_to_keep = set(map(frozenset, obj.data["ios_edges"]))
+11 -14
View File
@@ -939,7 +939,8 @@ class Loader(bonsai.core.tool.Loader):
# we do `.tolist()` because Blender can't assign `np.int32` to it's custom attributes
ios_edges = list(set(tuple(e) for e in ifcopenshell.util.shape.get_edges(geometry).tolist()))
mesh["ios_edges"] = ios_edges
mesh["ios_item_ids"] = ifcopenshell.util.shape.get_faces_representation_item_ids(geometry).tolist()
ios_item_ids = ifcopenshell.util.shape.get_faces_representation_item_ids(geometry).tolist()
mesh["ios_item_ids"] = ios_item_ids
mesh.vertices.add(num_vertices)
mesh.vertices.foreach_set("co", verts)
@@ -981,19 +982,13 @@ class Loader(bonsai.core.tool.Loader):
if rep.is_a("IfcShapeRepresentation"):
tool.Loader.load_indexed_colour_map(rep, mesh)
ios_edges_indices = [(e[0], e[1]) for e in ios_edges]
attribute_ios_edges = mesh.attributes.get("ios_edges")
if not attribute_ios_edges:
attribute_ios_edges = mesh.attributes.new("ios_edges", domain="EDGE", type="BOOLEAN")
attribute_ios_edges.data.foreach_set(
"value",
[
(e.vertices[0], e.vertices[1]) in ios_edges_indices
or (e.vertices[1], e.vertices[0]) in ios_edges_indices
for e in mesh.edges
],
)
ios_edges_values = [
(e.vertices[0], e.vertices[1]) in ios_edges
or (e.vertices[1], e.vertices[0]) in ios_edges
for e in mesh.edges
]
tool.Blender.Attribute.fill_attribute(mesh, "ios_edges", "EDGE", "BOOLEAN", ios_edges_values)
tool.Blender.Attribute.fill_attribute(mesh, "ios_item_ids", "FACE", "INT", ios_item_ids)
else:
e = geometry.edges
v = verts
@@ -1006,9 +1001,11 @@ class Loader(bonsai.core.tool.Loader):
except AttributeError:
edges_item_ids = []
mesh["ios_edges_item_ids"] = edges_item_ids
tool.Blender.Attribute.fill_attribute(mesh, "ios_edges_item_ids", "EDGE", "INT", edges_item_ids)
mesh["ios_materials"] = [m.instance_id() for m in geometry.materials]
mesh["ios_material_ids"] = geometry.material_ids
tool.Blender.Attribute.fill_attribute(mesh, "ios_material_ids", "FACE", "INT", geometry.material_ids)
return mesh
@classmethod