perf(sites): build terrain tiles from bulk field blocks

Building the 64 tiles of the Banc du Vigilant cost about 1.9 s through
per-vertex cell_world_position/normal_at_cell calls, leaving the 3 s
load budget with too little headroom (2.1-2.9 s measured, one 4.8 s
outlier). TerrainHeightField now returns positions and normals of a
cell block in one call, with normal_at_cell sharing the same formula;
the tile build drops to about 0.5 s.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
OlivierandClaude Opus 5.5 committed 2026-10-06 20:55:35 +02:00
1 parent bce5c20dec
commit ce3b75989e
3 files changed
+80 -16

No files matched your search

+14 -1
View File
@@ -7,7 +7,7 @@ const SitePlacement = preload("res://game/domain/sites/site_placement.gd")
const SiteRoute = preload("res://game/domain/sites/site_route.gd")
const DiveSiteDefinition = preload("res://game/domain/sites/dive_site_definition.gd")
const TEST_COUNT := 39
const TEST_COUNT := 41
var _failures: Array[String] = []
@@ -97,6 +97,19 @@ func _test_height_field_sampling() -> void:
_expect(field.material_at(-10.4, 100.0) == SonarMaterial.Value.ROCK, "material is the nearest cell")
_expect(field.material_at(-6.0, 103.0) == SonarMaterial.Value.SAND, "material of an interior cell")
_expect(field.normal_at_cell(1, 1).is_equal_approx(Vector3(0.0, 1.0, 1.0).normalized()), "normal leans against the downhill direction")
var block_positions := field.cell_block_positions(1, 2, 0, 3)
var block_normals := field.cell_block_normals(1, 2, 0, 3)
var block_matches := block_positions.size() == 8 and block_normals.size() == 8
var normals_match := block_matches
for row in 4:
for column in range(1, 3):
var index := row * 2 + column - 1
if block_matches and not block_positions[index].is_equal_approx(field.cell_world_position(column, row)):
block_matches = false
if normals_match and not block_normals[index].is_equal_approx(field.normal_at_cell(column, row)):
normals_match = false
_expect(block_matches, "cell block positions match cell_world_position, row-major")
_expect(normals_match, "cell block normals match normal_at_cell, edges included")
_expect(not field.contains(-11.0, 100.0) and field.contains(-8.0, 103.0), "contains follows the bounds")
_expect(is_equal_approx(field.reflectivity_for(SonarMaterial.Value.SAND), 0.45), "sand reflectivity comes from the data")