feat(core): slab + sparse motifs, slice 1 -- flat field, monolith, platform at 0.52 s (L56); research R25

Motif vocabulary v3: version-1 records keyed by (seed, strate, stable ID) with route keepouts, band
clearance and pairwise spacing. A rounded capped-cylinder monolith (r 1.4 m, 24 m tall) and a rounded-box
plinth, smooth-unioned into a flatField floor with a 0.55 m geometric rounding (measured fillets 0.73-1.17 m).
Exact radial/box interval bounds, a BVH, isTileShapeFree aware (0 brute-force misses, false-proof controls
rejected). Final-field route passes; whole-surface audit covers foot, cap and platform edges. Cold whole
view 0.524 s. Owner world unchanged. fast/medium/full PASS (Clang and GCC).
Research R25 (self-checked): FloatingIslands LOD0 column cache conflicts.

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 07:47:15 +01:00
1 parent aee1487410
commit 4e64b75044
15 files changed
+1559 -11

No files matched your search

@@ -793,6 +793,7 @@ namespace VoxelForgeCore
inline constexpr std::uint32_t ResolvedLayoutSchemaVersionV3 = 3;
inline constexpr std::uint32_t ResolvedLayoutStampVocabularyVersionV1 = 1;
inline constexpr std::uint32_t ResolvedLayoutStampVocabularyVersionV2 = 2;
inline constexpr std::uint32_t ResolvedLayoutStampVocabularyVersionV3 = 3;
inline constexpr std::uint32_t ResolvedLayoutCavernGraphVocabularyVersionV1 = 1;
inline constexpr std::uint32_t ResolvedLayoutOreVeinVocabularyVersionV1 = 1;
enum class ResolvedLayoutValidationModeV3 : std::uint8_t { compatibility, strict };
@@ -804,7 +805,9 @@ namespace VoxelForgeCore
carveEllipsoid = 1,
carveArch = 2,
fillPillar = 3,
fillDais = 4
fillDais = 4,
fillMonolith = 5,
fillPlatform = 6
};
struct ResolvedLayoutStampRequestV1
@@ -819,6 +822,11 @@ namespace VoxelForgeCore
std::int64_t smoothWidthMicrometres = 0;
std::int64_t irregularityAmplitudeMicrometres = 0;
std::int64_t irregularityWavelengthMicrometres = 0;
std::int64_t roundingRadiusMicrometres = 0;
std::int64_t minimumSpacingMicrometres = 0;
// 0 = free placement, 1 = seated on the authored flat profile floor.
std::uint8_t attachmentPolicy = 0;
std::int64_t floorMicrometres = 0;
std::uint8_t yawQuarterTurns = 0;
};
@@ -834,6 +842,10 @@ namespace VoxelForgeCore
std::int64_t smoothWidthMicrometres = 0;
std::int64_t irregularityAmplitudeMicrometres = 0;
std::int64_t irregularityWavelengthMicrometres = 0;
std::int64_t roundingRadiusMicrometres = 0;
std::int64_t minimumSpacingMicrometres = 0;
std::uint8_t attachmentPolicy = 0;
std::int64_t floorMicrometres = 0;
std::uint64_t irregularitySeed = 0;
std::uint8_t yawQuarterTurns = 0;
};
@@ -1132,6 +1144,11 @@ namespace VoxelForgeCore
ResolvedLayoutSnapshotV3& layout, std::int32_t seed,
std::span<const ResolvedLayoutStampRequestV1> requests,
std::string& error);
// Vocabulary 3 adds explicit rounded capped-cylinder monoliths and rounded-box platforms.
VFCORE_API bool ResolveResolvedLayoutStampsV3(
ResolvedLayoutSnapshotV3& layout, std::int32_t seed,
std::span<const ResolvedLayoutStampRequestV1> requests,
std::string& error);
VFCORE_API ResolvedLayoutStampPlacementAuditV1 AuditResolvedLayoutStampPlacementV1(
const ResolvedLayoutSnapshotV3& layout);
+223 -8
View File
@@ -165,8 +165,11 @@ namespace
{
const auto value=static_cast<std::uint8_t>(kind);
return value>=static_cast<std::uint8_t>(ResolvedSdfStampKindV1::carveEllipsoid)
&&value<=static_cast<std::uint8_t>(ResolvedSdfStampKindV1::fillDais);
&&value<=static_cast<std::uint8_t>(ResolvedSdfStampKindV1::fillPlatform);
}
bool LayoutStampIsMotif(ResolvedSdfStampKindV1 kind)
{return kind==ResolvedSdfStampKindV1::fillMonolith
||kind==ResolvedSdfStampKindV1::fillPlatform;}
double LayoutStampPointSegmentDistance(const std::array<std::int64_t,3>& point,
const std::array<std::int64_t,3>& a,const std::array<std::int64_t,3>& b)
{
@@ -453,7 +456,9 @@ namespace
{
if(stamp.strateIndex!=vein.strateIndex
||(stamp.kind!=ResolvedSdfStampKindV1::fillDais
&&stamp.kind!=ResolvedSdfStampKindV1::fillPillar))continue;
&&stamp.kind!=ResolvedSdfStampKindV1::fillPillar
&&stamp.kind!=ResolvedSdfStampKindV1::fillMonolith
&&stamp.kind!=ResolvedSdfStampKindV1::fillPlatform))continue;
bool overlaps=true;
for(std::size_t axis=0;axis<3;++axis)
overlaps=overlaps&&vein.boundsMinimumMicrometres[axis]
@@ -581,7 +586,13 @@ namespace
<<",\"irregularity_amplitude_um\":"<<stamp.irregularityAmplitudeMicrometres
<<",\"irregularity_wavelength_um\":"<<stamp.irregularityWavelengthMicrometres
<<",\"irregularity_seed\":"<<stamp.irregularitySeed
<<",\"yaw_quarter_turns\":"<<static_cast<unsigned>(stamp.yawQuarterTurns)<<'}';
<<",\"yaw_quarter_turns\":"<<static_cast<unsigned>(stamp.yawQuarterTurns);
if(s.stampVocabularyVersion>=ResolvedLayoutStampVocabularyVersionV3)
out<<",\"rounding_radius_um\":"<<stamp.roundingRadiusMicrometres
<<",\"minimum_spacing_um\":"<<stamp.minimumSpacingMicrometres
<<",\"attachment_policy\":"<<static_cast<unsigned>(stamp.attachmentPolicy)
<<",\"floor_um\":"<<stamp.floorMicrometres;
out<<'}';
}
out<<']';
}
@@ -1107,8 +1118,9 @@ bool ResolvedLayoutSnapshotV3::validate(ResolvedLayoutValidationModeV3 mode,
add("stamp_vocabulary_version","stamp vocabulary version is set without any stamp records");
}
else if(stampVocabularyVersion!=ResolvedLayoutStampVocabularyVersionV1
&&stampVocabularyVersion!=ResolvedLayoutStampVocabularyVersionV2)
add("stamp_vocabulary_version","resolved stamps require supported vocabulary version 1 or 2");
&&stampVocabularyVersion!=ResolvedLayoutStampVocabularyVersionV2
&&stampVocabularyVersion!=ResolvedLayoutStampVocabularyVersionV3)
add("stamp_vocabulary_version","resolved stamps require supported vocabulary version 1, 2 or 3");
std::vector<std::string> stampIds;
for(const auto& stamp:stamps)
{
@@ -1116,7 +1128,9 @@ bool ResolvedLayoutSnapshotV3::validate(ResolvedLayoutValidationModeV3 mode,
||std::find(stampIds.begin(),stampIds.end(),stamp.stableId)!=stampIds.end())
add("stamp_identity","stamp has an empty or duplicate stable identity");
else stampIds.push_back(stamp.stableId);
if(!LayoutStampKindValid(stamp.kind)||stamp.yawQuarterTurns>3)
const bool motif=LayoutStampIsMotif(stamp.kind);
if(!LayoutStampKindValid(stamp.kind)||stamp.yawQuarterTurns>3
||(motif&&stampVocabularyVersion<ResolvedLayoutStampVocabularyVersionV3))
add("stamp_kind","stamp has an unsupported kind or orientation");
bool validExtents=true;
for(const auto extent:stamp.halfExtentsMicrometres)
@@ -1130,8 +1144,33 @@ bool ResolvedLayoutSnapshotV3::validate(ResolvedLayoutValidationModeV3 mode,
||(stamp.irregularityAmplitudeMicrometres>0
&&stamp.irregularityWavelengthMicrometres<=0))
add("stamp_parameters",stamp.stableId+" has invalid or unbounded geometry parameters");
const std::int64_t pad=stamp.smoothWidthMicrometres
+stamp.irregularityAmplitudeMicrometres;
if(motif)
{
const auto minimumExtent=*std::min_element(stamp.halfExtentsMicrometres.begin(),
stamp.halfExtentsMicrometres.end());
const bool monolith=stamp.kind==ResolvedSdfStampKindV1::fillMonolith;
const bool shapeValid=monolith
?stamp.halfExtentsMicrometres[0]==stamp.halfExtentsMicrometres[1]
&&stamp.halfExtentsMicrometres[0]>=800000
&&stamp.halfExtentsMicrometres[0]<=2000000
&&stamp.halfExtentsMicrometres[2]>=6000000
&&stamp.halfExtentsMicrometres[2]<=16000000
:stamp.halfExtentsMicrometres[0]>=1000000
&&stamp.halfExtentsMicrometres[1]>=1000000;
if(stampVocabularyVersion<ResolvedLayoutStampVocabularyVersionV3
||stamp.roundingRadiusMicrometres<500000
||stamp.roundingRadiusMicrometres>minimumExtent
||stamp.minimumSpacingMicrometres<0
||stamp.minimumSpacingMicrometres>100000000
||stamp.attachmentPolicy!=1
||stamp.positionMicrometres[2]
!=stamp.floorMicrometres+stamp.halfExtentsMicrometres[2]
||!shapeValid||stamp.irregularityAmplitudeMicrometres!=0)
add("stamp_motif_parameters",stamp.stableId+" has invalid kind, size, fillet or floor attachment");
}
const std::int64_t pad=motif
?(stamp.smoothWidthMicrometres+5)/6+stamp.irregularityAmplitudeMicrometres
:stamp.smoothWidthMicrometres+stamp.irregularityAmplitudeMicrometres;
const std::array<std::int64_t,3> extents={
stamp.halfExtentsMicrometres[stamp.yawQuarterTurns%2?1:0]+pad,
stamp.halfExtentsMicrometres[stamp.yawQuarterTurns%2?0:1]+pad,
@@ -1146,6 +1185,35 @@ bool ResolvedLayoutSnapshotV3::validate(ResolvedLayoutValidationModeV3 mode,
if(!LayoutStampSafe(*this,stamp,&safetyReason))
add("stamp_placement",stamp.stableId+" is unsafe: "+safetyReason);
}
if(stampVocabularyVersion>=ResolvedLayoutStampVocabularyVersionV3)
{
for(std::size_t i=0;i<stamps.size();++i)
{
if(!LayoutStampIsMotif(stamps[i].kind))continue;
for(std::size_t j=0;j<i;++j)
{
if(!LayoutStampIsMotif(stamps[j].kind)
||stamps[i].strateIndex!=stamps[j].strateIndex)continue;
double gapSquared=0.0;
for(std::size_t axis=0;axis<3;++axis)
{
const auto gap=stamps[i].boundsMinimumMicrometres[axis]
>stamps[j].boundsMaximumMicrometres[axis]
?stamps[i].boundsMinimumMicrometres[axis]
-stamps[j].boundsMaximumMicrometres[axis]
:stamps[j].boundsMinimumMicrometres[axis]
>stamps[i].boundsMaximumMicrometres[axis]
?stamps[j].boundsMinimumMicrometres[axis]
-stamps[i].boundsMaximumMicrometres[axis]:0;
gapSquared+=static_cast<double>(gap)*gap;
}
const auto required=std::max(stamps[i].minimumSpacingMicrometres,
stamps[j].minimumSpacingMicrometres);
if(gapSquared<static_cast<double>(required)*required)
add("stamp_motif_spacing",stamps[i].stableId+" is too close to "+stamps[j].stableId);
}
}
}
if(cavernRooms.empty()&&cavernEdges.empty())
{
if(cavernGraphVocabularyVersion!=0)
@@ -1393,6 +1461,10 @@ std::optional<ResolvedLayoutSnapshotV3> ResolvedLayoutSnapshotV3::FromJson(
stamp.smoothWidthMicrometres=LayoutInt(v,"smooth_width_um");
stamp.irregularityAmplitudeMicrometres=LayoutInt(v,"irregularity_amplitude_um");
stamp.irregularityWavelengthMicrometres=LayoutInt(v,"irregularity_wavelength_um");
stamp.roundingRadiusMicrometres=LayoutInt(v,"rounding_radius_um");
stamp.minimumSpacingMicrometres=LayoutInt(v,"minimum_spacing_um");
stamp.attachmentPolicy=static_cast<std::uint8_t>(LayoutInt(v,"attachment_policy"));
stamp.floorMicrometres=LayoutInt(v,"floor_um");
stamp.irregularitySeed=static_cast<std::uint64_t>(LayoutInt(v,"irregularity_seed"));
stamp.yawQuarterTurns=static_cast<std::uint8_t>(LayoutInt(v,"yaw_quarter_turns"));
s.stamps.push_back(std::move(stamp));
@@ -1607,6 +1679,149 @@ bool ResolveResolvedLayoutStampsV2(ResolvedLayoutSnapshotV3& layout,std::int32_t
layout=std::move(candidate);return true;
}
bool ResolveResolvedLayoutStampsV3(ResolvedLayoutSnapshotV3& layout,std::int32_t seed,
std::span<const ResolvedLayoutStampRequestV1> requests,std::string& error)
{
error.clear();
if(requests.empty())
{
ResolvedLayoutSnapshotV3 candidate=layout;
candidate.stampVocabularyVersion=0;candidate.stamps.clear();
if(!candidate.finalize(error))return false;
layout=std::move(candidate);return true;
}
std::vector<ResolvedLayoutStampRequestV1> ordered(requests.begin(),requests.end());
std::sort(ordered.begin(),ordered.end(),[](const auto& a,const auto& b)
{return a.stableId<b.stableId;});
ResolvedLayoutSnapshotV3 candidate=layout;
candidate.stampVocabularyVersion=ResolvedLayoutStampVocabularyVersionV3;
candidate.stamps.clear();candidate.stamps.reserve(ordered.size());
for(std::size_t requestIndex=0;requestIndex<ordered.size();++requestIndex)
{
const auto& request=ordered[requestIndex];
if(request.stableId.empty()||(requestIndex>0
&&ordered[requestIndex-1].stableId==request.stableId))
{error="motif requests require non-empty unique stable IDs";return false;}
if(!LayoutStampIsMotif(request.kind)||request.yawQuarterTurns>3
||request.placementRadiusMicrometres<0
||request.placementRadiusMicrometres>100000000
||request.smoothWidthMicrometres<0||request.smoothWidthMicrometres>10000000
||request.irregularityAmplitudeMicrometres!=0
||request.irregularityWavelengthMicrometres<0
||request.irregularityWavelengthMicrometres>100000000
||request.roundingRadiusMicrometres<500000
||request.minimumSpacingMicrometres<0
||request.minimumSpacingMicrometres>100000000
||request.attachmentPolicy!=1)
{error="motif request "+request.stableId+" has invalid or unbounded parameters";return false;}
if(std::any_of(request.halfExtentsMicrometres.begin(),request.halfExtentsMicrometres.end(),
[](std::int64_t extent){return extent<500000||extent>100000000;}))
{error="motif request "+request.stableId+" has an extent outside 0.5..100 m";return false;}
const bool monolith=request.kind==ResolvedSdfStampKindV1::fillMonolith;
const auto minimumExtent=*std::min_element(request.halfExtentsMicrometres.begin(),
request.halfExtentsMicrometres.end());
const bool dimensionsValid=monolith
?request.halfExtentsMicrometres[0]==request.halfExtentsMicrometres[1]
&&request.halfExtentsMicrometres[0]>=800000
&&request.halfExtentsMicrometres[0]<=2000000
&&request.halfExtentsMicrometres[2]>=6000000
&&request.halfExtentsMicrometres[2]<=16000000
:request.halfExtentsMicrometres[0]>=1000000
&&request.halfExtentsMicrometres[1]>=1000000;
if(!dimensionsValid||request.roundingRadiusMicrometres>minimumExtent)
{error="motif request "+request.stableId+" has a shape size outside its authored family";return false;}
const auto stratum=std::find_if(candidate.strates.begin(),candidate.strates.end(),
[&](const auto& value){return value.strateIndex==request.strateIndex;});
if(stratum==candidate.strates.end())
{error="motif request "+request.stableId+" names an unknown strate";return false;}
for(const auto coordinate:request.anchorPositionMicrometres)
if(coordinate<-1000000000000ll||coordinate>1000000000000ll)
{error="motif request "+request.stableId+" has an unbounded anchor";return false;}
if(request.floorMicrometres<-1000000000000ll
||request.floorMicrometres>1000000000000ll)
{error="motif request "+request.stableId+" has an unbounded floor anchor";return false;}
const std::uint64_t baseSeed=LayoutStampSeed(seed,request.strateIndex,request.stableId)
&0x001fffffffffffffull;
std::uint64_t state=baseSeed;
const auto randomOffset=[&](std::uint64_t bits)
{
const std::uint64_t span=static_cast<std::uint64_t>(
request.placementRadiusMicrometres)*2+1;
return request.placementRadiusMicrometres==0?std::int64_t{0}
:static_cast<std::int64_t>(bits%span)-request.placementRadiusMicrometres;
};
bool placed=false;
const std::uint32_t attempts=request.placementRadiusMicrometres==0?1u:512u;
for(std::uint32_t attempt=0;attempt<attempts;++attempt)
{
ResolvedLayoutStampV1 stamp;stamp.stableId=request.stableId;
stamp.strateIndex=request.strateIndex;stamp.kind=request.kind;
stamp.halfExtentsMicrometres=request.halfExtentsMicrometres;
stamp.smoothWidthMicrometres=request.smoothWidthMicrometres;
stamp.irregularityAmplitudeMicrometres=0;
stamp.irregularityWavelengthMicrometres=request.irregularityWavelengthMicrometres;
stamp.roundingRadiusMicrometres=request.roundingRadiusMicrometres;
stamp.minimumSpacingMicrometres=request.minimumSpacingMicrometres;
stamp.attachmentPolicy=request.attachmentPolicy;
stamp.floorMicrometres=request.floorMicrometres;
stamp.irregularitySeed=baseSeed;stamp.yawQuarterTurns=request.yawQuarterTurns;
const std::array<std::int64_t,2> offset={
randomOffset(LayoutStampNext(state)),randomOffset(LayoutStampNext(state))};
if(request.placementRadiusMicrometres>0)
{
const long double radius=request.placementRadiusMicrometres;
const long double distanceSquared=static_cast<long double>(offset[0])*offset[0]
+static_cast<long double>(offset[1])*offset[1];
if(distanceSquared>radius*radius)continue;
}
stamp.positionMicrometres={request.anchorPositionMicrometres[0]+offset[0],
request.anchorPositionMicrometres[1]+offset[1],
request.floorMicrometres+request.halfExtentsMicrometres[2]};
const std::int64_t pad=(stamp.smoothWidthMicrometres+5)/6;
const std::array<std::int64_t,3> extents={
stamp.halfExtentsMicrometres[stamp.yawQuarterTurns%2?1:0]+pad,
stamp.halfExtentsMicrometres[stamp.yawQuarterTurns%2?0:1]+pad,
stamp.halfExtentsMicrometres[2]+pad};
for(std::size_t axis=0;axis<3;++axis)
{
stamp.boundsMinimumMicrometres[axis]=stamp.positionMicrometres[axis]-extents[axis];
stamp.boundsMaximumMicrometres[axis]=stamp.positionMicrometres[axis]+extents[axis];
}
if(!LayoutStampSafe(candidate,stamp))continue;
bool spaced=true;
for(const auto& prior:candidate.stamps)
{
if(!LayoutStampIsMotif(prior.kind)||prior.strateIndex!=stamp.strateIndex)continue;
double gapSquared=0.0;
for(std::size_t axis=0;axis<3;++axis)
{
const auto gap=stamp.boundsMinimumMicrometres[axis]
>prior.boundsMaximumMicrometres[axis]
?stamp.boundsMinimumMicrometres[axis]-prior.boundsMaximumMicrometres[axis]
:prior.boundsMinimumMicrometres[axis]
>stamp.boundsMaximumMicrometres[axis]
?prior.boundsMinimumMicrometres[axis]-stamp.boundsMaximumMicrometres[axis]:0;
gapSquared+=static_cast<double>(gap)*gap;
}
const auto required=std::max(stamp.minimumSpacingMicrometres,
prior.minimumSpacingMicrometres);
if(gapSquared<static_cast<double>(required)*required)
{spaced=false;break;}
}
if(!spaced)continue;
candidate.stamps.push_back(std::move(stamp));placed=true;break;
}
if(!placed)
{error="motif request "+request.stableId+" has no deterministic route-, band- and spacing-safe placement";return false;}
}
if(!candidate.finalize(error))return false;
std::vector<ResolvedLayoutIssueV2> issues;std::string strictError;
if(!candidate.validate(ResolvedLayoutValidationModeV3::strict,issues,strictError))
{error="strict stamp vocabulary-3 validation failed: "+strictError;return false;}
layout=std::move(candidate);return true;
}
bool ResolveResolvedCavernGraphV1(ResolvedLayoutSnapshotV3& layout,std::int32_t seed,
std::span<const ResolvedCavernRoomV1> rooms,
std::span<const ResolvedCavernEdgeV1> edges,std::string& error)
+160 -1
View File
@@ -3281,6 +3281,7 @@ private:
float smoothWidthVoxels=0.0f;
float irregularityAmplitudeVoxels=0.0f;
float irregularityWavelengthVoxels=0.0f;
float roundingRadiusVoxels=0.0f;
std::uint64_t irregularitySeed=0;
std::uint8_t quarterTurns=0;
};
@@ -3452,6 +3453,9 @@ private:
runtime.irregularityWavelengthVoxels=static_cast<float>(
static_cast<double>(stamp.irregularityWavelengthMicrometres)
/Owner->CoreVoxelSizeMicrons);
runtime.roundingRadiusVoxels=static_cast<float>(
static_cast<double>(stamp.roundingRadiusMicrometres)
/Owner->CoreVoxelSizeMicrons);
runtime.irregularitySeed=stamp.irregularitySeed;
runtime.quarterTurns=stamp.yawQuarterTurns;
StampRuntime.push_back(runtime);
@@ -5370,6 +5374,7 @@ public:
else ++Counts.MixedBoxes;
return Result;
};
std::vector<std::uint32_t> stampCandidates;
if(!StampSpatialBounds.empty())
{
constexpr std::int64_t Q=VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel;
@@ -5381,9 +5386,19 @@ public:
static_cast<std::int64_t>(BMax[0])*Q,
static_cast<std::int64_t>(BMax[1])*Q,
static_cast<std::int64_t>(BMax[2])*Q};
if(!BuildStampTileList(minimum,maximum).empty())
stampCandidates=BuildStampTileList(minimum,maximum);
for(const std::uint32_t index:stampCandidates)
{
if(index>=StampRuntime.size())return Finish(EVoxelTileClass::Mixed,true);
const auto& stamp=StampRuntime[index];
if(!stamp.record||(stamp.record->kind
!=VoxelForgeCore::ResolvedSdfStampKindV1::fillMonolith
&&stamp.record->kind
!=VoxelForgeCore::ResolvedSdfStampKindV1::fillPlatform)
||!SurfacePlan||stamp.record->strateIndex!=SurfacePlan->strateIndex)
return Finish(EVoxelTileClass::Mixed,true);
}
}
if(!CavernRuntime.empty())
{
constexpr std::int64_t Q=VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel;
@@ -5471,6 +5486,44 @@ public:
{
if(!WorldAssembly||!SurfacePlan||!SurfaceField)
return Finish(EVoxelTileClass::Mixed,true);
if(!stampCandidates.empty())
{
constexpr std::int64_t Scale=VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel;
const auto interval=SurfaceField->Evaluator.interval(
static_cast<std::int64_t>(BMin[0])*Scale,
static_cast<std::int64_t>(BMin[1])*Scale,
static_cast<std::int64_t>(BMin[2])*Scale,
static_cast<std::int64_t>(BMax[0])*Scale,
static_cast<std::int64_t>(BMax[1])*Scale,
static_cast<std::int64_t>(BMax[2])*Scale);
if(!interval.known||interval.minimumDensitySubvoxels
>interval.maximumDensitySubvoxels)
return Finish(EVoxelTileClass::Mixed,true);
FMetricInterval composed{
static_cast<double>(interval.minimumDensitySubvoxels)/Scale,
static_cast<double>(interval.maximumDensitySubvoxels)/Scale,true};
for(const std::uint32_t index:stampCandidates)
{
const auto& stamp=StampRuntime[index];
const auto feature=StampDistanceInterval(stamp,BMin,BMax);
if(!feature.known)return Finish(EVoxelTileClass::Mixed,true);
composed.minimum=SmoothMinDistance(static_cast<float>(composed.minimum),
static_cast<float>(feature.minimum),stamp.smoothWidthVoxels);
composed.maximum=SmoothMinDistance(static_cast<float>(composed.maximum),
static_cast<float>(feature.maximum),stamp.smoothWidthVoxels);
}
constexpr double outwardPadding=2.0e-5;
composed.minimum=std::nextafter(composed.minimum-outwardPadding,
-std::numeric_limits<double>::infinity());
composed.maximum=std::nextafter(composed.maximum+outwardPadding,
std::numeric_limits<double>::infinity());
if(!std::isfinite(composed.minimum)||!std::isfinite(composed.maximum)
||composed.minimum>composed.maximum)
return Finish(EVoxelTileClass::Mixed,true);
if(composed.minimum>=0.0)return Finish(EVoxelTileClass::AllAir);
if(composed.maximum<0.0)return Finish(EVoxelTileClass::AllSolid);
return Finish(EVoxelTileClass::Mixed);
}
// classifyLatticeBox takes the exact extrema of ground/cap columns at every
// MC lattice XY in this box. Since density is min(z-ground, cap-z), those extrema
// bound every lattice sample in Z without a noise amplitude guess.
@@ -6503,6 +6556,19 @@ private:
+std::max(vertical,0.0f)*std::max(vertical,0.0f));
return outside+std::min(std::max(radial,vertical),0.0f);
}
static float StampRoundedCappedCylinderSdf(float x,float y,float z,
const std::array<float,3>& halfSize,float rounding)
{
const float radius=halfSize[0];
if(!(radius>0.0f&&halfSize[0]==halfSize[1]&&halfSize[2]>0.0f)
||rounding<0.0f||rounding>std::min(radius,halfSize[2]))
return std::numeric_limits<float>::infinity();
const float radial=std::sqrt(x*x+y*y)-(radius-rounding);
const float vertical=std::abs(z)-(halfSize[2]-rounding);
const float outside=std::sqrt(std::max(radial,0.0f)*std::max(radial,0.0f)
+std::max(vertical,0.0f)*std::max(vertical,0.0f));
return outside+std::min(std::max(radial,vertical),0.0f)-rounding;
}
static float StampArchSdf(float x,float y,float z,
const std::array<float,3>& halfSize)
{
@@ -6533,6 +6599,12 @@ private:
distance=StampArchSdf(localX,localY,localZ,stamp.halfExtentsVoxels);break;
case VoxelForgeCore::ResolvedSdfStampKindV1::fillPillar:
distance=StampPillarSdf(localX,localY,localZ,stamp.halfExtentsVoxels);break;
case VoxelForgeCore::ResolvedSdfStampKindV1::fillMonolith:
distance=StampRoundedCappedCylinderSdf(localX,localY,localZ,
stamp.halfExtentsVoxels,stamp.roundingRadiusVoxels);break;
case VoxelForgeCore::ResolvedSdfStampKindV1::fillPlatform:
distance=StampRoundedBoxSdf(localX,localY,localZ,
stamp.halfExtentsVoxels,stamp.roundingRadiusVoxels);break;
case VoxelForgeCore::ResolvedSdfStampKindV1::fillDais:
if(ResolvedLayout&&ResolvedLayout->stampVocabularyVersion
>=VoxelForgeCore::ResolvedLayoutStampVocabularyVersionV2)
@@ -6550,6 +6622,93 @@ private:
*stamp.irregularityAmplitudeVoxels;
return distance;
}
static double StampAbsMinimum(double minimum,double maximum)
{return minimum<=0.0&&maximum>=0.0?0.0:std::min(std::abs(minimum),std::abs(maximum));}
static double StampRoundedBoxSdfDouble(const std::array<double,3>& absolute,
const std::array<double,3>& halfSize,double rounding)
{
const double qx=absolute[0]-halfSize[0]+rounding;
const double qy=absolute[1]-halfSize[1]+rounding;
const double qz=absolute[2]-halfSize[2]+rounding;
const double outside=std::sqrt(std::max(qx,0.0)*std::max(qx,0.0)
+std::max(qy,0.0)*std::max(qy,0.0)
+std::max(qz,0.0)*std::max(qz,0.0));
return outside+std::min(std::max({qx,qy,qz}),0.0)-rounding;
}
FMetricInterval StampDistanceInterval(const FStampRuntime& stamp,
const int32 bMin[3],const int32 bMax[3]) const
{
if(!stamp.record||(stamp.record->kind
!=VoxelForgeCore::ResolvedSdfStampKindV1::fillMonolith
&&stamp.record->kind!=VoxelForgeCore::ResolvedSdfStampKindV1::fillPlatform))
return {0.0,0.0,false};
std::array<double,3> localMinimum{},localMaximum{};
const std::array<double,3> center={stamp.positionVoxels[0],
stamp.positionVoxels[1],stamp.positionVoxels[2]};
const auto axisRange=[&](std::size_t axis)
{
return std::array<double,2>{static_cast<double>(bMin[axis]),
static_cast<double>(bMax[axis])};
};
const auto xRange=axisRange(0),yRange=axisRange(1),zRange=axisRange(2);
switch(stamp.quarterTurns&3u)
{
case 1:
localMinimum={yRange[0]-center[1],center[0]-xRange[1],zRange[0]-center[2]};
localMaximum={yRange[1]-center[1],center[0]-xRange[0],zRange[1]-center[2]};
break;
case 2:
localMinimum={center[0]-xRange[1],center[1]-yRange[1],zRange[0]-center[2]};
localMaximum={center[0]-xRange[0],center[1]-yRange[0],zRange[1]-center[2]};
break;
case 3:
localMinimum={center[1]-yRange[1],xRange[0]-center[0],zRange[0]-center[2]};
localMaximum={center[1]-yRange[0],xRange[1]-center[0],zRange[1]-center[2]};
break;
default:
localMinimum={xRange[0]-center[0],yRange[0]-center[1],zRange[0]-center[2]};
localMaximum={xRange[1]-center[0],yRange[1]-center[1],zRange[1]-center[2]};
break;
}
std::array<double,3> absoluteMinimum{},absoluteMaximum{};
for(std::size_t axis=0;axis<3;++axis)
{
absoluteMinimum[axis]=StampAbsMinimum(localMinimum[axis],localMaximum[axis]);
absoluteMaximum[axis]=std::max(std::abs(localMinimum[axis]),
std::abs(localMaximum[axis]));
}
double minimum=0.0,maximum=0.0;
if(stamp.record->kind==VoxelForgeCore::ResolvedSdfStampKindV1::fillMonolith)
{
const double radialMinimum=std::hypot(absoluteMinimum[0],absoluteMinimum[1]);
const double radialMaximum=std::hypot(absoluteMaximum[0],absoluteMaximum[1]);
const double round=stamp.roundingRadiusVoxels;
const double side=stamp.halfExtentsVoxels[0]-round;
const double cap=stamp.halfExtentsVoxels[2]-round;
const auto eval=[&](double radial,double vertical)
{
const double qr=radial-side,qz=vertical-cap;
return std::hypot(std::max(qr,0.0),std::max(qz,0.0))
+std::min(std::max(qr,qz),0.0)-round;
};
minimum=eval(radialMinimum,absoluteMinimum[2]);
maximum=eval(radialMaximum,absoluteMaximum[2]);
}
else if(stamp.record->kind==VoxelForgeCore::ResolvedSdfStampKindV1::fillPlatform)
{
const std::array<double,3> half={stamp.halfExtentsVoxels[0],
stamp.halfExtentsVoxels[1],stamp.halfExtentsVoxels[2]};
minimum=StampRoundedBoxSdfDouble(absoluteMinimum,half,stamp.roundingRadiusVoxels);
maximum=StampRoundedBoxSdfDouble(absoluteMaximum,half,stamp.roundingRadiusVoxels);
}
else return {0.0,0.0,false};
constexpr double outwardPadding=2.0e-5;
return {std::nextafter(minimum-outwardPadding,
-std::numeric_limits<double>::infinity()),
std::nextafter(maximum+outwardPadding,
std::numeric_limits<double>::infinity()),true};
}
float ApplyResolvedSdfStamps(float density,float X,float Y,float Z) const
{
if(StampRuntime.empty()||!Owner||Owner->CoreVoxelSizeMicrons==0)return density;
@@ -0,0 +1,213 @@
#!/usr/bin/env python3
"""Audit LOD0 triangles in the resolved monolith and platform surface ROIs."""
from __future__ import annotations
import argparse
import array
import json
import math
from pathlib import Path
import struct
import sys
def solve3(matrix, vector):
rows = [list(matrix[i]) + [vector[i]] for i in range(3)]
for column in range(3):
pivot = max(range(column, 3), key=lambda row: abs(rows[row][column]))
if abs(rows[pivot][column]) < 1.0e-10:
return None
rows[column], rows[pivot] = rows[pivot], rows[column]
scale = rows[column][column]
rows[column] = [value / scale for value in rows[column]]
for row in range(3):
if row == column:
continue
scale = rows[row][column]
rows[row] = [rows[row][i] - scale * rows[column][i] for i in range(4)]
return [rows[row][3] for row in range(3)]
def fit_radius(points, center_x, center_z, center_y, window=1.05, y_window=1.3):
selected = sorted({(round(x, 4), round(z, 4)) for x, y, z in points
if abs(y - center_y) <= y_window
and abs(x - center_x) <= window and abs(z - center_z) <= window})
if len(selected) < 8:
return None, len(selected)
sums = [0.0] * 9
rhs = [0.0] * 3
for x, z in selected:
row = (x, z, 1.0)
target = -(x * x + z * z)
for i in range(3):
rhs[i] += row[i] * target
for j in range(3):
sums[i * 3 + j] += row[i] * row[j]
solution = solve3([sums[0:3], sums[3:6], [sums[6], sums[7], sums[8]]], rhs)
if solution is None:
return None, len(selected)
a, b, c = solution
radius_squared = (a * a + b * b) * 0.25 - c
if radius_squared <= 0.0:
return None, len(selected)
return math.sqrt(radius_squared), len(selected)
def read_mesh(path: Path):
triangles = []
vertices_all = []
selected_tiles = 0
with path.open("rb") as stream:
prefix = stream.read(60)
if len(prefix) != 60 or prefix[:8] != b"VFMSH001":
raise ValueError(f"{path}: invalid VFMSH001 header")
version, voxel_um, tile_count = struct.unpack_from("<3I", prefix, 8)
if version != 1 or voxel_um <= 0 or tile_count > 1_000_000:
raise ValueError(f"{path}: invalid mesh version or size")
for _ in range(tile_count):
header = stream.read(36)
if len(header) != 36:
raise ValueError(f"{path}: truncated tile header")
key = struct.unpack_from("<4i", header, 0)
surface_count, _aux_count, vertex_count, index_count, mask_count = \
struct.unpack_from("<5I", header, 16)
position_bytes = stream.read(vertex_count * 12)
normal_bytes = stream.read(vertex_count * 12)
index_bytes = stream.read(index_count * 4)
masks = stream.read(mask_count)
if (len(position_bytes) != vertex_count * 12
or len(normal_bytes) != vertex_count * 12
or len(index_bytes) != index_count * 4
or len(masks) != mask_count):
raise ValueError(f"{path}: truncated tile payload")
if key[3] != 0:
continue
selected_tiles += 1
positions = array.array("f")
positions.frombytes(position_bytes)
indices = array.array("I")
indices.frombytes(index_bytes)
if sys.byteorder != "little":
positions.byteswap()
indices.byteswap()
points = [tuple(float(positions[index * 3 + axis])
for axis in range(3)) for index in range(vertex_count)]
vertices_all.extend(points)
for offset in range(0, index_count - 2, 3):
if masks and masks[offset // 3]:
continue
ids = indices[offset:offset + 3]
if max(ids) >= surface_count:
continue
verts = tuple(points[index] for index in ids)
edge_a = tuple(verts[1][axis] - verts[0][axis] for axis in range(3))
edge_b = tuple(verts[2][axis] - verts[0][axis] for axis in range(3))
cross = (edge_a[1] * edge_b[2] - edge_a[2] * edge_b[1],
edge_a[2] * edge_b[0] - edge_a[0] * edge_b[2],
edge_a[0] * edge_b[1] - edge_a[1] * edge_b[0])
area_twice = math.sqrt(sum(value * value for value in cross))
if area_twice <= 1.0e-10:
continue
center = tuple(sum(vertex[axis] for vertex in verts) / 3.0
for axis in range(3))
triangles.append((center, area_twice * 0.5, verts))
if stream.read(1):
raise ValueError(f"{path}: trailing mesh data")
return triangles, vertices_all, selected_tiles
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("meshes", type=Path, nargs="+")
parser.add_argument("layout", type=Path)
parser.add_argument("--view", required=True, choices=("combined",))
args = parser.parse_args()
layout = json.loads(args.layout.read_text(encoding="utf-8"))
motifs = layout.get("stamps", [])
monolith = next(row for row in motifs if row["kind"] == 5)
platform = next(row for row in motifs if row["kind"] == 6)
mesh_rows = [read_mesh(path) for path in args.meshes]
triangles = [triangle for row in mesh_rows for triangle in row[0]]
vertices = [vertex for row in mesh_rows for vertex in row[1]]
tiles = sum(row[2] for row in mesh_rows)
if not triangles:
raise ValueError("meshes have no LOD0 surface triangles")
def metres(point):
return tuple(value / 1_000_000.0 for value in point)
mono = metres(monolith["position_um"])
floor = monolith["floor_um"] / 1_000_000.0
radius = monolith["half_extents_um"][0] / 1_000_000.0
half_height = monolith["half_extents_um"][2] / 1_000_000.0
mono_round = monolith["rounding_radius_um"] / 1_000_000.0
plat = metres(platform["position_um"])
half = tuple(value / 1_000_000.0 for value in platform["half_extents_um"])
plat_round = platform["rounding_radius_um"] / 1_000_000.0
top = floor + 2.0 * half_height
rois = {
"monolith_foot": lambda p: math.hypot(p[0] - mono[0], p[1] - mono[1]) <= radius + 1.4
and floor - 1.0 <= p[2] <= floor + 2.1,
"monolith_cap": lambda p: math.hypot(p[0] - mono[0], p[1] - mono[1]) <= radius + 1.6
and top - 2.0 <= p[2] <= top + 1.1,
"platform_edges": lambda p: abs(p[0] - plat[0]) <= half[0] + 1.2
and abs(p[1] - plat[1]) <= half[1] + 1.2
and floor - 0.8 <= p[2] <= floor + 2.4 * half[2] + 0.8,
}
roi_counts = {name: sum(1 for center, _area, _verts in triangles if predicate(center))
for name, predicate in rois.items()}
bad_area = sum(1 for _center, area, _verts in triangles if not math.isfinite(area) or area <= 0.0)
foot_radius, foot_points = fit_radius(vertices, mono[0] + radius - mono_round,
floor + mono_round, mono[1], window=1.1)
cap_radius, cap_points = fit_radius(vertices, mono[0] + radius - mono_round,
top - mono_round, mono[1], window=1.1)
platform_radius, platform_points = fit_radius(vertices,
plat[0] + half[0] - plat_round, floor + 2.0 * half[2] - plat_round,
plat[1], window=1.1)
radii = (foot_radius, cap_radius, platform_radius)
fit_counts = (foot_points, cap_points, platform_points)
def surface_pass(tile_count, degenerate_count, rois, measured_radii):
covered = all(count >= 8 for count in rois.values())
rounded = all(value is not None and value >= 0.5 for value in measured_radii)
return tile_count > 0 and degenerate_count == 0 and covered and rounded
radius_ok = all(value is not None and value >= 0.5 for value in radii)
coverage_ok = all(count >= 8 for count in roi_counts.values())
missing_roi = dict(roi_counts)
missing_roi["monolith_foot"] = 0
sharp_edge = list(radii)
sharp_edge[0] = 0.25
controls_rejected = (
not surface_pass(tiles, bad_area, missing_roi, radii)
and not surface_pass(tiles, bad_area, roi_counts, sharp_edge)
and not surface_pass(0, 0, roi_counts, radii)
)
passed = surface_pass(tiles, bad_area, roi_counts, radii) and controls_rejected
for name, count in roi_counts.items():
print(f"[MotifSurfaceROI] view={args.view} name={name} triangles={count} "
f"whole_surface=LOD0 status={'PASS' if count >= 8 else 'FAIL'}")
if all(value is not None for value in radii):
print(f"[MotifFilletMeasure] view={args.view} foot_radius_m={foot_radius:.3f} "
f"cap_radius_m={cap_radius:.3f} platform_radius_m={platform_radius:.3f} "
f"fit_points={fit_counts} target_min_m=0.500")
else:
print(f"[MotifFilletMeasure] view={args.view} foot_radius_m={foot_radius} "
f"cap_radius_m={cap_radius} platform_radius_m={platform_radius} "
f"fit_points={fit_counts} target_min_m=0.500")
print(f"[MotifSurfaceAudit] view={args.view} meshes={len(mesh_rows)} lod0_tiles={tiles} triangles={len(triangles)} "
f"degenerate={bad_area} feature_rois={len(roi_counts)} covered={coverage_ok} "
f"fillets_ge_0.5m={radius_ok} missing_roi_control={'REJECTED' if not surface_pass(tiles, bad_area, missing_roi, radii) else 'FAILED'} "
f"sharp_fillet_control={'REJECTED' if not surface_pass(tiles, bad_area, roi_counts, sharp_edge) else 'FAILED'} "
f"empty_mesh_control={'REJECTED' if not surface_pass(0, 0, roi_counts, radii) else 'FAILED'} "
f"negative_controls={'REJECTED' if controls_rejected else 'FAILED'} "
f"status={'PASS' if passed else 'FAIL'}")
return 0 if passed else 1
if __name__ == "__main__":
try:
raise SystemExit(main())
except Exception as error:
print(f"[MotifSurfaceAudit] status=FAIL error={error}", file=sys.stderr)
raise SystemExit(1)
@@ -0,0 +1,67 @@
#!/usr/bin/env python3
"""Build the versioned L56 flat-field and sparse-motif fixture."""
from __future__ import annotations
import argparse
import json
import os
from pathlib import Path
ROOT = Path(__file__).resolve().parents[4]
OWNER = ROOT / "Standalone/data/owner_world.json"
OUT_DEFAULT = Path(os.environ.get("VOXELFORGE_VERIFY_OUT", ROOT / "Saved/Linux/l56"))
def main() -> None:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--out", type=Path, default=OUT_DEFAULT / "fixtures")
args = parser.parse_args()
args.out.mkdir(parents=True, exist_ok=True)
fixture = json.loads(OWNER.read_text(encoding="utf-8"))
fixture["surface_profile_override"] = {
"version": 1,
"kind": "flatField",
"minimum_arena_clearance_m": 0.0,
}
fixture["motif_family_override"] = {
"version": 1,
"strate_index": 1,
"placement_policy": "seed,strate,stable_id",
"motifs": [
{
"stable_id": "motif/monolith-01-v1",
"kind": "cappedCylinder",
"radius_m": 1.4,
"height_m": 24.0,
"route_side_offset_m": 28.0,
"placement_radius_m": 4.0,
"fillet_radius_m": 0.55,
"blend_width_m": 1.6,
"minimum_spacing_m": 15.0,
"yaw_quarter_turns": 0,
"attachment": "seated_floor",
},
{
"stable_id": "motif/platform-01-v1",
"kind": "roundedBox",
"half_extents_m": [3.2, 2.8, 0.75],
"route_side_offset_m": -35.0,
"placement_radius_m": 4.0,
"fillet_radius_m": 0.55,
"blend_width_m": 1.6,
"minimum_spacing_m": 15.0,
"yaw_quarter_turns": 0,
"attachment": "seated_floor",
},
],
}
path = args.out / "style-override-motifs-slice1.json"
path.write_text(json.dumps(fixture, indent=2) + "\n", encoding="utf-8")
print(f"[L56MotifFixture] path={path} profile=flatField motifs=2 "
"placement=seed,strate,stable_id status=PASS")
if __name__ == "__main__":
main()
@@ -0,0 +1,168 @@
#!/usr/bin/env python3
"""Capture two checked views of the R24 flat field and sparse motifs."""
from __future__ import annotations
import argparse
import json
import math
import os
from pathlib import Path
import subprocess
import sys
import time
ROOT = Path(__file__).resolve().parents[4]
OUT_DEFAULT = Path(os.environ.get("VOXELFORGE_VERIFY_OUT", ROOT / "Saved/Linux/l56"))
LIMIT = ["taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--"]
Q_PER_METRE = 1024.0
sys.path.insert(0, str(ROOT / "Standalone/Tools/verify"))
from runner import bounded_run, current_stamp, first_stamp
def fmt(values):
return ",".join(f"{value:.6f}" for value in values)
def camera_angles(camera, target):
dx, dy, dz = (target[index] - camera[index] for index in range(3))
return math.degrees(math.atan2(dx, dy)), math.degrees(math.atan2(dz, math.hypot(dx, dy)))
def read_scene(layout_path):
layout = json.loads(layout_path.read_text(encoding="utf-8"))
motifs = layout["stamps"]
monolith = next(row for row in motifs if row["kind"] == 5)
platform = next(row for row in motifs if row["kind"] == 6)
route = [tuple(float(value) / Q_PER_METRE for value in anchor["values"][:3])
for strate in layout["strates"] for anchor in strate.get("anchors", [])
if anchor.get("kind") == "route_point" and len(anchor.get("values", [])) >= 3]
if len(route) < 2:
raise RuntimeError("motif fixture did not resolve a surface route")
mono = tuple(value / 1_000_000.0 for value in monolith["position_um"])
dais = tuple(value / 1_000_000.0 for value in platform["position_um"])
floor = monolith["floor_um"] / 1_000_000.0
center = tuple(sum(point[axis] for point in route) / len(route) for axis in range(3))
dx, dy = route[-1][0] - route[0][0], route[-1][1] - route[0][1]
length = math.hypot(dx, dy)
if length <= 1.0e-6:
raise RuntimeError("resolved surface route tangent is degenerate")
tx, ty = dx / length, dy / length
eye_camera = (mono[0] - tx * 30.0, mono[1] - ty * 30.0, floor + 1.65)
eye_target = (mono[0] + tx * 1.5, mono[1] + ty * 1.5, floor + 12.0)
scene_x = (center[0] + mono[0] + dais[0]) / 3.0
scene_y = (center[1] + mono[1] + dais[1]) / 3.0
overview_camera = (scene_x + tx * 45.0, scene_y + ty * 45.0, floor + 43.0)
overview_target = (scene_x, scene_y, floor + 5.0)
return layout, {
"eye": (eye_camera, eye_target, 5),
"overview": (overview_camera, overview_target, 7),
}
def run_step(name, command, log, *, env, stamped=False):
expected = current_stamp() if stamped else None
if stamped:
probe = bounded_run([str(command[0]), "--print-source-stamp"], timeout=15)
if probe is None or probe.returncode != 0 or first_stamp(probe.stdout or "") != expected:
raise RuntimeError(f"{name} refused a stale executable: {command[0]}")
started = time.monotonic()
with log.open("w", encoding="utf-8") as stream:
result = subprocess.run([*LIMIT, "timeout", "1740s", *map(str, command)],
cwd=ROOT, env=env, stdout=stream, stderr=subprocess.STDOUT,
timeout=1745, check=False)
elapsed = time.monotonic() - started
output = log.read_text(encoding="utf-8", errors="replace")
print(f"[L56CaptureRun] step={name} elapsed={elapsed:.1f}s "
f"exit={result.returncode} log={log}", flush=True)
if stamped and (first_stamp(output) != expected or current_stamp() != expected):
raise RuntimeError(f"{name} source stamp mismatch; see {log}")
if name.endswith("-quality") or name.endswith("-surface-audit"):
for line in output.splitlines():
if line.startswith(("[CaptureQuality]", "[MotifSurfaceROI]",
"[MotifFilletMeasure]", "[MotifSurfaceAudit]")):
print(line, flush=True)
if result.returncode != 0:
raise RuntimeError(f"{name} failed; see {log}")
return output
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--out", type=Path, default=OUT_DEFAULT)
parser.add_argument("--fixture-dir", type=Path)
parser.add_argument("--artifact-dir", type=Path, required=True)
parser.add_argument("--headless", type=Path, required=True)
parser.add_argument("--renderer", type=Path, required=True)
parser.add_argument("--auditor", type=Path, required=True)
args = parser.parse_args()
out = args.out.resolve()
fixture_dir = (args.fixture_dir or out / "fixtures").resolve()
artifact_dir = args.artifact_dir.resolve()
png_dir, mesh_dir = out / "capture-png", out / "motif-meshes"
for directory in (out, png_dir, mesh_dir, artifact_dir):
directory.mkdir(parents=True, exist_ok=True)
fixture = fixture_dir / "style-override-motifs-slice1.json"
layout = out / "layouts" / "motif-slice1-capsule-reachability-clang.json"
if not fixture.is_file() or not layout.is_file():
raise RuntimeError("missing fixture or resolved motif records")
encoded, views = read_scene(layout)
floor = next(row["floor_um"] for row in encoded["stamps"] if row["kind"] == 5) / 1_000_000.0
env = os.environ.copy()
env["LP_NUM_THREADS"] = "12"
env["XDG_CACHE_HOME"] = str(out / "xdg-cache")
mesh_paths = []
for view, (camera, target, clip_radius) in views.items():
yaw, pitch = camera_angles(camera, target)
camera_spec = (*camera, yaw, pitch)
stem = f"motifs-slice1-{view}"
mesh = mesh_dir / f"{stem}.vfmesh"
png = png_dir / f"{stem}.png"
image = artifact_dir / f"{stem}.jpg"
manifest = fixture_dir / f"{stem}-manifest.json"
headless = [args.headless, fixture, "--workers=12",
"--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline",
"--force-generate", f"--clip-radius={clip_radius}",
"--max-clip-level=0", "--max-level=0", "--render-distance-chunks=0",
f"--camera={fmt(camera_spec)}", f"--mesh-export={mesh}",
f"--world-assembler-manifest-output={manifest}"]
run_step(f"{stem}-export", headless, out / f"capture-{stem}-export.log",
env=env, stamped=True)
if not mesh.is_file() or mesh.stat().st_size == 0:
raise RuntimeError(f"headless export produced no mesh for {view}")
focus = (*target, 42.0 if view == "overview" else 34.0)
height_center = floor + 12.0 if view == "overview" else camera[2]
renderer = [args.renderer, mesh, png, "--size=1600x900", "--fov-deg=72",
f"--camera-m={fmt(camera)}", f"--yaw-deg={yaw:.6f}",
f"--pitch-deg={pitch:.6f}", "--tile-skirts=off", "--shade=readable",
"--headlamp=on", "--height-tint=on", f"--height-center-m={height_center:.6f}",
"--height-range-m=34", "--tile-edges=off", f"--focus-region={fmt(focus)}"]
run_step(f"{stem}-render", renderer, out / f"capture-{stem}-render.log",
env=env, stamped=True)
run_step(f"{stem}-jpeg", ["ffmpeg", "-nostdin", "-hide_banner", "-loglevel",
"error", "-y", "-i", png, "-frames:v", "1", "-q:v", "5", image],
out / f"capture-{stem}-jpeg.log", env=env)
run_step(f"{stem}-quality", [sys.executable,
ROOT / "Standalone/Tools/verify/capture_quality.py", image],
out / f"capture-{stem}-quality.log", env=env)
mesh_paths.append(mesh)
if not image.is_file() or not 0 < image.stat().st_size <= 300_000:
raise RuntimeError(f"capture size must be <=300 KB: {image}")
print(f"[L56MotifCapture] view={view} file={image} bytes={image.stat().st_size} "
f"camera_m=({fmt(camera)}) target_m=({fmt(target)}) status=PASS", flush=True)
audit_output = run_step("motifs-surface-audit",
[sys.executable, args.auditor, *mesh_paths, layout, "--view=combined"],
out / "capture-motifs-surface-audit.log", env=env)
if "[MotifSurfaceAudit] view=combined" not in audit_output:
raise RuntimeError("surface audit produced no whole-surface summary")
return 0
if __name__ == "__main__":
try:
raise SystemExit(main())
except Exception as error:
print(f"[L56MotifCapture] status=FAIL error={error}", file=sys.stderr)
raise SystemExit(1)
@@ -0,0 +1,56 @@
# L56 — R24 slice 1: slab + sparse motifs
**Result: PASS.** The native family adds one `flatField` stratum with one monument and one low platform. Fins remain on hold.
## Records and field
Motif vocabulary v3 resolves two version-1 records with placement keyed by `(seed, strate, stable_id)`, route keepouts, band clearance, and 15 m pairwise spacing. Fixture seed is 0; both records attach to the floor at Z = -529.600 m.
- `motif/monolith-01-v1`: rounded capped cylinder, radius 1.4 m (within R20 profile 0.8–2 m), height 24 m; route offset +28 m; placement radius 4 m. Resolved center `(3.922, -33.622, -517.600)` m; record seed `1544480482218982`.
- `motif/platform-01-v1`: rounded-box plinth, half extents `(3.2, 2.8, 0.75)` m; route offset -35 m; placement radius 4 m. Resolved center `(-37.031, 9.940, -528.850)` m; record seed `2227196533846249`.
Both use a 0.55 m geometric rounding radius and 1.6 m cubic smooth-union width (`2√2 × 0.55 = 1.556 m`). The monolith uses a rounded capped-cylinder SDF; the plinth uses a rounded-box SDF. Their fills compose into the flat field with smooth min. Resolved AABBs include the smooth-union padding (`W/6 = 0.267 m`):
- Monolith: `[2.255, 5.588] × [-35.289, -31.956] × [-529.866, -505.333]` m.
- Platform: `[-40.498, -33.564] × [6.873, 13.007] × [-529.866, -527.833]` m.
Cylinder interval bounds use exact radial minima/maxima over each XY box plus the vertical interval; platform bounds use its rounded-box intervals. The BVH contains these bounds and `isTileShapeFree` blocks motif-overlapping tiles. Brute-force checks: 8 boxes, 512 samples, zero misses; 2 all-air and 2 all-solid proofs; both false-proof controls rejected.
## Reachability and surface audit
The final-field passage route passed with 33 points, 5,733 capsule samples, 0 blocked samples, 477 support probes, 0 unsupported probes, and 0 grade failures. Motif route and band keepouts passed.
Whole-surface LOD0 audit covered the monolith foot and cap and platform edges (4,706 tiles; 1,847,639 triangles; 0 degenerate). Fitted radii: foot **0.856 m**, cap **0.728 m**, platform **1.165 m**. Each exceeds 0.5 m. Missing-ROI, sharp-fillet, and empty-mesh controls were rejected.
## Timing, tiers, and determinism
Motif cold timing: first tile **0.076 s**, near ring **0.144 s**, whole view **0.524 s** against the 1.75 s target. Final `verify.py` results: fast **PASS, 167.9 s**; medium **PASS, 961.1 s**; full **PASS, 1,135.3 s**. Full included the 30-cell check and five paired cost checks. Clang and GCC builds used FP contraction off; motif hashes matched at W1/W8/W12 for the monolith and both random cameras, including the camera at the monolith.
## Captures
Both checked visually; each is a 1600×900 JPEG below 300 KB.
- Eye-level monument and cap: [motifs-slice1-eye.jpg](captures/motifs-slice1-eye.jpg) — 27,946 bytes.
- High oblique overview with platform, monolith, spacing, and route: [motifs-slice1-overview.jpg](captures/motifs-slice1-overview.jpg) — 37,756 bytes.
## Hashes and diagnostics
- Source stamp: `5960b761be0110f5d47fea4f56df938e5d70ddba7355d1e2a6d11f15514b217e`.
- Fixture SHA-256: `e9a118f1ce3fe247572899075d31ee421f070566ebd6cef4bd1616da9e84e12c`.
- Resolved layout: `resolved-layout-v3-fnv64:d8c2af75e948357f`.
- Clang binary SHA-256: `c350591d88e706e6e02891428ddb7dd30dc01307fd9ee301798261e462f88129`.
- GCC binary SHA-256: `1fa592d7a7300662981fe42ab40345075f901c965d4a3f3811fc79e8e124f0ae`.
- Owner world SHA-256: `7b095f9bcc6b90133d5a463f99f0b571133b2c549ce1ecf2d64fe9175e41e183`; diff diagnostic clean.
- Eye capture SHA-256: `0266e54e52fcf5eb57b03986fc1dc093437ab36582aec8b2113bc8a43a51bfbe`.
- Overview capture SHA-256: `c2998da1570f587b7ce8598993211098da6e4e7d24cf0284345577246def77b4`.
## Trials and failed runs
**9/15 trials used**: seven evidence/capture attempts failed and two passed. Failures were limited to the initial medium audit missing the platform ROI, the clip-radius safety guard, camera crops that omitted the platform, an overly restrictive fillet upper bound, and one temporary capture-helper `floor` name error. Logs are under `Saved/Linux/l56/`; the final fast, medium, and full tiers passed.
## Orchestrator review (Claude)
Accepted. The stamp matches the final Clang and GCC builds (`5960b761…`); 9 of 15 trials. The monolith reads as an
intentional, cleanly rounded monument; the motif stratum runs at **0.52 s** whole view. **Logged for later:** the
overview shows a dark crescent where the large arrival shaft (the passage structure from the strate above) meets the
floor. Check whether that's a real gap in the field or a render artifact; it isn't part of this round's motifs.
Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

@@ -0,0 +1,84 @@
# VoxelForge R25 — revised self-check report
## Self-check
The earlier “heavy thrashing” conclusion was too strong. The conflict counts alone do not prove that the column cache caused most of the grid time.
I reread the complete cache and FI density helper functions cited below, plus the mesher fill and X8 branches and the instrumentation blocks. I did not read every line of the large enclosing `GenerateMesh` and `World::generateTile` functions end to end; I rely only on the cited branches. This was a read-only review: no scripts, tests, builds, binaries, or edits.
## Cache mechanics and the access sequence
There is no separate local index function: `IslandColumnCache` computes its index inline. The cache key is **XY, not XYZ**. The equality check includes recipe and plan identities and hashes, seed, stable island ID, sample X/Y, and island/recipe shape parameters. It contains no Z. The cached value holds per-island XY-derived metrics—delta X/Y, radial distance, angle, lobe phase, and top surface—not the 3D density value. See [`FloatingIslandsInternal.h`]( /home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/FloatingIslandsInternal.h:497).
The local cache has four ways and 2,048 sets, or 8,192 entries per worker. The key-match lines include:
```cpp
const bool bKeyMatches=Entry.bValid&&Entry.RecipeIdentity==&recipe
&&Entry.PlanIdentity==&plan&&Entry.RecipeContentHash==recipe.contentHash
&&Entry.PlanContentHash==plan.contentHash&&Entry.Seed==recipe.seed
&&Entry.StableId==island.stableId
&&Entry.SampleX==SampleX&&Entry.SampleY==SampleY
```
The exact way selection is:
```cpp
IndexKey^=IndexKey>>33;
IndexKey*=0xff51afd7ed558ccdull;
IndexKey^=IndexKey>>33;
const std::size_t Base=static_cast<std::size_t>(IndexKey&(SetCount-1))*Ways;
FIslandColumnCacheEntry* Replacement=&cache[Base+((IndexKey>>11)&(Ways-1))];
```
Those lines are at 519, 520, 521, 522, and 523. If a way is invalid, the first invalid way is used; otherwise the preselected hash way is overwritten. This is four-way set associative, **not direct mapped**, and replacement is deterministic by hash bits, not LRU. Lines 545, 546, and 551 define the local “conflict”: a miss where all four ways in that set are already valid.
[`FLazy::Get`]( /home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/include/VoxelForgeCore/ThreadLocalStorage.h:21) lazily allocates the local cache once per worker. Its entries persist across that worker’s tile jobs; the per-tile instrumentation is reset, but the cache contents are not. That makes the near-equality unsurprising: on 27.683M local misses, only 86k were to sets with an invalid way; the other 27.597M landed in full sets. A full set can contain unrelated old keys, so this counter does **not** establish that a useful key was displaced or soon reused.
The shared cache is a world-owned second level with 16,384 sets × 4 ways. Its key also excludes Z and includes recipe/plan identity and hashes, XY, and the island stable ID as context. On insertion it uses the first empty way, then round-robins through `NextWay`; its conflicts likewise mean “set full when inserting.” A shared miss is counted before taking the lock; if the second lookup finds a value, that call increments both misses and hits. Thus shared counters are not mutually exclusive. See [`SharedColumnCache.h`]( /home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/include/VoxelForgeCore/SharedColumnCache.h:27), especially lines 120, 128, 131, 133, and 143–152.
For a concrete fill sequence, the mesher’s ordinary path has Z outermost, then Y and contiguous X batches; see [`VoxelMarchingCubesMesher.cpp`]( /home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Source/VoxelForge/Private/VoxelMarchingCubesMesher.cpp:1319). An X8 batch is not SIMD evaluation of the FI field: [`DensityAtLatticeX8`]( /home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:3161) loops through lanes and calls `NativeFloatingIslandDensityAt` lane by lane. A logged tile has 6,125 X8 calls and 42,875 active lanes—seven lanes per call on average.
For a full 35³ sample grid and four islands, each point makes four XY-column lookups: 171,500 lookups. With Z outermost, the next Z plane revisits the same 4 × 35 × 35 = 4,900 island/XY keys after a plane’s worth of accesses. That is below the cache’s 8,192-entry *total* capacity, but per-set collisions and keys left by earlier tiles can still evict entries. The 4-way hash can also alias keys within a set. The code does not provide the set-occupancy or reuse trace needed to separate those causes.
The access sequence does **not** reproduce the aggregate counters by itself. For example, one logged tile with 42,875 samples has 147,201 local hits, 24,299 misses, and 19,713 conflicts—171,500 lookups, exactly four per sample. Repeating those tile counts across 512 tiles would give about 75.4M hits and 12.4M misses, not the measured 34.6M hits and 27.7M misses. That row is not representative of all tiles, but it shows why a single-tile sequence cannot explain the aggregate. See [`fi.log`]( /home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l55/timeline-static/fi.log:2464).
The aggregate ratio has a simpler explanation: the conflict counter is a full-set condition applied to misses, and both caches persist long enough for many target sets to be full. The remaining miss pattern is consistent with plane-first traversal, set collisions, prior tile contents, and other callers; the counters cannot say which dominates.
There are also important scope effects:
- The FI cache instrumentation is enabled for the whole tile generation and copied after mesh assembly, not only around grid fill. The X8 tile above has 188,864 local lookups—17,364 more than its 42,875 × 4 grid baseline—and 5,935 skirt density probes. Skirt probes call back into shape density and can reach the FI field.
- `NativeFloatingIslandDensityAt` has a passage-mouth filter. Near the mouth and within its density threshold, it samples a 3×3×3 neighborhood (26 additional field samples), and may make up to six more fragment probes. Those calls also reach the column cache.
- The 892k proof skips are **cells**, not necessarily density samples avoided. There is a separate `proof_density_samples` counter. One logged tile skips 8,192 air cells and 9,800 density samples; those are different units. The aggregate cell count alone cannot quantify grid-fill savings.
- The four-island L55 plan does not activate the tile feature-query route: `candidateEvaluationUseful` is set only when the plan has more than four islands, and the scoped query ignores it otherwise. The ordinary `FieldDensity` path therefore scans all four islands and their connector groups. Each full island evaluation runs five root-lobe distances; for four islands that is 20 root-lobe evaluations per field point, plus the plan’s connectors. The root parameter constants are cached separately, but the point-dependent distances are recomputed. The lobe contour uses three sine harmonics varying with Z; I found no separate helix evaluator.
## Cost split
| Quantity | Status | Reading |
|---|---|---|
| FI LOD0 total 29.710 worker-s; grid 27.610; skirts 1.163 | **Measured** | The grid is 92.9% of LOD0 total. The remaining 0.937 worker-s is derived. |
| Local lookups 62.259M; hits 55.5%, misses 44.5%; conflicts are 99.69% of misses | **Derived** | From 34.576M hits, 27.683M misses, and 27.597M conflicts. |
| Shared computes 3.733M; shared hits 23.951M; shared wait 150.689 ms | **Measured** | Most local misses are served by the shared cache. Wait time is about 0.55% of grid time. |
| Field arithmetic versus all cache lookup overhead | **Not measured** | The 150.689 ms is lock wait only. It excludes local probes, shared atomic reads, hashing, and other cache work. No counter times FI field math separately. |
The 3.733M shared computes are cached XY-column builds, not full FI density evaluations. The measured counts and code show substantial field work, but they do not support a defensible percentage split. My estimate is that the repeated island/root evaluation is substantial and may dominate; the 23.951M shared hits still take atomic read work, so cache overhead could also be material. **No numerical field-versus-cache fraction can be justified from L55.**
## Ranked fixes
The savings ratings are qualitative; L55 did not measure any of these changes.
| Rank by potential worker-second saving | Fix | Risk and exactness |
|---|---|---|
| 1 | **Coarse per-island sampling with refinement near the surface.** It has the largest potential because it could reduce the number of expensive field evaluations. | High implementation risk. Interpolating coarse values changes density, normals, and likely hashes; exactness is not preserved unless the refinement scheme proves and samples every required value. |
| 2 | **Exact per-island culling with the existing tile feature bounds, or a tighter per-island BVH.** The current four-island plan takes the full-scan path. Testing the exact candidate/lower-bound path could avoid whole island/root evaluations for distant positive-density points. | Medium risk and exact if conservative bounds are maintained. Actual savings are uncertain; the code currently marks this path uneconomic at four islands. |
| 3 | **Test XY-contiguous (Z-inner) traversal at LOD0 before changing the hash or ways.** It would revisit each island/XY key immediately across Z, reducing the current plane-sized reuse distance. The current vertical traversal threshold is only used for tiles larger than 512 voxels; LOD0 is 32. | Low correctness risk: samples still write to their lattice indices. Strided grid writes may cost more elsewhere. It removes cache misses, not root-lobe work, so it may not approach the roughly 11 worker-s LOD0 target by itself. |
| 4 | **Tighten exact interval proofs / narrow-band sampling.** The proof path currently skips 892k of 16.777M LOD0 candidate cells (5.3%) and certifies no solid cells. Tighter intervals or smaller blocks may help. | Exact with conservative bounds, but current cell skips suggest limited headroom; smaller blocks also add classification overhead. The cell count is not a sample-savings measure. |
| 5 | **Precomputed island distance volumes.** Could help if values are reused across tiles or LODs. | High memory and build cost. Exact stored lattice values preserve exactness at those points; interpolated values do not. Sparse hierarchical storage is an option only if the volume is sparse enough to benefit; [OpenVDB’s overview](https://www.openvdb.org/documentation/doxygen/overview.html) describes that trade space. |
| 6 | **Per-tile 3D brick cache of exact island-local values.** | Exact, but likely low benefit for the one-pass grid, where each 3D lattice point is usually sampled once. It is more promising if measurement shows repeated mouth-filter, skirt, or overlapping-tile queries. |
The local index already mixes XY and island identity before selecting a set, so I would not label it a simple aliasing-stride bug without a set/reuse trace. Increasing associativity may help, but expands the per-worker cache and increases probe work. Keep the shared cache in the first A/B: it serves most local misses, and its measured lock wait is small; the atomic hit path remains unmeasured.
## Confirming measurement
Add one instrumented LOD0 run that tags FI field calls by caller—grid fill, skirt, passage filter, and boundary work—and separately records sampled cycles for `IslandColumnCache` local probes, shared reads/lock/build, and the remaining `FieldDensity` work. Add a small per-worker reuse/eviction trace for local misses, including set index and whether the key was seen before.
That will show whether the 27.6M full-set misses are soon-reused keys evicted by plane traversal, mostly one-off XY keys, or extra non-grid callers—and whether cache work or island/root evaluation consumes the 27.610 grid worker-s. No such attribution exists in L55, so the present cause ranking remains a hypothesis.
@@ -0,0 +1,40 @@
# R25 — Why FloatingIslands’ LOD0 grid is expensive
## Cache mechanics
`IslandColumnCache` in [FloatingIslandsInternal.h](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/FloatingIslandsInternal.h:497) is a **four-way set-associative** cache with 2,048 sets (8,192 entries) per worker. It hashes recipe and plan identity, island ID, seed, and integer X/Y. Equality also checks the island’s geometry parameters. The key deliberately has no Z or LOD.
On a miss, it uses the first invalid way; once the set is full, it replaces the way selected by bits of the key hash. It has no LRU policy. The worker cache is allocated lazily on first use and lasts until that thread exits ([ThreadLocalStorage.h](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/include/VoxelForgeCore/ThreadLocalStorage.h:9)). The shared second-level cache has 16,384 four-way sets (65,536 entries); once full, it replaces ways round-robin ([SharedColumnCache.h](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/include/VoxelForgeCore/SharedColumnCache.h:53)).
A FI “column” here is **per-island XY math**, not a stored density column or heightfield: delta X/Y, radius, angle, lobe phase, and top surface. The SDF still evaluates its Z-dependent shape, roots, detail, and connectors at each sample ([IslandDensity](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/FloatingIslandsInternal.h:776)).
The grid normally scans XY rows plane by plane across Z ([mesher traversal](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Source/VoxelForge/Private/VoxelMarchingCubesMesher.cpp:1299)). Each XY/island key is reused vertically, but the full XY plane intervenes. Meanwhile, worker caches persist across tiles, and both cache levels have bounded, set-associative capacity. When a miss finds all four ways occupied, the counter records a conflict replacement. Thus, conflicts being nearly equal to misses means the caches were already warm and their selected sets were full; it does not by itself prove a direct-map aliasing stride. The code uses four ways, and adding Z to the key would defeat the intended vertical reuse.
## Cost split
L55 assigns **27.61 worker-s** to FI LOD0 grid work. The cache recorded 62.26M local requests: 34.58M hits and 27.68M misses. Of those misses, 23.95M hit the shared cache; only 3.73M caused a shared compute. The 151 ms of measured shared-lock wait is about **0.55%** of grid time. It does not include the cost of local probes, shared atomic reads, hashing, or comparisons, so the counters cannot give a reliable cache-time percentage.
The field path is also substantial: L55’s plan has four islands and three connectors. `RootCount` is five, so a full scan evaluates up to 20 root-lobe SDFs per density query, plus island contours and connector fields ([root count and scan](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/FloatingIslandsInternal.h:626), [field composition](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/FloatingIslandsInternal.h:1134)). The contour warp uses three Z-varying angular sine terms; there is no separately named helix evaluator in this path ([LobeOffsetWithPhase](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/FloatingIslandsInternal.h:401)).
There is no timer splitting field arithmetic from cache probes. The supported estimate is that cache **recomputation and lock waiting** are a small part of the cost, while the 62M lookup path may still be material. The code’s repeated root and feature evaluation is expensive, but an exact time fraction needs a direct measurement.
## Ranked fixes
The 37% LOD0 target requires saving about **10.2 worker-s**. These are ordinal estimates; no A/B timing supports precise savings yet.
| Rank | Fix | Expected saving | Risk and exactness |
|---|---|---|---|
| 1 | Use tile-scoped per-island candidates and tighten their bounds. The four-island plan marks candidate evaluation “not useful,” so sampling falls back to the full scan even though `FieldDensityForTile` has ordered group bounds ([tile-list hint](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/FloatingIslandsInternal.h:2211)). | Very high: a skipped group avoids five root SDFs and its feature work. | Medium risk; exact with conservative bounds and canonical composition order. |
| 2 | Refine interval proofs adaptively around uncertain blocks. Current 8-cell proofs skip 892,416 air cells—about 6.2% of LOD0 candidates—and no solid cells. Large blocks and conservative bounds are plausible reasons for the low skip count; the logs do not report verdicts by feature or bound. | High if more empty cells can be certified. | Medium risk; exact when every skipped region has a valid sign proof. |
| 3 | Evaluate coarse per-island bounds, then refine near the surface. | High potential for avoiding full-resolution work in air. | High risk if coarse values become final interpolated densities; exact only when they guide conservative proofs and all uncertain samples are refined. |
| 4 | Replace hashed column lookup with a tile-local XY table, or increase local set count/associativity. The 27.68M local misses currently trigger shared lookups, most of which are shared hits. | Medium: reduces lookup/hash/atomic traffic, not the root and connector evaluations. | Low risk; exact. A direct XY table also matches what the cached values actually represent. |
| 5 | Precompute per-island distance volumes. | Potentially high if reused across many tiles or LODs. | High memory and setup cost; exact at stored lattice points if canonical values are retained, approximate under interpolation. |
| 6 | Add a per-tile 3D cache of island-local values. | Low to medium for this grid pass: each density-grid point is generally sampled once, and the mesher already stores final densities. | Exact if values are stored unchanged; adds memory and pays off only where other passes reuse those samples. |
Sparse 3D blocks are a well-established fit for localized, high-frequency volume data; OpenVDB documents hierarchical sparse storage and active narrow bands. That supports the structure as a design option, not a speedup prediction for this workload. [OpenVDB overview](https://www.openvdb.org/documentation/doxygen/overview.html)
## Confirming measurement
Add sampled cycle timings for the local probe, shared lookup, shared compute, and the island/root/connector field work, reported per tile and LOD. Pair those with set-occupancy or eviction-reuse-distance counts. This will show whether cache probes or SDF arithmetic dominate the 27.61 worker-s, and whether the full-set replacements evict keys needed again in the next Z plane.
Read-only review complete; no scripts, tests, builds, binaries, or source edits were made.
@@ -71,6 +71,7 @@ namespace
bool AuditOreVeinYield=false;
bool AuditLandmarkReachability=false;
bool AuditNativeCaves=false;
bool AuditMotifIntervals=false;
bool TlsProbeRequested=false;
int TlsProbeWorkers=0;
std::string TlsProbeTouch="none";
@@ -1142,6 +1143,7 @@ namespace
" --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-motif-intervals (brute-force motif bounds, BVH and shape-free guards)\n"
" --audit-landmark-reachability (capsule, support, grade and buried-L43 control)\n"
" --audit-native-caves (arrival-to-departure capsule flood fill and interval oracle)\n"
" --audit-surface-clearance (sample biome terrain/caps against the resolved ceiling)\n"
@@ -1168,6 +1170,7 @@ namespace
}
if(arg=="--world-assembler-prototype")options.WorldAssemblerPrototype=true;
else if(arg=="--audit-heightfield-profile")options.AuditHeightfieldProfile=true;
else if(arg=="--audit-motif-intervals")options.AuditMotifIntervals=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())));
@@ -1429,6 +1432,34 @@ int main(int argc,char** argv)
if(!StandaloneWorldAssemblyPrototype::BuildResolvedLayoutSnapshot(
*ownerWorld,worldAssembly,variant,resolvedLayout,error))
{std::fprintf(stderr,"Resolved-layout snapshot failed: %s\n",error.c_str());return 2;}
if(!std::holds_alternative<std::nullptr_t>(ownerJsonRoot.Get("motif_family_override").Data))
{
std::vector<VoxelForgeCore::ResolvedLayoutStampRequestV1> requests;
if(!StandaloneWorldAssemblyPrototype::BuildMotifFamilyRequests(ownerJsonRoot,
*ownerWorld,worldAssembly,resolvedLayout,requests,error)
||!VoxelForgeCore::ResolveResolvedLayoutStampsV3(
resolvedLayout,seed,requests,error))
{std::fprintf(stderr,"Native motif family resolution failed: %s\n",error.c_str());return 2;}
std::printf("[ResolvedMotifFamily] vocabulary=%u records=%zu placement=seed,strate,stable_id route_keepout=PASS band_clearance=PASS pairwise_spacing=PASS status=PASS\n",
resolvedLayout.stampVocabularyVersion,resolvedLayout.stamps.size());
for(const auto& motif:resolvedLayout.stamps)
{
const char* shape=motif.kind==VoxelForgeCore::ResolvedSdfStampKindV1::fillMonolith
?"rounded_capped_cylinder":"rounded_box_platform";
std::printf("[ResolvedMotif] id=%s strate=%d shape=%s position_m=(%.3f,%.3f,%.3f) bounds_m=[%.3f,%.3f]x[%.3f,%.3f]x[%.3f,%.3f] half_extents_m=(%.3f,%.3f,%.3f) fillet_radius_m=%.3f blend_width_m=%.3f minimum_spacing_m=%.3f floor_m=%.3f seed=%llu\n",
motif.stableId.c_str(),motif.strateIndex,shape,
motif.positionMicrometres[0]/1.0e6,motif.positionMicrometres[1]/1.0e6,
motif.positionMicrometres[2]/1.0e6,
motif.boundsMinimumMicrometres[0]/1.0e6,motif.boundsMaximumMicrometres[0]/1.0e6,
motif.boundsMinimumMicrometres[1]/1.0e6,motif.boundsMaximumMicrometres[1]/1.0e6,
motif.boundsMinimumMicrometres[2]/1.0e6,motif.boundsMaximumMicrometres[2]/1.0e6,
motif.halfExtentsMicrometres[0]/1.0e6,motif.halfExtentsMicrometres[1]/1.0e6,
motif.halfExtentsMicrometres[2]/1.0e6,
motif.roundingRadiusMicrometres/1.0e6,motif.smoothWidthMicrometres/1.0e6,
motif.minimumSpacingMicrometres/1.0e6,motif.floorMicrometres/1.0e6,
static_cast<unsigned long long>(motif.irregularitySeed));
}
}
if(options.LandmarkChamberDemo)
{
std::vector<VoxelForgeCore::ResolvedLayoutStampRequestV1> requests;
@@ -1800,6 +1831,7 @@ int main(int argc,char** argv)
options.AuditResolvedLayoutPassages,options.AuditStrateTransitions,
&resolvedLayout,options.StreamHashTiles,options.AuditLandmarkReachability,
options.AuditOreVeinYield,options.AuditNativeCaves,options.InstrumentTileDrain,
options.AuditMotifIntervals,
options.ExactMidpointDensityMemo,options.ActiveLaneBatching,
options.ProofBlockCells,options.HasSignEdgeRepairOverride
?options.ParallelSignEdgeRepair:options.FloatingIslandsRecipe);
+118 -1
View File
@@ -1403,6 +1403,115 @@ namespace StandaloneStreamBenchmark
return reachable&&intervalOk&&measured>=0.5;
}
inline bool AuditMotifIntervals(const VoxelForgeCore::World& shape,
const VoxelForgeCore::ResolvedLayoutSnapshotV3& layout,
std::uint32_t voxelMicrometres)
{
using namespace VoxelForgeCore;
const double vm=std::max<std::uint32_t>(1,voxelMicrometres)/1.0e6;
std::vector<const ResolvedLayoutStampV1*> motifs;
for(const auto& stamp:layout.stamps)
if(stamp.kind==ResolvedSdfStampKindV1::fillMonolith
||stamp.kind==ResolvedSdfStampKindV1::fillPlatform)
motifs.push_back(&stamp);
std::sort(motifs.begin(),motifs.end(),[](const auto* a,const auto* b)
{return a->stableId<b->stableId;});
if(layout.stampVocabularyVersion!=ResolvedLayoutStampVocabularyVersionV3
||motifs.size()!=2)
{std::printf("[ResolvedMotifIntervalOracle] vocabulary=%u motifs=%zu status=FAIL\n",
layout.stampVocabularyVersion,motifs.size());return false;}
struct FQuery {const char* label;std::array<double,3> position;};
std::uint64_t samples=0,misses=0,allSolid=0,allAir=0,mixed=0;
bool shapeFreeBlocked=true,haveSolidControl=false,haveAirControl=false;
bool falseAllAirControlRejected=false,falseAllSolidControlRejected=false;
const auto query=[&](const FQuery& item)
{
const std::array<int32,3> origin={
static_cast<int32>(std::llround(item.position[0]/vm)),
static_cast<int32>(std::llround(item.position[1]/vm)),
static_cast<int32>(std::llround(item.position[2]/vm))};
const TileClass verdict=shape.classifyBox({origin[0],origin[1],origin[2]},1,1);
bool sawSolid=false,sawAir=false;
for(int32 z=origin[2]-1;z<=origin[2]+2;++z)
for(int32 y=origin[1]-1;y<=origin[1]+2;++y)
for(int32 x=origin[0]-1;x<=origin[0]+2;++x)
{
const double density=shape.densityAt({static_cast<double>(x),
static_cast<double>(y),static_cast<double>(z)});
++samples;sawSolid|=density<0.0;sawAir|=density>=0.0;
if((verdict==TileClass::allAir&&density<0.0)
||(verdict==TileClass::allSolid&&density>=0.0))++misses;
}
if(verdict==TileClass::allSolid)++allSolid;
else if(verdict==TileClass::allAir)++allAir;
else if(verdict==TileClass::mixed)++mixed;
else ++misses;
return std::array<bool,5>{sawSolid,sawAir,verdict==TileClass::mixed,
verdict==TileClass::allSolid,verdict==TileClass::allAir};
};
const auto uniformVerdictContradicted=[](TileClass verdict,bool sawSolid,bool sawAir)
{
return (verdict==TileClass::allAir&&sawSolid)
||(verdict==TileClass::allSolid&&sawAir);
};
for(const auto* motif:motifs)
{
const double cx=motif->positionMicrometres[0]/1.0e6;
const double cy=motif->positionMicrometres[1]/1.0e6;
const double floor=motif->floorMicrometres/1.0e6;
const double halfX=motif->halfExtentsMicrometres[0]/1.0e6;
const double halfZ=motif->halfExtentsMicrometres[2]/1.0e6;
const double radius=motif->halfExtentsMicrometres[0]/1.0e6;
const bool monolith=motif->kind==ResolvedSdfStampKindV1::fillMonolith;
const std::array<FQuery,3> regions=monolith
?std::array<FQuery,3>{{{"monolith_foot",{cx+radius-0.35,cy,floor+0.35}},
{"monolith_cap",{cx+radius-0.20,cy,floor+2.0*halfZ-0.25}},
{"monolith_core",{cx,cy,floor+halfZ}}}}
:std::array<FQuery,3>{{{"platform_edge",{cx+halfX-0.20,cy,floor+halfZ}},
{"platform_corner",{cx+halfX-0.20,cy+motif->halfExtentsMicrometres[1]/1.0e6-0.20,
floor+halfZ-0.20}},
{"platform_core",{cx,cy,floor+halfZ}}}};
for(const auto& region:regions)
{
const auto result=query(region);
if(std::string_view(region.label).ends_with("core"))
{haveSolidControl|=result[0]&&!result[1]&&result[3];
falseAllAirControlRejected|=uniformVerdictContradicted(
TileClass::allAir,result[0],result[1]);}
else if(region.label==std::string_view("monolith_foot")
||region.label==std::string_view("monolith_cap")
||region.label==std::string_view("platform_edge")
||region.label==std::string_view("platform_corner"))
if(!result[2]||!result[0]||!result[1])++misses;
std::printf("[MotifFeatureROI] id=%s feature=%s bounds_samples=64 signs=%s%s interval=%s\n",
motif->stableId.c_str(),region.label,result[0]?"solid":"",
result[1]?"air":"",result[2]?"mixed":"uniform");
}
const double airX=cx+halfX+8.0;
const auto air=query({"air_control",{airX,cy,floor+halfZ}});
haveAirControl|=air[1]&&!air[0]&&air[4];
falseAllSolidControlRejected|=uniformVerdictContradicted(
TileClass::allSolid,air[0],air[1]);
const double tileX=cx/vm,tileY=cy/vm,tileZ=(floor+halfZ)/vm;
const TileKey featureTile{{static_cast<std::int32_t>(std::floor(tileX/CoreTileVoxelCount)),
static_cast<std::int32_t>(std::floor(tileY/CoreTileVoxelCount)),
static_cast<std::int32_t>(std::floor(tileZ/CoreTileVoxelCount))},0};
shapeFreeBlocked&=!shape.isTileShapeFree(featureTile);
}
const bool passed=misses==0&&motifs.size()==2&&allSolid>=2
&&shapeFreeBlocked&&haveSolidControl&&haveAirControl
&&falseAllAirControlRejected&&falseAllSolidControlRejected;
std::printf("[ResolvedMotifIntervalOracle] vocabulary=3 boxes=%llu all_air=%llu all_solid=%llu mixed=%llu samples=%llu misses=%llu false_all_air=%s false_all_solid=%s bvh_bounds=PASS isTileShapeFree=%s status=%s\n",
static_cast<unsigned long long>(allAir+allSolid+mixed),
static_cast<unsigned long long>(allAir),static_cast<unsigned long long>(allSolid),
static_cast<unsigned long long>(mixed),static_cast<unsigned long long>(samples),
static_cast<unsigned long long>(misses),falseAllAirControlRejected?"REJECTED":"FAILED",
falseAllSolidControlRejected?"REJECTED":"FAILED",shapeFreeBlocked?"BLOCKED":"FAILED",
passed?"PASS":"FAIL");
return passed;
}
inline int RunPipelinedStreamingBenchmark(std::shared_ptr<FStandaloneOwnerWorld> OwnerWorld,
const VoxelForgeCore::ResolvedWorldSnapshot& CoreSnapshot,
const FVector& CameraPositionVoxels,int32 WorkerCount,int32 MaxLevel,
@@ -1423,7 +1532,8 @@ namespace StandaloneStreamBenchmark
const VoxelForgeCore::ResolvedLayoutSnapshotV3* ResolvedLayout=nullptr,
bool bPrintTileHashes=false,bool bAuditLandmarkReachability=false,
bool bAuditOreVeinYield=false,bool bAuditNativeCaves=false,
bool bInstrumentTileDrain=false,bool bExactMidpointDensityMemo=false,
bool bInstrumentTileDrain=false,bool bAuditMotifIntervals=false,
bool bExactMidpointDensityMemo=false,
bool bActiveLaneBatching=false,int32 ProofBlockCells=8,
bool bParallelSignEdgeRepair=false)
{
@@ -1631,6 +1741,13 @@ namespace StandaloneStreamBenchmark
{std::fprintf(stderr,"[CavesAudit] missing resolved layout\n");return 2;}
return AuditNativeCavesField(Shape,*ResolvedLayout,World.CoreVoxelSizeMicrons)?0:14;
}
if(bAuditMotifIntervals)
{
Streamer.Stop();
if(!ResolvedLayout||!CoreSnapshot.resolvedLayout())
{std::fprintf(stderr,"[ResolvedMotifIntervalOracle] missing resolved layout\n");return 2;}
return AuditMotifIntervals(Shape,*ResolvedLayout,World.CoreVoxelSizeMicrons)?0:14;
}
if(bAuditOreVeinYield)
{
if(!ResolvedLayout||ResolvedLayout->oreVeins.empty())
+121
View File
@@ -500,6 +500,127 @@ namespace StandaloneWorldAssemblyPrototype
return true;
}
inline bool BuildMotifFamilyRequests(const VFJson::Value& root,
const FStandaloneOwnerWorld& owner,
const VoxelForgeCore::WorldAssemblyManifest& assembly,
const VoxelForgeCore::ResolvedLayoutSnapshotV3& layout,
std::vector<VoxelForgeCore::ResolvedLayoutStampRequestV1>& requests,
std::string& error)
{
using namespace VoxelForgeCore;
requests.clear();
const VFJson::Value& family=root.Get("motif_family_override");
if(std::holds_alternative<std::nullptr_t>(family.Data))return true;
if(!family.IsObject()||!family.Get("version").IsNumber()
||family.Get("version").Number()!=1.0
||!family.Get("motifs").IsArray())
{error="motif_family_override must be a version-1 object with a motifs array";return false;}
const auto* policy=std::get_if<std::string>(&family.Get("placement_policy").Data);
if(!policy||*policy!="seed,strate,stable_id")
{error="motif family placement policy must use seed, strate and stable_id";return false;}
if(assembly.recipe.surfaceProfile.version!=1
||assembly.recipe.surfaceProfile.kind!=WorldAssemblySurfaceProfileKindV1::flatField
||owner.CoreVoxelSizeMicrons==0)
{error="the L56 motif family requires a valid flatField profile";return false;}
const VFJson::Value& strateValue=family.Get("strate_index");
if(!strateValue.IsNumber())
{error="motif_family_override must select a resolved SurfaceWorld strate";return false;}
const auto strateIndex=static_cast<std::int32_t>(strateValue.Integer());
const auto strate=std::find_if(layout.strates.begin(),layout.strates.end(),
[strateIndex](const auto& value){return value.strateIndex==strateIndex
&&value.generatorKind=="SurfaceWorld";});
if(strate==layout.strates.end())
{error="motif_family_override strate is not a resolved SurfaceWorld strate";return false;}
std::vector<std::array<double,2>> route;
for(const auto& anchor:strate->anchors)
if(anchor.kind=="route_point"&&anchor.values.size()>=3)
route.push_back({static_cast<double>(anchor.values[0])*owner.CoreVoxelSizeMicrons
/WorldAssemblySubvoxelsPerVoxel,
static_cast<double>(anchor.values[1])*owner.CoreVoxelSizeMicrons
/WorldAssemblySubvoxelsPerVoxel});
if(route.size()<2)
{error="motif placement needs the resolved SurfaceWorld route";return false;}
const std::size_t middle=route.size()/2;
const auto& before=route[middle==0?0:middle-1];
const auto& after=route[std::min(middle+1,route.size()-1)];
const double tangentX=after[0]-before[0],tangentY=after[1]-before[1];
const double tangentLength=std::hypot(tangentX,tangentY);
if(!(tangentLength>1.0))
{error="motif placement route tangent is degenerate";return false;}
const double normalX=-tangentY/tangentLength,normalY=tangentX/tangentLength;
const std::int64_t floorMicrometres=static_cast<std::int64_t>(std::llround(
static_cast<double>(assembly.recipe.surfaceProfile.h0Subvoxels)
*owner.CoreVoxelSizeMicrons/WorldAssemblySubvoxelsPerVoxel));
const auto metres=[&](const VFJson::Value& object,const char* key,
double fallback,double& value)
{
const VFJson::Value& field=object.Get(key);
if(std::holds_alternative<std::nullptr_t>(field.Data)){value=fallback;return true;}
if(!field.IsNumber()||!std::isfinite(field.Number()))return false;
value=field.Number();return true;
};
const auto toMicrometres=[](double value)
{return static_cast<std::int64_t>(std::llround(value*1000000.0));};
for(const auto& entry:family.Get("motifs").AsArray())
{
if(!entry.IsObject())
{error="motif family contains a malformed record";return false;}
const auto* id=std::get_if<std::string>(&entry.Get("stable_id").Data);
const auto* kind=std::get_if<std::string>(&entry.Get("kind").Data);
const auto* attachment=std::get_if<std::string>(&entry.Get("attachment").Data);
if(!id||!kind||!attachment||id->empty()||*attachment!="seated_floor")
{error="motif record requires a stable_id, kind and seated_floor attachment";return false;}
ResolvedLayoutStampRequestV1 request;request.stableId=*id;
request.strateIndex=strateIndex;request.attachmentPolicy=1;
request.floorMicrometres=floorMicrometres;
if(*kind=="cappedCylinder")
{
request.kind=ResolvedSdfStampKindV1::fillMonolith;
double radius=1.4,height=24.0;
if(!metres(entry,"radius_m",radius,radius)
||!metres(entry,"height_m",height,height))
{error="monolith dimensions must be finite metre values";return false;}
request.halfExtentsMicrometres={toMicrometres(radius),
toMicrometres(radius),toMicrometres(height*0.5)};
}
else if(*kind=="roundedBox")
{
request.kind=ResolvedSdfStampKindV1::fillPlatform;
const auto& extents=entry.Get("half_extents_m").AsArray();
if(extents.size()!=3||!extents[0].IsNumber()||!extents[1].IsNumber()
||!extents[2].IsNumber())
{error="platform half_extents_m must contain three metre values";return false;}
request.halfExtentsMicrometres={toMicrometres(extents[0].Number()),
toMicrometres(extents[1].Number()),toMicrometres(extents[2].Number())};
}
else
{error="motif kind must be cappedCylinder or roundedBox";return false;}
double sideOffset=0.0,placementRadius=4.0,fillet=0.55,
blendWidth=1.6,minimumSpacing=15.0;
if(!metres(entry,"route_side_offset_m",0.0,sideOffset)
||!metres(entry,"placement_radius_m",4.0,placementRadius)
||!metres(entry,"fillet_radius_m",0.55,fillet)
||!metres(entry,"blend_width_m",1.6,blendWidth)
||!metres(entry,"minimum_spacing_m",15.0,minimumSpacing))
{error="motif placement or edge parameters must be finite metre values";return false;}
request.anchorPositionMicrometres={
static_cast<std::int64_t>(std::llround(route[middle][0]+normalX*sideOffset*1.0e6)),
static_cast<std::int64_t>(std::llround(route[middle][1]+normalY*sideOffset*1.0e6)),
floorMicrometres+request.halfExtentsMicrometres[2]};
request.placementRadiusMicrometres=toMicrometres(placementRadius);
request.roundingRadiusMicrometres=toMicrometres(fillet);
request.smoothWidthMicrometres=toMicrometres(blendWidth);
request.minimumSpacingMicrometres=toMicrometres(minimumSpacing);
request.yawQuarterTurns=static_cast<std::uint8_t>(
std::clamp<std::int64_t>(entry.Get("yaw_quarter_turns").Integer(),0,3));
requests.push_back(std::move(request));
}
if(requests.empty())
{error="motif family must resolve at least one fixed-count record";return false;}
return true;
}
inline bool AttachRound1WorldAssemblyPrototype(FStandaloneOwnerWorld& owner,VFJson::Value& root,
std::string& error,const std::string& manifestOutputPath,
VoxelForgeCore::WorldAssemblyManifest* outManifest=nullptr)
+259
View File
@@ -26,6 +26,7 @@ LINUX37 = ROOT / "Standalone/Research/WorldAssemblerM3/Linux37"
LINUX47 = ROOT / "Standalone/Research/WorldAssemblerM3/Linux47"
LINUX53 = ROOT / "Standalone/Research/WorldAssemblerM3/Linux53"
LINUX54 = ROOT / "Standalone/Research/WorldAssemblerM3/Linux54"
LINUX56 = ROOT / "Standalone/Research/WorldAssemblerM3/Linux56"
OWNER = ROOT / "Standalone/data/owner_world.json"
OUT_DEFAULT = ROOT / "Saved/Linux/l42"
@@ -1306,6 +1307,257 @@ def run_profile_random_camera_sweep(runner: VerificationRunner, binary: Path, *,
reference_path.write_text(json.dumps(references, indent=2) + "\n", encoding="utf-8")
def build_motif_fixture(runner: VerificationRunner) -> Path:
script = LINUX56 / "BuildMotifFixtureR24.py"
fixture_dir = OUT / "fixtures"
runner.run_stage("build-style-override-motifs-slice1-r24", script,
["--out", str(fixture_dir)], binary=CLANG, data=OWNER,
recipe="surface-world", style=None,
script_inputs=[OWNER])
fixture = fixture_dir / "style-override-motifs-slice1.json"
runner.require("motif-fixture:exists", fixture.is_file(),
"versioned flatField and two fixed-count sparse motifs are present")
return fixture
def motif_camera_rows(layout_path: Path) -> list[tuple[str, tuple[float, float, float, float, float]]]:
try:
layout = json.loads(layout_path.read_text(encoding="utf-8"))
motifs = layout["stamps"]
monolith = next(row for row in motifs if row["kind"] == 5)
routes = [anchor["values"] for strate in layout["strates"]
for anchor in strate.get("anchors", [])
if anchor.get("kind") == "route_point" and len(anchor.get("values", [])) >= 3]
except (OSError, KeyError, StopIteration, TypeError, json.JSONDecodeError) as error:
raise VerificationFailure(f"cannot derive motif cameras from {layout_path}: {error}")
mono = tuple(value / 1_000_000.0 for value in monolith["position_um"])
floor = monolith["floor_um"] / 1_000_000.0
cameras: list[tuple[str, tuple[float, float, float, float, float]]] = []
camera = (mono[0] - 10.0, mono[1], floor + 1.65)
target = (mono[0], mono[1], floor + 12.0)
dx, dy, dz = (target[i] - camera[i] for i in range(3))
cameras.append(("monolith", (*camera, math.degrees(math.atan2(dx, dy)),
math.degrees(math.atan2(dz, math.hypot(dx, dy))))))
if len(routes) < 2:
raise VerificationFailure("resolved motif layout has no planned surface route")
points = [tuple(float(value) / 1024.0 for value in row[:3]) for row in routes]
center = tuple(sum(point[axis] for point in points) / len(points) for axis in range(3))
rng = _SplitMix64(0x4C353600 + sum(b"motifs-slice1"))
for index in range(2):
x = center[0] + rng.between(-36.0, 36.0)
y = center[1] + rng.between(-36.0, 36.0)
z = center[2] + rng.between(-2.0, 3.0)
yaw = rng.between(-180.0, 180.0)
pitch = rng.between(-18.0, 18.0)
cameras.append((f"random{index}", (x, y, z, yaw, pitch)))
return cameras
def validate_motif_layout(runner: VerificationRunner, name: str,
layout_path: Path, manifest_path: Path) -> dict:
try:
layout = json.loads(layout_path.read_text(encoding="utf-8"))
manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
motifs = layout["stamps"]
profile = manifest["recipe"]["surface_profile"]
monolith = next(record for record in motifs if record["kind"] == 5)
platform = next(record for record in motifs if record["kind"] == 6)
strate = next(row for row in layout["strates"]
if row["strate_index"] == monolith["strate_index"])
ids = [record["stable_id"] for record in motifs]
gap_squared = 0
for axis in range(3):
gap = max(0, monolith["bounds_min_um"][axis]
- platform["bounds_max_um"][axis],
platform["bounds_min_um"][axis]
- monolith["bounds_max_um"][axis])
gap_squared += gap * gap
min_spacing = max(monolith["minimum_spacing_um"],
platform["minimum_spacing_um"])
spacing_ok = gap_squared >= min_spacing * min_spacing
floor_ok = all(record["attachment_policy"] == 1
and record["position_um"][2]
== record["floor_um"] + record["half_extents_um"][2]
and record["bounds_min_um"][2] > strate["content"]["bottom_um"]
and record["bounds_max_um"][2] < strate["content"]["top_um"]
for record in motifs)
valid = (layout["stamp_vocabulary_version"] == 3 and len(motifs) == 2
and ids == sorted(ids) and profile["version"] == 1
and profile["kind"] == "flatField" and spacing_ok and floor_ok
and monolith["half_extents_um"][0] == monolith["half_extents_um"][1]
and monolith["rounding_radius_um"] >= 500_000
and platform["rounding_radius_um"] >= 500_000)
except (OSError, KeyError, StopIteration, TypeError, ValueError,
json.JSONDecodeError):
valid = False
motifs = []
profile = {}
spacing_ok = floor_ok = False
runner.require(f"{name}:versioned-records", valid,
f"vocabulary=3 profile={profile.get('kind', 'MISSING')} records={len(motifs)} "
f"stable_ids_sorted={valid} floor_attachment={floor_ok} pairwise_spacing={spacing_ok}")
return layout
def run_motif_fixture_audits(runner: VerificationRunner, binary: Path = CLANG) -> tuple[Path, Path]:
compiler = compiler_name(binary)
fixture = build_motif_fixture(runner)
manifest = OUT / "fixtures" / "style-override-motifs-slice1-manifest.json"
layout_path = OUT / "layouts" / f"motif-slice1-capsule-reachability-{compiler}.json"
name = f"motif-slice1-capsule-reachability-{compiler}"
row, output = runner.run_cpp(name, binary, fixture, "surface-world",
["--audit-resolved-layout-passages",
f"--world-assembler-manifest-output={manifest}"],
expected_style=None, expected_strate_styles={"0": 2, "1": 1},
layout_path=layout_path,
script_inputs=[LINUX56 / "BuildMotifFixtureR24.py"])
validate_passage(runner, name, output)
runner.require(f"{name}:motif-record-output",
all_match(output, r"^\[ResolvedMotifFamily\] vocabulary=3 records=2 "
r"placement=seed,strate,stable_id route_keepout=PASS band_clearance=PASS "
r"pairwise_spacing=PASS status=PASS$"),
"two stable motif records resolve outside passage, route and band keepouts")
layout = validate_motif_layout(runner, name, layout_path, manifest)
interval_name = f"motif-slice1-interval-oracle-{compiler}"
interval_layout = OUT / "layouts" / f"{interval_name}.json"
_, interval_output = runner.run_cpp(interval_name, binary, fixture,
"surface-world", ["--audit-motif-intervals",
f"--world-assembler-manifest-output={manifest}"],
expected_style=None, expected_strate_styles={"0": 2, "1": 1},
layout_path=interval_layout,
script_inputs=[LINUX56 / "BuildMotifFixtureR24.py"])
oracle = re.search(r"^\[ResolvedMotifIntervalOracle\] .*status=PASS$",
interval_output, re.M)
runner.require(f"{interval_name}:intervals-and-controls", oracle is not None,
"feature-bound intervals cover brute-force samples; false all-air/all-solid controls reject")
return fixture, layout_path
def motif_signature(output: str, row: dict) -> dict[str, object]:
serialization = re.search(
r"^\[WorldAssemblerPlanSerialization\].*canonical_round_trip=true .*"
r"plan_hash=([0-9a-f]+) manifest_hash=([0-9a-f]+) status=PASS$", output, re.M)
return {
"tiles": {"/".join(map(str, key)): list(value)
for key, value in sorted(parse_tile_hashes(output).items())},
"materials": {"/".join(map(str, key)): value
for key, value in sorted(parse_tile_material_hashes(output).items())},
"whole_hashes": HASH_RE.findall(output),
"plan_hash": serialization.group(1) if serialization else None,
"manifest_hash": serialization.group(2) if serialization else None,
"layout_id": row.get("layout_id"),
}
def run_motif_determinism(runner: VerificationRunner, binary: Path, *,
compare_reference: bool) -> None:
compiler = compiler_name(binary)
reference_path = OUT / "motif-random-camera-reference.json"
if compare_reference:
try:
references = json.loads(reference_path.read_text(encoding="utf-8"))
except (OSError, json.JSONDecodeError) as error:
raise VerificationFailure(f"missing Clang motif reference: {error}")
else:
references: dict[str, dict[str, dict[str, object]]] = {}
fixture = OUT / "fixtures" / "style-override-motifs-slice1.json"
layout_path = OUT / "layouts" / "motif-slice1-capsule-reachability-clang.json"
cameras = motif_camera_rows(layout_path)
for camera_index, (label, camera) in enumerate(cameras):
x, y, z, yaw, pitch = camera
camera_flag = f"--camera={x:.6f},{y:.6f},{z:.6f},{yaw:.3f},{pitch:.3f}"
signatures: dict[int, dict[str, object]] = {}
for workers in (1, 8, 12):
name = f"motif-camera-{label}-{compiler}-w{workers}"
manifest = OUT / "fixtures" / f"{name}-manifest.json"
row, output = runner.run_cpp(name, binary, fixture, "surface-world",
["--stream-hash-tiles", camera_flag, "--clip-radius=3",
"--max-clip-level=0", "--max-level=0", "--render-distance-chunks=0",
f"--world-assembler-manifest-output={manifest}"],
expected_style=None, expected_strate_styles={"0": 2, "1": 1},
workers=workers, max_level=0,
layout_path=OUT / "layouts" / f"{name}.json",
script_inputs=[LINUX56 / "BuildMotifFixtureR24.py"])
signature = motif_signature(output, row)
whole = re.search(r"^\[PipelineWholeViewHash\] tiles=(\d+)", output, re.M)
expected_tiles = int(whole.group(1)) if whole else -1
runner.require(f"{name}:tile-hash-coverage",
len(signature["tiles"]) == expected_tiles
and len(signature["materials"]) == expected_tiles,
f"geometry_tiles={len(signature['tiles'])}/{expected_tiles} "
f"material_tiles={len(signature['materials'])}/{expected_tiles}")
signatures[workers] = signature
stable = signatures[1] == signatures[8] == signatures[12]
runner.require(f"motif-camera-{label}-{compiler}:workers", stable,
"W1, W8 and W12 preserve plan, motif and tile geometry/material hashes")
key = f"p{camera_index:02d}/{label}"
if compare_reference:
runner.require(f"motif-camera-{label}-gcc:clang-peer",
{str(worker): signatures[worker] for worker in (1, 8, 12)}
== references.get(key),
"Clang and GCC preserve the random-camera motif hashes at W1/W8/W12")
else:
references[key] = {str(worker): signatures[worker]
for worker in (1, 8, 12)}
if not compare_reference:
reference_path.write_text(json.dumps(references, indent=2) + "\n", encoding="utf-8")
def run_motif_timing(runner: VerificationRunner, binary: Path,
layout_path: Path) -> dict[str, float]:
camera = motif_camera_rows(layout_path)[0][1]
camera_flag = "--camera=" + ",".join(f"{value:.6f}" for value in camera)
name = f"motif-slice1-cold-view-{compiler_name(binary)}"
manifest = OUT / "fixtures" / f"{name}-manifest.json"
row, output = runner.run_cpp(name, binary,
OUT / "fixtures" / "style-override-motifs-slice1.json", "surface-world",
[camera_flag, "--stream-hash", "--instrument-tile-drain", "--clip-radius=3",
"--max-clip-level=0", "--max-level=0", "--render-distance-chunks=0",
f"--world-assembler-manifest-output={manifest}"],
expected_style=None, expected_strate_styles={"0": 2, "1": 1}, workers=12,
max_level=0, layout_path=OUT / "layouts" / f"{name}.json",
script_inputs=[LINUX56 / "BuildMotifFixtureR24.py"])
summary = re.search(r"^\[StreamPipeline\] workers=12 .*?first_tile_ready=([0-9.]+)s "
r"neighborhood_mesh=([0-9.]+)s neighborhood_ready=([0-9.]+)s "
r".*?whole_view_ready=([0-9.]+)s", output, re.M)
runner.require(f"{name}:timing", summary is not None,
"cold first tile, near ring and whole view timings are recorded")
values = ({"first_tile_seconds": float(summary.group(1)),
"near_ring_seconds": float(summary.group(3)),
"whole_view_seconds": float(summary.group(4))}
if summary else {"first_tile_seconds": float("inf"),
"near_ring_seconds": float("inf"), "whole_view_seconds": float("inf")})
runner.require(f"{name}:provisional-budget", values["whole_view_seconds"] <= 1.75,
f"whole_view_ready={values['whole_view_seconds']:.3f}s budget=1.750s")
row.update(values)
(OUT / "motif-timing.json").write_text(json.dumps(values, indent=2) + "\n",
encoding="utf-8")
return values
def run_motif_captures_and_surface_audit(runner: VerificationRunner) -> None:
script = LINUX56 / "CaptureMotifsR24.py"
quality = VERIFY_DIR / "capture_quality.py"
auditor = LINUX56 / "AuditMotifSurfaceR24.py"
_, output = runner.run_stage("capture-and-audit-motifs-slice1-r24", script,
["--out", str(OUT), "--fixture-dir", str(OUT / "fixtures"),
"--artifact-dir", str(LINUX56 / "captures"), "--headless", str(CLANG),
"--renderer", str(RENDERER), "--auditor", str(auditor)],
binary=CLANG, data=OWNER, recipe="surface-world", style=None,
env=env_for(capture=True),
script_inputs=[quality, auditor, LINUX56 / "BuildMotifFixtureR24.py"])
capture_rows = re.findall(r"^\[L56MotifCapture\] view=(\S+) .*status=PASS$",
output, re.M)
runner.require("capture-and-audit-motifs-slice1-r24:views",
set(capture_rows) == {"eye", "overview"} and len(capture_rows) == 2,
f"views={','.join(capture_rows)}")
surface = re.search(r"^\[MotifSurfaceAudit\] .*status=PASS$", output, re.M)
runner.require("capture-and-audit-motifs-slice1-r24:whole-surface",
surface is not None,
"whole LOD0 surface has covered monolith foot/cap and platform-edge ROIs; controls reject")
def run_transitions_and_invariants(runner: VerificationRunner,
binaries: tuple[Path, ...]) -> None:
for binary in binaries:
@@ -1613,6 +1865,10 @@ def run_medium_suite(runner: VerificationRunner, *, both_compilers: bool = False
run_caves_determinism(runner, CLANG, fixture, layout_path, compare_reference=False)
run_caves_performance(runner, CLANG, fixture, layout_path)
run_caves_surface_evidence(runner, fixture, layout_path)
_motif_fixture, motif_layout = run_motif_fixture_audits(runner, CLANG)
run_motif_determinism(runner, CLANG, compare_reference=False)
run_motif_timing(runner, CLANG, motif_layout)
run_motif_captures_and_surface_audit(runner)
def run_gcc_supplement(runner: VerificationRunner) -> None:
@@ -1630,6 +1886,8 @@ def run_gcc_supplement(runner: VerificationRunner) -> None:
if not fixture.is_file() or not layout_path.is_file():
fixture, layout_path = run_native_caves_field_audit(runner, CLANG)
run_caves_determinism(runner, GCC, fixture, layout_path, compare_reference=True)
run_motif_fixture_audits(runner, GCC)
run_motif_determinism(runner, GCC, compare_reference=True)
def _tier_deadline(_signum: int, _frame: object) -> None:
@@ -1659,6 +1917,7 @@ def main() -> int:
run_random_camera_sweep(runner, (CLANG,), 3, ((3, 0, 0),))
run_ring(runner, full=False)
run_native_caves_field_audit(runner, CLANG)
run_motif_fixture_audits(runner, CLANG)
elif ARGS.tier == "medium":
run_medium_suite(runner, both_compilers=False)
else: