wip(assembler): round L21 -- resolved strate layout snapshot + validator (no world change)

Core ResolvedLayoutSnapshotV1 (canonical JSON, stable identity): per strate stable ID, generator,
recipe, interior bounds in metres, ceiling/bedrock bands as Core really applies them, transition
mode/width, dispatch provenance. Validator: compat mode reports today's deviations; strict mode
enforces ceiling -> content -> bedrock -> next ceiling (owner rule), two separate bands, nominal
contiguity, interpenetration only within the declared EVoxelStrateTransition width; 7 negative
controls rejected. Findings: SW built at -120..-632 m although the params say -60 m; a 60 m unowned
gap filled by analytic FI fallback; no active bedrock bands; transitions ignored by Core.
All L19 hashes unchanged (28 + 14 crossing runs). The Unreal adapter exports resolved_layout
(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:
Fr0zkaandClaude Opus 5.5 committed 2026-10-20 10:22:00 +02:00
1 parent 5d5447dc32
commit 8753f6dbe4
12 files changed
+1347 -3

No files matched your search

+58 -1
View File
@@ -63,6 +63,9 @@ namespace
float CameraYawDegrees=0.0f;
float CameraPitchDegrees=0.0f;
std::filesystem::path MeshExportPath;
std::filesystem::path ResolvedLayoutOutputPath;
bool ResolvedLayoutOnly=false;
bool AuditResolvedLayoutBoundaries=false;
};
bool ParseInteger(std::string_view text,int& output)
@@ -117,6 +120,9 @@ namespace
" --mesh-export=FILE (write the exact generated tile meshes for offline rendering)\n"
" --profile-column-overlap --far-horizon-lod8-step=N --force-generate\n"
" --seed=N --recipe=surface-world|floating-islands\n"
" --resolved-layout-output=FILE (canonical plan-time layout snapshot)\n"
" --resolved-layout-only (exit after plan and snapshot validation)\n"
" --audit-resolved-layout-boundaries (query Core at each recorded endpoint)\n"
" --auto-surface-camera (place the 27-tile cube on this seed's surface)\n"
" --mesh-coverage (report non-empty tiles and indexed triangles)\n"
" --screen-space-gate (measure display error and historical negative controls)\n"
@@ -134,6 +140,8 @@ namespace
return false;
}
if(arg=="--world-assembler-prototype")options.WorldAssemblerPrototype=true;
else if(arg=="--resolved-layout-only")options.ResolvedLayoutOnly=true;
else if(arg=="--audit-resolved-layout-boundaries")options.AuditResolvedLayoutBoundaries=true;
else if(arg=="--stream-benchmark")options.StreamBenchmark=true;
else if(arg=="--stream-pipeline")options.StreamPipeline=true;
else if(arg=="--stream-hash")options.StreamHash=true;
@@ -155,6 +163,8 @@ namespace
else if(recipe=="floating-islands")options.FloatingIslandsRecipe=true;
else {std::fprintf(stderr,"Invalid --recipe value: %.*s\n",static_cast<int>(recipe.size()),recipe.data());return false;}
}
else if(arg.starts_with("--resolved-layout-output="))
options.ResolvedLayoutOutputPath=std::string(arg.substr(std::string_view("--resolved-layout-output=").size()));
else if(arg.starts_with("--seed="))
{if(!readInt("--seed=",options.SeedOverride))return false;options.HasSeedOverride=true;}
else if(arg.starts_with("--render-distance-chunks="))
@@ -314,6 +324,52 @@ int main(int argc,char** argv)
&&!StandaloneWorldAssemblyPrototype::AttachFloatingIslandWorldAssembly(
*ownerWorld,ownerJsonRoot,worldAssembly,error))
{std::fprintf(stderr,"Floating-island assembly setup failed: %s\n",error.c_str());return 2;}
VoxelForgeCore::ResolvedLayoutSnapshotV1 resolvedLayout;
const bool buildResolvedLayout=!options.ResolvedLayoutOutputPath.empty()
||options.AuditResolvedLayoutBoundaries||options.ResolvedLayoutOnly;
if(buildResolvedLayout)
{
const std::string_view variant=options.FloatingIslandsRecipe?"floating-islands":"surface-world";
if(!StandaloneWorldAssemblyPrototype::BuildResolvedLayoutSnapshot(
*ownerWorld,worldAssembly,variant,resolvedLayout,error))
{std::fprintf(stderr,"Resolved-layout snapshot failed: %s\n",error.c_str());return 2;}
const std::string layoutJson=resolvedLayout.ToJson();
if(!options.ResolvedLayoutOutputPath.empty())
{
const auto roundTrip=VoxelForgeCore::ResolvedLayoutSnapshotV1::FromJson(layoutJson,error);
if(!roundTrip||roundTrip->ToJson()!=layoutJson||roundTrip->stableIdentity!=resolvedLayout.stableIdentity)
{if(error.empty())error="resolved-layout canonical serialization did not round-trip";
std::fprintf(stderr,"Resolved-layout round trip failed: %s\n",error.c_str());return 2;}
if(!options.ResolvedLayoutOutputPath.parent_path().empty())
std::filesystem::create_directories(options.ResolvedLayoutOutputPath.parent_path());
std::ofstream output(options.ResolvedLayoutOutputPath,std::ios::binary);
if(!output){std::fprintf(stderr,"Could not write resolved-layout snapshot: %s\n",options.ResolvedLayoutOutputPath.c_str());return 2;}
output.write(layoutJson.data(),static_cast<std::streamsize>(layoutJson.size()));
if(!output){std::fprintf(stderr,"Resolved-layout snapshot write failed: %s\n",options.ResolvedLayoutOutputPath.c_str());return 2;}
}
const auto controls=VoxelForgeCore::AuditResolvedLayoutValidatorV1();
std::vector<VoxelForgeCore::ResolvedLayoutIssueV1> compatibilityIssues;
std::string compatibilityError;
const bool compatibilityAccepted=resolvedLayout.validate(
VoxelForgeCore::ResolvedLayoutValidationModeV1::compatibility,
compatibilityIssues,compatibilityError);
std::printf("[ResolvedLayoutSnapshot] schema=%u stable_identity=%s strata=%zu bytes=%zu round_trip=PASS\n",
resolvedLayout.schemaVersion,resolvedLayout.stableIdentity.c_str(),resolvedLayout.strates.size(),layoutJson.size());
std::printf("[ResolvedLayoutCompatibility] accepted=%s issues=%zu error=%s\n",
compatibilityAccepted?"true":"false",compatibilityIssues.size(),compatibilityError.c_str());
for(const auto& issue:compatibilityIssues)
std::printf("[ResolvedLayoutCompatibilityIssue] code=%s detail=%s\n",
issue.code.c_str(),issue.detail.c_str());
if(!compatibilityAccepted)
{std::fprintf(stderr,"Resolved-layout compatibility validation failed: %s\n",compatibilityError.c_str());return 2;}
std::printf("[ResolvedLayoutValidatorControls] rejected=%u/%u status=%s\n",
controls.controlsRejectedAsExpected,controls.controlsRun,controls.passed?"PASS":"FAIL");
if(!controls.passed)
{for(const auto& failure:controls.failures)std::printf("[ResolvedLayoutValidatorControlFailure] %s %s\n",failure.code.c_str(),failure.detail.c_str());return 2;}
if(!options.ResolvedLayoutOutputPath.empty())
std::printf("[ResolvedLayoutSnapshotOutput] path=%s\n",options.ResolvedLayoutOutputPath.c_str());
if(options.ResolvedLayoutOnly)return 0;
}
if(options.AutoSurfaceCamera)
{
constexpr std::int64_t UnitsPerVoxel=VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel;
@@ -377,5 +433,6 @@ int main(int argc,char** argv)
cameraStepVoxels,options.AuditUniformBlockProofs,options.ProfileLodWork,
options.RegionCrossing,options.AuditTileShapeReadiness,
options.DiagnosticSlowShapeCompileMs,options.AuditBasePageEquivalence,
options.AuditRouteParity);
options.AuditRouteParity,options.AuditResolvedLayoutBoundaries,
buildResolvedLayout?&resolvedLayout:nullptr);
}
+86 -1
View File
@@ -253,7 +253,9 @@ namespace StandaloneStreamBenchmark
bool bAuditUniformBlockProofs=false,bool bReportLodWorkProfile=false,
bool bRegionCrossing=false,
bool bAuditTileShapeReadiness=false,int DiagnosticSlowShapeCompileMs=0,
bool bAuditBasePageEquivalence=false,bool bAuditRouteParity=false)
bool bAuditBasePageEquivalence=false,bool bAuditRouteParity=false,
bool bAuditResolvedLayoutBoundaries=false,
const VoxelForgeCore::ResolvedLayoutSnapshotV1* ResolvedLayout=nullptr)
{
using Clock=std::chrono::steady_clock;
FStandaloneOwnerWorld& World=*OwnerWorld;
@@ -438,6 +440,89 @@ namespace StandaloneStreamBenchmark
Streamer.Stop();
std::fprintf(stderr,"[StreamPipeline] full shape build failed: %s\n",BuildError.c_str());return 2;
}
if(bAuditResolvedLayoutBoundaries)
{
if(ResolvedLayout==nullptr)
{Streamer.Stop();std::fprintf(stderr,"[ResolvedLayoutProbe] missing plan-time snapshot\n");return 2;}
std::vector<std::int64_t> endpoints;
for(const auto& Stratum:ResolvedLayout->strates)
{
endpoints.push_back(Stratum.interiorBottomMicrometres);
endpoints.push_back(Stratum.interiorTopMicrometres);
endpoints.push_back(Stratum.ceiling.bottomMicrometres);
endpoints.push_back(Stratum.ceiling.topMicrometres);
endpoints.push_back(Stratum.bedrock.bottomMicrometres);
endpoints.push_back(Stratum.bedrock.topMicrometres);
}
for(std::size_t StratumIndex=0;StratumIndex+1<ResolvedLayout->strates.size();++StratumIndex)
{
const auto& Upper=ResolvedLayout->strates[StratumIndex];
if(Upper.transitionMode=="Hard"||Upper.transitionWidthMicrometres<=0)continue;
endpoints.push_back(Upper.interiorBottomMicrometres-Upper.transitionWidthMicrometres);
endpoints.push_back(Upper.interiorBottomMicrometres+Upper.transitionWidthMicrometres);
}
std::sort(endpoints.begin(),endpoints.end());
endpoints.erase(std::unique(endpoints.begin(),endpoints.end()),endpoints.end());
std::uint64_t probes=0,disagreements=0;
const double CoreVoxelMicrometres=std::max<std::uint32_t>(1,World.CoreVoxelSizeMicrons);
const auto expectedAt=[&](std::int64_t zMicrometres)
{
std::vector<std::string> candidates;
for(const auto& Stratum:ResolvedLayout->strates)
{
const auto contains=[zMicrometres](const VoxelForgeCore::ResolvedLayoutBandV1& Band)
{return Band.presentInCurrentField&&zMicrometres>=Band.bottomMicrometres
&&zMicrometres<Band.topMicrometres;};
if(contains(Stratum.ceiling))candidates.push_back(Stratum.generatorKind+"/ceiling");
if(contains(Stratum.content))candidates.push_back(Stratum.generatorKind+"/content");
if(contains(Stratum.bedrock))candidates.push_back(Stratum.generatorKind+"/bedrock");
}
return candidates;
};
const std::array<std::int64_t,3> offsets{{
-static_cast<std::int64_t>(World.CoreVoxelSizeMicrons),0,
static_cast<std::int64_t>(World.CoreVoxelSizeMicrons)}};
for(const std::int64_t Endpoint:endpoints)
for(const std::int64_t Offset:offsets)
{
const std::int64_t zMicrometres=Endpoint+Offset;
const double zVoxel=static_cast<double>(zMicrometres)/CoreVoxelMicrometres;
const VoxelForgeCore::Vec3d position{0.0,0.0,zVoxel};
const std::string actual=Shape.densityDispatchPathAt(position);
const auto expected=expectedAt(zMicrometres);
std::string expectedLabel;
std::vector<std::string> expectedGenerators;
for(const auto& Candidate:expected)
{
if(!expectedLabel.empty())expectedLabel+=',';
expectedLabel+=Candidate;
const auto Separator=Candidate.find('/');
const std::string Kind=Candidate.substr(0,Separator);
if(std::find(expectedGenerators.begin(),expectedGenerators.end(),Kind)==expectedGenerators.end())
expectedGenerators.push_back(Kind);
}
if(expected.empty())expectedLabel="uncovered";
std::string actualGenerator;
if(actual=="SurfaceWorld-native"||actual=="SurfaceWorld-legacy")actualGenerator="SurfaceWorld";
else if(actual=="FloatingIslands-native")actualGenerator="FloatingIslands";
else if(actual.rfind("compiled-analytic/",0)==0)actualGenerator=actual.substr(18);
const bool mismatch=expected.empty()
?actual!="compiled-analytic/fallback"
:std::find(expectedGenerators.begin(),expectedGenerators.end(),actualGenerator)==expectedGenerators.end();
const float density=Shape.densityAt(position);
const bool solid=density<0.0f;
++probes;disagreements+=mismatch?1u:0u;
std::printf("[ResolvedLayoutProbe] endpoint_um=%lld offset_um=%lld z_m=%.3f expected=%s actual=%s density=%.7g occupancy=%s disagreement=%s\n",
static_cast<long long>(Endpoint),static_cast<long long>(Offset),
static_cast<double>(zMicrometres)/1000000.0,expectedLabel.c_str(),actual.c_str(),density,
solid?"solid":"air",mismatch?"YES":"no");
}
std::printf("[ResolvedLayoutProbeSummary] probes=%llu disagreements=%llu status=%s\n",
static_cast<unsigned long long>(probes),static_cast<unsigned long long>(disagreements),
disagreements==0?"PASS":"DEVIATIONS_RECORDED");
Streamer.Stop();
return 0;
}
const auto ShapeReady=Clock::now();
const double ShapeSeconds=std::chrono::duration<double>(ShapeReady-ShapeBuildStart).count();
if(bAuditTileShapeReadiness)
+157
View File
@@ -525,4 +525,161 @@ namespace StandaloneWorldAssemblyPrototype
return true;
}
inline const char* GeneratorKind(ECaveGeneratorType type)
{
switch(type)
{
case ECaveGeneratorType::TunnelNetwork:return "TunnelNetwork";
case ECaveGeneratorType::FlatPlain:return "FlatPlain";
case ECaveGeneratorType::CrystalChamber:return "CrystalChamber";
case ECaveGeneratorType::Maze:return "Maze";
case ECaveGeneratorType::SurfaceWorld:return "SurfaceWorld";
case ECaveGeneratorType::VerticalShafts:return "VerticalShafts";
case ECaveGeneratorType::FloatingIslands:return "FloatingIslands";
case ECaveGeneratorType::Underwater:return "Underwater";
}
return "Unknown";
}
inline const char* TransitionKind(EVoxelStrateTransition type)
{
switch(type)
{
case EVoxelStrateTransition::Gradient:return "Gradient";
case EVoxelStrateTransition::Hard:return "Hard";
case EVoxelStrateTransition::Interleaved:return "Interleaved";
}
return "Unknown";
}
inline bool BuildResolvedLayoutSnapshot(const FStandaloneOwnerWorld& owner,
const VoxelForgeCore::WorldAssemblyManifest& assembly,std::string_view recipeVariant,
VoxelForgeCore::ResolvedLayoutSnapshotV1& out,std::string& error)
{
using namespace VoxelForgeCore;
if(!owner.Manager){error="resolved layout builder requires the initialized director";return false;}
(void)recipeVariant;
out={};out.worldIdentity="owner-world/seed/"+std::to_string(owner.Seed);
out.ownerVoxelSizeMicrometres=owner.OwnerVoxelSizeMicrons;
out.coreVoxelSizeMicrometres=owner.CoreVoxelSizeMicrons;
const std::int64_t coreMicrons=std::max<std::uint32_t>(1,owner.CoreVoxelSizeMicrons);
const std::int64_t managerChunkMicrons=CHUNK_SIZE*static_cast<std::int64_t>(owner.OwnerVoxelSizeMicrons);
const auto fixedToMicrons=[&](std::int64_t fixed)
{return static_cast<std::int64_t>(std::llround(static_cast<double>(fixed)
*static_cast<double>(coreMicrons)/(WorldAssemblySubvoxelsPerVoxel)));};
for(const FStrateSlot& slot:owner.Manager->GetLayout())
{
if(!slot.Definition)continue;
const auto type=owner.Manager->GetGeneratorTypeForChunk(FIntVector(0,0,slot.TopChunkZ));
ResolvedLayoutStratumV1 s;s.strateIndex=slot.StrateIndex;s.generatorKind=GeneratorKind(type);
s.stableId=out.worldIdentity+"/strate/"+std::to_string(slot.StrateIndex)
+"/generator/"+GeneratorKind(type);
s.recipeId=type==ECaveGeneratorType::SurfaceWorld?"SurfaceWorld.Heightfield2D"
:type==ECaveGeneratorType::FloatingIslands?"FloatingIslands.ClusterField":"legacy."+std::string(GeneratorKind(type));
s.recipeVersion=type==ECaveGeneratorType::SurfaceWorld?assembly.recipe.schemaVersion
:type==ECaveGeneratorType::FloatingIslands&&!assembly.floatingIslands.empty()
?assembly.floatingIslands.front().manifest.recipe.geometryVersion:0;
s.voxelSizeMicrometres=owner.CoreVoxelSizeMicrons;
s.latticeOriginMicrometres={0,0,0};
std::int64_t bottom=static_cast<std::int64_t>(slot.BottomChunkZ)*CHUNK_SIZE*coreMicrons;
std::int64_t top=static_cast<std::int64_t>(slot.TopChunkZ+1)*CHUNK_SIZE*coreMicrons;
if(type==ECaveGeneratorType::FloatingIslands)
{
const auto it=std::find_if(assembly.floatingIslands.begin(),assembly.floatingIslands.end(),
[&](const auto& p){return p.strateIndex==slot.StrateIndex;});
if(it!=assembly.floatingIslands.end())
{bottom=fixedToMicrons(it->manifest.recipe.layoutMinimumZSubvoxels);
top=fixedToMicrons(it->manifest.recipe.layoutMaximumZSubvoxels);}
}
s.interiorBottomMicrometres=bottom;s.interiorTopMicrometres=top;
s.content={"content",bottom,top,true,true,false,"current generator interior","none","none"};
s.transitionMode=TransitionKind(slot.Definition->TransitionType);
s.transitionBlendChunks=slot.Definition->TransitionBlendChunks;
s.transitionWidthMicrometres=static_cast<std::int64_t>(s.transitionBlendChunks)*managerChunkMicrons;
s.transitionWarpAmplitudeMicrometres=s.transitionMode=="Interleaved"
?2*managerChunkMicrons:0;
s.transitionInterpenetrationMicrometres=0;
s.transitionHonouredInCore=false;
s.transitionDispatchPath="upper strate owns lower interface; UVoxelStrateManager::GetGenerationParams can blend legacy vectors, but Core's compiled field selects per-strate/native recipe fields without transition blending";
s.managerLookup="UVoxelStrateManager::GetGeneratorTypeForChunk; upper strate TransitionType owns lower interface";
s.managerChunkWidthMicrometres=managerChunkMicrons;
s.dispatchChunkWidthMicrometres=type==ECaveGeneratorType::FloatingIslands
?static_cast<std::int64_t>(CHUNK_SIZE)*owner.OwnerVoxelSizeMicrons
:static_cast<std::int64_t>(CHUNK_SIZE)*coreMicrons;
if(type==ECaveGeneratorType::SurfaceWorld)
{s.boundDispatchPath="BuildSurfaceStratumPlan: (chunkZ*CHUNK_SIZE) Core voxels; 32 Core voxels per chunk";
s.queryDispatchPath="FStandaloneShapeWorld::NativeSurfaceDensityAt: floor(Z/CHUNK_SIZE), manager lookup; 32 Core voxels per chunk";}
else if(type==ECaveGeneratorType::FloatingIslands)
{s.boundDispatchPath="BuildFloatingIslandStratumPlan: owner chunk * 32 * owner/Core voxel ratio";
s.queryDispatchPath="FStandaloneShapeWorld::NativeFloatingIslandDensityAt: floor(Z/(32*owner/Core ratio)), manager lookup";}
else
{s.boundDispatchPath="legacy strata slot bounds scaled by Core chunk width";
s.queryDispatchPath="legacy Core field; manager lookup uses floor(Z/CHUNK_SIZE)";}
const std::int64_t legacySealMicrons=static_cast<std::int64_t>(std::llround(
std::max(0.0f,slot.Definition->GenerationParams.BoundarySealThickness)
*owner.OwnerVoxelSizeMicrons));
if(type==ECaveGeneratorType::FloatingIslands)
{
const auto it=std::find_if(assembly.floatingIslands.begin(),assembly.floatingIslands.end(),
[&](const auto& p){return p.strateIndex==slot.StrateIndex;});
const std::int64_t seal=it==assembly.floatingIslands.end()?0:fixedToMicrons(
it->manifest.recipe.boundarySealSubvoxels);
s.ceiling={"ceiling",top-seal,top,seal>0,true,false,
"v3 shared upper boundary density seal; one sided; inset from upper edge","upper/interior side","VF_ApplyUpperBoundarySeal"};
s.bedrock={"bedrock",bottom,bottom,false,true,false,
"no lower boundary seal in geometryVersion 3","none","none"};
if(it!=assembly.floatingIslands.end())
{
for(std::size_t n=0;n<it->manifest.plan.islands.size();++n)
{const auto& a=it->manifest.plan.islands[n];ResolvedLayoutAnchorV1 anchor;
anchor.kind="island_anchor";anchor.stableId="island/"+std::to_string(n);anchor.units="1/256 Core voxel";
anchor.values={a.centerSubvoxels[0],a.centerSubvoxels[1],a.centerSubvoxels[2],a.radiusSubvoxels,a.topHalfSubvoxels};
s.anchors.push_back(std::move(anchor));}
}
}
else if(type==ECaveGeneratorType::SurfaceWorld)
{
s.ceiling={"ceiling",top,top,false,true,false,
"no separate volumetric ceiling band; cap profile is internal to content","none",
"Heightfield2D cap profile + AppendStratumBoundaryCeilings fallback mesh"};
s.bedrock={"bedrock",bottom,bottom,false,true,false,"no lower bedrock band","none","none"};
for(const auto& p:assembly.recipe.biomes)
if(p.hasCapProfile)
{ResolvedLayoutAnchorV1 a;a.kind="cap_profile";a.stableId="biome/"+std::to_string(p.stableId);
a.units="1/256 Core voxel";a.values={p.capHeightSubvoxels,p.capUndulationSubvoxels,
p.capWavelengthSubvoxels,p.capDetailAmplitudeSubvoxels,p.capRidgeAmplitudeSubvoxels};s.anchors.push_back(std::move(a));}
const auto plan=std::find_if(assembly.plan.strates.begin(),assembly.plan.strates.end(),
[&](const auto& p){return p.strateIndex==slot.StrateIndex;});
if(plan!=assembly.plan.strates.end())
{
for(std::size_t n=0;n<plan->route.size();++n)
{const auto& p=plan->route[n];ResolvedLayoutAnchorV1 a;a.kind="route_point";a.stableId="route/"+std::to_string(n);
a.units="1/256 Core voxel";a.values={p.positionSubvoxels[0],p.positionSubvoxels[1],p.positionSubvoxels[2],p.radiusSubvoxels};
s.anchors.push_back(std::move(a));}
}
}
else
{
s.ceiling={"ceiling",top,top+legacySealMicrons,false,true,false,
"manager configures a two-sided legacy seal, but Core's compiled analytic field does not apply this density band",
"configured upper side","legacy VF_ApplyBoundarySeal; absent from current Core density path"};
s.bedrock={"bedrock",bottom-legacySealMicrons,bottom,false,true,false,
"manager configures a two-sided legacy seal, but Core's compiled analytic field does not apply this density band; breakable by default",
"configured lower side","legacy VF_ApplyBoundarySeal; absent from current Core density path"};
}
for(std::size_t n=0;n<owner.Manager->GetPassages().Num();++n)
{
const auto& passage=owner.Manager->GetPassages()[static_cast<int32>(n)];
if(passage.UpperStrateIndex!=slot.StrateIndex&&passage.LowerStrateIndex!=slot.StrateIndex)continue;
ResolvedLayoutAnchorV1 a;a.kind="passage";a.stableId="passage/"+std::to_string(n);
a.units="milli owner voxels";a.values={std::llround(passage.UpperPoint.X*1000.0),
std::llround(passage.UpperPoint.Y*1000.0),std::llround(passage.UpperPoint.Z*1000.0),
std::llround(passage.LowerPoint.X*1000.0),std::llround(passage.LowerPoint.Y*1000.0),
std::llround(passage.LowerPoint.Z*1000.0)};s.anchors.push_back(std::move(a));
}
out.strates.push_back(std::move(s));
}
return out.finalize(error);
}
} // namespace StandaloneWorldAssemblyPrototype