From f9bff64f0ded124851223bc6233a8073205e11d1 Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Mon, 30 Jan 2023 13:43:58 +0500 Subject: [PATCH] ifc geonodes modifier prototype --- .../scripts/geonodes_modifier_prototype.py | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 src/blenderbim/scripts/geonodes_modifier_prototype.py diff --git a/src/blenderbim/scripts/geonodes_modifier_prototype.py b/src/blenderbim/scripts/geonodes_modifier_prototype.py new file mode 100644 index 0000000000..c33cbb2a04 --- /dev/null +++ b/src/blenderbim/scripts/geonodes_modifier_prototype.py @@ -0,0 +1,101 @@ +import ifcopenshell +import blenderbim.tool as tool +from blenderbim.bim.ifc import IfcStore + +import bpy +import bmesh +import json + +# Below is the code for +# prototype for geonodes modifier (similar to ifc sverchok modifier) + +# Since geonodes cannot be evaluated without input context (unlike sverchok) +# we add geonodes modifier to current object, add the node graph to it, +# get the data, save it to ifc pset and then remove the modifier. +# But it also saves the data taking into account all other existing modifiers. +# Removing other modifiers sounds a bit destructive +# but without it they will be reapplied to the saved geometry + +# At this point I'm not sure if that's really will be useful for users and won't be just confusing. +# and therefore I leave this modifier just as prototype + + +def update_geometry_data(): + obj = bpy.context.active_object + element = tool.Ifc.get_entity(obj) + # props = obj.BIMGeonodesProperties + # node_group = props.node_group + node_group = bpy.data.node_groups["Geometry Nodes"] + + # get geo nodes modifier + currently_added_modifiers = [m for m in obj.modifiers if m.type == "NODES" and m.node_group == node_group] + if not currently_added_modifiers: + m = obj.modifiers.new(name="ifc_geo_nodes", type="NODES") + m.node_group = node_group + else: + m = currently_added_modifiers[0] + m.node_group = node_group + + # save data to pset + depsgraph = bpy.context.evaluated_depsgraph_get() + geo_mesh = obj.evaluated_get(depsgraph).data + geo_data = { + "vertices": [v.co for v in geo_mesh.vertices], + "edges": [e.vertices[:] for e in geo_mesh.edges], + "polygons": [f.vertices[:] for f in geo_mesh.polygons], + } + psets = ifcopenshell.util.element.get_psets(element) + pset = psets.get("BBIM_Geonodes", None) + if pset: + pset = tool.Ifc.get().by_id(pset["id"]) + else: + pset = ifcopenshell.api.run("pset.add_pset", tool.Ifc.get(), product=element, name="BBIM_Geonodes") + ifcopenshell.api.run( + "pset.edit_pset", + tool.Ifc.get(), + pset=pset, + properties={"Data": json.dumps(geo_data, default=list)}, + ) + + # remove the redundant modifier + if not currently_added_modifiers: + obj.modifiers.remove(m) + + # update current geometry from saved data + update_geonodes_modifier() + + +def update_geonodes_modifier(): + obj = bpy.context.active_object + element = tool.Ifc.get_entity(obj) + psets = ifcopenshell.util.element.get_psets(element) + pset = psets.get("BBIM_Geonodes", None) + sverchok_data = json.loads(pset["Data"]) if pset else dict() + + vertices = sverchok_data.get("vertices", []) + edges = sverchok_data.get("edges", []) + faces = sverchok_data.get("polygons", []) + + bm = bmesh.new() + bm.verts.index_update() + bm.edges.index_update() + bm.faces.index_update() + + new_verts = [bm.verts.new(v) for v in vertices] + new_edges = [bm.edges.new([new_verts[vi] for vi in edge]) for edge in edges] + new_faces = [bm.faces.new([new_verts[vi] for vi in face]) for face in faces] + bm.verts.index_update() + bm.edges.index_update() + bm.faces.index_update() + + if bpy.context.object.mode == "EDIT": + bmesh.update_edit_mesh(obj.data) + else: + bm.to_mesh(obj.data) + bm.free() + obj.data.update() + IfcStore.edited_objs.add(obj) + + +if __name__ == "__main__": + update_geometry_data()