update
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
extends Node3D
|
||||
## Baut aus 2D-Stuetzpunkten eine geschlossene Gleisschleife inkl. Optik.
|
||||
## Streckennetz aus Abschnitten. Ein Abschnitt hat einen oder zwei
|
||||
## Nachfolger - bei zweien steht dort eine Weiche.
|
||||
|
||||
const Mat = preload("res://scripts/mat.gd")
|
||||
const Deco = preload("res://scripts/deco.gd")
|
||||
@@ -9,37 +10,69 @@ const SLEEPER := Color("5e4130")
|
||||
const RAIL := Color("9a9da2")
|
||||
const STEP := 1.2
|
||||
|
||||
var path: Path3D
|
||||
## Jeder Eintrag: { "name", "curve": Curve3D, "length", "next": [ids], "prev": [ids] }
|
||||
var segments: Array = []
|
||||
|
||||
func build(points: PackedVector2Array) -> void:
|
||||
path = Path3D.new()
|
||||
path.name = "TrackPath"
|
||||
## Abschnitt anlegen. Anfangs- und Endrichtung werden vorgegeben, damit
|
||||
## sich mehrere Abschnitte an einer Weiche ohne Knick treffen.
|
||||
func add_segment(seg_name: String, points: Array, t_start: Vector2, t_end: Vector2) -> int:
|
||||
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]
|
||||
for i in n:
|
||||
var p: Vector2 = points[i]
|
||||
var t: Vector2
|
||||
if i == 0:
|
||||
t = t_start.normalized() * p.distance_to(points[1]) / 3.0
|
||||
elif i == n - 1:
|
||||
t = t_end.normalized() * p.distance_to(points[n - 2]) / 3.0
|
||||
else:
|
||||
t = (points[i + 1] - points[i - 1]) / 6.0
|
||||
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()
|
||||
segments.append({"name": seg_name, "curve": c, "length": c.get_baked_length(),
|
||||
"next": [], "prev": []})
|
||||
return segments.size() - 1
|
||||
|
||||
func length() -> float:
|
||||
return path.curve.get_baked_length()
|
||||
func connect_segments(from: int, to: int) -> void:
|
||||
segments[from]["next"].append(to)
|
||||
segments[to]["prev"].append(from)
|
||||
|
||||
func sample(offset: float) -> Transform3D:
|
||||
return path.curve.sample_baked_with_rotation(fposmod(offset, length()), true, true)
|
||||
func finish() -> void:
|
||||
for i in segments.size():
|
||||
_build_visuals(i)
|
||||
|
||||
func _build_visuals() -> void:
|
||||
var count := int(length() / STEP)
|
||||
func seg_length(i: int) -> float:
|
||||
return float(segments[i]["length"])
|
||||
|
||||
func seg_name(i: int) -> String:
|
||||
return String(segments[i]["name"])
|
||||
|
||||
func next_of(i: int) -> Array:
|
||||
return segments[i]["next"]
|
||||
|
||||
func prev_of(i: int) -> Array:
|
||||
return segments[i]["prev"]
|
||||
|
||||
func is_switch(i: int) -> bool:
|
||||
return segments[i]["next"].size() > 1
|
||||
|
||||
func sample(i: int, offset: float) -> Transform3D:
|
||||
var c: Curve3D = segments[i]["curve"]
|
||||
return c.sample_baked_with_rotation(clampf(offset, 0.0, seg_length(i)), true, false)
|
||||
|
||||
## Nächster Punkt auf irgendeinem Abschnitt - für die Deko-Verteilung.
|
||||
func distance_to_track(p: Vector2) -> float:
|
||||
var best := INF
|
||||
for s in segments:
|
||||
var c: Curve3D = s["curve"]
|
||||
var q: Vector3 = c.get_closest_point(Vector3(p.x, 0, p.y))
|
||||
best = minf(best, Vector2(q.x, q.z).distance_to(p))
|
||||
return best
|
||||
|
||||
func _build_visuals(i: int) -> void:
|
||||
var count := int(seg_length(i) / STEP)
|
||||
var xf: Array[Transform3D] = []
|
||||
for i in count:
|
||||
xf.append(sample(i * STEP))
|
||||
|
||||
for k in count:
|
||||
xf.append(sample(i, k * STEP + STEP * 0.5))
|
||||
_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,
|
||||
|
||||
Reference in New Issue
Block a user