From 4451f5c5b87937caae9f78d76ed3362529cbe5d7 Mon Sep 17 00:00:00 2001 From: Nitwel Date: Mon, 29 Apr 2024 18:12:45 +0200 Subject: [PATCH] support doors on subdiv grid --- app/content/system/house/mini/miniature.gd | 10 ++- app/lib/utils/mesh/construct_room_mesh.gd | 100 +++++++++++++++++++++ 2 files changed, 109 insertions(+), 1 deletion(-) diff --git a/app/content/system/house/mini/miniature.gd b/app/content/system/house/mini/miniature.gd index 8079754..2b8f3f6 100644 --- a/app/content/system/house/mini/miniature.gd +++ b/app/content/system/house/mini/miniature.gd @@ -63,7 +63,15 @@ func _ready(): model.add_child(walls_mesh) model.add_child(floor_mesh) - walls_mesh.mesh=ConstructRoomMesh.generate_wall_mesh_grid(room.corners, room.height) + var doors=[] + + for door in Store.house.state.doors: + if door.room1 == room.name: + doors.append([door.room1_position1, door.room1_position2]) + elif door.room2 == room.name: + doors.append([door.room2_position1, door.room2_position2]) + + walls_mesh.mesh=ConstructRoomMesh.generate_wall_mesh_with_doors_grid(room.corners, room.height, doors) floor_mesh.mesh=ConstructRoomMesh.generate_ceiling_mesh_grid(room.corners) walls_mesh.material_override=wall_material diff --git a/app/lib/utils/mesh/construct_room_mesh.gd b/app/lib/utils/mesh/construct_room_mesh.gd index ac43f31..2ea55e6 100644 --- a/app/lib/utils/mesh/construct_room_mesh.gd +++ b/app/lib/utils/mesh/construct_room_mesh.gd @@ -131,6 +131,106 @@ static func generate_ceiling_mesh(corners): return _create_mesh_2d(points, triangles) +static func generate_wall_mesh_with_doors_grid(corners, height, doors, grid:=0.1): + if corners.size() < 3: + return null + + var mesh = ArrayMesh.new() + + for i in range(0, corners.size()): + var corner = corners[i] + var next_corner = corners[(i + 1) % corners.size()] + + var forward = Vector3(next_corner.x - corner.x, 0, next_corner.y - corner.y).normalized() + + var points := PackedVector2Array() + + points.append(Vector2(0, 0)) + points.append(Vector2(0, height)) + points.append(Vector2(corner.distance_to(next_corner), height)) + points.append(Vector2(corner.distance_to(next_corner), 0)) + + for door in doors: + var door_point1 = Vector2(door[0].x, door[0].z) + var door_point2 = Vector2(door[1].x, door[1].z) + var proj_point1 = Geometry2D.get_closest_point_to_segment_uncapped(door_point1, corner, next_corner) + var proj_point2 = Geometry2D.get_closest_point_to_segment_uncapped(door_point2, corner, next_corner) + + if proj_point1.distance_to(door_point1) > 0.02&&proj_point2.distance_to(door_point2) > 0.02: + continue + + if proj_point1.distance_to(proj_point2) < 0.02: + continue + + var point1_distance = corner.distance_to(proj_point1) + var point2_distance = corner.distance_to(proj_point2) + + var door_points := PackedVector2Array() + + door_points.append(Vector2(point1_distance, -1)) + door_points.append(Vector2(point1_distance, door[0].y)) + door_points.append(Vector2(point2_distance, door[1].y)) + door_points.append(Vector2(point2_distance, -1)) + + var clip = Geometry2D.clip_polygons(points, door_points) + if clip.size() == 0: + continue + + assert(clip.size() != 2, "Door clip should not create holes") + + points = clip[0] + + # Subdivide edge to grid + + var new_points = PackedVector2Array() + + for k in range(points.size()): + var point = points[k] + var next_point = points[(k + 1) % points.size()] + + new_points.append(point) + + var steps = floor(point.distance_to(next_point) / grid) + + for x in range(1, steps): + new_points.append(point + (next_point - point).normalized() * grid * x) + + points = new_points + + var edges = PackedInt32Array() + for k in range(points.size()): + edges.append(k) + edges.append((k + 1) % points.size()) + + # Subdivide inner polygon to grid + var steps = ceil(Vector2(corner.distance_to(next_corner) / grid, height / grid)) + + for y in range(1, steps.y): + for x in range(1, steps.x): + var point = Vector2(x * grid, y * grid) + + points.append(point) + + var cdt: ConstrainedTriangulation = ConstrainedTriangulation.new() + cdt.init(true, true, 0.001) + + cdt.insert_vertices(points) + cdt.insert_edges(edges) + + cdt.erase_outer_triangles() + + points = cdt.get_all_vertices() + var triangles: PackedInt32Array = cdt.get_all_triangles() + + var points_3d = PackedVector3Array() + + for k in range(points.size()): + points_3d.append(Vector3(corner.x, 0, corner.y) + points[k].x * forward + Vector3(0, points[k].y, 0)) + + mesh = _create_mesh_3d(points_3d, triangles, mesh) + + return mesh + static func generate_wall_mesh_grid(corners, height, grid: Vector2=Vector2(0.1, 0.1)): if corners.size() < 3: return null