From f05d7b1a80ada4a7d7d698dbe949cd0599724ec0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Argentina=20Ortega=20S=C3=A1inz?= Date: Fri, 17 Jan 2025 01:18:25 +0100 Subject: [PATCH] Add 3d mesh generation --- src/fpm/generators/mesh.py | 54 ++++++++++++++++++++++---------------- src/fpm/graph.py | 32 ++++++++++++++++++++++ 2 files changed, 64 insertions(+), 22 deletions(-) diff --git a/src/fpm/generators/mesh.py b/src/fpm/generators/mesh.py index 7a07acf..078efd6 100644 --- a/src/fpm/generators/mesh.py +++ b/src/fpm/generators/mesh.py @@ -6,7 +6,7 @@ create_mesh, create_collection, ) -from fpm.graph import get_floorplan_model_name +from fpm.graph import get_floorplan_model_name, get_3d_structure from fpm.utils import save_file @@ -19,31 +19,41 @@ def generate_3d_mesh(g, output_path, **custom_args): # clear the blender scene clear_scene() - spaces = model.spaces - # create wall spaces - for space in spaces: - for i, wall in enumerate(space.walls): - vertices, faces = wall.generate_3d_structure() - create_mesh(building, wall.name, vertices, faces) + print("Getting 3D structures") + elements = get_3d_structure(g, "Wall") + create_element_mesh(building, elements) - for feature in space.floor_features: - vertices, faces = feature.generate_3d_structure() - create_mesh(building, feature.name, vertices, faces) + columns = get_3d_structure(g, "Column") + create_element_mesh(building, columns) - wall_openings = model.wall_openings - # create wall openings - for wall_opening in wall_openings: + dividers = get_3d_structure(g, "Divider") + create_element_mesh(building, dividers) - vertices, faces = wall_opening.generate_3d_structure() - create_mesh(building, wall_opening.name, vertices, faces) + entryways = get_3d_structure(g, "Entryway") + create_element_mesh(building, entryways) + subtract_opening(entryways) - # boolean operation for walls and opening - boolean_operation_difference(wall_opening.wall_a.name, wall_opening.name) - if not wall_opening.wall_b is None: - boolean_operation_difference(wall_opening.wall_b.name, wall_opening.name) - - bpy.data.objects[wall_opening.name].select_set(True) - bpy.ops.object.delete() + windows = get_3d_structure(g, "Window") + create_element_mesh(building, windows) + subtract_opening(windows) file_name = "{name}.{ext}".format(name=model_name, ext=file_format) save_file(output_path, file_name, None) + + +def create_element_mesh(building, elements): + for e in elements: + name = e.get("name") + vertices = e.get("vertices") + faces = e.get("faces") + create_mesh(building, name, vertices, faces) + + +def subtract_opening(openings): + # boolean operation for walls and opening + for opening in openings: + name = opening.get("name") + for wall in opening.get("voids", list()): + boolean_operation_difference(wall, name) + bpy.data.objects[name].select_set(True) + bpy.ops.object.delete() diff --git a/src/fpm/graph.py b/src/fpm/graph.py index 510135b..0342dd8 100644 --- a/src/fpm/graph.py +++ b/src/fpm/graph.py @@ -217,6 +217,38 @@ def get_opening_points(g, element="Entryway"): return opening_points +def get_3d_structure(g, element="Wall"): + elements = list() + coords_m = get_coordinates_map(g) + for e, _, _ in g.triples((None, RDF.type, FP[element])): + poly = g.value(e, FP["3d-shape"]) + vertices_ptr = g.value(poly, POLY["points"]) + vertices = get_list_from_ptr(g, vertices_ptr) + positions = list() + for point in vertices: + p = get_point_position(g, point) + x, y = get_waypoint_coord(g, p, coords_m) + positions.append((x, y, p["z"])) + + faces_ptr = g.value(poly, POLY["faces"]) + faces_nodes = get_list_from_ptr(g, faces_ptr) + faces = list() + for f in faces_nodes: + face_vertices = get_list_from_ptr(g, f) + face = [vertices.index(point) for point in face_vertices] + faces.append(face) + + name = prefixed(g, e).split(":")[-1] + d = {"name": name, "vertices": positions, "faces": faces} + if element in ["Entryway", "Window"]: + voids_ptr = g.value(e, FP["voids"]) + voids = get_list_from_ptr(g, voids_ptr) + d["voids"] = [prefixed(g, v).split(":")[-1] for v in voids] + elements.append(d) + + return elements + + def get_point_positions_in_space(g, space): polygon = g.value(space, FP["shape"])