62 lines
1.8 KiB
GDScript
62 lines
1.8 KiB
GDScript
extends Node3D
|
|
## Baut aus 2D-Stuetzpunkten eine geschlossene Gleisschleife inkl. Optik.
|
|
|
|
const Mat = preload("res://scripts/mat.gd")
|
|
const Deco = preload("res://scripts/deco.gd")
|
|
|
|
const BALLAST := Color("d98d4a")
|
|
const SLEEPER := Color("5e4130")
|
|
const RAIL := Color("9a9da2")
|
|
const STEP := 1.2
|
|
|
|
var path: Path3D
|
|
|
|
func build(points: PackedVector2Array) -> void:
|
|
path = Path3D.new()
|
|
path.name = "TrackPath"
|
|
var c := Curve3D.new()
|
|
var n := points.size()
|
|
# Catmull-Rom Tangenten -> weiche, geschlossene Schleife.
|
|
for i in n + 1:
|
|
var idx := i % n
|
|
var prev := points[(idx - 1 + n) % n]
|
|
var nxt := points[(idx + 1) % n]
|
|
var t := (nxt - prev) / 6.0
|
|
var p := points[idx]
|
|
c.add_point(Vector3(p.x, 0, p.y), Vector3(-t.x, 0, -t.y), Vector3(t.x, 0, t.y))
|
|
path.curve = c
|
|
add_child(path)
|
|
_build_visuals()
|
|
|
|
func length() -> float:
|
|
return path.curve.get_baked_length()
|
|
|
|
func sample(offset: float) -> Transform3D:
|
|
return path.curve.sample_baked_with_rotation(fposmod(offset, length()), true, true)
|
|
|
|
func _build_visuals() -> void:
|
|
var count := int(length() / STEP)
|
|
var xf: Array[Transform3D] = []
|
|
for i in count:
|
|
xf.append(sample(i * STEP))
|
|
|
|
_multi(Deco.box(Vector3(2.7, 0.16, STEP * 1.12)), BALLAST, xf, [Vector3(0, 0.08, 0)])
|
|
_multi(Deco.box(Vector3(2.1, 0.09, 0.34)), SLEEPER, xf, [Vector3(0, 0.20, 0)])
|
|
_multi(Deco.box(Vector3(0.09, 0.11, STEP * 1.08)), RAIL, xf,
|
|
[Vector3(-0.62, 0.29, 0), Vector3(0.62, 0.29, 0)])
|
|
|
|
func _multi(mesh: Mesh, color: Color, xf: Array[Transform3D], offsets: Array) -> void:
|
|
var mm := MultiMesh.new()
|
|
mm.transform_format = MultiMesh.TRANSFORM_3D
|
|
mm.mesh = mesh
|
|
mm.instance_count = xf.size() * offsets.size()
|
|
var i := 0
|
|
for t in xf:
|
|
for o in offsets:
|
|
mm.set_instance_transform(i, t.translated_local(o))
|
|
i += 1
|
|
var mmi := MultiMeshInstance3D.new()
|
|
mmi.multimesh = mm
|
|
mmi.material_override = Mat.flat(color)
|
|
add_child(mmi)
|