Files

74 lines
3.1 KiB
GDScript

class_name QuarryShell
extends RefCounted
const STEPS := 512
const LEVELS := [-6.0, 0.0, 2.4, 3.0, 5.4, 6.1, 8.7, 9.4, 12.2, 13.0, 16.2, 17.0, 20.4, 21.1, 24.0, 25.2, 28.2, 30.0]
static func perimeter(t: float) -> Vector3:
var corners := [Vector3(-50, 0, -69), Vector3(50, 0, -69), Vector3(50, 0, 69), Vector3(-50, 0, 69)]
var edge := floori(t * 4) % 4
return corners[edge].lerp(corners[(edge + 1) % 4], fmod(t * 4, 1.0))
static func point(i: int, level: int) -> Vector3:
var t := float(i % STEPS) / STEPS
var p := perimeter(t)
var direction := p.normalized()
var along := t * TAU
var erosion := 3.8 + sin(along * 13 + sin(along * 5) * 0.6 + level * 0.06) * 2.8 + sin(along * 31 + level * 0.15) * 0.65
var terrace := level * 0.23 + sin(along * 9 + level * 0.7) * 1.2 + sin(along * 57 + level * 2.3) * 0.65
p += direction * (terrace + erosion + sin(along * 83 + level * 0.3) * 0.28 + sin(along * 137 + level) * 0.13)
var height_scale := 1.0 + 0.15 * sin(along * 3 + 0.6) + 0.065 * cos(along * 7)
p.y = LEVELS[level] * height_scale * 0.76 + (sin(along * 17) * 0.38 + sin(along * 37 + level * 0.35) * 0.32 if level > 1 else 0.0)
if level >= LEVELS.size() - 2: p.y += sin(along * 23) * 1.1 + sin(along * 41) * 0.45
return p
static func build(root: Node3D) -> void:
# Closed contiguous rock surface. Shared vertices at every seam, including corners.
var tool := SurfaceTool.new()
tool.begin(Mesh.PRIMITIVE_TRIANGLES)
for i in STEPS:
for j in LEVELS.size() - 1:
tool.set_smooth_group(0)
for p in [point(i, j), point(i + 1, j + 1), point(i + 1, j), point(i, j), point(i, j + 1), point(i + 1, j + 1)]:
tool.set_uv(Vector2(p.x + p.z, p.y) * 0.2)
tool.add_vertex(p)
tool.generate_normals()
var mesh := MeshInstance3D.new()
mesh.name = "ContinuousStrataWall"
mesh.mesh = tool.commit()
mesh.material_override = QuarryLandscape.sandstone(null)
root.add_child(mesh)
# Extend visual ground beneath the complete perimeter; no collider or route changes.
var floor_mesh := MeshInstance3D.new()
floor_mesh.name = "BuriedQuarryApron"
var plane := PlaneMesh.new()
plane.size = Vector2(220, 250)
floor_mesh.mesh = plane
floor_mesh.position.y = -0.045
floor_mesh.material_override = UrbanMaterials.get_surface("sand", Color("d0b895"))
root.add_child(floor_mesh)
build_scree(root)
static func build_scree(root: Node3D) -> void:
var tool := SurfaceTool.new()
tool.begin(Mesh.PRIMITIVE_TRIANGLES)
for i in STEPS:
var a := perimeter(float(i) / STEPS)
var b := perimeter(float((i + 1) % STEPS) / STEPS)
var near_a := a * Vector3(0.915, 1, 0.94)
var near_b := b * Vector3(0.915, 1, 0.94)
near_a.y = -0.02
near_b.y = -0.02
a.y = 2.0 + sin(i * 0.83) * 0.55
b.y = 2.0 + sin(((i + 1) % STEPS) * 0.83) * 0.55
for p in [near_a, b, near_b, near_a, a, b]:
tool.set_uv(Vector2(p.x, p.z))
tool.add_vertex(p)
tool.generate_normals()
var mesh := MeshInstance3D.new()
mesh.name = "ContinuousScreeFoot"
mesh.mesh = tool.commit()
mesh.material_override = UrbanMaterials.get_surface("sand", Color("c6aa83")).duplicate()
mesh.material_override.cull_mode = BaseMaterial3D.CULL_DISABLED
root.add_child(mesh)