Files
fps_project_1/addons/proton_scatter/src/shapes/sphere_shape.gd

72 lines
1.7 KiB
GDScript

@tool
class_name ProtonScatterSphereShape
extends ProtonScatterBaseShape
@export var radius := 1.0:
set(val):
radius = val
_radius_squared = val * val
emit_changed()
var _radius_squared := 0.0
func get_copy():
var copy = ProtonScatterSphereShape.new()
copy.radius = radius
return copy
func is_point_inside(point: Vector3, global_transform: Transform3D) -> bool:
var shape_center = global_transform * Vector3.ZERO
return shape_center.distance_squared_to(point) < _radius_squared
func get_corners_global(gt: Transform3D) -> Array:
var res := []
var corners := [
Vector3(-1, -1, -1),
Vector3(-1, -1, 1),
Vector3(1, -1, 1),
Vector3(1, -1, -1),
Vector3(-1, 1, -1),
Vector3(-1, 1, 1),
Vector3(1, 1, 1),
Vector3(1, 1, -1),
]
for c in corners:
c *= radius
res.push_back(gt * c)
return res
# Returns the circle matching the intersection between the scatter node XZ plane
# and the sphere. Returns an empty array if there's no intersection.
func get_closed_edges(shape_t: Transform3D) -> Array[PackedVector2Array]:
var edge := PackedVector2Array()
var plane := Plane(Vector3.UP, 0.0)
var sphere_center := shape_t.origin
var dist2plane = plane.distance_to(sphere_center)
var radius_at_ground_level := sqrt(pow(radius, 2) - pow(dist2plane, 2))
# No intersection with plane
if radius_at_ground_level <= 0.0 or radius_at_ground_level > radius:
return []
var origin := Vector2(sphere_center.x, sphere_center.z)
var steps: int = max(16, int(radius_at_ground_level * 12))
var angle: float = TAU / steps
for i in steps + 1:
var theta = angle * i
var point := origin + Vector2(cos(theta), sin(theta)) * radius_at_ground_level
edge.push_back(point)
return [edge]