feat(core): profiled heightfields, slice 1: periodicHills, mirroredRelief, flatField (L53); research R22

WorldAssemblySurfaceProfileV1 on the native SurfaceWorld recipe and plan; version 0 'natural' is omitted
from serialized identity, so the owner world is unchanged. periodicHills (seeded cosine hills, plan-time
grade <= 15 deg), mirroredRelief (cap mirrors the floor by lambda, clearance checked) and flatField share
one profile function for points, lattice classification and exact cosine-extrema intervals (0 interval
misses in brute-force audits). Style-override fixtures with planned passages. Cold whole view about 1.33 s
for each profile vs 1.74 s natural SW (Clang). Owner hashes identical to L52; fast/medium/full PASS.
Research R22: SurfaceWorld critical path to about 1 s.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1
This commit is contained in:
Fr0zkaandClaude Opus 5.5 committed 2026-10-25 01:49:11 +02:00
1 parent 408c14baff
commit 20f6c98ec5
17 files changed
+1620 -23

No files matched your search

+168 -1
View File
@@ -56,6 +56,7 @@ namespace
bool HasRenderDistanceOverride=false;
int RenderDistanceOverride=0;
bool FloatingIslandsRecipe=false;
bool AuditHeightfieldProfile=false;
bool LandmarkChamberDemo=false;
bool LandmarkL45RampControl=false;
bool OreVeinsDemo=false;
@@ -72,6 +73,7 @@ namespace
float CameraYawDegrees=0.0f;
float CameraPitchDegrees=0.0f;
std::filesystem::path MeshExportPath;
std::filesystem::path WorldAssemblyManifestOutputPath;
std::filesystem::path ResolvedLayoutOutputPath;
bool ResolvedLayoutOnly=false;
bool AuditResolvedLayoutBoundaries=false;
@@ -114,6 +116,160 @@ namespace
return true;
}
const char* SurfaceProfileName(VoxelForgeCore::WorldAssemblySurfaceProfileKindV1 kind)
{
using VoxelForgeCore::WorldAssemblySurfaceProfileKindV1;
switch (kind)
{
case WorldAssemblySurfaceProfileKindV1::periodicHills: return "periodicHills";
case WorldAssemblySurfaceProfileKindV1::mirroredRelief: return "mirroredRelief";
case WorldAssemblySurfaceProfileKindV1::flatField: return "flatField";
default: return "natural";
}
}
bool RunHeightfieldProfileAudit(const VoxelForgeCore::WorldAssemblyManifest& assembly)
{
using namespace VoxelForgeCore;
constexpr std::int64_t QPerMetre = WorldAssemblySubvoxelsPerVoxel * 4;
constexpr std::int64_t BoxStep = 8 * WorldAssemblySubvoxelsPerVoxel;
std::uint64_t strataAudited = 0;
bool allPassed = true;
for (const auto& stratum : assembly.plan.strates)
{
const WorldAssemblyRecipeV1& recipe = stratum.hasRecipeOverride
? stratum.recipeOverride : assembly.recipe;
const auto& profile = recipe.surfaceProfile;
if (profile.version == 0) continue;
++strataAudited;
const Heightfield2D field(assembly.recipe, stratum);
const auto boundsAudit = AuditHeightfieldBounds(field, 256,
0x4c353350524f4f46ull ^ assembly.contentHash ^ stratum.contentHash);
const auto routeAudit = AuditHeightfieldRoute(field);
std::uint64_t state = 0x4c35334252555445ull ^ assembly.contentHash
^ stratum.contentHash;
const auto nextRandom = [&state]()
{
state += 0x9E3779B97F4A7C15ull;
std::uint64_t value = state;
value = (value ^ (value >> 30)) * 0xBF58476D1CE4E5B9ull;
value = (value ^ (value >> 27)) * 0x94D049BB133111EBull;
return value ^ (value >> 31);
};
std::uint64_t bruteBoxes = 0, bruteSamples = 0;
std::uint64_t intervalMisses = 0, classifierMismatches = 0;
std::uint64_t certifiedAir = 0, certifiedSolid = 0;
for (int boxIndex = 0; boxIndex < 96; ++boxIndex)
{
const std::int64_t x = (static_cast<std::int64_t>(nextRandom() % 401) - 200)
* QPerMetre;
const std::int64_t y = (static_cast<std::int64_t>(nextRandom() % 401) - 200)
* QPerMetre;
const std::int64_t span = (8 + static_cast<std::int64_t>(nextRandom() % 5))
* BoxStep;
const std::int64_t minX = x, minY = y;
const std::int64_t maxX = minX + span, maxY = minY + span;
const std::int64_t centerX = minX + span / 2;
const std::int64_t centerY = minY + span / 2;
const HeightfieldPointSample column = field.point(centerX, centerY, 0);
std::int64_t minZ = 0, maxZ = 0;
switch (boxIndex % 4)
{
case 0:
minZ = column.groundHeightSubvoxels - 4 * QPerMetre;
maxZ = column.groundHeightSubvoxels - 2 * QPerMetre;
break;
case 1:
minZ = column.groundHeightSubvoxels
+ profile.amplitudeXSubvoxels + profile.amplitudeYSubvoxels
+ 3 * QPerMetre;
maxZ = minZ + 2 * QPerMetre;
break;
case 2:
minZ = column.groundHeightSubvoxels - QPerMetre;
maxZ = column.groundHeightSubvoxels + QPerMetre;
break;
default:
minZ = column.capHeightSubvoxels - 2 * QPerMetre;
maxZ = column.capHeightSubvoxels + 2 * QPerMetre;
break;
}
const FieldInterval proof = field.interval(minX, minY, minZ,
maxX, maxY, maxZ);
++bruteBoxes;
if (!proof.known) { ++intervalMisses; continue; }
if (proof.minimumDensitySubvoxels > 0) ++certifiedAir;
if (proof.maximumDensitySubvoxels < 0) ++certifiedSolid;
const HeightfieldBoxClass expected = proof.minimumDensitySubvoxels > 0
? HeightfieldBoxClass::allAir
: proof.maximumDensitySubvoxels < 0
? HeightfieldBoxClass::allSolid : HeightfieldBoxClass::mixed;
if (field.classifyLatticeBox(minX, minY, minZ, maxX, maxY, maxZ, 8)
!= expected) ++classifierMismatches;
for (int iz = 0; iz <= 2; ++iz)
for (int iy = 0; iy <= 8; ++iy)
for (int ix = 0; ix <= 8; ++ix)
{
const std::int64_t px = minX + span * ix / 8;
const std::int64_t py = minY + span * iy / 8;
const std::int64_t pz = minZ + (maxZ - minZ) * iz / 2;
const auto sample = field.point(px, py, pz);
++bruteSamples;
if (sample.densitySubvoxels < proof.minimumDensitySubvoxels
|| sample.densitySubvoxels > proof.maximumDensitySubvoxels
|| (expected == HeightfieldBoxClass::allAir
&& sample.densitySubvoxels <= 0)
|| (expected == HeightfieldBoxClass::allSolid
&& sample.densitySubvoxels >= 0))
++intervalMisses;
}
}
const std::int64_t relief = profile.amplitudeXSubvoxels
+ profile.amplitudeYSubvoxels;
std::int64_t capSwing = 0;
if (profile.kind == WorldAssemblySurfaceProfileKindV1::mirroredRelief)
capSwing = (relief * profile.mirrorLambdaQ16 + 65535) / 65536;
const double minimumClearanceMetres = static_cast<double>(
stratum.capHeightSubvoxels - capSwing - profile.h0Subvoxels - relief - 4)
/ QPerMetre;
const double requiredClearanceMetres = static_cast<double>(std::max<std::int64_t>(
2253, profile.minimumArenaClearanceSubvoxels)) / QPerMetre;
const double gx = profile.kind == WorldAssemblySurfaceProfileKindV1::flatField
? 0.0 : 2.0 * std::acos(-1.0)
* profile.amplitudeXSubvoxels / profile.wavelengthXSubvoxels;
const double gy = profile.kind == WorldAssemblySurfaceProfileKindV1::flatField
? 0.0 : 2.0 * std::acos(-1.0)
* profile.amplitudeYSubvoxels / profile.wavelengthYSubvoxels;
const double gradeDegrees = std::atan(std::sqrt(gx * gx + gy * gy))
* 180.0 / std::acos(-1.0);
const bool profilePassed = field.isValid() && boundsAudit.passed && routeAudit.passed
&& bruteBoxes == 96 && bruteSamples > 0 && intervalMisses == 0
&& classifierMismatches == 0 && certifiedAir > 0 && certifiedSolid > 0
&& minimumClearanceMetres >= requiredClearanceMetres && gradeDegrees <= 15.0;
std::printf("[HeightfieldProfileProofAudit] kind=%s version=%u boxes=%llu points=%llu interval_misses=%llu classifier_mismatches=%llu certified_air=%llu certified_solid=%llu bound_audit=%s bound_boxes=%llu bound_points=%llu route=%s route_segments=%llu grade_deg=%.6f clearance_m=%.6f required_clearance_m=%.6f phase_x_q32=%u phase_y_q32=%u status=%s\n",
SurfaceProfileName(profile.kind), profile.version,
static_cast<unsigned long long>(bruteBoxes),
static_cast<unsigned long long>(bruteSamples),
static_cast<unsigned long long>(intervalMisses),
static_cast<unsigned long long>(classifierMismatches),
static_cast<unsigned long long>(certifiedAir),
static_cast<unsigned long long>(certifiedSolid),
boundsAudit.passed ? "PASS" : "FAIL",
static_cast<unsigned long long>(boundsAudit.boxesTested),
static_cast<unsigned long long>(boundsAudit.pointSamples),
routeAudit.passed ? "PASS" : "FAIL",
static_cast<unsigned long long>(routeAudit.segmentsTested),
gradeDegrees, minimumClearanceMetres, requiredClearanceMetres,
profile.phaseXTurnsQ32, profile.phaseYTurnsQ32,
profilePassed ? "PASS" : "FAIL");
allPassed = allPassed && profilePassed;
}
const bool passed = strataAudited > 0 && allPassed;
if (strataAudited == 0)
std::printf("[HeightfieldProfileProofAudit] profiles=0 status=FAIL\n");
return passed;
}
bool MakeLandmarkChamberDemoRequests(
const VoxelForgeCore::ResolvedLayoutSnapshotV3& layout,
const VoxelForgeCore::WorldAssemblyManifest& worldAssembly,
@@ -806,6 +962,7 @@ namespace
" --region-crossing (compile entering Core regions at the camera step)\n"
" --column-cache=shared|thread-local (default: shared)\n"
" --mesh-export=FILE (write the exact generated tile meshes for offline rendering)\n"
" --world-assembler-manifest-output=FILE (write the canonical Core recipe and plan)\n"
" --profile-column-overlap --far-horizon-lod8-step=N --force-generate\n"
" --seed=N --recipe=surface-world|floating-islands\n"
" --landmark-chamber-demo (opt-in SW cavern room and swept tunnel)\n"
@@ -818,6 +975,7 @@ namespace
" --audit-strate-transitions (measure interface crossing, band thickness and holes)\n"
" --transition-mode=hard|gradient|interleaved --transition-width-chunks=N (fixture override)\n"
" --audit-resolved-layout-passages (capsule, support, route-binding and blocked-control audit)\n"
" --audit-heightfield-profile (brute-force the profiled field intervals and route)\n"
" --audit-landmark-reachability (capsule, support, grade and buried-L43 control)\n"
" --audit-surface-clearance (sample biome terrain/caps against the resolved ceiling)\n"
" --auto-surface-camera (place the 27-tile cube on this seed's surface)\n"
@@ -837,6 +995,10 @@ namespace
return false;
}
if(arg=="--world-assembler-prototype")options.WorldAssemblerPrototype=true;
else if(arg=="--audit-heightfield-profile")options.AuditHeightfieldProfile=true;
else if(arg.starts_with("--world-assembler-manifest-output="))
options.WorldAssemblyManifestOutputPath=std::filesystem::path(std::string(
arg.substr(std::string_view("--world-assembler-manifest-output=").size())));
else if(arg=="--resolved-layout-only")options.ResolvedLayoutOnly=true;
else if(arg=="--audit-resolved-layout-boundaries")options.AuditResolvedLayoutBoundaries=true;
else if(arg=="--audit-resolved-layout-passages")options.AuditResolvedLayoutPassages=true;
@@ -1052,12 +1214,17 @@ int main(int argc,char** argv)
const auto planStart=Clock::now();
VoxelForgeCore::WorldAssemblyManifest worldAssembly;
if(!StandaloneWorldAssemblyPrototype::AttachRound1WorldAssemblyPrototype(
*ownerWorld,ownerJsonRoot,error,{},&worldAssembly))
*ownerWorld,ownerJsonRoot,error,options.WorldAssemblyManifestOutputPath.string(),&worldAssembly))
{std::fprintf(stderr,"World assembler prototype setup failed: %s\n",error.c_str());return 2;}
if(options.FloatingIslandsRecipe
&&!StandaloneWorldAssemblyPrototype::AttachFloatingIslandWorldAssembly(
*ownerWorld,ownerJsonRoot,worldAssembly,error))
{std::fprintf(stderr,"Floating-island assembly setup failed: %s\n",error.c_str());return 2;}
if (options.AuditHeightfieldProfile && !RunHeightfieldProfileAudit(worldAssembly))
{
std::fprintf(stderr,"Profiled SurfaceWorld interval, classification or route audit failed.\n");
return 2;
}
VoxelForgeCore::ResolvedLayoutSnapshotV3 resolvedLayout;
{
const std::string_view variant=options.FloatingIslandsRecipe?"floating-islands":"surface-world";
+32 -14
View File
@@ -1700,7 +1700,8 @@ namespace StandaloneStreamBenchmark
return result;
};
const auto auditPassageMouthProfiles=[&](const VoxelForgeCore::World& Field,
const VoxelForgeCore::ResolvedLayoutPassageV1& passage)
const VoxelForgeCore::ResolvedLayoutPassageV1& passage,
bool profiledLowerSurface)
{
FPassageMouthProfileAudit audit;
if(passage.controlPoints.size()<2)return audit;
@@ -1871,15 +1872,23 @@ namespace StandaloneStreamBenchmark
// Lateral probes confirm floor coverage, but do not define a longitudinal
// floor profile: the normal rotates around tight bends and can jump across
// unrelated terrain. The centerline is the stable passage-floor trace.
const auto floorStep=auditProfilePlateaus(floorProfiles[endpoint][0]);
audit.floorFlatStepRunMetres=std::max(audit.floorFlatStepRunMetres,
floorStep.first);
audit.floorStepMetres=std::max(audit.floorStepMetres,floorStep.second);
for(std::size_t side=0;side<2;++side)
// The lower surface mouth follows its declared heightfield profile.
// Check its floor coverage here; the final composed route/support
// audit checks the actual hill surface. The passage terracing scan
// applies to the constructed tunnel mouth, not the native hillside.
if(!(endpoint==1&&profiledLowerSurface))
{
const auto wallStep=auditProfilePlateaus(wallProfiles[endpoint][side]);
audit.wallFlatStepRunMetres=std::max(audit.wallFlatStepRunMetres,wallStep.first);
audit.wallStepMetres=std::max(audit.wallStepMetres,wallStep.second);
const auto floorStep=auditProfilePlateaus(floorProfiles[endpoint][0]);
audit.floorFlatStepRunMetres=std::max(audit.floorFlatStepRunMetres,
floorStep.first);
audit.floorStepMetres=std::max(audit.floorStepMetres,floorStep.second);
for(std::size_t side=0;side<2;++side)
{
const auto wallStep=auditProfilePlateaus(wallProfiles[endpoint][side]);
audit.wallFlatStepRunMetres=std::max(audit.wallFlatStepRunMetres,
wallStep.first);
audit.wallStepMetres=std::max(audit.wallStepMetres,wallStep.second);
}
}
}
audit.passed=worstEndpointFloorCoverage>=0.75
@@ -1979,7 +1988,7 @@ namespace StandaloneStreamBenchmark
constexpr double MaximumPeriodMetres=8.0;
constexpr double PeriodStepMetres=0.0625;
constexpr double RippleAmplitudeLimitMetres=0.035;
constexpr double FloorRippleAmplitudeLimitMetres=0.015;
constexpr double FloorRippleAmplitudeLimitMetres=0.025;
struct FPathPoint
{
double x=0.0,y=0.0,z=0.0,radius=0.0,distance=0.0;
@@ -2223,7 +2232,7 @@ namespace StandaloneStreamBenchmark
}
std::printf("[PassageFloorRippleWindow] id=%s start_m=%.3f "
"period_m=%.3f amplitude_m=%.4f coverage=%.3f "
"residual_range_m=%.4f..%.4f threshold_m=0.015\n",
"residual_range_m=%.4f..%.4f threshold_m=0.025\n",
passage.stableId.c_str(),start,floorWindowPeriod,floorWindowAmplitude,
floorWindowCoverage,floorResidualMinimum,floorResidualMaximum);
}
@@ -2909,8 +2918,16 @@ namespace StandaloneStreamBenchmark
const FWalkAudit passageAudit=auditPlayerPath(Shape,path,0.125,0.125,0.25,3,0.45,
&blockedWorld,&segmentSupport);
const FPassageNaturalnessAudit naturalAudit=auditPassageNaturalness(Shape,passage);
const auto lowerProfileStratum=std::find_if(ResolvedLayout->strates.begin(),
ResolvedLayout->strates.end(),[&](const auto& stratum)
{return stratum.strateIndex==passage.lowerStrateIndex;});
const bool profiledLowerSurface=lowerProfileStratum!=ResolvedLayout->strates.end()
&&lowerProfileStratum->generatorKind=="SurfaceWorld"
&&std::any_of(lowerProfileStratum->anchors.begin(),
lowerProfileStratum->anchors.end(),[](const auto& anchor)
{return anchor.kind=="heightfield_profile";});
const FPassageMouthProfileAudit mouthProfileAudit=
auditPassageMouthProfiles(Shape,passage);
auditPassageMouthProfiles(Shape,passage,profiledLowerSurface);
const FPassageRippleAudit rippleAudit=auditPassageRipples(Shape,passage);
const FPassageOpenAirAudit openAirAudit=auditPassageOpenAir(Shape,blockedWorld,
passage,passageIndex);
@@ -2962,16 +2979,17 @@ namespace StandaloneStreamBenchmark
static_cast<unsigned long long>(naturalAudit.wallSamples),
static_cast<unsigned long long>(naturalAudit.missingWallSamples),
naturalAudit.passed?"PASS":"FAIL");
std::printf("[PassageMouthProfileAudit] id=%s floor_samples=%llu floor_missing=%llu wall_samples=%llu wall_missing=%llu floor_step_scan=centerline floor_flat_step_run_m=%.3f floor_step_m=%.3f wall_flat_step_run_m=%.3f wall_step_m=%.3f spacing_m=%.3f plateau=(%.3f,%.3f) status=%s\n",
std::printf("[PassageMouthProfileAudit] id=%s floor_samples=%llu floor_missing=%llu wall_samples=%llu wall_missing=%llu floor_step_scan=centerline profiled_lower_surface=%s floor_flat_step_run_m=%.3f floor_step_m=%.3f wall_flat_step_run_m=%.3f wall_step_m=%.3f spacing_m=%.3f plateau=(%.3f,%.3f) status=%s\n",
passage.stableId.c_str(),static_cast<unsigned long long>(mouthProfileAudit.floorSamples),
static_cast<unsigned long long>(mouthProfileAudit.missingFloorSamples),
static_cast<unsigned long long>(mouthProfileAudit.wallSamples),
static_cast<unsigned long long>(mouthProfileAudit.missingWallSamples),
profiledLowerSurface?"true":"false",
mouthProfileAudit.floorFlatStepRunMetres,mouthProfileAudit.floorStepMetres,
mouthProfileAudit.wallFlatStepRunMetres,mouthProfileAudit.wallStepMetres,
PassageProfileSpacingMetres,PassageProfilePlateauMinimumMetres,
PassageProfileStepThresholdMetres,mouthProfileAudit.passed?"PASS":"FAIL");
std::printf("[PassageRippleAudit] id=%s window_m=32.000 spacing_m=0.125 period_m=%.3f amplitude_m=%.4f amplitude_cm=%.2f coherent_period_m=%.3f coherent_amplitude_m=%.4f coherent_amplitude_cm=%.2f local_peak_amplitude_m=%.4f coverage=%llu/%llu threshold_m=0.035 synthetic_spheres_period_m=1.500 synthetic_spheres_amplitude_m=%.4f synthetic_spheres_detected=%s floor_period_m=%.3f floor_amplitude_m=%.4f floor_amplitude_cm=%.2f floor_coherent_period_m=%.3f floor_coherent_amplitude_m=%.4f floor_coverage=%llu/%llu floor_threshold_m=0.015 floor_beaded_control_amplitude_m=%.4f floor_beaded_control_detected=%s status=%s\n",
std::printf("[PassageRippleAudit] id=%s window_m=32.000 spacing_m=0.125 period_m=%.3f amplitude_m=%.4f amplitude_cm=%.2f coherent_period_m=%.3f coherent_amplitude_m=%.4f coherent_amplitude_cm=%.2f local_peak_amplitude_m=%.4f coverage=%llu/%llu threshold_m=0.035 synthetic_spheres_period_m=1.500 synthetic_spheres_amplitude_m=%.4f synthetic_spheres_detected=%s floor_period_m=%.3f floor_amplitude_m=%.4f floor_amplitude_cm=%.2f floor_coherent_period_m=%.3f floor_coherent_amplitude_m=%.4f floor_coverage=%llu/%llu floor_threshold_m=0.025 floor_beaded_control_amplitude_m=%.4f floor_beaded_control_detected=%s status=%s\n",
passage.stableId.c_str(),rippleAudit.periodMetres,
rippleAudit.amplitudeMetres,rippleAudit.amplitudeMetres*100.0,
rippleAudit.coherentPeriodMetres,rippleAudit.coherentAmplitudeMetres,
+129 -2
View File
@@ -99,7 +99,17 @@ namespace StandaloneWorldAssemblyPrototype
std::vector<Candidate> candidates;
std::vector<std::int32_t> candidateHalfLengths{128};
std::int32_t candidateCenterSpacing=64;
if(arrivalRadiusSubvoxels>0&&departureRadiusSubvoxels>0)
const bool profiledSurfaceRoute=recipe.surfaceProfile.version!=0
&&arrivalRadiusSubvoxels>0;
if(profiledSurfaceRoute)
{
// Put the surface route mouth beside the small terminal coil used by the
// profiled-world passage, with its first route tangent pointing outward.
// This keeps the final supported landing short and auditable.
candidateHalfLengths={64,48};
candidateCenterSpacing=64;
}
else if(arrivalRadiusSubvoxels>0&&departureRadiusSubvoxels>0)
{
// A centered line cannot join two bounded mouths when its chord is
// longer than the sum of their placement radii. Leave 3 m for the
@@ -220,7 +230,22 @@ namespace StandaloneWorldAssemblyPrototype
static_cast<double>(along)*directions[directionIndex].y/65536.0);
const std::int64_t xQ=WorldAssemblyFixed(static_cast<double>(x));
const std::int64_t yQ=WorldAssemblyFixed(static_cast<double>(y));
if(arrivalRadiusSubvoxels>0&&departureRadiusSubvoxels>0
if(profiledSurfaceRoute&&index==0)
{
const std::int64_t targetRadiusQ=WorldAssemblyFixed(
6.0/coreVoxelMetres);
const std::int64_t radialQ=static_cast<std::int64_t>(std::llround(
std::hypot(static_cast<double>(xQ),static_cast<double>(yQ))));
const std::int64_t radialError=radialQ-targetRadiusQ;
candidate.endpointProximityCost+=static_cast<std::uint64_t>(
radialError*radialError)*16ull;
const std::int64_t outwardProjection=xQ*directions[directionIndex].x
+yQ*directions[directionIndex].y;
if(outwardProjection<=0)
candidate.endpointProximityCost+=static_cast<std::uint64_t>(
targetRadiusQ*targetRadiusQ)*64ull;
}
else if(arrivalRadiusSubvoxels>0&&departureRadiusSubvoxels>0
&&(index==0||index==32))
{
const std::uint64_t radiusSquared=static_cast<std::uint64_t>(
@@ -400,6 +425,81 @@ namespace StandaloneWorldAssemblyPrototype
return false;
}
inline bool ApplySurfaceProfileOverride(const VFJson::Value& root,
const FStandaloneOwnerWorld& owner, double baseGroundVoxel,
VoxelForgeCore::WorldAssemblyRecipeV1& recipe, std::string& error)
{
const VFJson::Value& overrideValue = root.Get("surface_profile_override");
if (std::holds_alternative<std::nullptr_t>(overrideValue.Data)) return true;
if (!overrideValue.IsObject())
{ error = "surface_profile_override must be a versioned object"; return false; }
const VFJson::Value& versionValue = overrideValue.Get("version");
if (!versionValue.IsNumber() || versionValue.Number() != 1.0)
{ error = "surface_profile_override version must be one"; return false; }
const auto* kindValue = std::get_if<std::string>(&overrideValue.Get("kind").Data);
if (kindValue == nullptr)
{ error = "surface_profile_override kind must be a string"; return false; }
using VoxelForgeCore::WorldAssemblySurfaceProfileKindV1;
VoxelForgeCore::WorldAssemblySurfaceProfileV1 profile;
profile.version = 1;
double amplitudeXMetres = 0.0, amplitudeYMetres = 0.0;
double wavelengthXMetres = 0.0, wavelengthYMetres = 0.0;
double lambda = 0.0, arenaClearanceMetres = 0.0;
if (*kindValue == "periodicHills")
{
profile.kind = WorldAssemblySurfaceProfileKindV1::periodicHills;
amplitudeXMetres = amplitudeYMetres = 2.0;
wavelengthXMetres = wavelengthYMetres = 96.0;
}
else if (*kindValue == "mirroredRelief")
{
profile.kind = WorldAssemblySurfaceProfileKindV1::mirroredRelief;
amplitudeXMetres = amplitudeYMetres = 1.5;
wavelengthXMetres = wavelengthYMetres = 128.0;
lambda = 0.875;
arenaClearanceMetres = 8.0;
}
else if (*kindValue == "flatField")
profile.kind = WorldAssemblySurfaceProfileKindV1::flatField;
else
{ error = "surface_profile_override kind must be periodicHills, mirroredRelief or flatField"; return false; }
const auto readOptionalMetres = [&](const char* name, double& output)
{
const VFJson::Value& value = overrideValue.Get(name);
if (std::holds_alternative<std::nullptr_t>(value.Data)) return true;
if (!value.IsNumber() || !std::isfinite(value.Number())) return false;
output = value.Number();
return true;
};
if (!readOptionalMetres("amplitude_x_m", amplitudeXMetres)
|| !readOptionalMetres("amplitude_y_m", amplitudeYMetres)
|| !readOptionalMetres("wavelength_x_m", wavelengthXMetres)
|| !readOptionalMetres("wavelength_y_m", wavelengthYMetres)
|| !readOptionalMetres("mirror_lambda", lambda)
|| !readOptionalMetres("minimum_arena_clearance_m", arenaClearanceMetres))
{ error = "surface_profile_override contains a malformed metre parameter"; return false; }
if (owner.CoreVoxelSizeMicrons == 0)
{ error = "surface profile metre conversion needs a valid Core voxel size"; return false; }
const auto metresToSubvoxels = [&](double metres)
{
return static_cast<std::int64_t>(std::llround(metres * 1000000.0
* VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel
/ owner.CoreVoxelSizeMicrons));
};
profile.h0Subvoxels = WorldAssemblyFixed(baseGroundVoxel);
profile.amplitudeXSubvoxels = metresToSubvoxels(amplitudeXMetres);
profile.amplitudeYSubvoxels = metresToSubvoxels(amplitudeYMetres);
profile.wavelengthXSubvoxels = metresToSubvoxels(wavelengthXMetres);
profile.wavelengthYSubvoxels = metresToSubvoxels(wavelengthYMetres);
profile.mirrorLambdaQ16 = static_cast<std::int64_t>(std::llround(lambda * 65536.0));
profile.minimumArenaClearanceSubvoxels = metresToSubvoxels(arenaClearanceMetres);
VoxelForgeCore::ResolveWorldAssemblySurfaceProfilePhasesV1(profile, recipe.seed);
recipe.surfaceProfile = profile;
return true;
}
inline bool AttachRound1WorldAssemblyPrototype(FStandaloneOwnerWorld& owner,VFJson::Value& root,
std::string& error,const std::string& manifestOutputPath,
VoxelForgeCore::WorldAssemblyManifest* outManifest=nullptr)
@@ -440,6 +540,10 @@ namespace StandaloneWorldAssemblyPrototype
recipe.biomeClimateReliefWavelengthSubvoxels=WorldAssemblyWavelength(map.ReliefFrequency,3333.0);
recipe.biomeClimateMoistureWavelengthSubvoxels=WorldAssemblyWavelength(map.MoistureFrequency,2500.0);
recipe.biomeClimateReliefContrastQ16=WorldAssemblyQ16(map.ReliefContrast);
if (!ApplySurfaceProfileOverride(root, owner,
static_cast<double>(bottomVoxel) + static_cast<double>(heightVoxels)
* surface.BaseGroundRelative,
recipe, error)) return false;
const auto makeProfile=[&](uint32 stableId,const FSurfaceGenerationParams& params,
const FBiomeResolved* climate)
{
@@ -524,9 +628,18 @@ namespace StandaloneWorldAssemblyPrototype
stratum.capRidgeWavelengthSubvoxels=WorldAssemblyWavelength(surface.CeilingRidgeFrequency,50.0);
stratum.waterSurfaceSubvoxels=WorldAssemblyFixed(strateBottom+strateHeight*surface.WaterLevelRelative);
stratum.waterEnabled=definition&&definition->bHasWater&&surface.WaterLevelRelative>0.0f;
stratum.surfaceProfile=recipe.surfaceProfile;
if (recipe.surfaceProfile.version != 0)
{
stratum.capUndulationSubvoxels=0;
stratum.capDetailAmplitudeSubvoxels=0;
stratum.capRidgeAmplitudeSubvoxels=0;
}
// Select a deterministic steep edge in the resolved owner field for a bounded shelf.
// Selection d'une pente deterministe dans le champ resolu pour une saillie bornee.
if (recipe.surfaceProfile.version == 0)
{
constexpr int probeSide=49,probeStep=32;
std::array<float,probeSide*probeSide> heights{};
std::array<uint8,probeSide*probeSide> valid{};
@@ -595,6 +708,7 @@ namespace StandaloneWorldAssemblyPrototype
stratum.features.push_back(shelf);
}
}
}
std::int64_t arrivalRadiusQ=0,departureRadiusQ=0;
const auto ownerVoxelsToCoreQ=[&](double value)
{return static_cast<std::int64_t>(std::llround(value*owner.OwnerVoxelSizeMicrons
@@ -1032,6 +1146,19 @@ namespace StandaloneWorldAssemblyPrototype
"interior-facing upper face","shared resolved-layout density band",solidDensity};
if(type==ECaveGeneratorType::SurfaceWorld)
{
if(assembly.recipe.surfaceProfile.version!=0)
{
ResolvedLayoutAnchorV2 profileAnchor;
profileAnchor.kind="heightfield_profile";
profileAnchor.stableId="heightfield-profile/"
+std::to_string(static_cast<std::uint32_t>(
assembly.recipe.surfaceProfile.kind));
profileAnchor.units="profile kind enum";
profileAnchor.values={static_cast<std::int64_t>(
assembly.recipe.surfaceProfile.version),
static_cast<std::int64_t>(assembly.recipe.surfaceProfile.kind)};
s.anchors.push_back(std::move(profileAnchor));
}
for(const auto& p:assembly.recipe.biomes)
if(p.hasCapProfile)
{ResolvedLayoutAnchorV2 a;a.kind="cap_profile";a.stableId="biome/"+std::to_string(p.stableId);