Group Holes with Hull Convex

This commit is contained in:
2025-11-24 20:29:46 -05:00
parent 0a3919ce4c
commit 1c8e3d7314
13 changed files with 77 additions and 39 deletions

Binary file not shown.

View File

@@ -10,10 +10,11 @@ enum ExtrudeDirection {
@export_category("TrechBroom Generated Values")
@export var verts2d: PackedVector2Array
@export var meshInstance3d: MeshInstance3D
@export var extrusion_direction: ExtrudeDirection
@export var depth: float = 0.1
@export var depth_position_offset: Vector3 = Vector3.ZERO
@export_category("User Defined Values")
@export_category("TrechBroom User Values")
@export var extrusion_direction: ExtrudeDirection
@export var hole_proximity: float
@export var edge_non_fracture: float = 0.1
var parentNode
@@ -44,6 +45,8 @@ func _func_godot_apply_properties(entity_properties: Dictionary) -> void:
var verticies = meshInstance3d.mesh.surface_get_arrays(0)[Mesh.ARRAY_VERTEX]
extrusion_direction = entity_properties["extrude_direction"]
hole_proximity = entity_properties["hole_proximity"]
edge_non_fracture = entity_properties["edge_non_fractured"]
var depth_min: float
var depth_max: float
@@ -192,6 +195,24 @@ func _add_hole(new_hole: PackedVector2Array) -> bool:
var bound_rect = UTIL.get_bounding_rect(merged)
inner_rtree.add(bound_rect.position, bound_rect.end, hole.hole_id)
var hole_prox_boundary = bound_rect.grow(hole.area * 4)
var prox_holes_ids = inner_rtree.query_rect(hole_prox_boundary.position, hole_prox_boundary.end)
# any holes that are close in proximity convex hull
if len(prox_holes_ids) <= 1: # needs to be length 2 or more because it will always return the hole just created
return true
var proxmity_hole_vectors = []
for id in prox_holes_ids:
proxmity_hole_vectors.append_array(inner_polygons.get_hole(id).vectors)
inner_rtree.remove(id)
inner_polygons.remove_hole(id)
var convex_vectors = Geometry2D.convex_hull(proxmity_hole_vectors)
hole = inner_polygons.add_hole(convex_vectors)
bound_rect = UTIL.get_bounding_rect(convex_vectors)
inner_rtree.add(bound_rect.position, bound_rect.end, hole.hole_id)
return true
func _find_static_body():

View File

@@ -3,12 +3,16 @@ extends Resource
class_name Hole
var hole_id: int
var vectors: PackedVector2Array
var vectors: PackedVector2Array # verticies
var area: float
func _init(hole_id: int, vectors: PackedVector2Array):
self.hole_id = hole_id
self.vectors = vectors
self.area = UTIL.get_polygon_area(self.vectors)
func center():
var avg_vert = Vector2.ZERO

View File

@@ -25,3 +25,13 @@ static func get_bounding_rect(vectors: PackedVector2Array) -> Rect2:
# The 'position' of the Rect2 will be the minimum corner
return rect
static func get_polygon_area(vectors: PackedVector2Array) -> float:
var result := 0.0
var num_vertices := vectors.size()
for q in range(num_vertices):
var p = (q - 1 + num_vertices) % num_vertices
result += vectors[q].cross(vectors[p])
return abs(result * 0.5)

View File

@@ -1,24 +0,0 @@
extends Node
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
var rtree = RectangleTree.new()
var min1 = Vector2(0, 0)
var max1 = Vector2(1, 1)
var min2 = Vector2(0, 0)
var max2 = Vector2(0.5, 0.5)
rtree.add(min1, max1, 0)
rtree.add(min2, max2, 1)
var result = rtree.query(Vector2(0.25, 0.25))
print(result)
rtree.remove(0)
result = rtree.query(Vector2(0.25, 0.25))
print(result)

View File

@@ -1 +0,0 @@
uid://18smkusl55no

View File

@@ -183,6 +183,8 @@ verts2d = PackedVector2Array(-1, -1.5, 1, -1.5, 1, 1.5, -1, 1.5, -1, -1.5)
meshInstance3d = NodePath("entity_2_mesh_instance")
depth = -1.0
depth_position_offset = Vector3(0, 0, 0.5)
hole_proximity = 1.0
edge_non_fracture = 0.01
[node name="entity_2_mesh_instance" type="MeshInstance3D" parent="FuncGodotMap/entity_2_func_destructablewall"]
mesh = SubResource("ArrayMesh_eudka")
@@ -192,9 +194,11 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3.75, 2, -2.953125)
script = ExtResource("6_u45fp")
verts2d = PackedVector2Array(-2.546875, -1.5, 2.546875, -1.5, 2.546875, 1.5, -2.546875, 1.5, -2.546875, -1.5)
meshInstance3d = NodePath("entity_3_mesh_instance")
extrusion_direction = 1
depth = -0.5
depth_position_offset = Vector3(-0.25, 0, 0)
extrusion_direction = 1
hole_proximity = 1.0
edge_non_fracture = 0.01
[node name="entity_3_mesh_instance" type="MeshInstance3D" parent="FuncGodotMap/entity_3_func_destructablewall"]
mesh = SubResource("ArrayMesh_qtvpr")
@@ -204,9 +208,11 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 9.953125, 0.75, -4.5)
script = ExtResource("6_u45fp")
verts2d = PackedVector2Array(-1.546875, -2, 1.546875, -2, 1.546875, 2, -1.546875, 2, -1.546875, -2)
meshInstance3d = NodePath("entity_4_mesh_instance")
extrusion_direction = 2
depth = -0.5
depth_position_offset = Vector3(0, -0.25, 0)
extrusion_direction = 2
hole_proximity = 1.0
edge_non_fracture = 0.01
[node name="entity_4_mesh_instance" type="MeshInstance3D" parent="FuncGodotMap/entity_4_func_destructablewall"]
mesh = SubResource("ArrayMesh_drwxn")
@@ -218,6 +224,8 @@ verts2d = PackedVector2Array(-1.046875, -1.5, 1.046875, -1.5, 1.046875, 1.5, -1.
meshInstance3d = NodePath("entity_5_mesh_instance")
depth = -1.0
depth_position_offset = Vector3(0, 0, 0.5)
hole_proximity = 1.0
edge_non_fracture = 0.01
[node name="entity_5_mesh_instance" type="MeshInstance3D" parent="FuncGodotMap/entity_5_func_destructablewall"]
mesh = SubResource("ArrayMesh_rmkky")
@@ -227,9 +235,11 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3.75, 2, 2.546875)
script = ExtResource("6_u45fp")
verts2d = PackedVector2Array(-2.546875, -1.5, 2.546875, -1.5, 2.546875, 1.5, -2.546875, 1.5, -2.546875, -1.5)
meshInstance3d = NodePath("entity_6_mesh_instance")
extrusion_direction = 1
depth = -0.5
depth_position_offset = Vector3(-0.25, 0, 0)
extrusion_direction = 1
hole_proximity = 1.0
edge_non_fracture = 0.01
[node name="entity_6_mesh_instance" type="MeshInstance3D" parent="FuncGodotMap/entity_6_func_destructablewall"]
mesh = SubResource("ArrayMesh_epu3l")
@@ -239,9 +249,11 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 3, 1, -3.7500305)
script = ExtResource("6_u45fp")
verts2d = PackedVector2Array(-1.0000001, -0.7500305, 0.9998779, -0.25006104, 1, -0.24996948, 1, 0.7500305, -1.0000001, 0.7500305, -1.0000001, -0.7500305)
meshInstance3d = NodePath("entity_7_mesh_instance")
extrusion_direction = 2
depth = -1.0000000596046448
depth_position_offset = Vector3(0, -0.5, 0)
extrusion_direction = 2
hole_proximity = 1.0
edge_non_fracture = 0.01
[node name="entity_7_mesh_instance" type="MeshInstance3D" parent="FuncGodotMap/entity_7_func_destructablewall"]
mesh = SubResource("ArrayMesh_lqn8c")
@@ -253,6 +265,8 @@ verts2d = PackedVector2Array(-1.046875, -1.5, 1.046875, -1.5, 1.046875, 1.5, -1.
meshInstance3d = NodePath("entity_8_mesh_instance")
depth = -0.03125
depth_position_offset = Vector3(0, 0, 0.015625)
hole_proximity = 1.0
edge_non_fracture = 0.01
[node name="entity_8_mesh_instance" type="MeshInstance3D" parent="FuncGodotMap/entity_8_func_destructablewall"]
mesh = SubResource("ArrayMesh_08uri")

View File

@@ -1,6 +0,0 @@
[gd_scene load_steps=2 format=3 uid="uid://bip0c3ydxx12r"]
[ext_resource type="Script" uid="uid://18smkusl55no" path="res://assets/scripts/test.gd" id="1_errlg"]
[node name="Test" type="Node"]
script = ExtResource("1_errlg")

View File

@@ -10,7 +10,9 @@ classname = "func_destructablewall"
description = "Set the brush entity as a destructable.
"
class_properties = {
"extrude_direction": 0
"edge_non_fractured": 0.01,
"extrude_direction": 0,
"hole_proximity": 1.0
}
node_class = "Node3D"
metadata/_custom_type_script = "uid://5cow84q03m6a"

View File

@@ -16,6 +16,8 @@ void RectangleTree::_bind_methods() {
&RectangleTree::query);
ClassDB::bind_method(godot::D_METHOD("nearest", "point", "number"),
&RectangleTree::nearest);
ClassDB::bind_method(godot::D_METHOD("query_rect", "min", "max"),
&RectangleTree::query_rect);
}
void RectangleTree::add(const Vector2 &min_bound, const Vector2 &max_bound,
@@ -58,3 +60,18 @@ PackedInt32Array RectangleTree::nearest(const Vector2 &point,
return return_value;
}
PackedInt32Array RectangleTree::query_rect(const Vector2 &min,
const Vector2 &max) {
Rect rect = Rect(min.x, min.y, max.x, max.y);
PackedInt32Array return_value;
auto callbackLambda = [&return_value](int index) {
return_value.push_back(index);
return true;
};
tree.Search(rect.min, rect.max, callbackLambda);
return return_value;
}

View File

@@ -51,4 +51,5 @@ public:
void remove(const int &polygon_index);
PackedInt32Array query(const Vector2 &point);
PackedInt32Array nearest(const Vector2 &point, const int &number);
PackedInt32Array query_rect(const Vector2 &min, const Vector2 &max);
};

Binary file not shown.