Cutting Holes Into Mesh
We be cutting holes :)
This commit is contained in:
103
demo/scripts/destructable_wall.gd
Normal file
103
demo/scripts/destructable_wall.gd
Normal file
@@ -0,0 +1,103 @@
|
||||
extends Node
|
||||
|
||||
@export var outer_polygon: PackedVector2Array
|
||||
@export var inner_polygons: Array[PackedVector2Array]
|
||||
@export var edge_non_fracture: float = 0.1
|
||||
|
||||
@onready var camera: Camera3D = get_node("/root/Node3D/Camera3D")
|
||||
@onready var meshInstance = MeshInstance3D.new()
|
||||
@onready var parentNode = get_node("..")
|
||||
|
||||
var depth: float:
|
||||
set(value):
|
||||
if value > 0:
|
||||
depth = -value
|
||||
depth = value
|
||||
|
||||
var static_body: StaticBody3D
|
||||
|
||||
func _ready() -> void:
|
||||
assert(camera, "camera was not found")
|
||||
assert(len(outer_polygon) > 2, "outer polygon does not meet the required length")
|
||||
|
||||
camera.connect("wall_hit", _handle_hit_signal)
|
||||
|
||||
self.add_child(meshInstance)
|
||||
_draw()
|
||||
|
||||
func _draw():
|
||||
var vector_indexes = GeoPolyTriangulization.triangulate(outer_polygon, inner_polygons)
|
||||
var vectors = []
|
||||
|
||||
vectors.append_array(outer_polygon)
|
||||
for ip in inner_polygons:
|
||||
vectors.append_array(ip)
|
||||
|
||||
var meshGenerator = GeoPolyMesh.new(vector_indexes, vectors)
|
||||
var mesh = meshGenerator.commit_mesh()
|
||||
|
||||
meshInstance.mesh = mesh
|
||||
meshInstance.create_trimesh_collision()
|
||||
static_body = _find_static_body()
|
||||
|
||||
func _re_draw():
|
||||
meshInstance.remove_child(static_body)
|
||||
static_body.queue_free()
|
||||
|
||||
var vector_indexes = GeoPolyTriangulization.triangulate(outer_polygon, inner_polygons)
|
||||
var vectors = []
|
||||
|
||||
vectors.append_array(outer_polygon)
|
||||
for ip in inner_polygons:
|
||||
vectors.append_array(ip)
|
||||
|
||||
var meshGenerator = GeoPolyMesh.new(vector_indexes, vectors)
|
||||
var mesh = meshGenerator.commit_mesh()
|
||||
|
||||
meshInstance.mesh = mesh
|
||||
meshInstance.create_trimesh_collision()
|
||||
static_body = _find_static_body()
|
||||
|
||||
|
||||
func _handle_hit_signal(wall_id: int, position: Vector3, cutter: PackedVector2Array):
|
||||
# validate that the hit was to this wall, if not return
|
||||
if wall_id != static_body.get_instance_id():
|
||||
return
|
||||
|
||||
var hole_position_offset = self.position + position
|
||||
var hole_vector2_offset = Vector2(hole_position_offset.x, hole_position_offset.y)
|
||||
|
||||
# translate the cutter
|
||||
var hole_vectors = Transform2D(0, hole_vector2_offset) * cutter
|
||||
|
||||
_add_hole(hole_vectors)
|
||||
|
||||
_re_draw()
|
||||
|
||||
func _add_hole(new_hole: PackedVector2Array):
|
||||
var values_to_remove = []
|
||||
|
||||
var merged: PackedVector2Array = new_hole
|
||||
for index in range(len(self.inner_polygons)):
|
||||
var result = Geometry2D.merge_polygons(merged, self.inner_polygons[index])
|
||||
|
||||
if len(result) == 1:
|
||||
merged = result[0]
|
||||
values_to_remove.append(self.inner_polygons[index])
|
||||
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])
|
||||
|
||||
for i in values_to_remove:
|
||||
self.inner_polygons.erase(i)
|
||||
|
||||
inner_polygons.append(merged)
|
||||
|
||||
func _find_static_body():
|
||||
for child in meshInstance.get_children():
|
||||
if child is StaticBody3D:
|
||||
return child
|
||||
Reference in New Issue
Block a user