49 lines
1.8 KiB
GDScript
49 lines
1.8 KiB
GDScript
class_name StairGuard
|
|
extends RefCounted
|
|
|
|
# One continuous sloping prism replaces the stepped collision faces of a guard.
|
|
static func build(parent: Node3D, x: float, first_z: float, direction: float, bottom: float, rise: float, batch: UrbanMeshBatch = null) -> void:
|
|
var body := parent as StaticBody3D
|
|
if body == null: body = StaticBody3D.new()
|
|
if body != parent: body.name = "SmoothStairGuard"
|
|
body.collision_layer = 1
|
|
body.collision_mask = 0
|
|
var points := PackedVector3Array()
|
|
for end in [0.0, 1.0]:
|
|
var z: float = first_z + direction * (-0.2 + end * 7.6)
|
|
var y: float = bottom + rise / 38.0 + end * rise
|
|
for side in [-0.06, 0.06]:
|
|
for height in [0.0, 0.96]: points.append(Vector3(x + side, y + height, z))
|
|
var shape := ConvexPolygonShape3D.new()
|
|
shape.points = points
|
|
var collider := CollisionShape3D.new()
|
|
collider.shape = shape
|
|
body.add_child(collider)
|
|
if body != parent: parent.add_child(body)
|
|
|
|
if batch:
|
|
batch.mesh(surface(points), Vector3.ZERO, "metal", Color("343b3d"))
|
|
|
|
static func surface(points: PackedVector3Array) -> ArrayMesh:
|
|
# Use the collision prism's exact corners: the visible top is equally smooth.
|
|
var tool := SurfaceTool.new()
|
|
tool.begin(Mesh.PRIMITIVE_TRIANGLES)
|
|
var center := Vector3.ZERO
|
|
for point in points: center += point / 8.0
|
|
for face in [[0,2,3,1], [4,5,7,6], [0,1,5,4], [2,6,7,3], [1,3,7,5], [0,4,6,2]]:
|
|
for triangle in [[face[0],face[1],face[2]], [face[0],face[2],face[3]]]:
|
|
var a: Vector3 = points[triangle[0]]
|
|
var b: Vector3 = points[triangle[1]]
|
|
var c: Vector3 = points[triangle[2]]
|
|
var normal := (c-a).cross(b-a).normalized()
|
|
if normal.dot((a+b+c)/3.0-center) < 0:
|
|
var swap := b
|
|
b = c
|
|
c = swap
|
|
normal = -normal
|
|
for vertex in [a,b,c]:
|
|
tool.set_normal(normal)
|
|
tool.set_uv(Vector2(vertex.z,vertex.y))
|
|
tool.add_vertex(vertex)
|
|
return tool.commit()
|