feat(tools): Strata modifier quantises steep walls into ledges

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
OlivierandClaude Fable 5.1 committed 2026-10-06 21:39:30 +02:00
1 parent 6dd2e86f91
commit 26f29ce14f
2 files changed
+78 -1

No files matched your search

+39 -1
View File
@@ -8,7 +8,7 @@ const SiteTerrainData = preload("res://game/domain/sites/site_terrain_data.gd")
const ZONE1_TERRAIN_PATH := "res://content/sites/zone1_vigilant_terrain.res"
const TEST_COUNT := 36
const TEST_COUNT := 40
var _failures: Array[String] = []
@@ -22,6 +22,7 @@ func _init() -> void:
_test_escarpment()
_test_outcrop()
_test_boulder_field()
_test_strata()
if _failures.is_empty():
print("Site baker unit tests: %d passed, 0 failed." % TEST_COUNT)
@@ -174,6 +175,43 @@ func _test_boulder_field() -> void:
_expect(stacked.elevation_delta(0.0, 0.0) <= 4.0 + 0.001, "overlapping boulders combine by maximum, not by sum")
func _test_strata() -> void:
# A 45 degree plane sampled every 0.5 m: four cells per 2 m layer.
var recipe := _small_recipe()
recipe.columns = 41
recipe.rows = 41
recipe.cell_size_m = 0.5
recipe.origin_x_m = -10.0
recipe.origin_z_m = -10.0
recipe.primitives.append(SiteTerrainBaker.SlopedPlane.new(30.0, 1.0, 0.0, 0.0, 0.0))
var plain := SiteTerrainBaker.bake(recipe)
recipe.modifiers.append(SiteTerrainBaker.Strata.new(2.0, 0.9, 20.0, 35.0, Vector2.ZERO, 0.0))
var terraced := SiteTerrainBaker.bake(recipe)
var flat_cells := 0
var riser_cells := 0
for column in range(5, 35):
var rise := terraced.elevations_m[terraced.index_of(column + 1, 20)] - terraced.elevations_m[terraced.index_of(column, 20)]
if rise < 0.1:
flat_cells += 1
elif rise > 0.9:
riser_cells += 1
_expect(flat_cells >= 8 and riser_cells >= 4, "strata turn a steep slope into ledges and risers (%d flat, %d risers)" % [flat_cells, riser_cells])
_expect(is_equal_approx(terraced.elevations_m[terraced.index_of(20, 20)], plain.elevations_m[plain.index_of(20, 20)]), "strata keep the layer boundaries where they were")
var flat := _small_recipe()
flat.primitives.append(SiteTerrainBaker.SlopedPlane.new(30.3, 0.0, 0.0, 0.0, 0.0))
flat.modifiers.append(SiteTerrainBaker.Strata.new(2.0, 0.9, 20.0, 35.0, Vector2.ZERO, 0.0))
var flat_data := SiteTerrainBaker.bake(flat)
_expect(is_equal_approx(flat_data.elevations_m[flat_data.index_of(10, 10)], -30.3), "strata leave flat ground alone")
var identity := _small_recipe()
identity.primitives.append(SiteTerrainBaker.SlopedPlane.new(30.0, 1.0, 0.0, 0.0, 0.0))
var before := SiteTerrainBaker.bake(identity)
identity.modifiers.append(SiteTerrainBaker.Strata.new(2.0, 0.0, 20.0, 35.0, Vector2.ZERO, 0.0))
var after := SiteTerrainBaker.bake(identity)
_expect(before.elevations_m == after.elevations_m, "sharpness 0 is the identity")
func _test_zone1_artefact_is_stable() -> void:
var versioned := load(ZONE1_TERRAIN_PATH) as SiteTerrainData
_expect(versioned != null, "versioned zone 1 terrain loads")