Wall off the table's own 6 edges too, not just the outer ridges
_build_region_borders() previously only bordered the 6 seams between adjacent outer regions (table corner -> girdle corner). Generalized _build_ridge() into _build_border_segment(p0, p1), which chains overlap-guaranteed props along any straight 3D segment, and reused it for the 6 table edges (table corner -> next table corner) as well — these separate the center region from each outer region. Verified headless the same way as the ridges: 43/43 pairs on one table edge genuinely overlap (worst case -0.13 units). 744 border props total across all 12 edges now.
This commit is contained in:
parent
eac8fdf042
commit
37e0151988
55
terrain.gd
55
terrain.gd
@ -134,47 +134,62 @@ func _build_pavilion() -> void:
|
||||
add_child(mi)
|
||||
|
||||
# ═══════════════════════════════════════════════
|
||||
# GRENZEN — Berg/Wald entlang der 6 Grate zwischen den Regionen
|
||||
# Grat k = Strecke von Tisch-Ecke T[k] zu Rundiste-Ecke G[k]
|
||||
# (gemeinsame Kante von Facette k-1 und Facette k)
|
||||
# GRENZEN — Berg/Wald entlang aller Kanten zwischen den 7 Regionen:
|
||||
# 6 Grate Tisch-Ecke T[k] -> Rundiste-Ecke G[k] (zwischen den Außenregionen)
|
||||
# + 6 Tisch-Kanten T[k] -> T[k+1] (zwischen Zentrum und jeder Außenregion)
|
||||
# ═══════════════════════════════════════════════
|
||||
func _build_region_borders() -> void:
|
||||
var borders := Node3D.new()
|
||||
borders.name = "Borders"
|
||||
add_child(borders)
|
||||
|
||||
var table_pts : Array[Vector3] = []
|
||||
var girdle_pts : Array[Vector3] = []
|
||||
for k in range(6):
|
||||
var a := _hex_angle(k)
|
||||
var dir := Vector3(cos(a), 0.0, sin(a))
|
||||
var perp := Vector3(-dir.z, 0.0, dir.x)
|
||||
_build_ridge(borders, dir, perp)
|
||||
table_pts.append(Vector3(cos(a) * table_radius, 0.0, sin(a) * table_radius))
|
||||
girdle_pts.append(Vector3(cos(a) * girdle_radius, -crown_drop, sin(a) * girdle_radius))
|
||||
|
||||
# Kettet Props entlang eines Grats: jeder neue Prop wird so nah an den vorigen
|
||||
# gesetzt, dass sich ihre Welt-Radien garantiert überlappen (Distanz zwischen
|
||||
# den Mittelpunkten <= (r1+r2) * border_overlap). Kein Rätselraten über feste
|
||||
# Abstände mehr — die Lücke wird pro Prop-Paar explizit geprüft und korrigiert.
|
||||
func _build_ridge(borders: Node3D, dir: Vector3, perp: Vector3) -> void:
|
||||
var t := table_radius
|
||||
for k in range(6):
|
||||
var k1 := (k + 1) % 6
|
||||
_build_border_segment(borders, table_pts[k], girdle_pts[k]) # Grat: Außenregion <-> Außenregion
|
||||
_build_border_segment(borders, table_pts[k], table_pts[k1]) # Tisch-Kante: Zentrum <-> Außenregion
|
||||
|
||||
# Kettet Props entlang einer geraden Strecke p0->p1: jeder neue Prop wird so nah
|
||||
# an den vorigen gesetzt, dass sich ihre Welt-Radien garantiert überlappen
|
||||
# (Distanz zwischen den Mittelpunkten <= (r1+r2) * border_overlap). Kein
|
||||
# Rätselraten über feste Abstände mehr — die Lücke wird pro Prop-Paar
|
||||
# explizit geprüft und korrigiert. Funktioniert für geneigte (Grat) wie
|
||||
# flache (Tisch-Kante) Strecken gleichermaßen, da einfach entlang der echten
|
||||
# 3D-Linie zwischen den beiden Punkten gelaufen wird.
|
||||
func _build_border_segment(borders: Node3D, p0: Vector3, p1: Vector3) -> void:
|
||||
var length := p0.distance_to(p1)
|
||||
if length < 0.001:
|
||||
return
|
||||
var dir := (p1 - p0) / length
|
||||
var perp := Vector3(-dir.z, 0.0, dir.x)
|
||||
|
||||
var t := 0.0
|
||||
var prev_pos := Vector3.ZERO
|
||||
var prev_radius := 0.0
|
||||
var first := true
|
||||
|
||||
while t <= girdle_radius:
|
||||
while t <= length:
|
||||
var kind: Dictionary = BORDER_KINDS[randi() % BORDER_KINDS.size()]
|
||||
var radius: float = kind["radius"] * kind["scale"]
|
||||
var lateral := randf_range(-border_jitter, border_jitter)
|
||||
var pos := _ridge_point(dir, perp, t, lateral)
|
||||
var pos := p0 + dir * t + perp * lateral
|
||||
|
||||
if not first:
|
||||
var min_dist := (prev_radius + radius) * border_overlap
|
||||
# Iterativ korrigieren statt blind zu vertrauen: die Facette ist geneigt,
|
||||
# daher ist die Distanz nicht rein radial (Höhe hängt am Abstand mit dran).
|
||||
# Iterativ korrigieren statt blind zu vertrauen (seitlicher Jitter
|
||||
# verschiebt den Punkt leicht von der reinen Geraden weg).
|
||||
for _i in range(4):
|
||||
var actual_dist := pos.distance_to(prev_pos)
|
||||
if actual_dist <= min_dist:
|
||||
break
|
||||
t -= (actual_dist - min_dist)
|
||||
pos = _ridge_point(dir, perp, t, lateral)
|
||||
pos = p0 + dir * t + perp * lateral
|
||||
|
||||
_spawn_border_prop(borders, kind, pos)
|
||||
prev_pos = pos
|
||||
@ -182,12 +197,6 @@ func _build_ridge(borders: Node3D, dir: Vector3, perp: Vector3) -> void:
|
||||
first = false
|
||||
t += radius # nächster Kandidat startet grob hinter diesem Prop; obige Prüfung zieht ihn bei Bedarf näher
|
||||
|
||||
func _ridge_point(dir: Vector3, perp: Vector3, t: float, lateral: float) -> Vector3:
|
||||
var frac: float = clamp((t - table_radius) / (girdle_radius - table_radius), 0.0, 1.0)
|
||||
var pos := dir * t + perp * lateral
|
||||
pos.y = lerp(0.0, -crown_drop, frac)
|
||||
return pos
|
||||
|
||||
func _spawn_border_prop(parent: Node3D, kind: Dictionary, pos: Vector3) -> void:
|
||||
var inst := (kind["scene"] as PackedScene).instantiate() as Node3D
|
||||
inst.position = pos
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user