Implemented R-Tree

Would like to switch the identifer of the hole to a random string.
This commit is contained in:
2025-11-23 13:29:57 -05:00
parent 36c648cfe5
commit c208d069bb
11 changed files with 113 additions and 33 deletions

View File

@@ -13,15 +13,32 @@ enum ExtrudeDirection {
@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 var edge_non_fracture: float = 0.1
@onready var parentNode = get_node("..")
var parentNode
var inner_rtree: RectangleTree
var outer_polygon: PackedVector2Array
var inner_polygons: Array[PackedVector2Array]
var inner_polygons: Holes
var static_body: StaticBody3D
func _ready() -> void:
if Engine.is_editor_hint():
return
parentNode = get_node("..")
inner_polygons = Holes.new()
inner_rtree = RectangleTree.new()
outer_polygon = verts2d
_draw()
func _exit_tree() -> void:
if Engine.is_editor_hint():
return
inner_rtree.free()
func _func_godot_apply_properties(entity_properties: Dictionary) -> void:
meshInstance3d = _find_mesh_body()
var verticies = meshInstance3d.mesh.surface_get_arrays(0)[Mesh.ARRAY_VERTEX]
@@ -75,20 +92,12 @@ func _func_godot_apply_properties(entity_properties: Dictionary) -> void:
var outer_boudary = Geometry2D.convex_hull(verts_2d)
verts2d = outer_boudary
func _ready() -> void:
if Engine.is_editor_hint():
return
outer_polygon = verts2d
_draw()
func _draw():
var vector_indexes = GeoPolyTriangulization.triangulate(outer_polygon, inner_polygons)
var vector_indexes = GeoPolyTriangulization.triangulate(outer_polygon, inner_polygons.get_holes())
var vectors = []
vectors.append_array(outer_polygon)
for ip in inner_polygons:
vectors.append_array(ip)
vectors.append_array(inner_polygons.get_hole_verticies())
var meshGenerator = GeoPolyMesh.new(vector_indexes, vectors, extrusion_direction, depth)
var commited_mesh = meshGenerator.commit_mesh(meshInstance3d.get_active_material(0))
@@ -101,24 +110,29 @@ func _draw():
static_body = _find_static_body()
func _re_draw():
meshInstance3d.remove_child(static_body)
static_body.queue_free()
var vector_indexes = GeoPolyTriangulization.triangulate(outer_polygon, inner_polygons)
var vector_indexes = GeoPolyTriangulization.triangulate(outer_polygon, inner_polygons.get_holes())
var vectors = []
vectors.append_array(outer_polygon)
for ip in inner_polygons:
vectors.append_array(ip)
vectors.append_array(inner_polygons.get_hole_verticies())
WorkerThreadPool.add_task(_generate_mesh.bind(vector_indexes, vectors))
func _deffered_draw(mesh: Mesh, task_id: int):
if task_id:
WorkerThreadPool.wait_for_task_completion(task_id)
meshInstance3d.remove_child(static_body)
static_body.queue_free()
meshInstance3d.mesh = mesh
meshInstance3d.create_trimesh_collision()
static_body = _find_static_body()
func _generate_mesh(vector_indexes: PackedInt32Array, vectors: PackedVector2Array):
var meshGenerator = GeoPolyMesh.new(vector_indexes, vectors, extrusion_direction, depth)
var commited_mesh = meshGenerator.commit_mesh(meshInstance3d.get_active_material(0))
meshGenerator.free()
meshInstance3d.mesh = commited_mesh
meshInstance3d.create_trimesh_collision()
static_body = _find_static_body()
self.call_deferred("_deffered_draw", commited_mesh, WorkerThreadPool.get_caller_task_id())
func hit(position: Vector3):
var cutter = Cutter.circleCutter()
@@ -134,13 +148,18 @@ func hit(position: Vector3):
# translate the cutter
var hole_vectors = Transform2D(0, hole_vector2_offset) * cutter
var draw = _add_hole(hole_vectors)
var rtree_search = []
for hv in hole_vectors:
rtree_search.append_array(inner_rtree.query(hv))
var draw = _add_hole(hole_vectors, rtree_search)
if draw:
_re_draw()
func _add_hole(new_hole: PackedVector2Array) -> bool:
var values_to_remove = []
func _add_hole(new_hole: PackedVector2Array, holes_id: PackedInt32Array) -> bool:
var ids_to_remove = []
# validate that the hole is valid
var boundary_polygon = Geometry2D.offset_polygon(outer_polygon, -edge_non_fracture)
@@ -150,24 +169,28 @@ func _add_hole(new_hole: PackedVector2Array) -> bool:
return false
var merged: PackedVector2Array = boundary_hole[0]
for index in range(len(self.inner_polygons)):
var result = Geometry2D.merge_polygons(merged, self.inner_polygons[index])
for id in holes_id:
var result = Geometry2D.merge_polygons(merged, inner_polygons.get_hole(id).vectors)
if len(result) == 1:
merged = result[0]
values_to_remove.append(self.inner_polygons[index])
ids_to_remove.append(id)
elif len(result) > 1:
# need to check that they have no overlapping area if they do clip
var overlap = Geometry2D.intersect_polygons(result[0], result[1])
if len(overlap) != 0:
merged = Geometry2D.clip_polygons(result[0], result[1])[0]
values_to_remove.append(self.inner_polygons[index])
ids_to_remove.append(id)
for i in values_to_remove:
inner_polygons.erase(i)
for id in ids_to_remove:
inner_rtree.remove(id)
inner_polygons.remove_hole(id)
inner_polygons.append(merged)
var hole = inner_polygons.add_hole(merged)
var bound_rect = UTIL.get_bounding_rect(merged)
inner_rtree.add(bound_rect.position, bound_rect.end, hole.hole_id)
return true