wip(assembler): round L22 -- one 8 m layout chunk for every strate; real ceiling -> content -> bedrock
StrateLayoutChunkSizeMeters (world setting, default 8 m; owner decision) is resolved once in the director/adapter and standalone loader; every generator reads the resolved width (no CHUNK_SIZE / Core-tile inference). Every strate gets solid ceiling and bedrock bands from its BoundarySealThickness in the shared composition path (diggable by default); faces come from the shared boundary path. Owner world: FloatingIslands +8..-120 m (128 m, now with a bedrock floor), SurfaceWorld -120..-632 m (unchanged; full-detail and exact-query hashes equal L21); the 60 m gap is gone. The strict layout validator passes on the real world, with 0 endpoint dispatch disagreements. Spawn/benchmark camera derived from route.front. Ledges under the islands gone (reviewer capture). Evaluator 7, recipe schema 2, layout snapshot 2, FI geometry 4. Open: SW cap profiles exceed the ceiling band (owner call); transitions still Hard; Unreal setting/manager/adapter edits uncompiled here. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CSFYgsdW8ejZSyiMf4qRSX
This commit is contained in:
1 parent
8753f6dbe4
commit
55c26a05a7
28 files changed
+1432
-579
No files matched your search
@@ -235,6 +235,9 @@ namespace world_assembly_detail
|
||||
|| recipe.evaluatorVersion > WorldAssemblyEvaluatorVersion
|
||||
|| recipe.unitsPerVoxel != WorldAssemblySubvoxelsPerVoxel)
|
||||
{ error = "world assembly recipe version, evaluator or fixed scale is unsupported"; return false; }
|
||||
if (recipe.layoutChunkWidthSubvoxels <= 0
|
||||
|| recipe.layoutChunkWidthSubvoxels > 256ll * 512ll)
|
||||
{ error = "resolved strate-layout chunk width is outside the supported physical range"; return false; }
|
||||
if (recipe.biomes.empty() || recipe.biomes.size() > MaxBiomeCount)
|
||||
{ error = "world assembly recipe must contain one to eight biome profiles"; return false; }
|
||||
if (recipe.biomeCellSizeSubvoxels <= 0 || recipe.biomeCellSizeSubvoxels > 100000000ll
|
||||
@@ -296,7 +299,8 @@ namespace world_assembly_detail
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool ValidateStratum(const WorldAssemblyStratumPlanV1& stratum, std::string& error)
|
||||
inline bool ValidateStratum(const WorldAssemblyStratumPlanV1& stratum,
|
||||
std::int64_t layoutChunkWidthSubvoxels, std::string& error)
|
||||
{
|
||||
if (stratum.strateIndex < 0 || stratum.topChunkZ < stratum.bottomChunkZ
|
||||
|| stratum.capWavelengthSubvoxels <= 0 || stratum.capUndulationSubvoxels < 0
|
||||
@@ -330,9 +334,9 @@ namespace world_assembly_detail
|
||||
if (feature.type == 2 || feature.type == 4)
|
||||
{
|
||||
const std::int64_t stratumMinZ = static_cast<std::int64_t>(stratum.bottomChunkZ)
|
||||
* 32 * WorldAssemblySubvoxelsPerVoxel;
|
||||
* layoutChunkWidthSubvoxels;
|
||||
const std::int64_t stratumMaxZ = (static_cast<std::int64_t>(stratum.topChunkZ) + 1)
|
||||
* 32 * WorldAssemblySubvoxelsPerVoxel;
|
||||
* layoutChunkWidthSubvoxels;
|
||||
constexpr std::int64_t maximumExceptionExtent = 1024
|
||||
* WorldAssemblySubvoxelsPerVoxel;
|
||||
for (std::size_t axis = 0; axis < 3; ++axis)
|
||||
@@ -420,6 +424,7 @@ namespace world_assembly_detail
|
||||
std::uint64_t hash = StartHash();
|
||||
HashWord(hash, recipe.schemaVersion, 4); HashWord(hash, recipe.evaluatorVersion, 4);
|
||||
HashWord(hash, recipe.unitsPerVoxel, 4); HashWord(hash, recipe.seed, 4);
|
||||
HashWord(hash, static_cast<std::uint64_t>(recipe.layoutChunkWidthSubvoxels), 8);
|
||||
HashWord(hash, static_cast<std::uint64_t>(recipe.biomeCellSizeSubvoxels), 8);
|
||||
HashWord(hash, static_cast<std::uint64_t>(recipe.biomeWarpSubvoxels), 8);
|
||||
HashWord(hash, static_cast<std::uint64_t>(recipe.biomeWarpWavelengthSubvoxels), 8);
|
||||
@@ -628,6 +633,7 @@ namespace world_assembly_detail
|
||||
if (!value.IsObject() || !ReadU32(value.Get("schema_version"), recipe.schemaVersion)
|
||||
|| !ReadU32(value.Get("evaluator_version"), recipe.evaluatorVersion)
|
||||
|| !ReadU32(value.Get("units_per_voxel"), recipe.unitsPerVoxel)
|
||||
|| !ReadInteger(value.Get("layout_chunk_width_q"), recipe.layoutChunkWidthSubvoxels)
|
||||
|| !ReadU32(value.Get("seed"), recipe.seed)
|
||||
|| !ReadInteger(value.Get("biome_cell_size_q"), recipe.biomeCellSizeSubvoxels)
|
||||
|| !ReadInteger(value.Get("biome_warp_q"), recipe.biomeWarpSubvoxels)
|
||||
@@ -693,6 +699,7 @@ namespace world_assembly_detail
|
||||
out << "{\"schema_version\":" << recipe.schemaVersion
|
||||
<< ",\"evaluator_version\":" << recipe.evaluatorVersion
|
||||
<< ",\"units_per_voxel\":" << recipe.unitsPerVoxel
|
||||
<< ",\"layout_chunk_width_q\":" << recipe.layoutChunkWidthSubvoxels
|
||||
<< ",\"seed\":" << recipe.seed
|
||||
<< ",\"biome_cell_size_q\":" << recipe.biomeCellSizeSubvoxels
|
||||
<< ",\"biome_warp_q\":" << recipe.biomeWarpSubvoxels
|
||||
@@ -861,7 +868,8 @@ namespace world_assembly_detail
|
||||
|| !ReadI32(islandValue.Get("bottom_chunk_z"), entry.bottomChunkZ))
|
||||
{ error = "world assembly floating-island slot is missing its resolved strate bounds"; return std::nullopt; }
|
||||
const std::string nestedJson = JsonText(islandValue.Get("manifest"));
|
||||
auto parsedIsland = FloatingIslandManifestV1::FromJson(nestedJson, error);
|
||||
auto parsedIsland = FloatingIslandManifestV1::FromJson(
|
||||
nestedJson, error, manifest.recipe.layoutChunkWidthSubvoxels);
|
||||
if (!parsedIsland) return std::nullopt;
|
||||
entry.manifest = std::move(*parsedIsland);
|
||||
manifest.floatingIslands.push_back(std::move(entry));
|
||||
@@ -1751,15 +1759,15 @@ bool WorldAssemblyManifest::finalize(std::string& error)
|
||||
{ error = "SurfaceWorld stratum recipe seed does not match the world assembly season seed"; return false; }
|
||||
stratum.recipeOverride.contentHash = world_assembly_detail::HashRecipe(stratum.recipeOverride);
|
||||
}
|
||||
if (!world_assembly_detail::ValidateStratum(stratum, error)) return false;
|
||||
if (!world_assembly_detail::ValidateStratum(stratum, recipe.layoutChunkWidthSubvoxels, error)) return false;
|
||||
if (recipe.evaluatorVersion >= 4)
|
||||
{
|
||||
if (stratum.routeConstraints.version != 1 || stratum.route.size() < 2)
|
||||
{ error = "world assembly evaluator 4 requires a versioned entrance-to-exit route"; return false; }
|
||||
const std::int64_t bottomZ = static_cast<std::int64_t>(stratum.bottomChunkZ)
|
||||
* 32 * WorldAssemblySubvoxelsPerVoxel;
|
||||
* recipe.layoutChunkWidthSubvoxels;
|
||||
const std::int64_t topZ = (static_cast<std::int64_t>(stratum.topChunkZ) + 1)
|
||||
* 32 * WorldAssemblySubvoxelsPerVoxel;
|
||||
* recipe.layoutChunkWidthSubvoxels;
|
||||
const std::int64_t halfHeight = stratum.routeConstraints.capsuleHeightSubvoxels / 2;
|
||||
for (const auto& point : stratum.route)
|
||||
{
|
||||
@@ -1789,14 +1797,12 @@ bool WorldAssemblyManifest::finalize(std::string& error)
|
||||
const auto& Scale = islands.manifest.recipe;
|
||||
if (Scale.ownerToCoreScaleNumerator == 0 || Scale.ownerToCoreScaleDenominator == 0)
|
||||
{ error = "floating-island owner-to-Core scale is invalid"; return false; }
|
||||
const double CoreVoxelsPerOwnerChunk = static_cast<double>(CoreTileVoxelCount)
|
||||
* Scale.ownerToCoreScaleNumerator / Scale.ownerToCoreScaleDenominator;
|
||||
const std::int64_t bottomQ = static_cast<std::int64_t>(std::llround(
|
||||
static_cast<double>(islands.bottomChunkZ) * CoreVoxelsPerOwnerChunk
|
||||
* WorldAssemblySubvoxelsPerVoxel));
|
||||
const std::int64_t topQ = static_cast<std::int64_t>(std::llround(
|
||||
static_cast<double>(static_cast<std::int64_t>(islands.topChunkZ) + 1)
|
||||
* CoreVoxelsPerOwnerChunk * WorldAssemblySubvoxelsPerVoxel));
|
||||
if(Scale.layoutChunkWidthSubvoxels<=0)
|
||||
{error="floating-island strate has no resolved layout chunk width";return false;}
|
||||
const std::int64_t bottomQ = static_cast<std::int64_t>(islands.bottomChunkZ)
|
||||
*Scale.layoutChunkWidthSubvoxels;
|
||||
const std::int64_t topQ = (static_cast<std::int64_t>(islands.topChunkZ)+1)
|
||||
*Scale.layoutChunkWidthSubvoxels;
|
||||
if (islands.manifest.recipe.layoutMinimumZSubvoxels < bottomQ
|
||||
|| islands.manifest.recipe.layoutMaximumZSubvoxels > topQ)
|
||||
{ error = "floating-island recipe layout escapes the resolved owner strate bounds"; return false; }
|
||||
@@ -2000,7 +2006,7 @@ std::array<std::int64_t,2> Heightfield2D::capHeightBounds() const noexcept
|
||||
if(recipe_->evaluatorVersion>=5)
|
||||
{
|
||||
const long double TopSubvoxels=(static_cast<long double>(plan_->topChunkZ)+1.0L)
|
||||
*CoreTileVoxelCount*WorldAssemblySubvoxelsPerVoxel;
|
||||
*recipe_->layoutChunkWidthSubvoxels;
|
||||
Minimum=std::min(Minimum,TopSubvoxels);
|
||||
Maximum=std::min(Maximum,TopSubvoxels);
|
||||
}
|
||||
@@ -2019,7 +2025,7 @@ std::int64_t Heightfield2D::farSurfaceCapHeightSubvoxels(std::int64_t x,
|
||||
// Clip only the far render surface. Keep the near density evaluator bit-identical.
|
||||
// Borner uniquement le plafond lointain. L'evaluateur de densite proche reste identique.
|
||||
const std::int64_t ownedUpperBoundary=(static_cast<std::int64_t>(plan_->topChunkZ)+1)
|
||||
*CoreTileVoxelCount*WorldAssemblySubvoxelsPerVoxel;
|
||||
*recipe_->layoutChunkWidthSubvoxels;
|
||||
return std::min(column.capHeightSubvoxels,ownedUpperBoundary);
|
||||
}
|
||||
|
||||
@@ -2298,8 +2304,8 @@ FieldInfluenceBounds Heightfield2D::influenceBounds() const noexcept
|
||||
{
|
||||
FieldInfluenceBounds out;
|
||||
if (!isValid()) return out;
|
||||
out.minimumZSubvoxels = static_cast<std::int64_t>(plan_->bottomChunkZ) * 32 * WorldAssemblySubvoxelsPerVoxel;
|
||||
out.maximumZSubvoxels = (static_cast<std::int64_t>(plan_->topChunkZ) + 1) * 32 * WorldAssemblySubvoxelsPerVoxel;
|
||||
out.minimumZSubvoxels = static_cast<std::int64_t>(plan_->bottomChunkZ) * recipe_->layoutChunkWidthSubvoxels;
|
||||
out.maximumZSubvoxels = (static_cast<std::int64_t>(plan_->topChunkZ) + 1) * recipe_->layoutChunkWidthSubvoxels;
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user