wip(assembler): M1 round 2 -- surface recipe closer to legacy; native still slower and visibly buggy

Luna, M1 round 2 of 4: round 1's mismatch was an underfit recipe (two synthetic profiles,
missing large-scale surface terms). Now: biome IDs match 4,096/4,096, mean height offset
-1.366 vox, density MAE 274.04 -> 17.23 vox, sign mismatches 55.2% -> 18.14%. Bound audit
298 boxes / 8,046 points, 0 misses, negative control caught. Hash c5e0371612e927af at
W1/W8/W16. Surface query 8-14 ms / 4,096 points. Matched 3D capture pairs added.
Problems (my review of the captures + her timings):
- matched 120-tile views: full-detail readiness 5.227 s native vs 2.882 s legacy -- SLOWER;
- surface capture shows a rectangular flat-topped raised block with vertical walls
  (tile/patch-level height bug, inferred);
- cliff capture is broken (floating shard, debris trail), not a cliff.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MmSoF64BbRFmk9C3p1VsBJ
This commit is contained in:
Fr0zkaandClaude Opus 5.5 committed 2026-10-09 00:38:55 +02:00
1 parent 874c796c65
commit fcb16fd265
15 files changed
+1375 -91

No files matched your search

+33 -20
View File
@@ -79,22 +79,33 @@ Pass `analyticOnly = false` to retain the reference packed-page compiler. Packed
parent-cell coordinates and an 8-voxel apron; each covers a 128-voxel cube or one larger coarse
tile. This path remains available for parity checks and workloads that need the packed lattice.
## World assembler manifest v1 (prototype)
## World assembler manifest v1 (prototype; evaluator v1 and v2)
`ResolvedWorldSnapshot::FromJson` accepts an optional `world_assembly` object alongside the owner
snapshot. The object is the shipped-plan payload shape: a fixed-scale recipe and finite-strate plan
with hashes, no generated mesh or voxel samples. The reviewed sample payload is
[`round1-manifest.json`](../Research/WorldAssemblerM1/round1-manifest.json). Round 4 still needs to
connect this payload to the season asset/hash path.
with hashes, no generated mesh or voxel samples. The current evaluator-v2 review payload is
[`round2/world_assembly.json`](../Research/WorldAssemblerM1/round2/world_assembly.json); the
evaluator-v1 sample remains at [`round1-manifest.json`](../Research/WorldAssemblerM1/round1-manifest.json).
Round 4 still needs to connect this payload to the season asset/hash path.
Every coordinate and scalar uses signed integer units of 1/256 voxel (`units_per_voxel: 256`),
independent of the plugin's 25 cm Core voxel and of tile size. Schema and evaluator versions are
both 1. JSON integer fields are canonicalized in declared field order and hashed as 4- or 8-byte
little-endian words with FNV-1a 64. Hashes are emitted as 16 lowercase hexadecimal characters;
JSON key order and whitespace do not affect them. The root, recipe, plan and each stratum carry a
content hash. The recipe stores its seed, warped biome-map settings and one to eight biome profiles;
the plan stores finite-strate extents, cap settings, stable-ID features and route points. Bounds,
feature count and route count are validated before a manifest is accepted.
independent of the plugin's 25 cm Core voxel and of tile size. The schema version is 1; evaluator
versions 1 and 2 are accepted, with evaluator 2 used for new recipes. Evaluator 1 retains its
original evaluation and hash semantics. JSON integer fields are canonicalized in declared field
order and hashed as 4- or 8-byte little-endian words with FNV-1a 64. Hashes are emitted as 16
lowercase hexadecimal characters; JSON key order and whitespace do not affect them. The root,
recipe, plan and each stratum carry a content hash. The recipe stores its seed, warped biome-map
settings and one to eight biome profiles; the plan stores finite-strate extents, cap settings,
stable-ID features, fixed-season water and route points. Bounds, feature count and route count are
validated before a manifest is accepted.
Evaluator 2 adds climate-based biome assignment, output-space blending of both ground and cap
profiles, per-biome relief and height warp, beach width, cliff limits, and optional per-biome cap
profiles. Feature types 1, 2 and 3 represent a cliff plane, a bounded 3D overhang box and an authored
cap feature. An overhang feature has a stable ID and a finite AABB clipped to its stratum; intervals
outside the box can use its certified influence bound, while intersecting intervals remain on the
evaluation path. Water surface and fill are separate sample outputs. The season water plane is fixed;
this block does not generate a water mesh.
```cpp
std::string error;
@@ -105,18 +116,20 @@ const auto* loaded = snapshot.worldAssembly(); // null when the owner snapshot h
`Heightfield2D` is the first field block. `point(xQ, yQ, zQ)` evaluates the biome map and blended
height profiles at fixed-scale coordinates, returning the ground and cap heights, primary and
neighbor biome IDs, Q16 blend weight, and signed density. Negative density is solid. Its block
contract reads `biome` and writes `height` plus `rock`; `water`, `waterSurface`, `route` and
`surfaceTags` are declared channels for later blocks. The detail envelope reports maximum absolute
vertical displacement and minimum feature size. Influence is global in XY and limited to the
finite stratum's Z extent.
neighbor biome IDs, Q16 blend weight and signed density. Evaluator 2 also returns the fixed water
surface and water-fill sample values. Negative density is solid. Its contract reads `biome` and
writes `height`, `rock`, `water` and `waterSurface`; route and `surfaceTags` remain declared channels
for later blocks. The detail envelope reports maximum absolute displacement and minimum feature
size. Influence is global in XY and limited to the finite stratum's Z extent, except for the
explicitly bounded evaluator-v2 feature boxes.
`interval(minXQ, minYQ, minZQ, maxXQ, maxYQ, maxZQ)` returns a conservative density range or
`known == false`; callers must keep evaluating when it is unknown. The current heightfield range
uses the maximum recipe-profile amplitude and cap undulation over the whole biome set. The public
`AuditHeightfieldBounds` samples points inside randomized boxes and includes a deliberately false
one-sided range as a negative control. A pass means no sampled point escaped and the negative
control was rejected; it is an audit of this block implementation, not a proof for future blocks.
uses conservative profile, beach, cliff, cap and bounded-feature envelopes. The public
`AuditHeightfieldBounds` samples points in randomized boxes and targeted biome-border, cliff, cap,
negative-coordinate and overhang boxes, and includes a deliberately false one-sided range as a
negative control. A pass means no sampled point escaped and the negative control was rejected; it
is an audit of this block implementation, not a proof for future blocks.
## Queries and tiles
@@ -103,7 +103,7 @@ namespace VoxelForgeCore
// L'assembleur v1 encode coordonnees et scalaires en 1/256 de voxel, independamment des tuiles.
inline constexpr std::int64_t WorldAssemblySubvoxelsPerVoxel = 256;
inline constexpr std::uint32_t WorldAssemblySchemaVersion = 1;
inline constexpr std::uint32_t WorldAssemblyEvaluatorVersion = 1;
inline constexpr std::uint32_t WorldAssemblyEvaluatorVersion = 2;
enum class FieldChannel : std::uint32_t
{
@@ -124,6 +124,29 @@ namespace VoxelForgeCore
std::int64_t mountainWavelengthSubvoxels = 256 * 128;
std::int64_t detailAmplitudeSubvoxels = 0;
std::int64_t detailWavelengthSubvoxels = 256 * 16;
// Evaluator 2: climate box and the resolved surface-operation parameters.
// Evaluateur 2 : plage climatique et parametres resolus des operations de surface.
std::int64_t reliefMinimumQ16 = 0, reliefMaximumQ16 = 1ll << 16;
std::int64_t moistureMinimumQ16 = 0, moistureMaximumQ16 = 1ll << 16;
std::int64_t reliefStrengthQ16 = 0, reliefContrastQ16 = 1ll << 16;
std::int64_t reliefWavelengthSubvoxels = 256 * 1024;
std::int64_t heightWarpStrengthSubvoxels = 0;
std::int64_t heightWarpWavelengthSubvoxels = 256 * 128;
std::int64_t beachWidthSubvoxels = 0;
std::int64_t cliffStrengthQ16 = 0, cliffSlopeThresholdQ16 = 1ll << 15;
std::int64_t cliffSharpnessQ16 = 2ll << 16;
std::int64_t cliffSampleDistanceSubvoxels = 256 * 2;
std::int64_t cliffMaximumDisplacementSubvoxels = 0;
bool hasCapProfile = false;
std::int64_t capHeightSubvoxels = 0;
std::int64_t capWarpStrengthSubvoxels = 0;
std::int64_t capWarpWavelengthSubvoxels = 256 * 128;
std::int64_t capUndulationSubvoxels = 0;
std::int64_t capWavelengthSubvoxels = 256 * 512;
std::int64_t capDetailAmplitudeSubvoxels = 0;
std::int64_t capDetailWavelengthSubvoxels = 256 * 16;
std::int64_t capRidgeAmplitudeSubvoxels = 0;
std::int64_t capRidgeWavelengthSubvoxels = 256 * 64;
};
struct WorldAssemblyRecipeV1
@@ -136,6 +159,11 @@ namespace VoxelForgeCore
std::int64_t biomeWarpSubvoxels = 256 * 250;
std::int64_t biomeWarpWavelengthSubvoxels = 256 * 556;
std::int64_t biomeBorderBlendSubvoxels = 256 * 120;
// Climate fields used to assign deterministic biome sites.
// Champs climatiques utilises pour affecter les sites de biome de facon deterministe.
std::int64_t biomeClimateReliefWavelengthSubvoxels = 256 * 3333;
std::int64_t biomeClimateMoistureWavelengthSubvoxels = 256 * 2500;
std::int64_t biomeClimateReliefContrastQ16 = 2ll << 16;
std::vector<WorldAssemblyBiomeProfileV1> biomes;
std::uint64_t contentHash = 0;
};
@@ -167,6 +195,14 @@ namespace VoxelForgeCore
std::int64_t capHeightSubvoxels = 0;
std::int64_t capUndulationSubvoxels = 0;
std::int64_t capWavelengthSubvoxels = 256 * 512;
// Optional evaluator-2 cap layers; all zero preserves the evaluator-1 payload hash.
// Couches de plafond optionnelles; zero conserve le hash historique des payloads v1.
std::int64_t capDetailAmplitudeSubvoxels = 0;
std::int64_t capDetailWavelengthSubvoxels = 256 * 16;
std::int64_t capRidgeAmplitudeSubvoxels = 0;
std::int64_t capRidgeWavelengthSubvoxels = 256 * 64;
std::int64_t waterSurfaceSubvoxels = 0;
bool waterEnabled = false;
std::vector<WorldAssemblyFeatureV1> features;
std::vector<WorldAssemblyRoutePointV1> route;
std::uint64_t contentHash = 0;
@@ -204,6 +240,8 @@ namespace VoxelForgeCore
std::uint32_t neighborBiomeId = 0;
std::uint32_t biomeWeightQ16 = 0;
std::int64_t densitySubvoxels = 0;
std::int64_t waterSurfaceSubvoxels = 0;
std::int64_t waterFillSubvoxels = 0;
};
struct FieldInterval
@@ -254,6 +292,8 @@ namespace VoxelForgeCore
FieldInfluenceBounds influenceBounds() const noexcept;
FieldDetailEnvelope detailEnvelope() const noexcept;
FieldBlockContract contract() const noexcept;
const WorldAssemblyRecipeV1* recipe() const noexcept { return recipe_; }
const WorldAssemblyStratumPlanV1* plan() const noexcept { return plan_; }
private:
const WorldAssemblyRecipeV1* recipe_ = nullptr;
@@ -266,6 +306,12 @@ namespace VoxelForgeCore
std::uint64_t pointSamples = 0;
std::uint64_t missedBounds = 0;
std::uint64_t unknownBounds = 0;
std::uint64_t biomeBorderBoxes = 0;
std::uint64_t cliffBoxes = 0;
std::uint64_t capBoxes = 0;
std::uint64_t negativeCoordinateBoxes = 0;
std::uint64_t exceptionBoxes = 0;
std::uint64_t exceptionPointSamples = 0;
bool negativeControlDetected = false;
bool passed = false;
};
File diff suppressed because it is too large. Load diff