Terrain des sites de plongée : champ de hauteur authoré, Banc du Vigilant, formes variées et rendu sous-marin #4
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 ZONE1_TERRAIN_PATH := "res://content/sites/zone1_vigilant_terrain.res"
|
||||||
|
|
||||||
const TEST_COUNT := 36
|
const TEST_COUNT := 40
|
||||||
|
|
||||||
var _failures: Array[String] = []
|
var _failures: Array[String] = []
|
||||||
|
|
||||||
@@ -22,6 +22,7 @@ func _init() -> void:
|
|||||||
_test_escarpment()
|
_test_escarpment()
|
||||||
_test_outcrop()
|
_test_outcrop()
|
||||||
_test_boulder_field()
|
_test_boulder_field()
|
||||||
|
_test_strata()
|
||||||
|
|
||||||
if _failures.is_empty():
|
if _failures.is_empty():
|
||||||
print("Site baker unit tests: %d passed, 0 failed." % TEST_COUNT)
|
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")
|
_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:
|
func _test_zone1_artefact_is_stable() -> void:
|
||||||
var versioned := load(ZONE1_TERRAIN_PATH) as SiteTerrainData
|
var versioned := load(ZONE1_TERRAIN_PATH) as SiteTerrainData
|
||||||
_expect(versioned != null, "versioned zone 1 terrain loads")
|
_expect(versioned != null, "versioned zone 1 terrain loads")
|
||||||
|
|||||||
@@ -415,6 +415,45 @@ class Modifier extends RefCounted:
|
|||||||
return elevation_m
|
return elevation_m
|
||||||
|
|
||||||
|
|
||||||
|
## Quantises steep ground into horizontal ledges layer_height_m apart: the stratified
|
||||||
|
## walls of a canyon or cliff. Flat floors and summits are below minimum_slope_degrees and
|
||||||
|
## stay untouched; the effect is full from full_slope_degrees. sharpness 0 leaves the
|
||||||
|
## field unchanged, 1 cuts hard steps. radius_m 0 applies everywhere.
|
||||||
|
class Strata extends Modifier:
|
||||||
|
var layer_height_m: float
|
||||||
|
var sharpness: float
|
||||||
|
var centre: Vector2
|
||||||
|
var radius_m: float
|
||||||
|
var _minimum_tangent: float
|
||||||
|
var _full_tangent: float
|
||||||
|
|
||||||
|
func _init(
|
||||||
|
p_layer_height_m: float,
|
||||||
|
p_sharpness: float,
|
||||||
|
p_minimum_slope_degrees: float,
|
||||||
|
p_full_slope_degrees: float,
|
||||||
|
p_centre: Vector2,
|
||||||
|
p_radius_m: float
|
||||||
|
) -> void:
|
||||||
|
layer_height_m = p_layer_height_m
|
||||||
|
sharpness = clampf(p_sharpness, 0.0, 0.999)
|
||||||
|
centre = p_centre
|
||||||
|
radius_m = p_radius_m
|
||||||
|
_minimum_tangent = tan(deg_to_rad(p_minimum_slope_degrees))
|
||||||
|
_full_tangent = tan(deg_to_rad(p_full_slope_degrees))
|
||||||
|
|
||||||
|
func modify(x_m: float, z_m: float, elevation_m: float, gradient: Vector2) -> float:
|
||||||
|
var weight := smoothstep(_minimum_tangent, _full_tangent, gradient.length())
|
||||||
|
if radius_m > 0.0:
|
||||||
|
weight *= 1.0 - smoothstep(radius_m * 0.8, radius_m, Vector2(x_m, z_m).distance_to(centre))
|
||||||
|
if weight <= 0.0:
|
||||||
|
return elevation_m
|
||||||
|
var layer := floorf(elevation_m / layer_height_m)
|
||||||
|
var fraction := elevation_m / layer_height_m - layer
|
||||||
|
var sharpened := clampf((fraction - 0.5) / (1.0 - sharpness) + 0.5, 0.0, 1.0)
|
||||||
|
return lerpf(elevation_m, (layer + sharpened) * layer_height_m, weight)
|
||||||
|
|
||||||
|
|
||||||
class MaterialPatch extends RefCounted:
|
class MaterialPatch extends RefCounted:
|
||||||
var centre: Vector2
|
var centre: Vector2
|
||||||
var radius_m: float
|
var radius_m: float
|
||||||
|
|||||||
Reference in new issue
Block a user