wip(assembler): round S4 -- continuous far ceiling at the strate's upper boundary
S3's far cap sat up to 8.2 m above the near roof and read as floating pieces. The far render cap now projects onto the owning strate's upper boundary (density unchanged), on a global XY lattice, LOD4 16-voxel grid + LOD5-8 128-voxel. Cap agreement 0.05 cm (100 cm control detected), 2520/2520 upward rays hit roof on the owner walk. Far recipe v2; LOD0-3 hashes equal S2/S3. Tile p95 flat; cold clipmap +4.4%. Far-cliff fluting left open (coarse MC step). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MmSoF64BbRFmk9C3p1VsBJ
This commit is contained in:
1 parent
d0f97bf79a
commit
9d3c50ca95
14 files changed
+1376
-34
No files matched your search
@@ -1463,8 +1463,9 @@ namespace world_assembly_detail
|
||||
+secondaryHeight*(65536-primaryWeight))/65536;
|
||||
out.biomeId=primary->stableId;out.neighborBiomeId=secondary->stableId;
|
||||
out.biomeWeightQ16=primaryWeight;
|
||||
out.capHeightSubvoxels=plan.capHeightSubvoxels+MulQ16(plan.capUndulationSubvoxels,
|
||||
std::int64_t cap=plan.capHeightSubvoxels+MulQ16(plan.capUndulationSubvoxels,
|
||||
Noise2D(x,y,plan.capWavelengthSubvoxels,recipe.seed,0x4341505f554e4431ull));
|
||||
out.capHeightSubvoxels=cap;
|
||||
out.waterSurfaceSubvoxels=plan.waterSurfaceSubvoxels;
|
||||
return out;
|
||||
}
|
||||
@@ -1816,6 +1817,65 @@ bool Heightfield2D::isValid() const noexcept
|
||||
});
|
||||
}
|
||||
|
||||
std::array<std::int64_t,2> Heightfield2D::capHeightBounds() const noexcept
|
||||
{
|
||||
if(!isValid())return {0,0};
|
||||
long double Minimum=std::numeric_limits<long double>::infinity();
|
||||
long double Maximum=-std::numeric_limits<long double>::infinity();
|
||||
const auto IncludeBiome=[&](const WorldAssemblyBiomeProfileV1& Biome)
|
||||
{
|
||||
const long double Base=Biome.hasCapProfile
|
||||
?static_cast<long double>(Biome.capHeightSubvoxels)
|
||||
:static_cast<long double>(plan_->capHeightSubvoxels);
|
||||
const long double Undulation=Biome.hasCapProfile
|
||||
?static_cast<long double>(Biome.capUndulationSubvoxels)
|
||||
:static_cast<long double>(plan_->capUndulationSubvoxels);
|
||||
const long double Detail=Biome.hasCapProfile
|
||||
?static_cast<long double>(Biome.capDetailAmplitudeSubvoxels)
|
||||
:static_cast<long double>(plan_->capDetailAmplitudeSubvoxels);
|
||||
const long double Ridge=Biome.hasCapProfile
|
||||
?static_cast<long double>(Biome.capRidgeAmplitudeSubvoxels)
|
||||
:static_cast<long double>(plan_->capRidgeAmplitudeSubvoxels);
|
||||
Minimum=std::min(Minimum,Base-Undulation-Detail-Ridge);
|
||||
Maximum=std::max(Maximum,Base+Undulation);
|
||||
};
|
||||
if(recipe_->biomes.empty())
|
||||
{
|
||||
const WorldAssemblyBiomeProfileV1 Fallback{};
|
||||
IncludeBiome(Fallback);
|
||||
}
|
||||
else for(const auto& Biome:recipe_->biomes)IncludeBiome(Biome);
|
||||
long double FeatureAmplitude=0.0L;
|
||||
for(const auto& Feature:plan_->features)
|
||||
if(Feature.type==3)
|
||||
FeatureAmplitude+=std::abs(static_cast<long double>(Feature.parametersSubvoxels[0]));
|
||||
Minimum-=FeatureAmplitude;Maximum+=FeatureAmplitude;
|
||||
if(recipe_->evaluatorVersion>=5)
|
||||
{
|
||||
const long double TopSubvoxels=(static_cast<long double>(plan_->topChunkZ)+1.0L)
|
||||
*CoreTileVoxelCount*WorldAssemblySubvoxelsPerVoxel;
|
||||
Minimum=std::min(Minimum,TopSubvoxels);
|
||||
Maximum=std::min(Maximum,TopSubvoxels);
|
||||
}
|
||||
const long double Int64Minimum=static_cast<long double>(std::numeric_limits<std::int64_t>::min());
|
||||
const long double Int64Maximum=static_cast<long double>(std::numeric_limits<std::int64_t>::max());
|
||||
return {static_cast<std::int64_t>(std::clamp(Minimum,Int64Minimum,Int64Maximum)),
|
||||
static_cast<std::int64_t>(std::clamp(Maximum,Int64Minimum,Int64Maximum))};
|
||||
}
|
||||
|
||||
std::int64_t Heightfield2D::farSurfaceCapHeightSubvoxels(std::int64_t x,
|
||||
std::int64_t y) const noexcept
|
||||
{
|
||||
if(!isValid())return 0;
|
||||
const HeightfieldPointSample column=point(x,y,0);
|
||||
if(recipe_->evaluatorVersion<5)return column.capHeightSubvoxels;
|
||||
// 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;
|
||||
return std::min(column.capHeightSubvoxels,ownedUpperBoundary);
|
||||
}
|
||||
|
||||
WorldAssemblyFeatureTileListV1 Heightfield2D::buildFeatureTileList(
|
||||
const std::array<std::int64_t,3>& minimum,
|
||||
const std::array<std::int64_t,3>& maximum) const
|
||||
|
||||
Reference in new issue
Block a user