feat(tools): irregular strata and angular boulder blocks
Strata gain a dip, a slow seeded warp that bends and notches the beds, and a per-bed thickness and hardness jitter with ordered boundaries, so walls never invert. BoulderField gains an angularity parameter: elongated super-ellipse slabs with flat tops, sharp shoulders, random heading and tilt, footprint area preserved. Both sites are re-baked with the new settings; the coral heads stay rounded. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
34b39a8dbc
commit
61ef4a892d
15 files changed
+237
-46
No files matched your search
@@ -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 := 48
|
||||
const TEST_COUNT := 53
|
||||
|
||||
var _failures: Array[String] = []
|
||||
|
||||
@@ -24,6 +24,8 @@ func _init() -> void:
|
||||
_test_boulder_field()
|
||||
_test_strata()
|
||||
_test_slope_roughness()
|
||||
_test_irregular_strata()
|
||||
_test_angular_boulders()
|
||||
|
||||
if _failures.is_empty():
|
||||
print("Site baker unit tests: %d passed, 0 failed." % TEST_COUNT)
|
||||
@@ -225,6 +227,72 @@ func _test_strata() -> void:
|
||||
_expect(north_same and south_changed, "strata stay inside their region")
|
||||
|
||||
|
||||
func _test_irregular_strata() -> void:
|
||||
# 45 degree plane at 0.5 m per cell, beds of 2 m with dip, warp and thickness variation.
|
||||
var recipe := _small_recipe()
|
||||
recipe.columns = 81
|
||||
recipe.rows = 81
|
||||
recipe.cell_size_m = 0.5
|
||||
recipe.origin_x_m = -20.0
|
||||
recipe.origin_z_m = -20.0
|
||||
recipe.primitives.append(SiteTerrainBaker.SlopedPlane.new(30.3, 1.0, 0.0, 0.0, 0.0))
|
||||
var regular_recipe := _small_recipe()
|
||||
regular_recipe.columns = 81
|
||||
regular_recipe.rows = 81
|
||||
regular_recipe.cell_size_m = 0.5
|
||||
regular_recipe.origin_x_m = -20.0
|
||||
regular_recipe.origin_z_m = -20.0
|
||||
regular_recipe.primitives.append(SiteTerrainBaker.SlopedPlane.new(30.3, 1.0, 0.0, 0.0, 0.0))
|
||||
regular_recipe.modifiers.append(SiteTerrainBaker.Strata.new(2.0, 0.9, 20.0, 35.0, Rect2()))
|
||||
var regular := SiteTerrainBaker.bake(regular_recipe)
|
||||
recipe.modifiers.append(SiteTerrainBaker.Strata.new(2.0, 0.9, 20.0, 35.0, Rect2(), Vector2(0.0, 0.05), 11, 1.0, 0.6))
|
||||
var irregular := SiteTerrainBaker.bake(recipe)
|
||||
var monotonic := true
|
||||
var ledges := 0
|
||||
var on_ledge := false
|
||||
var off_grid_ledges := 0
|
||||
for column in range(10, 70):
|
||||
var here := irregular.elevations_m[irregular.index_of(column, 40)]
|
||||
var next := irregular.elevations_m[irregular.index_of(column + 1, 40)]
|
||||
# Ledges follow the bent beds, so a ledge may tilt back a little; the wall
|
||||
# itself must never step down.
|
||||
monotonic = monotonic and next >= here - 0.3
|
||||
if next - here < 0.1:
|
||||
if not on_ledge:
|
||||
ledges += 1
|
||||
var nearest_regular := roundf(here / 2.0) * 2.0
|
||||
if absf(here - nearest_regular) > 0.2:
|
||||
off_grid_ledges += 1
|
||||
on_ledge = true
|
||||
else:
|
||||
on_ledge = false
|
||||
_expect(monotonic, "irregular strata never cut a back-step deeper than 0.3 m")
|
||||
_expect(ledges >= 4, "irregular strata still cut distinct ledges (%d)" % ledges)
|
||||
_expect(off_grid_ledges >= 2, "irregular bed boundaries leave the regular 2 m grid (%d of %d)" % [off_grid_ledges, ledges])
|
||||
var north := irregular.elevations_m[irregular.index_of(40, 10)]
|
||||
var south := irregular.elevations_m[irregular.index_of(40, 70)]
|
||||
var regular_north := regular.elevations_m[regular.index_of(40, 10)]
|
||||
var regular_south := regular.elevations_m[regular.index_of(40, 70)]
|
||||
_expect(absf((south - north) - (regular_south - regular_north)) > 0.3, "dip and warp move the ledges along the wall")
|
||||
|
||||
|
||||
func _test_angular_boulders() -> void:
|
||||
var round := SiteTerrainBaker.BoulderField.new(Vector2.ZERO, 0.0, 21, 1, 5.0, 5.0, 1.0, 0.0)
|
||||
var angular := SiteTerrainBaker.BoulderField.new(Vector2.ZERO, 0.0, 21, 1, 5.0, 5.0, 1.0, 1.0)
|
||||
_expect(round.boulders() == angular.boulders(), "angularity changes the shape, not the placement")
|
||||
var round_ring := 0.0
|
||||
var angular_ring := 0.0
|
||||
var bounded := true
|
||||
for step in 16:
|
||||
var angle := TAU * float(step) / 16.0
|
||||
round_ring += round.elevation_delta(1.5 * cos(angle), 1.5 * sin(angle))
|
||||
var height := angular.elevation_delta(1.5 * cos(angle), 1.5 * sin(angle))
|
||||
angular_ring += height
|
||||
bounded = bounded and height <= 5.0 * (1.0 + SiteTerrainBaker.BoulderField.MAXIMUM_TILT) + 0.001
|
||||
_expect(angular_ring > round_ring, "angular blocks have flatter tops than half-ellipsoids")
|
||||
_expect(bounded, "angular block height stays within the tilt bound")
|
||||
|
||||
|
||||
func _test_slope_roughness() -> void:
|
||||
var recipe := _small_recipe()
|
||||
recipe.primitives.append(SiteTerrainBaker.SlopedPlane.new(30.0, 0.0, 0.0, 0.0, 0.0))
|
||||
|
||||
Reference in new issue
Block a user