72 lines
1.7 KiB
GDScript
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]
|