diff --git a/Standalone/Core/include/VoxelForgeCore/PassageSpline.h b/Standalone/Core/include/VoxelForgeCore/PassageSpline.h new file mode 100644 index 0000000..6b61bb9 --- /dev/null +++ b/Standalone/Core/include/VoxelForgeCore/PassageSpline.h @@ -0,0 +1,255 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace VoxelForgeCore::PassageSpline +{ + using FPoint = std::array; + inline constexpr std::size_t ArcTableSteps = 32; + inline constexpr double UpperMouthFloorBlendRadiusMetres = 3.5; + + struct FSegment + { + FPoint a{},b{}; + double alongMetres=0.0,lengthMetres=0.0; + std::size_t controlSpan=0; + double tA=0.0,tB=1.0; + double plannedFloorA=0.0,plannedFloorB=0.0; + }; + + inline double KnotSpan(const FPoint& a,const FPoint& b,double unitsPerMetre) + { + const double dx=(b[0]-a[0])/unitsPerMetre; + const double dy=(b[1]-a[1])/unitsPerMetre; + return std::max(1.0e-6,std::sqrt(std::sqrt(dx*dx+dy*dy))); + } + + inline FPoint EvaluateRaw(std::span controls,std::size_t span, + double t,double unitsPerMetre) + { + const auto& p1=controls[span]; + const auto& p2=controls[span+1]; + const auto& p0=controls[span==0?0:span-1]; + const auto& p3=controls[std::min(span+2,controls.size()-1)]; + const double dt0=KnotSpan(p0,p1,unitsPerMetre); + const double dt1=KnotSpan(p1,p2,unitsPerMetre); + const double dt2=KnotSpan(p2,p3,unitsPerMetre); + const double t2=t*t,t3=t2*t; + FPoint result{}; + for(const std::size_t axis:{0u,1u,3u}) + { + const double m1=dt1*((p1[axis]-p0[axis])/dt0 + -(p2[axis]-p0[axis])/(dt0+dt1) + +(p2[axis]-p1[axis])/dt1); + const double m2=dt1*((p2[axis]-p1[axis])/dt1 + -(p3[axis]-p1[axis])/(dt1+dt2) + +(p3[axis]-p2[axis])/dt2); + result[axis]=(2.0*t3-3.0*t2+1.0)*p1[axis] + +(-2.0*t3+3.0*t2)*p2[axis] + +(t3-2.0*t2+t)*m1+(t3-t2)*m2; + } + result[2]=std::lerp(p1[2],p2[2],t); + result[3]=std::clamp(result[3],std::min(p1[3],p2[3]), + std::max(p1[3],p2[3])); + return result; + } + + inline bool ClosestRouteHeightAtXY(std::span> route, + double x,double y,double& height,double& distanceSquared) + { + if(route.empty())return false; + distanceSquared=std::numeric_limits::infinity(); + const auto consider=[&](const std::array& point) + { + const double dx=x-point[0],dy=y-point[1]; + const double candidate=dx*dx+dy*dy; + if(candidate1.0e-12 + ?std::clamp(((x-a[0])*dx+(y-a[1])*dy)/lengthSquared,0.0,1.0):0.0; + const std::array point={a[0]+t*dx,a[1]+t*dy, + std::lerp(a[2],b[2],t)}; + consider(point); + } + return std::isfinite(distanceSquared); + } + + inline double BlendUpperMouthFloorAtXY( + std::span> receivingRoute,double x,double y, + double plannedFloor,double mouthX,double mouthY,double mouthFloor, + double tangentX,double tangentY, + double blendRadiusMetres,double playerCenterAboveFloorMetres, + double unitsPerMetre=1.0) + { + if(receivingRoute.empty()||!(blendRadiusMetres>0.0) + ||!(unitsPerMetre>0.0))return plannedFloor; + const double dx=(x-mouthX)/unitsPerMetre; + const double dy=(y-mouthY)/unitsPerMetre; + if(dx*tangentX+dy*tangentY>=0.0)return plannedFloor; + const double dz=(plannedFloor-mouthFloor)/unitsPerMetre; + const double distance=std::sqrt(dx*dx+dy*dy+dz*dz); + double routeHeight=0.0,routeDistanceSquared=0.0; + if(distance>blendRadiusMetres + ||!ClosestRouteHeightAtXY(receivingRoute,x,y,routeHeight, + routeDistanceSquared) + ||routeDistanceSquared>std::pow(2.0*blendRadiusMetres*unitsPerMetre,2.0)) + return plannedFloor; + const double t=std::clamp(distance/blendRadiusMetres,0.0,1.0); + const double blend=t*t*(3.0-2.0*t); + const double receivingFloor=routeHeight + -playerCenterAboveFloorMetres*unitsPerMetre; + return std::lerp(plannedFloor,receivingFloor,blend); + } + + inline std::vector BuildSegments(std::span controls, + std::size_t spanCount,double spacingMetres,double unitsPerMetre=1.0, + std::span plannedFloorProfile={}, + double maximumChordErrorMetres=0.0) + { + std::vector result; + if(controls.size()<2||!(spacingMetres>0.0)||!(unitsPerMetre>0.0))return result; + spanCount=std::min(spanCount,controls.size()-1); + double alongMetres=0.0; + for(std::size_t span=0;span horizontalArc{}; + auto previous=EvaluateRaw(controls,span,0.0,unitsPerMetre); + for(std::size_t step=1;step<=ArcTableSteps;++step) + { + const auto current=EvaluateRaw(controls,span, + static_cast(step)/ArcTableSteps,unitsPerMetre); + const double dx=(current[0]-previous[0])/unitsPerMetre; + const double dy=(current[1]-previous[1])/unitsPerMetre; + horizontalArc[step]=horizontalArc[step-1]+std::sqrt(dx*dx+dy*dy); + previous=current; + } + const double spanLength=horizontalArc.back(); + const std::size_t baseSegmentCount=std::max(1, + static_cast(std::ceil(spanLength/spacingMetres))); + std::vector points; + std::vector parameters; + points.reserve(baseSegmentCount+1); + parameters.reserve(baseSegmentCount+1); + const auto parameterAtArc=[&](double targetArc) + { + const auto upper=std::lower_bound(horizontalArc.begin()+1, + horizontalArc.end(),targetArc); + const std::size_t upperIndex=static_cast( + upper-horizontalArc.begin()); + const std::size_t lowerIndex=upperIndex-1; + const double arcSpan=horizontalArc[upperIndex]-horizontalArc[lowerIndex]; + const double arcT=arcSpan>1.0e-12 + ?std::clamp((targetArc-horizontalArc[lowerIndex])/arcSpan,0.0,1.0):0.0; + return (static_cast(lowerIndex)+arcT)/ArcTableSteps; + }; + parameters.push_back(0.0); + const double chordError=std::max(0.0,maximumChordErrorMetres); + const auto appendAdaptive=[&](auto&& self,double tA,double tB, + const FPoint& a,const FPoint& b,unsigned depth)->void + { + constexpr std::array CheckFractions={0.25,0.5,0.75}; + double maximumError=0.0,polylineLength=0.0; + FPoint previous=a; + for(const double fraction:CheckFractions) + { + const FPoint current=EvaluateRaw(controls,span, + std::lerp(tA,tB,fraction),unitsPerMetre); + const double chordX=std::lerp(a[0],b[0],fraction); + const double chordY=std::lerp(a[1],b[1],fraction); + const double dx=(current[0]-chordX)/unitsPerMetre; + const double dy=(current[1]-chordY)/unitsPerMetre; + const double dr=(current[3]-std::lerp(a[3],b[3],fraction)) + /unitsPerMetre; + maximumError=std::max(maximumError, + std::sqrt(dx*dx+dy*dy+dr*dr)); + const double segmentX=(current[0]-previous[0])/unitsPerMetre; + const double segmentY=(current[1]-previous[1])/unitsPerMetre; + polylineLength+=std::sqrt(segmentX*segmentX+segmentY*segmentY); + previous=current; + } + const double finalX=(b[0]-previous[0])/unitsPerMetre; + const double finalY=(b[1]-previous[1])/unitsPerMetre; + polylineLength+=std::sqrt(finalX*finalX+finalY*finalY); + const bool split=(polylineLength>spacingMetres*(1.0+1.0e-9) + ||(chordError>0.0&&maximumError>chordError))&&depth<12; + if(split) + { + const double tMid=(tA+tB)*0.5; + const FPoint middle=EvaluateRaw(controls,span,tMid,unitsPerMetre); + self(self,tA,tMid,a,middle,depth+1); + self(self,tMid,tB,middle,b,depth+1); + return; + } + parameters.push_back(tB); + }; + for(std::size_t segment=1;segment<=baseSegmentCount;++segment) + { + const double targetA=spanLength*static_cast(segment-1) + /baseSegmentCount; + const double targetB=spanLength*static_cast(segment) + /baseSegmentCount; + const double tA=parameterAtArc(targetA); + const double tB=parameterAtArc(targetB); + const FPoint a=EvaluateRaw(controls,span,tA,unitsPerMetre); + const FPoint b=EvaluateRaw(controls,span,tB,unitsPerMetre); + appendAdaptive(appendAdaptive,tA,tB,a,b,0); + } + points.reserve(parameters.size()); + for(const double t:parameters) + points.push_back(EvaluateRaw(controls,span,t,unitsPerMetre)); + std::vector sampledHorizontalArc(points.size(),0.0); + for(std::size_t i=1;i1.0e-12 + ?sampledHorizontalArc[i]/sampledSpanLength:parameters[i]; + points[i][2]=std::lerp(controls[span][2],controls[span+1][2],progress); + } + for(std::size_t i=1;i1.0e-12 + ?sampledHorizontalArc[index]/sampledSpanLength:parameters[index]; + return std::lerp(plannedFloorProfile[span], + plannedFloorProfile[span+1],progress); + }; + result.push_back({points[i-1],points[i],alongMetres,length,span, + parameters[i-1],parameters[i],floorAt(i-1),floorAt(i)}); + alongMetres+=length; + } + } + return result; + } +} diff --git a/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h b/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h index 972aaf8..dc4ca32 100644 --- a/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h +++ b/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h @@ -12,6 +12,7 @@ #include #include "VoxelForgeCore/Linux77Profiler.h" +#include "VoxelForgeCore/PassageSpline.h" // UBT supplies this export/import macro for the runtime module. The standalone target has no // module boundary, so leave it empty there. UBT fournit la macro; le viewer autonome reste neutre. @@ -137,46 +138,44 @@ namespace VoxelForgeCore bool passageComposerProfiled = false; std::uint64_t passageTileFeatureCount = 0; std::uint64_t passageTileRouteSegmentCandidates = 0; - std::uint64_t passageTileMouthSegmentCandidates = 0; std::uint64_t resolvedBoundaryBandQueries = 0; std::uint64_t passageComposerQueries = 0; std::uint64_t passageIterations = 0; - std::uint64_t passageTileBoundChecks = 0; - std::uint64_t passageTileBoundRejects = 0; - std::uint64_t passageTileBoundSkippedIterations = 0; - std::uint64_t passageUpperMouthFilterChecks = 0; - std::uint64_t passageColumnCandidates = 0; - std::uint64_t passageColumnDistanceCalls = 0; - std::uint64_t passageNegativeBoundChecks = 0; - std::uint64_t passageNegativeBoundRejects = 0; - std::uint64_t passagePositiveBoundChecks = 0; - std::uint64_t passagePositiveBoundRejects = 0; std::uint64_t passageCarveSegmentVisits = 0; - std::uint64_t passageSmoothCarveJoins = 0; - std::uint64_t passageSupportSegmentVisits = 0; - std::uint64_t passageSmoothSupportJoins = 0; - std::uint64_t passageSupportCapsuleChecks = 0; - std::uint64_t passageLaterBoreChecks = 0; - std::uint64_t passageOtherCapsuleChecks = 0; - std::uint64_t passageMouthSupportCalls = 0; - std::uint64_t passageMouthRouteSegmentChecks = 0; std::uint64_t passageReliefFieldCalls = 0; - std::uint64_t passageSmoothstepEvaluations = 0; // L99 tile-local swept-tube base and detail passes. These are populated only // by the opt-in passage composer profile, except the mesh composition itself. std::uint64_t passageSweepRouteSegmentCandidates = 0; std::uint64_t passageSweepSegmentSamplePairs = 0; + std::uint64_t passageSweepPrepareNanoseconds = 0; std::uint64_t passageSweepOutsideInfluencePairs = 0; + std::uint64_t passageSweepShellSupportSkips = 0; std::uint64_t passageSweepMinimumUpdates = 0; std::uint64_t passageSweepBaseInfluenceSamples = 0; std::uint64_t passageSweepDetailShellSamples = 0; std::uint64_t passageSweepGridSamples = 0; std::uint64_t passageSweepNoInfluenceGridSamples = 0; + std::uint64_t passageSweepTouchedSamples = 0; + std::uint64_t passageSweepStampedOutsideSamples = 0; + std::uint64_t passageSweepCacheValidSamples = 0; + std::uint64_t passageSweepCacheValidUniqueSamples = 0; + std::uint64_t passageSweepUniqueTouchedSamples = 0; + std::uint64_t passageSweepBodyBandSamples = 0; + std::uint64_t passageSweepShellBandSamples = 0; + std::uint64_t passageSweepUniqueBandSamples = 0; + std::uint64_t passageSweepOverlapPairs = 0; + std::uint64_t passageSweepContributingPairs = 0; + std::uint64_t passageSweepCrossPassageOverlaps = 0; + std::uint64_t passageSweepFloorProfileCalls = 0; + std::uint64_t passageSweepAllocatedBytes = 0; + std::uint64_t passageSweepPrepareScratchBytes = 0; std::uint64_t passageSweepLookups = 0; std::uint64_t passageSweepCacheHits = 0; std::uint64_t passageSweepBaseInfluenceHits = 0; std::uint64_t passageSweepOutOfInfluenceHits = 0; std::uint64_t passageSweepMissingSamples = 0; + std::uint64_t passageSweepOffGridMisses = 0; + std::uint64_t passageSweepUnpreparedMisses = 0; std::array passageSweepMissingLookupsByCaller{}; std::array passageSweepExactRouteFallbacksByCaller{}; std::array passageSweepFeatureBoundSkipsByCaller{}; @@ -488,7 +487,14 @@ namespace VoxelForgeCore // Version 210 keeps bulk native-cave sampling on the scalar field path at strata edges. // Version 211 makes coordinate biasing in the shared cell hash unsigned, removing signed-overflow UB. // Version 212 balances generated entry routes against existing walk lanes and preserves their shared treads. - inline constexpr std::uint32_t WorldAssemblyEvaluatorVersion = 216; + // Version 218 sweeps passages around a dense smooth spline and limits exposed shells to a trough. + // Version 219 smooths passage XY while mapping each planned height chord over its sampled horizontal arc. + // Version 220 adaptively samples passage curves and rounds open-air wall crests. + // Version 221 ranks passage segments before floor shaping and preserves their signed exterior distance. + // Version 223 projects the floor onto one continuous arc-length profile and groups + // dense passage samples into coarse tile candidates. Version 224 keeps the same + // continuous floor while relaxing the spline chord tolerance and bounding shell work. + inline constexpr std::uint32_t WorldAssemblyEvaluatorVersion = 225; enum class FieldChannel : std::uint32_t { @@ -1041,7 +1047,6 @@ namespace VoxelForgeCore { bool hasSurfaceLanding = false; bool hasFloatingIslandLanding = false; - bool usePassageAnchorForColumns = false; bool hasNativeCaveField = false; bool hasNativeLatticeField = false; }; @@ -1145,28 +1150,6 @@ namespace VoxelForgeCore std::vector controlPoints; }; - struct PassageVoidCrossingAuditV1 - { - std::size_t passageIndex = 0; - std::size_t firstSegment = 0; - std::size_t lastSegment = 0; - std::uint64_t unsupportedSamples = 0; - double unsupportedLengthMetres = 0.0; - std::array startPointSubvoxels{}; - std::array endPointSubvoxels{}; - bool needsColumn = false; - bool connectedAtStart = false; - bool connectedAtEnd = false; - std::array columnAxisSubvoxels{}; - std::int64_t columnTopZSubvoxels = 0; - std::int64_t columnBottomZSubvoxels = 0; - std::int64_t columnMinimumRadiusSubvoxels = 0; - std::int64_t columnNominalRadiusSubvoxels = 0; - std::int64_t columnMaximumRadiusSubvoxels = 0; - double maximumRouteOffsetMetres = 0.0; - double maximumBoreRadiusMetres = 0.0; - }; - struct ResolvedLayoutPassageConfigV1 { std::int32_t upperStrateIndex = -1; @@ -1836,10 +1819,6 @@ namespace VoxelForgeCore bool profileMesherStages = false; // Research-only: count passage-composer work per generated tile. bool profilePassageComposer = false; - // Research-only field comparison. A nonnegative value clamps the source density - // entering passage composition to at least -N voxel units for this tile. - // A negative value leaves the process-level diagnostic override in control. - double diagnosticPassageSourceFloorVoxels = -1.0; // Research-only field comparison. Zero keeps the unbounded passage carve; // a positive value bounds its signed-distance reach in metres. A negative // value leaves the process-level L93 setting in control. @@ -1932,12 +1911,6 @@ namespace VoxelForgeCore OreMiningYieldV1 measureOreMiningYieldForSphere( Vec3d centerVoxel, double radiusMetres, double sampleSpacingMetres = 0.25) const; - // Audit-only view of density-field columns and short spans supporting passage voids. - std::vector passageVoidCrossings() const; - bool isPassageColumnSample(std::size_t passageIndex, std::size_t segmentIndex, - Vec3d voxelPosition) const; - bool isPassageShortSpanSample(std::size_t passageIndex, std::size_t segmentIndex, - Vec3d voxelPosition) const; // Audit-only selector provenance for the same point evaluator; never used by meshing. std::string densityDispatchPathAt(Vec3d voxelPosition) const; // Analytic source distance without the occupancy-preserving near-zero clamp or packed proxy. diff --git a/Standalone/Core/src/ResolvedLayoutInternal.h b/Standalone/Core/src/ResolvedLayoutInternal.h index cc3dc23..5fcb719 100644 --- a/Standalone/Core/src/ResolvedLayoutInternal.h +++ b/Standalone/Core/src/ResolvedLayoutInternal.h @@ -888,10 +888,7 @@ bool ResolvedLayoutSnapshotV3::finalize(std::string& error) else if(IsNativeLatticeFieldStratum(x)) x.passageCapabilities.hasNativeLatticeField=true; else if(x.generatorKind=="FloatingIslands") - { x.passageCapabilities.hasFloatingIslandLanding=true; - x.passageCapabilities.usePassageAnchorForColumns=true; - } if(i+10.0 - ?Parsed:0.0; - }(); - return Value; -} - static double VF_L93PassageCarveReachMetres() { // The generated world uses a fixed bounded tube influence. An explicit diagnostic @@ -276,47 +250,29 @@ public: EKind Kind=EKind::Legacy; }; - const std::vector& GetPassageVoidCrossings() const - {return PassageVoidCrossings;} - class FScopedPassageTileQueries { public: struct FCandidateSegment { std::size_t segmentIndex=0; + std::size_t segmentEndIndex=0; std::array minimumSubvoxels{},maximumSubvoxels{}; std::array sweepMinimumSubvoxels{},sweepMaximumSubvoxels{}; }; - struct FSegmentRangeCache - { - std::ptrdiff_t first=-1,end=-1; - std::vector activeNodes; - }; - enum class EPreparedSegmentUse : std::uint8_t - { Carve,Support,Capsule,Mouth }; - struct FReuseCounters - { - std::atomic projectionColumns{0}; - std::atomic projectionComputes{0}; - std::atomic projectionHits{0}; - std::atomic floorProfileReads{0}; - std::array,4> preparedSegmentUses{}; - }; - struct FProjectionCacheEntry - { - std::uint64_t generation=0; - double numerator=0.0; - }; struct FPassageSweepSample { double signedDistance=std::numeric_limits::infinity(); - double t=0.0; + double shellSignedDistance=std::numeric_limits::infinity(); + double roundSignedDistance=std::numeric_limits::infinity(); + double centerZSubvoxels=0.0,floorCenterZSubvoxels=0.0; + double radiusSubvoxels=0.0,floorDepthSubvoxels=0.0; + double floorCenterDistanceSq=std::numeric_limits::infinity(); + double t=0.0,floorT=0.0; std::uint32_t segmentIndex=std::numeric_limits::max(); - std::uint8_t scanPhase=std::numeric_limits::max(); - float wallRelief=0.0f,mouthSurfaceRelief=0.0f,mouthTreadFieldRelief=0.0f; - bool valid=false,hasWallRelief=false,hasMouthSurfaceRelief=false, - hasMouthTreadFieldRelief=false; + std::uint32_t floorSegmentIndex=std::numeric_limits::max(); + float wallRelief=0.0f; + bool valid=false,hasWallRelief=false,hasExactContribution=false; }; struct FPassageTileSweepData { @@ -332,7 +288,8 @@ public: std::vector passageToSweep; std::vector passages; std::atomic lookups{0},cacheHits{0},baseInfluenceHits{0}, - outOfInfluenceHits{0},missingSamples{0}; + outOfInfluenceHits{0},missingSamples{0},offGridMisses{0}, + unpreparedMisses{0}; std::array,PassageDensityQueryCallerCount> missingLookupsByCaller{},exactRouteFallbacksByCaller{}, featureBoundSkipsByCaller{},tileFreeSkipsByCaller{}, @@ -343,282 +300,73 @@ public: const std::array& minimumSubvoxels, const std::array& maximumSubvoxels, VoxelForgeCore::TileGenerationStats* profileStats=nullptr,int32 profileLod=0, - double passageSourceFloorVoxels=-1.0, double passageCarveReachMetres=-1.0) :shape_(&shape),minimumSubvoxels_(minimumSubvoxels), maximumSubvoxels_(maximumSubvoxels),previous_(ActivePassageTileQueries), profileStats_(profileStats),profileLod_(profileLod), - candidateProfiled_(profileStats!=nullptr&&shape.L90PassageCandidateProgramEnabled), - passageSourceFloorVoxels_(std::isfinite(passageSourceFloorVoxels) - &&passageSourceFloorVoxels>=0.0?passageSourceFloorVoxels - :VF_L91PassageSourceFloorVoxels()), passageCarveReachMetres_(std::isfinite(passageCarveReachMetres) &&passageCarveReachMetres>=0.0?passageCarveReachMetres :VF_L93PassageCarveReachMetres()) { - if(passageSourceFloorVoxels_>0.0) - clampCounters_=std::make_shared(); mayContainResolvedBoundaryBand_=shape.ResolvedBoundaryBandsIntersectSubvoxelRange( minimumSubvoxels_[2],maximumSubvoxels_[2]); const bool disablePassageComposition=VF_IsL88PassageCompositionDisabled(); - const bool disableBoundaryBands=VF_IsL88BoundaryBandsDisabled(); - if(disableBoundaryBands)mayContainResolvedBoundaryBand_=false; - mayContainTransitionPassageFade_ = !disablePassageComposition - && shape.ResolvedTransitionPassageFadeIntersectsTileXY( - minimumSubvoxels_, maximumSubvoxels_); - if (!disablePassageComposition) - { - featureIndices_ = shape.BuildPassageFeatureTileList( - minimumSubvoxels_, maximumSubvoxels_); - } + if(VF_IsL88BoundaryBandsDisabled())mayContainResolvedBoundaryBand_=false; + mayContainTransitionPassageFade_=!disablePassageComposition + &&shape.ResolvedTransitionPassageFadeIntersectsTileXY( + minimumSubvoxels_,maximumSubvoxels_); + if(!disablePassageComposition) + featureIndices_=shape.BuildPassageFeatureTileList( + minimumSubvoxels_,maximumSubvoxels_); stampIndices_=shape.BuildStampTileList(minimumSubvoxels_,maximumSubvoxels_); cavernFeatureIndices_=shape.BuildCavernFeatureTileList( minimumSubvoxels_,maximumSubvoxels_); - passageRoutes_.assign(shape.ResolvedLayout && !disablePassageComposition - ? shape.ResolvedLayout->passages.size() : 0, 0); - passageColumns_=passageRoutes_; - passageMouthSupports_=passageRoutes_; + passageRoutes_.assign(shape.ResolvedLayout&&!disablePassageComposition + ?shape.ResolvedLayout->passages.size():0,0); passageRouteSegments_.resize(passageRoutes_.size()); - passageMouthSupportSegments_.resize(passageRoutes_.size()); - passageSegmentRangeCaches_.resize(passageRoutes_.size()); - if(!disablePassageComposition&&shape.ResolvedLayout - &&!shape.ResolvedLayout->passages.empty()) - { - constexpr double Q=static_cast( - VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel); - const double qPerMetre=Q*1000000.0/ - std::max(1, - shape.ResolvedLayout->coreVoxelSizeMicrometres); - const double horizontalReach=15.0*qPerMetre; - const double verticalReach=8.0*qPerMetre; - const bool failOpen=minimumSubvoxels_[0]>maximumSubvoxels_[0] - ||minimumSubvoxels_[1]>maximumSubvoxels_[1] - ||minimumSubvoxels_[2]>maximumSubvoxels_[2]; - for(std::size_t passageIndex=0; - passageIndexpassages.size();++passageIndex) - { - if(failOpen) - { - upperMouthSupportPassages_.push_back(passageIndex); - continue; - } - const auto& mouth=shape.ResolvedLayout->passages[ - passageIndex].upperMouthSubvoxels; - if(static_cast(mouth[0])+horizontalReach>=minimumSubvoxels_[0] - &&static_cast(mouth[0])-horizontalReach<=maximumSubvoxels_[0] - &&static_cast(mouth[1])+horizontalReach>=minimumSubvoxels_[1] - &&static_cast(mouth[1])-horizontalReach<=maximumSubvoxels_[1] - &&static_cast(mouth[2])+verticalReach>=minimumSubvoxels_[2] - &&static_cast(mouth[2])-verticalReach<=maximumSubvoxels_[2]) - upperMouthSupportPassages_.push_back(passageIndex); - } - } - if(!disablePassageComposition) - { - for(const auto& crossing:shape.PassageVoidCrossings) - if(crossing.needsColumn - &&crossing.bottomZSubvoxels<=maximumSubvoxels_[2] - &&crossing.topZSubvoxels>=minimumSubvoxels_[2]) - columnZOverlap_=true; - } for(const std::uint32_t featureIndex:featureIndices_) { if(featureIndex>=shape.PassageTileFeatures.size())continue; const auto& feature=shape.PassageTileFeatures[featureIndex]; if(feature.passageIndex>=passageRoutes_.size())continue; - const auto& featureBounds=shape.PassageFeatureBounds[featureIndex]; + const auto& bounds=shape.PassageFeatureBounds[featureIndex]; FCandidateSegment candidate; candidate.segmentIndex=feature.segmentIndex; - candidate.minimumSubvoxels=featureBounds.minimumSubvoxels; - candidate.maximumSubvoxels=featureBounds.maximumSubvoxels; - if(!feature.bColumn&&!feature.bMouthSupport - &&feature.passageIndex(); ActivePassageTileQueries=this; } - // Duplicate the immutable per-tile masks onto a density-grid helper worker. Mutable - // segment-range caches remain lane-local so helpers never race with the parent query. explicit FScopedPassageTileQueries(const FScopedPassageTileQueries& source) :shape_(source.shape_),minimumSubvoxels_(source.minimumSubvoxels_), maximumSubvoxels_(source.maximumSubvoxels_),featureIndices_(source.featureIndices_), stampIndices_(source.stampIndices_),cavernFeatureIndices_(source.cavernFeatureIndices_), - passageRoutes_(source.passageRoutes_),passageColumns_(source.passageColumns_), - passageMouthSupports_(source.passageMouthSupports_), + passageRoutes_(source.passageRoutes_), passageRouteSegments_(source.passageRouteSegments_), - passageMouthSupportSegments_(source.passageMouthSupportSegments_), - passageSegmentRangeCaches_(source.passageSegmentRangeCaches_.size()), - upperMouthSupportPassages_(source.upperMouthSupportPassages_), - routeSegmentCandidateCount_(source.routeSegmentCandidateCount_), - routeFeatureOverlap_(source.routeFeatureOverlap_),columnZOverlap_(source.columnZOverlap_), - mayContainResolvedBoundaryBand_(source.mayContainResolvedBoundaryBand_), - mayContainTransitionPassageFade_(source.mayContainTransitionPassageFade_), previous_(ActivePassageTileQueries),profileStats_(source.profileStats_), profileLod_(source.profileLod_), - candidateProfiled_(source.candidateProfiled_), - passageSourceFloorVoxels_(source.passageSourceFloorVoxels_), passageCarveReachMetres_(source.passageCarveReachMetres_), passageSweepData_(source.passageSweepData_), - ownsPassageSweepDiagnostics_(false), - clampCounters_(source.clampCounters_),ownsClampCounters_(false), - projectionCacheSize_(source.projectionCacheSize_), - reuseCounters_(source.reuseCounters_),ownsReuseCounters_(false) - { ActivePassageTileQueries=this; } + ownsPassageSweepDiagnostics_(false) + {ActivePassageTileQueries=this;} ~FScopedPassageTileQueries() { ActivePassageTileQueries=previous_; - if(ownsPassageSweepDiagnostics_&&profileStats_&&passageSweepData_) - { - profileStats_->passageSweepLookups=passageSweepData_->lookups.load( - std::memory_order_relaxed); - profileStats_->passageSweepCacheHits=passageSweepData_->cacheHits.load( - std::memory_order_relaxed); - profileStats_->passageSweepBaseInfluenceHits= - passageSweepData_->baseInfluenceHits.load(std::memory_order_relaxed); - profileStats_->passageSweepOutOfInfluenceHits= - passageSweepData_->outOfInfluenceHits.load(std::memory_order_relaxed); - profileStats_->passageSweepMissingSamples=passageSweepData_->missingSamples.load( - std::memory_order_relaxed); - for(std::size_t caller=0;callerpassageSweepMissingLookupsByCaller[caller]= - passageSweepData_->missingLookupsByCaller[caller].load( - std::memory_order_relaxed); - profileStats_->passageSweepExactRouteFallbacksByCaller[caller]= - passageSweepData_->exactRouteFallbacksByCaller[caller].load( - std::memory_order_relaxed); - profileStats_->passageSweepFeatureBoundSkipsByCaller[caller]= - passageSweepData_->featureBoundSkipsByCaller[caller].load( - std::memory_order_relaxed); - profileStats_->passageSweepTileFreeSkipsByCaller[caller]= - passageSweepData_->tileFreeSkipsByCaller[caller].load( - std::memory_order_relaxed); - profileStats_->passageSweepVerticalBoundSkipsByCaller[caller]= - passageSweepData_->verticalBoundSkipsByCaller[caller].load( - std::memory_order_relaxed); - profileStats_->passageSweepNegativeReachSkipsByCaller[caller]= - passageSweepData_->negativeReachSkipsByCaller[caller].load( - std::memory_order_relaxed); - profileStats_->passageSweepPositiveReachSkipsByCaller[caller]= - passageSweepData_->positiveReachSkipsByCaller[caller].load( - std::memory_order_relaxed); - } - } - if(ownsReuseCounters_&&reuseCounters_) - std::printf("[L98PassageReuseTile] lod=%d projection_columns=%llu projection_computes=%llu projection_hits=%llu floor_profile_reads=%llu carve_prepared=%llu support_prepared=%llu capsule_prepared=%llu mouth_prepared=%llu\n", - profileLod_, - static_cast(reuseCounters_->projectionColumns.load( - std::memory_order_relaxed)), - static_cast(reuseCounters_->projectionComputes.load( - std::memory_order_relaxed)), - static_cast(reuseCounters_->projectionHits.load( - std::memory_order_relaxed)), - static_cast(reuseCounters_->floorProfileReads.load( - std::memory_order_relaxed)), - static_cast(reuseCounters_->preparedSegmentUses[0].load( - std::memory_order_relaxed)), - static_cast(reuseCounters_->preparedSegmentUses[1].load( - std::memory_order_relaxed)), - static_cast(reuseCounters_->preparedSegmentUses[2].load( - std::memory_order_relaxed)), - static_cast(reuseCounters_->preparedSegmentUses[3].load( - std::memory_order_relaxed))); - if(ownsClampCounters_&&clampCounters_&&passageSourceFloorVoxels_>0.0) - std::printf("[L91PassageSourceClampTile] lod=%d floor_vox=%.3f source_clamped=%llu source_delta_sum=%.9g deepest_source_vox=%.9g\n", - profileLod_,passageSourceFloorVoxels_, - static_cast(clampCounters_->samples.load()), - clampCounters_->deltaSum.load(),clampCounters_->deepestSource.load()); - if(!candidateProfiled_||l90Queries_==0)return; - std::array,4> HistText{}; - constexpr std::array Names={"carve","tread","clearance","mouth_column"}; - for(std::size_t semantic=0;semantic(l90CandidateHistogram_[semantic][bin])); - if(written<0)break; - offset=std::min(HistText[semantic].size(),offset+static_cast(written)); - if(offset>=HistText[semantic].size())break; - } - } - std::printf("[L90PassageCandidateTile] lod=%d min=(%lld,%lld,%lld) max=(%lld,%lld,%lld) queries=%llu no_brick=%llu fallback_iterations=%llu fallback_reach=%llu fallback_shortspan=%llu fallback_invalid=%llu fallback_proof=%llu fallback_ns=%llu query_ns=%llu fallback_carve=%llu fallback_tread=%llu fallback_clearance=%llu fallback_mouth=%llu proof_checks=(%llu,%llu,%llu,%llu,%llu,%llu) proof_misses=(%llu,%llu,%llu,%llu,%llu,%llu) carve_hist=%s tread_hist=%s clearance_hist=%s mouth_column_hist=%s\n", - profileLod_,static_cast(minimumSubvoxels_[0]), - static_cast(minimumSubvoxels_[1]), - static_cast(minimumSubvoxels_[2]), - static_cast(maximumSubvoxels_[0]), - static_cast(maximumSubvoxels_[1]), - static_cast(maximumSubvoxels_[2]), - static_cast(l90Queries_), - static_cast(l90NoBrickQueries_), - static_cast(l90FallbackIterations_), - static_cast(l90FallbackReachOverflow_), - static_cast(l90FallbackShortSpan_), - static_cast(l90FallbackInvalid_), - static_cast(l90FallbackProof_), - static_cast(l90FallbackNanoseconds_), - static_cast(l90QueryNanoseconds_), - static_cast(l90FallbackCarveVisits_), - static_cast(l90FallbackTreadVisits_), - static_cast(l90FallbackClearanceChecks_), - static_cast(l90FallbackMouthChecks_), - static_cast(l90ProofChecks_[0]), - static_cast(l90ProofChecks_[1]), - static_cast(l90ProofChecks_[2]), - static_cast(l90ProofChecks_[3]), - static_cast(l90ProofChecks_[4]), - static_cast(l90ProofChecks_[5]), - static_cast(l90ProofMisses_[0]), - static_cast(l90ProofMisses_[1]), - static_cast(l90ProofMisses_[2]), - static_cast(l90ProofMisses_[3]), - static_cast(l90ProofMisses_[4]), - static_cast(l90ProofMisses_[5]), - HistText[0].data(),HistText[1].data(),HistText[2].data(),HistText[3].data()); + copySweptTubeRuntimeCounts(); } FScopedPassageTileQueries& operator=(const FScopedPassageTileQueries&)=delete; @@ -631,7 +379,7 @@ public: bool hasSweptTubeBase() const noexcept{return passageSweepData_!=nullptr;} void copySweptTubeRuntimeCounts() const noexcept { - if(!profileStats_||!passageSweepData_)return; + if(!ownsPassageSweepDiagnostics_||!profileStats_||!passageSweepData_)return; profileStats_->passageSweepLookups=passageSweepData_->lookups.load( std::memory_order_relaxed); profileStats_->passageSweepCacheHits=passageSweepData_->cacheHits.load( @@ -642,6 +390,10 @@ public: passageSweepData_->outOfInfluenceHits.load(std::memory_order_relaxed); profileStats_->passageSweepMissingSamples=passageSweepData_->missingSamples.load( std::memory_order_relaxed); + profileStats_->passageSweepOffGridMisses=passageSweepData_->offGridMisses.load( + std::memory_order_relaxed); + profileStats_->passageSweepUnpreparedMisses= + passageSweepData_->unpreparedMisses.load(std::memory_order_relaxed); for(std::size_t caller=0;callerpassageSweepMissingLookupsByCaller[caller]= @@ -686,9 +438,7 @@ public: 1,std::memory_order_relaxed); } enum class ESweepMissSkipReason : std::uint8_t - { - TileFree,VerticalBound,NegativeReach,PositiveReach - }; + {TileFree,VerticalBound,NegativeReach,PositiveReach}; void recordSweepMissSkip(ESweepMissSkipReason reason) const noexcept { if(!profileStats_||!passageSweepData_)return; @@ -709,75 +459,19 @@ public: } if(counts)counts->fetch_add(1,std::memory_order_relaxed); } - bool beginProjectionColumn() const + static const FScopedPassageTileQueries* CurrentFor( + const FStandaloneShapeWorld& shape) { - const bool previous=projectionColumnActive_; - projectionColumnActive_=true; - ++projectionGeneration_; - if(projectionGeneration_==0) - { - for(auto& entry:projectionCache_)entry.generation=0; - projectionGeneration_=1; - } - if(reuseCounters_) - reuseCounters_->projectionColumns.fetch_add(1,std::memory_order_relaxed); - return previous; - } - void endProjectionColumn(bool previous) const - {projectionColumnActive_=previous;} - double projectionNumerator(std::size_t flatIndex,double qx,double qy, - double ax,double ay,double dx,double dy) const - { - const auto compute=[&](){return (qx-ax)*dx+(qy-ay)*dy;}; - if(!projectionColumnActive_||!shape_)return compute(); - if(projectionCache_.size()!=projectionCacheSize_) - projectionCache_.resize(projectionCacheSize_); - if(flatIndex>=projectionCache_.size())return compute(); - FProjectionCacheEntry& entry=projectionCache_[flatIndex]; - if(entry.generation==projectionGeneration_) - { - if(reuseCounters_) - reuseCounters_->projectionHits.fetch_add(1,std::memory_order_relaxed); - return entry.numerator; - } - entry.numerator=compute(); - entry.generation=projectionGeneration_; - if(reuseCounters_) - reuseCounters_->projectionComputes.fetch_add(1,std::memory_order_relaxed); - return entry.numerator; - } - void recordPreparedSegmentUse(EPreparedSegmentUse use) const - { - if(reuseCounters_) - reuseCounters_->preparedSegmentUses[static_cast(use)] - .fetch_add(1,std::memory_order_relaxed); - } - void recordPreparedFloorProfileRead() const - { - if(reuseCounters_) - reuseCounters_->floorProfileReads.fetch_add(1,std::memory_order_relaxed); - } - static const FScopedPassageTileQueries* CurrentFor(const FStandaloneShapeWorld& shape) - { - const FScopedPassageTileQueries* current=ActivePassageTileQueries; + const auto* current=ActivePassageTileQueries; return current&¤t->shape_==&shape?current:nullptr; } - bool hasFeature(std::size_t passageIndex,bool columnFeature) const - { - const auto& candidates=columnFeature?passageColumns_:passageRoutes_; - return passageIndex=passageRouteSegments_.size())return false; - for(const FCandidateSegment& candidate:passageRouteSegments_[passageIndex]) + for(const auto& candidate:passageRouteSegments_[passageIndex]) { if(qxcandidate.maximumSubvoxels[0] @@ -789,39 +483,6 @@ public: } return false; } - const std::vector& mouthSupportSegments(std::size_t passageIndex) const - { - static const std::vector Empty; - return passageIndex* segmentRangeNodeMask(std::size_t passageIndex, - std::ptrdiff_t first,std::ptrdiff_t end,int priority) const - { - if(passageIndex>=passageSegmentRangeCaches_.size() - ||priority<0||priority>=4)return nullptr; - FSegmentRangeCache& cache=passageSegmentRangeCaches_[passageIndex][ - static_cast(priority)]; - if(cache.first!=first||cache.end!=end) - { - cache.first=first; - cache.end=end; - cache.activeNodes=shape_->BuildPassageSegmentRangeNodeMask( - passageIndex,first,end); - } - return &cache.activeNodes; - } - bool hasMouthSupport(std::size_t passageIndex) const - {return passageIndex& upperMouthSupportPassages() const - {return upperMouthSupportPassages_;} bool mayContainResolvedBoundaryBand() const{return mayContainResolvedBoundaryBand_;} bool mayContainTransitionPassageFade() const{return mayContainTransitionPassageFade_;} bool mayContainResolvedBoundaryBandAtZ(double zMicrometres) const @@ -833,55 +494,7 @@ public: std::size_t routeSegmentCandidateCount() const{return routeSegmentCandidateCount_;} VoxelForgeCore::TileGenerationStats* profileStats() const noexcept {return profileStats_;} - bool candidateCensusProfiled() const noexcept{return candidateProfiled_;} - double passageSourceFloorVoxels() const noexcept{return passageSourceFloorVoxels_;} double passageCarveReachMetres() const noexcept{return passageCarveReachMetres_;} - void recordPassageSourceClamp(float sourceDensity) const noexcept - { - if(passageSourceFloorVoxels_<=0.0)return; - const double delta=-passageSourceFloorVoxels_-static_cast(sourceDensity); - if(!(delta>0.0)||!std::isfinite(delta))return; - if(!clampCounters_)clampCounters_=std::make_shared(); - clampCounters_->samples.fetch_add(1,std::memory_order_relaxed); - clampCounters_->deltaSum.fetch_add(delta,std::memory_order_relaxed); - double prior=clampCounters_->deepestSource.load(std::memory_order_relaxed); - while(static_cast(sourceDensity)deepestSource.compare_exchange_weak(prior,sourceDensity, - std::memory_order_relaxed,std::memory_order_relaxed)){} - } - void recordL90CandidateHit(const std::array& counts,bool haveBrick) const - { - if(!candidateProfiled_)return; - ++l90Queries_; - if(!haveBrick)++l90NoBrickQueries_; - for(std::size_t semantic=0;semantic(counts[semantic],16)]; - } - void recordL90Fallback(std::uint64_t elapsedNanoseconds, - std::uint64_t carveVisits,std::uint64_t treadVisits, - std::uint64_t clearanceChecks,std::uint64_t mouthChecks, - std::uint8_t reason) const - { - if(!candidateProfiled_)return; - ++l90FallbackIterations_; - l90FallbackNanoseconds_+=elapsedNanoseconds; - l90FallbackCarveVisits_+=carveVisits; - l90FallbackTreadVisits_+=treadVisits; - l90FallbackClearanceChecks_+=clearanceChecks; - l90FallbackMouthChecks_+=mouthChecks; - if(reason==1)++l90FallbackReachOverflow_; - else if(reason==2)++l90FallbackShortSpan_; - else if(reason==3)++l90FallbackProof_; - else ++l90FallbackInvalid_; - } - void recordL90QueryNanoseconds(std::uint64_t elapsedNanoseconds) const - {if(candidateProfiled_)l90QueryNanoseconds_+=elapsedNanoseconds;} - void recordL90ProofCheck(std::size_t semantic,bool contained) const - { - if(!candidateProfiled_||semantic>=l90ProofChecks_.size())return; - ++l90ProofChecks_[semantic]; - if(!contained)++l90ProofMisses_[semantic]; - } bool hasStampCandidates() const{return !stampIndices_.empty();} const std::vector& stampCandidates() const{return stampIndices_;} bool hasCavernCandidates() const{return !cavernFeatureIndices_.empty();} @@ -889,91 +502,21 @@ public: {return cavernFeatureIndices_;} private: - struct FPassageSourceClampCounters - { - std::atomic samples{0}; - std::atomic deltaSum{0.0}; - std::atomic deepestSource{0.0}; - }; const FStandaloneShapeWorld* shape_; std::array minimumSubvoxels_,maximumSubvoxels_; - std::vector featureIndices_; - std::vector stampIndices_; - std::vector cavernFeatureIndices_; - std::vector passageRoutes_,passageColumns_,passageMouthSupports_; + std::vector featureIndices_,stampIndices_,cavernFeatureIndices_; + std::vector passageRoutes_; std::vector> passageRouteSegments_; - std::vector> passageMouthSupportSegments_; - mutable std::vector> passageSegmentRangeCaches_; - std::vector upperMouthSupportPassages_; std::size_t routeSegmentCandidateCount_=0; - bool routeFeatureOverlap_=false,columnZOverlap_=false; - bool mayContainResolvedBoundaryBand_=true; - bool mayContainTransitionPassageFade_=true; + bool mayContainResolvedBoundaryBand_=true,mayContainTransitionPassageFade_=true; const FScopedPassageTileQueries* previous_; VoxelForgeCore::TileGenerationStats* profileStats_=nullptr; int32 profileLod_=0; - bool candidateProfiled_=false; - double passageSourceFloorVoxels_=0.0; double passageCarveReachMetres_=0.0; std::shared_ptr passageSweepData_; bool ownsPassageSweepDiagnostics_=true; - mutable std::shared_ptr clampCounters_; - bool ownsClampCounters_=true; - std::size_t projectionCacheSize_=0; - mutable std::vector projectionCache_; - mutable std::uint64_t projectionGeneration_=0; - mutable bool projectionColumnActive_=false; - std::shared_ptr reuseCounters_; - bool ownsReuseCounters_=true; - mutable std::uint64_t l90Queries_=0,l90NoBrickQueries_=0; - mutable std::uint64_t l90FallbackIterations_=0,l90FallbackNanoseconds_=0, - l90QueryNanoseconds_=0,l90FallbackCarveVisits_=0,l90FallbackTreadVisits_=0, - l90FallbackClearanceChecks_=0,l90FallbackMouthChecks_=0, - l90FallbackReachOverflow_=0,l90FallbackShortSpan_=0,l90FallbackInvalid_=0, - l90FallbackProof_=0; - mutable std::array l90ProofChecks_{},l90ProofMisses_{}; - mutable std::array,4> l90CandidateHistogram_{}; }; - class FScopedPassageColumnXYReuse - { - public: - explicit FScopedPassageColumnXYReuse(const FStandaloneShapeWorld& shape) - :queries_(FScopedPassageTileQueries::CurrentFor(shape)) - { - if(queries_)previousActive_=queries_->beginProjectionColumn(); - } - ~FScopedPassageColumnXYReuse() - {if(queries_)queries_->endProjectionColumn(previousActive_);} - FScopedPassageColumnXYReuse(const FScopedPassageColumnXYReuse&)=delete; - FScopedPassageColumnXYReuse& operator=(const FScopedPassageColumnXYReuse&)=delete; - private: - const FScopedPassageTileQueries* queries_=nullptr; - bool previousActive_=false; - }; - - bool IsResolvedPassageColumnSample(std::size_t PassageIndex,std::size_t SegmentIndex, - const VoxelForgeCore::Vec3d& Position) const - { - (void)SegmentIndex; - for(const auto& range:PassageVoidCrossings) - { - if(!range.needsColumn||range.passageIndex!=PassageIndex)continue; - if(PassageColumnSignedDistance(range,static_cast(Position.x), - static_cast(Position.y),static_cast(Position.z))<=0.0)return true; - } - return false; - } - - bool IsResolvedPassageShortSpanSample(std::size_t PassageIndex,std::size_t SegmentIndex, - const VoxelForgeCore::Vec3d& Position) const - { - return IsPassageShortSpanSegment(PassageIndex,SegmentIndex) - &&PassageBridgeSignedDistance(PassageIndex,SegmentIndex, - static_cast(Position.x),static_cast(Position.y), - static_cast(Position.z))<=0.0; - } - double GetCoreVoxelSizeCm() const { return Owner == nullptr || Owner->CoreVoxelSizeMicrons == 0 @@ -1652,1386 +1195,345 @@ public: return -std::max(0.05f,static_cast(band->solidDensityQ16)/65536.0f); } - float ApplyResolvedStratePassageCarves(float density,float X,float Y,float Z) const + float ApplyResolvedStratePassageCarves(float density,float X,float Y,float Z, + float nativeTunnelFieldDensity=std::numeric_limits::lowest(), + float nativeFloorSupport=std::numeric_limits::lowest()) const { VoxelForgeCore::Linux77Profiler::FScopedPhase l77PassagePhase( VoxelForgeCore::Linux77Profiler::EPhase::Passage); if(!ResolvedLayout||ResolvedLayout->passages.empty()||!std::isfinite(X) ||!std::isfinite(Y)||!std::isfinite(Z))return density; constexpr double Q=static_cast(VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel); + constexpr double FloorShellThicknessMetres=0.75; + constexpr double WallReliefMetres=0.21; + constexpr double OpenAirSideWallHeightMetres=1.0; + constexpr double MouthShellBlendMetres=5.0; const double qPerMetre=Q*1000000.0/ std::max(1,ResolvedLayout->coreVoxelSizeMicrometres); const double qx=static_cast(X)*Q,qy=static_cast(Y)*Q, qz=static_cast(Z)*Q; + const double shellThickness=FloorShellThicknessMetres*qPerMetre; const auto* passageTileQueries=ActivePassageTileQueries; const bool passageTileScopeMatches=passageTileQueries &&passageTileQueries->matches(*this); auto* passageProfile=passageTileScopeMatches ?passageTileQueries->profileStats():nullptr; - const double passageCarveReachMetres=passageTileScopeMatches - ?passageTileQueries->passageCarveReachMetres() - :VF_L93PassageCarveReachMetres(); - const bool passageCarveReachEnabled=passageCarveReachMetres>0.0 - &&std::isfinite(passageCarveReachMetres); - const double passageCarveReachQ=passageCarveReachEnabled - ?passageCarveReachMetres*qPerMetre - :std::numeric_limits::infinity(); - const auto carveSourceReachQ=[&](float source) - { - const double sourceReach=source<0.0f - ?-static_cast(source)*Q+0.24*qPerMetre - :std::max(2.25*qPerMetre,-static_cast(source)*Q - +0.24*qPerMetre); - return passageCarveReachEnabled - ?std::min(sourceReach,passageCarveReachQ):sourceReach; - }; if(passageProfile)++passageProfile->passageComposerQueries; - const bool l90CandidateProfiled=passageTileScopeMatches - &&passageTileQueries->candidateCensusProfiled(); - const auto* l90CandidateBrick=l90CandidateProfiled - ?FindPassageCandidateBrick(qx,qy,qz):nullptr; - const std::array l90CandidateCounts=l90CandidateBrick - ?std::array{ - l90CandidateBrick->semantics[0].size(),l90CandidateBrick->semantics[1].size(), - l90CandidateBrick->semantics[2].size(),l90CandidateBrick->semantics[3].size()} - :std::array{}; - if(l90CandidateProfiled) - passageTileQueries->recordL90CandidateHit(l90CandidateCounts, - l90CandidateBrick!=nullptr); - struct FL90QueryTimer - { - const FScopedPassageTileQueries* scope=nullptr; - std::chrono::steady_clock::time_point start{}; - ~FL90QueryTimer() - { - if(scope)scope->recordL90QueryNanoseconds(static_cast( - std::chrono::duration_cast( - std::chrono::steady_clock::now()-start).count())); - } - } l90QueryTimer{l90CandidateProfiled?passageTileQueries:nullptr, - l90CandidateProfiled?std::chrono::steady_clock::now() - :std::chrono::steady_clock::time_point{}}; - struct FL90CandidateBrickScope - { - const FPassageCandidateBrick* previous=nullptr; - explicit FL90CandidateBrickScope(const FPassageCandidateBrick* current) - :previous(FStandaloneShapeWorld::ActivePassageCandidateBrick) - {FStandaloneShapeWorld::ActivePassageCandidateBrick=current;} - ~FL90CandidateBrickScope() - {FStandaloneShapeWorld::ActivePassageCandidateBrick=previous;} - } l90CandidateBrickScope(l90CandidateBrick); - const double passageSourceFloorVoxels=passageTileScopeMatches - ?passageTileQueries->passageSourceFloorVoxels() - :VF_L91PassageSourceFloorVoxels(); - if(passageSourceFloorVoxels>0.0 - &&static_cast(density)<-passageSourceFloorVoxels) - { - if(passageTileScopeMatches) - passageTileQueries->recordPassageSourceClamp(density); - density=static_cast(-passageSourceFloorVoxels); - } - if(passageTileScopeMatches&&density>=0.0f - &&!passageTileQueries->hasRouteFeatureOverlap() - &&!passageTileQueries->hasColumnZOverlap() - &&!passageTileQueries->hasAnyMouthSupport() - &&!passageTileQueries->mayContainUpperMouthSupport())return density; - // On solid samples, the unbounded SDF carve can move density far outside the tube. - // Bound that source-dependent tail, or cap it at the explicit carve reach. Whole-tile - // rejection is limited to tiles with no route, column, or mouth feature, so the separate - // support and landing paths keep their existing envelopes. Invalid values fail open. - static const double PassageBoundPaddingVoxels=[] + struct FNearestTubeSample { - constexpr double DefaultPaddingVoxels=0.0; - const char* Value=std::getenv( - "VOXELFORGE_L81_PASSAGE_BOUND_PADDING_VOXELS"); - if(!Value||!*Value)return DefaultPaddingVoxels; - char* End=nullptr; - const double Parsed=std::strtod(Value,&End); - if(End==Value||*End!='\0'||!std::isfinite(Parsed)||Parsed<0.0) - return std::numeric_limits::infinity(); - return Parsed; - }(); - if(passageTileScopeMatches&&density<0.0f - &&std::isfinite(PassageBoundPaddingVoxels) - &&!passageTileQueries->hasColumnZOverlap() - &&!passageTileQueries->hasAnyMouthSupport() - &&!passageTileQueries->mayContainUpperMouthSupport() - &&(!passageCarveReachEnabled - ||!passageTileQueries->hasRouteFeatureOverlap())) - { - if(passageProfile)++passageProfile->passageTileBoundChecks; - bool bAnyPassageWithinBound=false; - const double ExtraPadding=PassageBoundPaddingVoxels*Q; - for(std::size_t PassageIndex=0; - PassageIndexpassages.size();++PassageIndex) - { - const auto& Passage=ResolvedLayout->passages[PassageIndex]; - if(Passage.controlPoints.size()<2)continue; - const auto& Constants=PassageComposerConstants[PassageIndex]; - if(qz>Constants.firstFloorQ+2.0*Passage.mouthRadiusSubvoxels - ||qzrecordPreparedFloorProfileRead(); - return FloorProfile>Value; - }; - const auto CarveHigh=std::lower_bound(FloorProfileQ.begin(), - FloorProfileQ.begin()+LowerMouthIndex+1, - qz+Constants.carveSearchMargin, - CompareFloorProfile); - const auto CarveLow=std::lower_bound(FloorProfileQ.begin(), - FloorProfileQ.begin()+LowerMouthIndex+1, - qz-Constants.carveSearchMargin, - CompareFloorProfile); - const std::ptrdiff_t CarveBegin=std::max(0, - (CarveHigh-FloorProfileQ.begin())-1); - const std::ptrdiff_t CarveEnd=std::min(LowerMouthIndex-1, - (CarveLow-FloorProfileQ.begin())+1); - const double rawSignedDistanceLimit=-static_cast(density)*Q - +0.24*qPerMetre; - const double SignedDistanceLimit=passageCarveReachEnabled - ?std::min(rawSignedDistanceLimit,passageCarveReachQ)+ExtraPadding - :rawSignedDistanceLimit+ExtraPadding; - if(PassageMayAffectDensity(PassageIndex,CarveBegin,CarveEnd, - LowerMouthIndex,Constants.mouthSearchBegin,Constants.mouthSearchEnd, - Constants.lastIndex,qx,qy,qz,SignedDistanceLimit)) - { - bAnyPassageWithinBound=true; - break; - } - } - if(!bAnyPassageWithinBound) - { - if(passageProfile) - { - ++passageProfile->passageTileBoundRejects; - passageProfile->passageTileBoundSkippedIterations - +=ResolvedLayout->passages.size(); - } - return density; - } - } - bool queryNearUpperMouthSupport=false; - const auto checkUpperMouth=[&](const auto& passage) - { - if(passageProfile)++passageProfile->passageUpperMouthFilterChecks; - const double dx=qx-static_cast(passage.upperMouthSubvoxels[0]); - const double dy=qy-static_cast(passage.upperMouthSubvoxels[1]); - const double dz=qz-static_cast(passage.upperMouthSubvoxels[2]); - const double reach=15.0*qPerMetre; - if(dx*dx+dy*dy<=reach*reach&&std::abs(dz)<=8.0*qPerMetre) - queryNearUpperMouthSupport=true; + double signedDistance=std::numeric_limits::infinity(); + double shellSignedDistance=std::numeric_limits::infinity(); + double roundSignedDistance=std::numeric_limits::infinity(); + double centerZ=0.0,floorCenterZ=0.0,radius=0.0,floorDepth=0.0; + double t=0.0,floorT=0.0; + std::size_t segmentIndex=0,floorSegmentIndex=0; + bool valid=false; + const FScopedPassageTileQueries::FPassageSweepSample* swept=nullptr; }; - if(passageTileScopeMatches) + double unionDistance=std::numeric_limits::infinity(); + double unionShellDistance=std::numeric_limits::infinity(); + const std::uint32_t reliefSeed=static_cast(Owner?Owner->Seed:0); + const auto* queryStratum=FindBoundStratumForManagerZ(Z); + for(std::size_t passageIndex=0;passageIndexpassages.size(); + ++passageIndex) { - for(const std::size_t passageIndex: - passageTileQueries->upperMouthSupportPassages()) - { - checkUpperMouth(ResolvedLayout->passages[passageIndex]); - if(queryNearUpperMouthSupport)break; - } - } - else - { - for(const auto& passage:ResolvedLayout->passages) - { - checkUpperMouth(passage); - if(queryNearUpperMouthSupport)break; - } - } - if(passageTileScopeMatches&&density>=0.0f - &&!passageTileQueries->hasRouteFeatureOverlap() - &&!passageTileQueries->hasColumnZOverlap() - &&!passageTileQueries->hasAnyMouthSupport() - &&!queryNearUpperMouthSupport)return density; - const double floorThicknessVoxels=qPerMetre/Q; - const double playerCenterAboveFloorQ=1.13*qPerMetre; - float composed=density; - float deferredSupportDensity=std::numeric_limits::infinity(); - const auto composeRouteMouthSupport=[&](std::size_t passageIndex) - { - VoxelForgeCore::Linux77Profiler::FScopedPhase l77MouthSupportPhase( - VoxelForgeCore::Linux77Profiler::EPhase::Support); - // Surface-route treads may reinforce native solid terrain only. - if(!(density<0.0f))return; - if(passageIndex>=ResolvedLayout->passages.size() - ||passageIndex>=PassageMouthSupportRoutes.size())return; const auto& passage=ResolvedLayout->passages[passageIndex]; - const auto& mouth=passage.upperMouthSubvoxels; - const double mouthDx=qx-static_cast(mouth[0]); - const double mouthDy=qy-static_cast(mouth[1]); - const double routeSupportReach=13.0*qPerMetre; - if(mouthDx*mouthDx+mouthDy*mouthDy>routeSupportReach*routeSupportReach)return; - const auto& route=PassageMouthSupportRoutes[passageIndex]; - if(route.empty())return; - constexpr double MouthSupportBlendMetres=0.45; - // Route anchors encode the player center at half the authored capsule - // height above the tread. Keep the support deck below that same foot - // plane so the route audit's 0.5 m support search reaches solid tread. - constexpr double RouteCenterAboveFootMetres=0.88; - const double mouthBlendWidth=MouthSupportBlendMetres*qPerMetre; - double mouthSupportDistance=std::numeric_limits::infinity(); - const auto evaluateSegment=[&](std::size_t index) - { - if(index>=route.size())return; - if(passageProfile)++passageProfile->passageMouthRouteSegmentChecks; - const auto& segment=route[index]; - const auto* l98TileQueries=ActivePassageTileQueries; - if(l98TileQueries&&l98TileQueries->matches(*this)) - l98TileQueries->recordPreparedSegmentUse( - FScopedPassageTileQueries::EPreparedSegmentUse::Mouth); - const double dx=segment.preparedDelta[0],dy=segment.preparedDelta[1]; - const double lengthSq=segment.horizontalLengthSq; - const double t=lengthSq>0.0?std::clamp( - PassageMouthSupportXYProjectionNumerator(passageIndex,index,qx,qy) - /lengthSq,0.0,1.0):0.0; - const double centerX=segment.preparedA[0]+t*dx, - centerY=segment.preparedA[1]+t*dy; - const double centerZ=segment.preparedA[2]+t*segment.preparedDelta[2]; - const double routeRadius=segment.hasRadius - ?segment.preparedA[3]+t*segment.preparedDelta[3]:0.0; - const double halfWidth=std::clamp(routeRadius, - 0.42*qPerMetre,0.56*qPerMetre); - const double horizontalX=qx-centerX,horizontalY=qy-centerY; - const double horizontalDistance=DeterministicSqrt( - horizontalX*horizontalX+horizontalY*horizontalY); - const double floorQ=centerZ-RouteCenterAboveFootMetres*qPerMetre - -0.25*qPerMetre; - const double sideDistance=horizontalDistance-halfWidth; - const double topDistance=qz-floorQ; - const double bottomDistance=floorQ-qPerMetre-qz; - const double verticalDistance=std::max(topDistance,bottomDistance); - if(sideDistance>mouthBlendWidth||verticalDistance>mouthBlendWidth)return; - if(l90CandidateProfiled) - { - const bool contained=PassageCandidateBrickContains(l90CandidateBrick,3, - passageIndex,static_cast(index),2); - passageTileQueries->recordL90ProofCheck(3,contained); - } - const double outside=DeterministicSqrt( - std::max(sideDistance,0.0)*std::max(sideDistance,0.0) - +std::max(verticalDistance,0.0)*std::max(verticalDistance,0.0)); - const double inside=std::min(std::max(sideDistance,verticalDistance),0.0); - mouthSupportDistance=std::min(mouthSupportDistance,outside+inside); - }; - if(passageTileScopeMatches) - { - for(const auto& candidate:passageTileQueries->mouthSupportSegments(passageIndex)) - { - const bool containsPoint=qx>=candidate.minimumSubvoxels[0] - &&qx<=candidate.maximumSubvoxels[0] - &&qy>=candidate.minimumSubvoxels[1] - &&qy<=candidate.maximumSubvoxels[1] - &&qz>=candidate.minimumSubvoxels[2] - &&qz<=candidate.maximumSubvoxels[2]; - if(containsPoint)evaluateSegment(candidate.segmentIndex); - } - } - else - { - for(std::size_t index=0;index(mouthSupportDistance/Q), - static_cast(mouthBlendWidth/Q)); - }; - // The connected passage tread continues the surface route into the tunnel. - const std::size_t passageIterationCount=ResolvedLayout->passages.size(); - struct FL90IterationTimer - { - const FScopedPassageTileQueries* scope=nullptr; - std::chrono::steady_clock::time_point start{}; - bool fallback=false; - std::uint8_t fallbackReason=0; - std::uint64_t carveVisits=0,treadVisits=0,clearanceChecks=0,mouthChecks=0; - void requireFallback(std::uint8_t reason) - {fallback=true;fallbackReason=reason;} - void recordCarve(){++carveVisits;} - void recordTread(){++treadVisits;} - void recordClearance(){++clearanceChecks;} - void recordMouth(){++mouthChecks;} - ~FL90IterationTimer() - { - if(scope&&fallback) - scope->recordL90Fallback(static_cast( - std::chrono::duration_cast( - std::chrono::steady_clock::now()-start).count()), - carveVisits,treadVisits,clearanceChecks,mouthChecks,fallbackReason); - } - }; - for(std::size_t passageIteration=0;passageIterationResolved + &&queryStratum->Resolved->passageCapabilities.hasNativeCaveField + &&passage.lowerStrateIndex==queryStratum->StrateIndex) + continue; if(passageProfile)++passageProfile->passageIterations; - const auto& passage=ResolvedLayout->passages[passageIndex]; - if(passage.controlPoints.size()<2)continue; - const auto& passageConstants=PassageComposerConstants[passageIndex]; - // A passage is internal when both mouths are bounded by their strate - // content and neither endpoint is a SurfaceWorld landing. Route order - // and the total number of strata are irrelevant. - const bool internalChainPassage=passageConstants.internalChainPassage; - const auto laterPassageMayCarve=[&](std::ptrdiff_t supportSegment, - double sampleX,double sampleY,double sampleZ) - { - l90IterationTimer.recordClearance(); - if(passageProfile)++passageProfile->passageLaterBoreChecks; - return PassageSupportMayBeCarvedByLaterBore(passageIndex, - supportSegment,sampleX,sampleY,sampleZ,0.35*qPerMetre); - }; - const bool floatingIslandPassage=passageConstants.floatingIslandPassage; - const bool surfaceToTunnelSupport=passageConstants.surfaceToTunnelSupport; - const double firstFloorQ=passageConstants.firstFloorQ; - const double lastFloorQ=passageConstants.lastFloorQ; - if(!passageTileScopeMatches - ||passageTileQueries->hasFeature(passageIndex,true)) - for(const auto& crossing:PassageVoidCrossings) - { - if(!crossing.needsColumn||crossing.passageIndex!=passageIndex - ||qz>crossing.topZSubvoxels||qz(crossing.firstSegment),3); - passageTileQueries->recordL90ProofCheck(4,contained); - if(!contained)l90IterationTimer.requireFallback(3); - } - else if(columnDistance(inputComposed)*Q) - l90IterationTimer.requireFallback(1); - }; - if(passageProfile)++passageProfile->passageColumnCandidates; -#if defined(VF_L30_ENABLE_COST_COUNTERS) - ++ThreadClassificationStats().ColumnZOverlapCalls; -#endif - double columnDistance; - const bool tileProvesColumnExterior=passageTileScopeMatches - &&!ActivePassageTileQueries->hasFeature(passageIndex,true); - if(tileProvesColumnExterior) - { -#if defined(VF_L30_ENABLE_COST_COUNTERS) - ++ThreadClassificationStats().ColumnGuardCalls; -#endif - if(composed<0.0f) - { -#if defined(VF_L30_ENABLE_COST_COUNTERS) - ++ThreadClassificationStats().ColumnGuardNonpositiveSkips; -#endif - continue; - } - const double dx=qx-crossing.centerXSubvoxels; - const double dy=qy-crossing.centerYSubvoxels; - const double horizontalSquared=dx*dx+dy*dy; - const double maximumRadius=static_cast(crossing.maximumRadiusSubvoxels); - const double exteriorLimit=maximumRadius - +static_cast(composed)*Q+1.0e-4; -#if defined(VF_L30_ENABLE_COST_COUNTERS) - if(horizontalSquared>exteriorLimit*exteriorLimit) - { - ++ThreadClassificationStats().ColumnGuardRadialRejects; - continue; - } - ++ThreadClassificationStats().ColumnSignedDistanceCalls; -#else - if(horizontalSquared>exteriorLimit*exteriorLimit)continue; -#endif - if(passageProfile)++passageProfile->passageColumnDistanceCalls; - columnDistance=PassageColumnSignedDistance(crossing,X,Y,Z); - } - else - { -#if defined(VF_L30_ENABLE_COST_COUNTERS) - ++ThreadClassificationStats().ColumnSignedDistanceCalls; -#endif - if(passageProfile)++passageProfile->passageColumnDistanceCalls; - columnDistance=PassageColumnSignedDistance(crossing,X,Y,Z); - } - if(l90CandidateProfiled)recordColumnProof(columnDistance,composed); - composed=std::min(composed,static_cast(columnDistance/Q)); - } - const bool preparedPassageSweepRequested=passageTileScopeMatches - &&passageCarveReachEnabled + if(passageTileScopeMatches&&!passageTileQueries->hasRouteFeature(passageIndex)) + continue; + const auto& constants=PassageComposerConstants[passageIndex]; + + FNearestTubeSample nearest; + const bool usePreparedSweep=passageTileScopeMatches &&passageTileQueries->hasSweptTubeBase(); - const auto* preparedSweepSample=preparedPassageSweepRequested + const auto* swept=usePreparedSweep ?passageTileQueries->sweptSample(passageIndex,qx,qy,qz):nullptr; - // The sweep is indexed at the tile's exact lattice points. Mesher and seam - // queries can also arrive at interpolated off-grid positions; a cache miss - // at those points says nothing about route influence, so use the exact direct - // route search instead of dropping the carve. - const bool usePreparedPassageSweep=preparedSweepSample!=nullptr; - // Candidate route bounds include the carve reach, tread/clearance extents, - // and conservative padding. A missing lattice sample outside every route - // bound cannot affect this query, even when another segment or column in - // this tile overlaps elsewhere. Column composition above and mouth-support - // paths below remain separate and are preserved. - if(preparedPassageSweepRequested&&!preparedSweepSample - &&!passageTileQueries->hasMouthSupport(passageIndex) - &&!passageTileQueries->hasUpperMouthSupport(passageIndex) - &&!passageTileQueries->routeFeatureMayAffect(passageIndex,qx,qy,qz)) + if(swept) { - passageTileQueries->recordFeatureBoundSkip(); - continue; - } - if(usePreparedPassageSweep - &&preparedSweepSample->signedDistance>passageCarveReachQ)continue; - const bool tilePassageFree=passageTileScopeMatches - &&!ActivePassageTileQueries->hasFeature(passageIndex,false); - if(composed>=0.0f&&tilePassageFree) - { - if(preparedPassageSweepRequested&&!preparedSweepSample) - passageTileQueries->recordSweepMissSkip( - FScopedPassageTileQueries::ESweepMissSkipReason::TileFree); - continue; - } - if(qz>firstFloorQ+2.0*passage.mouthRadiusSubvoxels - ||qzrecordSweepMissSkip( - FScopedPassageTileQueries::ESweepMissSkipReason::VerticalBound); - continue; - } - const std::ptrdiff_t lastIndex=passageConstants.lastIndex; - const std::ptrdiff_t lowerMouthIndex=passageConstants.lowerMouthIndex; - const auto& floorProfileQ=passageConstants.controlFloorProfileQ; - // The tube radius is measured from its centerline, while floorProfile is - // one player-center offset away. Search the full vertical radius of the SDF; - // a narrow point window misses earlier turns of a low-pitch helix. - const double carveSearchMargin=passageConstants.carveSearchMargin; - const auto compareFloorProfile=[&](double floorProfile,double value) - { - if(passageTileScopeMatches) - passageTileQueries->recordPreparedFloorProfileRead(); - return floorProfile>value; - }; - const auto carveHigh=std::lower_bound(floorProfileQ.begin(), - floorProfileQ.begin()+lowerMouthIndex+1, - qz+carveSearchMargin, - compareFloorProfile); - const auto carveLow=std::lower_bound(floorProfileQ.begin(), - floorProfileQ.begin()+lowerMouthIndex+1, - qz-carveSearchMargin, - compareFloorProfile); - const std::ptrdiff_t carveBegin=std::max(0, - (carveHigh-floorProfileQ.begin())-1); - const std::ptrdiff_t carveEnd=std::min(lowerMouthIndex-1, - (carveLow-floorProfileQ.begin())+1); - const std::ptrdiff_t mouthSearchBegin=passageConstants.mouthSearchBegin; - const std::ptrdiff_t mouthSearchEnd=passageConstants.mouthSearchEnd; - if(l90CandidateProfiled) - { - const double signedDistanceLimit=carveSourceReachQ(composed); - const bool sourceProofAvailable=L90PassageCandidateProgramValid - &&std::isfinite(signedDistanceLimit) - &&signedDistanceLimit<=L90PassageCandidateReachMetres*qPerMetre - &&!(density>=0.0f&&PassageHasShortSpanSegments(passageIndex)); - if(!sourceProofAvailable) - { - const std::uint8_t reason=!L90PassageCandidateProgramValid - ||!std::isfinite(signedDistanceLimit)?0 - :signedDistanceLimit>L90PassageCandidateReachMetres*qPerMetre?1:2; - l90IterationTimer.requireFallback(reason); - } - } - if(density<0.0f&&tilePassageFree) - { - // A tile without this passage's route feature cannot contain its separate - // tread/support work, so the carve reach is sufficient for this query skip. - if(passageProfile)++passageProfile->passageNegativeBoundChecks; - if(!PassageMayAffectDensity(passageIndex,carveBegin,carveEnd, - lowerMouthIndex,mouthSearchBegin,mouthSearchEnd,lastIndex,qx,qy,qz, - carveSourceReachQ(composed))) - { - if(passageProfile)++passageProfile->passageNegativeBoundRejects; - if(preparedPassageSweepRequested&&!preparedSweepSample) - passageTileQueries->recordSweepMissSkip( - FScopedPassageTileQueries::ESweepMissSkipReason::NegativeReach); - continue; - } - } - // For a positive source sample, the tube can only change it within relief reach; - // the supported column tread is within 2.25 m of its centerline. A short-span - // bridge's positive exterior SDF is not bounded this way, so keep its full query. - // Pour un échantillon source positif, le tube ne change le champ qu'à portée du relief ; - // le plancher du pilier reste à 2,25 m de son axe. Le SDF extérieur d'une courte passerelle - // n'a pas cette borne, donc sa requête complète est conservée. - const bool canCullPositiveRoute=passageTileScopeMatches&&density>=0.0f - &&!PassageHasShortSpanSegments(passageIndex); - if(canCullPositiveRoute) - { - if(passageProfile)++passageProfile->passagePositiveBoundChecks; - if(!PassageMayAffectDensity(passageIndex,carveBegin,carveEnd, - lowerMouthIndex,mouthSearchBegin,mouthSearchEnd,lastIndex,qx,qy,qz, - carveSourceReachQ(composed))) - { - if(passageProfile)++passageProfile->passagePositiveBoundRejects; - if(preparedPassageSweepRequested&&!preparedSweepSample) - passageTileQueries->recordSweepMissSkip( - FScopedPassageTileQueries::ESweepMissSkipReason::PositiveReach); - continue; - } - } - double bestSignedDistance=std::numeric_limits::infinity(); - double bestPlayerCapsuleSignedDistance=std::numeric_limits::infinity(); - double bestT=0.0; - std::ptrdiff_t bestIndex=0; - int bestScanPhase=std::numeric_limits::max(); - std::ptrdiff_t bestScanIndex=std::numeric_limits::max(); - std::ptrdiff_t bestSupportSegmentIndex=0; - bool hasSupportFloor=false; - bool bestSupportIsMouthTread=false; - double bestSupportMouthBlend=1.0; - double bestSupportDistanceSquared=std::numeric_limits::infinity(); - double bestSupportDensity=std::numeric_limits::infinity(); - double bestSupportNativeBlend=0.0; - double bestSupportFloorQ=0.0; - bool bestSupportUsesSignedDistance=false; - std::ptrdiff_t selectedSupportSegmentIndex=-1; - const double lowerMouthDx=qx-passage.lowerMouthSubvoxels[0]; - const double lowerMouthDy=qy-passage.lowerMouthSubvoxels[1]; - const double lowerMouthDz=qz-passage.lowerMouthSubvoxels[2]; - const double lowerMouthDistance=DeterministicSqrt( - lowerMouthDx*lowerMouthDx+lowerMouthDy*lowerMouthDy - +lowerMouthDz*lowerMouthDz)/qPerMetre; - const double lowerMouthT=std::clamp((20.0-lowerMouthDistance)/12.0,0.0,1.0); - if(passageProfile)++passageProfile->passageSmoothstepEvaluations; - const double lowerMouthBlend=lowerMouthT*lowerMouthT - *(3.0-2.0*lowerMouthT); - const auto considerCarveSegment=[&](std::size_t segmentIndex,int scanPhase) - { - l90IterationTimer.recordCarve(); - if(passageProfile)++passageProfile->passageCarveSegmentVisits; - const FPassageSegmentData& segment=GetPassageSegmentData( - passageIndex,segmentIndex); - if(passageTileScopeMatches) - passageTileQueries->recordPreparedSegmentUse( - FScopedPassageTileQueries::EPreparedSegmentUse::Carve); - const std::ptrdiff_t index=static_cast(segmentIndex); - const double ax=segment.a[0],ay=segment.a[1],az=segment.a[2]; - const double dx=segment.delta[0],dy=segment.delta[1],dz=segment.delta[2]; - const double lengthSq=segment.lengthSq; - if(lengthSq<=0.0)return; - const double projectionXY=PassageXYProjectionNumerator( - passageIndex,segmentIndex,qx,qy); - const double t=std::clamp((projectionXY+(qz-az)*dz)/lengthSq,0.0,1.0); - if(!passageTileScopeMatches) - { - const double horizontalLengthSq=segment.horizontalLengthSq; - const double playerT=horizontalLengthSq>0.0 - ?std::clamp(projectionXY/horizontalLengthSq,0.0,1.0):t; - const double playerDx=qx-(ax+playerT*dx); - const double playerDy=qy-(ay+playerT*dy); - const double playerRadius=segment.radiusA+playerT*segment.radiusDelta; - const double playerCenterZ=az+playerT*dz-playerRadius+playerCenterAboveFloorQ; - const double playerVertical=std::max(0.0, - std::abs(qz-playerCenterZ)-0.54*qPerMetre); - bestPlayerCapsuleSignedDistance=std::min(bestPlayerCapsuleSignedDistance, - DeterministicSqrt(playerDx*playerDx+playerDy*playerDy - +playerVertical*playerVertical)-0.34*qPerMetre); - } - double cx=ax+t*dx,cy=ay+t*dy,cz=az+t*dz; - const bool smoothCarveJoin=index>2 - &&index+(internalChainPassage?2:12)passageSmoothCarveJoins; - constexpr double SmoothJoinWeight=1.0; - const double t2=t*t,t3=t2*t; - for(std::size_t axis=0;axis<3;++axis) - { - const double v0=segment.catmullBefore[axis]; - const double v1=segment.a[axis]; - const double v2=segment.b[axis]; - const double v3=segment.catmullAfter[axis]; - const double curve=0.5*((2.0*v1)+(-v0+v2)*t - +(2.0*v0-5.0*v1+4.0*v2-v3)*t2 - +(-v0+3.0*v1-3.0*v2+v3)*t3); - const double line=axis==0?cx:axis==1?cy:cz; - const double blended=line+(curve-line)*SmoothJoinWeight; - if(axis==0)cx=blended; - else if(axis==1)cy=blended; - else cz=blended; - } - } - const double ex=qx-cx,ey=qy-cy,ez=qz-cz; - const double radius=segment.radiusA+t*segment.radiusDelta; - const double signedDistance=DeterministicSqrt(ex*ex+ey*ey+ez*ez)-radius; - if(signedDistancesignedDistance; - bestT=preparedSweepSample->t; - bestIndex=static_cast(preparedSweepSample->segmentIndex); - bestScanPhase=preparedSweepSample->scanPhase; - bestScanIndex=bestIndex; - } - else if(passageTileScopeMatches) - { - passageTileQueries->recordExactRouteFallback(); - VisitNearestPassageSegmentRange(passageIndex,carveBegin,carveEnd,qx,qy,qz, - 0,bestSignedDistance,considerCarveSegment); - VisitNearestPassageSegmentRange(passageIndex,0, - std::min(8,lowerMouthIndex)-1,qx,qy,qz, - 1,bestSignedDistance,considerCarveSegment); - VisitNearestPassageSegmentRange(passageIndex,mouthSearchBegin,mouthSearchEnd-1, - qx,qy,qz,2,bestSignedDistance,considerCarveSegment); - VisitNearestPassageSegmentRange(passageIndex,lowerMouthIndex,lastIndex-1, - qx,qy,qz,3,bestSignedDistance,considerCarveSegment); + nearest.signedDistance=swept->signedDistance; + nearest.shellSignedDistance=swept->shellSignedDistance; + nearest.roundSignedDistance=swept->roundSignedDistance; + nearest.segmentIndex=swept->segmentIndex; + nearest.t=swept->t; + nearest.centerZ=swept->centerZSubvoxels; + nearest.floorCenterZ=swept->floorCenterZSubvoxels; + nearest.radius=swept->radiusSubvoxels; + nearest.floorDepth=swept->floorDepthSubvoxels; + nearest.floorSegmentIndex=swept->floorSegmentIndex; + nearest.floorT=swept->floorT; + nearest.valid=true; + nearest.swept=swept; } else { - for(std::ptrdiff_t index=carveBegin;index<=carveEnd;++index) - considerCarveSegment(static_cast(index),0); - for(std::ptrdiff_t index=0;index(8,lowerMouthIndex);++index) - considerCarveSegment(static_cast(index),1); - for(std::ptrdiff_t index=mouthSearchBegin;index(index),2); - for(std::ptrdiff_t index=lowerMouthIndex;index(index),3); + if(usePreparedSweep) + { + if(!passageTileQueries->routeFeatureMayAffect(passageIndex,qx,qy,qz)) + { + passageTileQueries->recordFeatureBoundSkip(); + continue; + } + passageTileQueries->recordExactRouteFallback(); + } + + const std::ptrdiff_t lastIndex=static_cast( + PassageSegmentData[passageIndex].size())-1; + const auto& segments=PassageSegmentData[passageIndex]; + double bestDistance=std::numeric_limits::infinity(); + double bestFloorCenterDistanceSq=std::numeric_limits::infinity(); + const auto visitSegment=[&](std::size_t segmentIndex,int) + { + if(passageProfile)++passageProfile->passageCarveSegmentVisits; + const auto& segment=PassageSegmentData[passageIndex][segmentIndex]; + if(segment.lengthSq<=0.0)return; + const double projection=(qx-segment.a[0])*segment.delta[0] + +(qy-segment.a[1])*segment.delta[1] + +(qz-segment.a[2])*segment.delta[2]; + const double t=std::clamp(projection/segment.lengthSq,0.0,1.0); + double cx=segment.a[0]+t*segment.delta[0]; + double cy=segment.a[1]+t*segment.delta[1]; + double cz=segment.a[2]+t*segment.delta[2]; + const double radius=segment.radiusA+t*segment.radiusDelta; + const double ex=qx-cx,ey=qy-cy,ez=qz-cz; + const double roundDistance=DeterministicSqrt( + ex*ex+ey*ey+ez*ez)-radius; + const double floorT=segment.horizontalLengthSq>1.0e-12 + ?(((qx-segment.a[0])*segment.delta[0] + +(qy-segment.a[1])*segment.delta[1]) + /segment.horizontalLengthSq):t; + const double floorTClamped=std::clamp(floorT,0.0,1.0); + const double floorCenterDistanceSq=ex*ex+ey*ey+ez*ez; + const double floorRadius=segment.radiusA + +floorTClamped*segment.radiusDelta; + const double floorDepth=PassageFlatFloorDepthSubvoxels( + constants,segmentIndex,floorTClamped,floorRadius,qPerMetre); + const double floorCenterZ=PassageFlatFloorCenterZSubvoxels( + constants,segments,segmentIndex,floorT,segment, + qx,qy,floorDepth,qPerMetre); + const double flatDistance=PassageFlatBottomDistance( + static_cast(roundDistance),floorCenterZ,qz,floorDepth,qPerMetre); + // The profile uses the closest route projection's arc length. Tube + // radius selects the bore shape only; it never selects floor height. + if(floorCenterDistanceSq(nearest.roundSignedDistance), + nearest.floorCenterZ,qz,nearest.floorDepth,qPerMetre); + + // Shells form a union over nearby route segments, even when another + // segment supplies the nearest interior distance. The hierarchy bound + // is deliberately wider than the shell so its radius and corner blend + // cannot prune a segment that contributes a boundary shell. + double shellSearchBound=2.0*qPerMetre; + const auto visitShellSegment=[&](std::size_t segmentIndex,int) + { + const auto& segment=PassageSegmentData[passageIndex][segmentIndex]; + if(segment.lengthSq<=0.0)return; + const double projection=(qx-segment.a[0])*segment.delta[0] + +(qy-segment.a[1])*segment.delta[1] + +(qz-segment.a[2])*segment.delta[2]; + const double t=std::clamp(projection/segment.lengthSq,0.0,1.0); + const double cx=segment.a[0]+t*segment.delta[0]; + const double cy=segment.a[1]+t*segment.delta[1]; + const double cz=segment.a[2]+t*segment.delta[2]; + const double radius=segment.radiusA+t*segment.radiusDelta; + const double ex=qx-cx,ey=qy-cy,ez=qz-cz; + const double roundDistance=DeterministicSqrt(ex*ex+ey*ey+ez*ez)-radius; + const double floorT=segment.horizontalLengthSq>1.0e-12 + ?(((qx-segment.a[0])*segment.delta[0] + +(qy-segment.a[1])*segment.delta[1]) + /segment.horizontalLengthSq):t; + const double floorTClamped=std::clamp(floorT,0.0,1.0); + const auto& segments=PassageSegmentData[passageIndex]; + const double floorRadius=segment.radiusA + +floorTClamped*segment.radiusDelta; + const double floorDepth=PassageFlatFloorDepthSubvoxels( + constants,segmentIndex,floorTClamped,floorRadius,qPerMetre); + const double floorCenterZ=PassageFlatFloorCenterZSubvoxels( + constants,segments,segmentIndex,floorT,segment, + qx,qy,floorDepth,qPerMetre); + const double flatDistance=PassageFlatBottomDistance( + static_cast(roundDistance),floorCenterZ,qz,floorDepth,qPerMetre); + const double alongMetres=segment.authoredAlongMetres + +t*segment.authoredLengthMetres; + const double mouthDistanceMetres=std::max(0.0,std::min(alongMetres, + constants.totalPathLengthMetres-alongMetres)); + const double shellFade=std::clamp(mouthDistanceMetres/ + MouthShellBlendMetres,0.0,1.0); + const double smoothShellFade=shellFade*shellFade + *(3.0-2.0*shellFade); + const double floorDistanceMetres=(floorCenterZ-floorDepth-qz) + /qPerMetre; + const double floorBlend=std::clamp(floorDistanceMetres/0.25,0.0,1.0); + const double smoothFloorBlend=floorBlend*floorBlend + *(3.0-2.0*floorBlend); + const double wallElevationMetres=(qz-(floorCenterZ-floorDepth)) + /qPerMetre; + const double mouthWallThickness=segment.routeSegment + ?smoothShellFade*shellThickness:0.0; + double floorExtensionFade=1.0; + if(!segment.routeSegment) + { + const double pastMouthMetres=std::max(0.0,alongMetres + -constants.totalPathLengthMetres); + const double extensionFade=std::clamp(1.0 + -pastMouthMetres/MouthShellBlendMetres,0.0,1.0); + floorExtensionFade=extensionFade*extensionFade + *(3.0-2.0*extensionFade); + } + const double floorShellThickness=smoothFloorBlend*shellThickness + *floorExtensionFade*smoothShellFade; + const double wallShellDistance=PassageRoundedWallShellDistance( + flatDistance,wallElevationMetres*qPerMetre, + OpenAirSideWallHeightMetres*qPerMetre,mouthWallThickness); + const double floorShellDistance=std::max(-static_cast(flatDistance), + static_cast(flatDistance)-floorShellThickness); + const double localShellDistance=std::min(wallShellDistance, + floorShellDistance); + nearest.shellSignedDistance=std::min(nearest.shellSignedDistance, + localShellDistance); + }; + double shellFloorSearchBoundSq=-1.0; + VisitNearestPassageSegmentRange(passageIndex,0,lastIndex-1, + qx,qy,qz,0,shellSearchBound,shellFloorSearchBoundSq, + visitShellSegment); } - if(!std::isfinite(bestSignedDistance))continue; - const double l90SignedDistanceLimit=carveSourceReachQ(composed); - if(l90CandidateProfiled&&bestSignedDistance<=l90SignedDistanceLimit - &&l90SignedDistanceLimit<=L90PassageCandidateReachMetres*qPerMetre) - passageTileQueries->recordL90ProofCheck(0, - L90PassageCandidateProgramValid - &&PassageCandidateBrickContains(l90CandidateBrick,0,passageIndex, - static_cast(bestIndex))); - const FPassageSegmentData& nearestSegment=PassageSegmentData[passageIndex][ - static_cast(bestIndex)]; - const double nearestRadius=nearestSegment.radiusA - +bestT*nearestSegment.radiusDelta; - const double distanceToCenter=std::max(1.0e-9,bestSignedDistance+nearestRadius); + if(!nearest.valid)continue; + const double wallElevationMetres=(qz-(nearest.floorCenterZ + -nearest.floorDepth))/qPerMetre; + double distanceToCenter=std::max(1.0e-9, + nearest.roundSignedDistance+nearest.radius); const double verticalWallAlignment=distanceToCenter>1.0e-9 - ?std::clamp(-(qz-(nearestSegment.a[2]+bestT*nearestSegment.delta[2])) - /distanceToCenter,0.0,1.0):0.0; - const std::uint32_t passageReliefSeed=static_cast(Owner?Owner->Seed:0); - float cachedWallRelief=0.0f,cachedMouthSurfaceRelief=0.0f, - cachedMouthTreadFieldRelief=0.0f; - bool hasCachedWallRelief=false,hasCachedMouthSurfaceRelief=false, - hasCachedMouthTreadFieldRelief=false; - const auto getWallRelief=[&]() + ?std::clamp(-(qz-nearest.centerZ)/distanceToCenter,0.0,1.0):0.0; + const double crestFade=std::clamp((OpenAirSideWallHeightMetres + -wallElevationMetres)/0.25,0.0,1.0); + const double smoothCrestFade=crestFade*crestFade*(3.0-2.0*crestFade); + const double wallReliefWeight=(0.05+0.95*(1.0-verticalWallAlignment)) + *smoothCrestFade; + float relief=0.0f; + if(nearest.swept) { - if(!hasCachedWallRelief) - { - if(usePreparedPassageSweep) - cachedWallRelief=preparedSweepSample->hasWallRelief - ?preparedSweepSample->wallRelief:0.0f; - else - { - cachedWallRelief=VF_FieldPassageWallRelief(static_cast(X), - static_cast(Y),static_cast(Z),passageReliefSeed); - if(passageProfile)++passageProfile->passageReliefFieldCalls; - } - hasCachedWallRelief=true; - } - return cachedWallRelief; - }; - const auto getMouthSurfaceRelief=[&]() - { - if(!hasCachedMouthSurfaceRelief) - { - if(usePreparedPassageSweep - &&preparedSweepSample->hasMouthSurfaceRelief) - cachedMouthSurfaceRelief=preparedSweepSample->mouthSurfaceRelief; - else - { - cachedMouthSurfaceRelief=VF_FieldSurfaceRelief( - static_cast(X)*1.5f,static_cast(Y)*1.5f, - static_cast(Z)*1.5f,passageReliefSeed^0x4D4F5554u); - if(passageProfile)++passageProfile->passageReliefFieldCalls; - } - hasCachedMouthSurfaceRelief=true; - } - return cachedMouthSurfaceRelief; - }; - const auto getMouthTreadFieldRelief=[&]() - { - if(!hasCachedMouthTreadFieldRelief) - { - if(usePreparedPassageSweep - &&preparedSweepSample->hasMouthTreadFieldRelief) - cachedMouthTreadFieldRelief= - preparedSweepSample->mouthTreadFieldRelief; - else - { - cachedMouthTreadFieldRelief=VF_FieldSurfaceRelief( - static_cast(X)*0.75f,static_cast(Y)*0.75f, - static_cast(Z)*0.75f,passageReliefSeed^0x54485244u); - if(passageProfile)++passageProfile->passageReliefFieldCalls; - } - hasCachedMouthTreadFieldRelief=true; - } - return cachedMouthTreadFieldRelief; - }; - const auto routeSegmentLengthMetres=[&](std::ptrdiff_t routeIndex) - { - if(passageTileScopeMatches) - passageTileQueries->recordPreparedSegmentUse( - FScopedPassageTileQueries::EPreparedSegmentUse::Mouth); - return PassageSegmentData[passageIndex][ - static_cast(routeIndex)].lengthMetres; - }; - double distanceFromOpenMouth=std::numeric_limits::infinity(); - if(bestIndex<=2) - { - distanceFromOpenMouth=bestT*routeSegmentLengthMetres(bestIndex); - for(std::ptrdiff_t routeIndex=0;routeIndexhasWallRelief)relief=nearest.swept->wallRelief; } - else if(bestIndex>=lowerMouthIndex-2&&bestIndex<=lowerMouthIndex+2) + else { - if(bestIndexpassageReliefFieldCalls; } - double mouthEntryFloorAlignment=0.0; - double mouthEntryPlanDistance=std::numeric_limits::infinity(); - double mouthEntryFloorQ=0.0; - bool upperMouthFloorFade=false; + const double roughRoundDistance=nearest.roundSignedDistance + +static_cast(std::clamp(relief,-1.0f,1.0f)) + *WallReliefMetres*qPerMetre*wallReliefWeight; + const double shapedDistance=PassageFlatBottomDistance( + static_cast(roughRoundDistance),nearest.floorCenterZ,qz, + nearest.floorDepth,qPerMetre); + const auto& segment=PassageSegmentData[passageIndex][nearest.segmentIndex]; + const auto& floorSegment=PassageSegmentData[passageIndex][nearest.floorSegmentIndex]; + const double alongMetres=segment.authoredAlongMetres + +nearest.t*segment.authoredLengthMetres; + const double mouthDistanceMetres=std::max(0.0,std::min(alongMetres, + constants.totalPathLengthMetres-alongMetres)); + const double shellFade=std::clamp(mouthDistanceMetres/ + MouthShellBlendMetres,0.0,1.0); + const double smoothShellFade=shellFade*shellFade*(3.0-2.0*shellFade); + // Ease both wall and floor shell into the host ground over five metres. + // The floor shell remains below the floor plane throughout that blend. + const double floorDistanceMetres=(nearest.floorCenterZ + -nearest.floorDepth-qz)/qPerMetre; + const double floorBlend=std::clamp(floorDistanceMetres/0.25,0.0,1.0); + const double smoothFloorBlend=floorBlend*floorBlend + *(3.0-2.0*floorBlend); + const double mouthWallThickness=segment.routeSegment + ?smoothShellFade*shellThickness:0.0; + double floorExtensionFade=1.0; + if(!floorSegment.routeSegment) { - // The large mouth bore overlaps several inner coils. Its global - // nearest SDF can belong to a later turn even at the lip, so use the - // projected entrance path to recover the local floor orientation. - double prefixMetres=0.0; - double nearestEntryPlanDistance=std::numeric_limits::infinity(); - double projectedEntryDistance=std::numeric_limits::infinity(); - for(std::ptrdiff_t routeIndex=0; - routeIndex(3,lowerMouthIndex);++routeIndex) - { - if(passageProfile)++passageProfile->passageMouthRouteSegmentChecks; - const FPassageSegmentData& routeSegment=PassageSegmentData[ - passageIndex][static_cast(routeIndex)]; - if(passageTileScopeMatches) - passageTileQueries->recordPreparedSegmentUse( - FScopedPassageTileQueries::EPreparedSegmentUse::Mouth); - const double ax=routeSegment.a[0],ay=routeSegment.a[1], - az=routeSegment.a[2]; - const double dx=routeSegment.delta[0],dy=routeSegment.delta[1], - dz=routeSegment.delta[2]; - const double horizontalLengthSq=routeSegment.horizontalLengthSq; - const double t=horizontalLengthSq>0.0?std::clamp( - PassageXYProjectionNumerator(passageIndex, - static_cast(routeIndex),qx,qy) - /horizontalLengthSq,0.0,1.0):0.0; - double projectedX=ax+t*dx,projectedY=ay+t*dy; - const double horizontalLength=routeSegment.horizontalLength; - if(horizontalLength>1.0e-6) - { - const double pathRelief=std::clamp(static_cast( - VF_FieldSurfaceRelief(static_cast(projectedX/qPerMetre*1.5), - static_cast(projectedY/qPerMetre*1.5), - static_cast((az+t*dz)/qPerMetre*1.5), - static_cast(Owner?Owner->Seed:0)^0x4D4F5554u)), - -1.0,1.0); - if(passageProfile)++passageProfile->passageReliefFieldCalls; - const double lateralOffset=pathRelief*0.18*qPerMetre; - projectedX-=dy/horizontalLength*lateralOffset; - projectedY+=dx/horizontalLength*lateralOffset; - } - const double planDx=qx-projectedX,planDy=qy-projectedY; - const double planDistance=DeterministicSqrt(planDx*planDx+planDy*planDy); - if(planDistance1.0e-9 - ?std::clamp(-(qz-centerZ)/centerDistance,0.0,1.0):0.0; - projectedEntryDistance=prefixMetres - +t*routeSegmentLengthMetres(routeIndex); - } - prefixMetres+=routeSegmentLengthMetres(routeIndex); - } - if(nearestEntryPlanDistance<=2.0*qPerMetre - &&projectedEntryDistance<=8.0 - &&std::abs(qz-mouthEntryFloorQ)<=4.0*qPerMetre) - { - distanceFromOpenMouth=projectedEntryDistance; - mouthEntryPlanDistance=nearestEntryPlanDistance/qPerMetre; - upperMouthFloorFade=true; - } - } - double mouthFloorBlend=0.0; - if(std::isfinite(distanceFromOpenMouth)) - { - const double fade=std::clamp(distanceFromOpenMouth/11.0,0.0,1.0); - if(passageProfile)++passageProfile->passageSmoothstepEvaluations; - const double smooth=fade*fade*(3.0-2.0*fade); - mouthFloorBlend=1.0-smooth; - } - const double floorReliefT=std::clamp((verticalWallAlignment-0.55)/0.45,0.0,1.0); - if(passageProfile)++passageProfile->passageSmoothstepEvaluations; - const double floorReliefWeight=floorReliefT*floorReliefT - *(3.0-2.0*floorReliefT); - const double wallOpening=1.0-verticalWallAlignment; - const double wallReliefWeight=0.05+0.95*wallOpening; - const bool shortSpanCarve=IsPassageShortSpanSegment(passageIndex, - static_cast(bestIndex)); - float carveInputAfterBridge=composed; - if(shortSpanCarve) - { - if(l90CandidateProfiled) - { - const bool contained=PassageCandidateBrickContains(l90CandidateBrick,3, - passageIndex,static_cast(bestIndex),4); - passageTileQueries->recordL90ProofCheck(5,contained); - } - carveInputAfterBridge=std::min(composed,static_cast( - PassageBridgeSignedDistance(passageIndex, - static_cast(bestIndex),X,Y,Z)/Q)); - } - const double maximumWallReliefOffset=0.21*qPerMetre*wallReliefWeight; - const double maximumMouthFloorReliefOffset=upperMouthFloorFade - ?0.20*qPerMetre*mouthFloorBlend*floorReliefWeight:0.0; - const double maximumCarvedDensity=-(bestSignedDistance - -maximumWallReliefOffset-maximumMouthFloorReliefOffset)/Q; - const bool wallReliefCanChangeCarve=!std::isfinite(maximumCarvedDensity) - ||maximumCarvedDensity>static_cast(carveInputAfterBridge); - const float relief=wallReliefCanChangeCarve?getWallRelief():0.0f; - const float mouthTerrainRelief=upperMouthFloorFade - ?getMouthSurfaceRelief():0.0f; - const double floorReliefOffset=std::clamp( - static_cast(mouthTerrainRelief),-1.0,1.0) - *0.20*qPerMetre*mouthFloorBlend*floorReliefWeight - *(upperMouthFloorFade?1.0:0.0); - const double roughSignedDistance=bestSignedDistance - +static_cast(std::clamp(relief,-1.0f,1.0f))*0.21*qPerMetre*wallReliefWeight - +floorReliefOffset; - if(shortSpanCarve)composed=carveInputAfterBridge; - // Leave native crater ground at the lip. The bore opens through the walls - // immediately, while its floor cut eases in along the passage centerline. - double mouthCarveFade=1.0; - if(upperMouthFloorFade) - { - constexpr double mouthCarveFadeMetres=8.0; - mouthCarveFade=std::clamp(distanceFromOpenMouth/mouthCarveFadeMetres, - 0.0,1.0); - if(passageProfile)++passageProfile->passageSmoothstepEvaluations; - mouthCarveFade=mouthCarveFade*mouthCarveFade*(3.0-2.0*mouthCarveFade); - } - const double floorAlignment=std::max(verticalWallAlignment, - mouthEntryFloorAlignment)*std::max(verticalWallAlignment, - mouthEntryFloorAlignment); - double floorBelowWeight=0.0; - if(upperMouthFloorFade) - { - const double belowFloor=(mouthEntryFloorQ-qz)/qPerMetre; - const double supportRamp=std::clamp(belowFloor/0.15,0.0,1.0); - const double supportFade=std::clamp((1.0-belowFloor)/0.35,0.0,1.0); - if(passageProfile)passageProfile->passageSmoothstepEvaluations+=2; - const double rampSmooth=supportRamp*supportRamp*(3.0-2.0*supportRamp); - const double fadeSmooth=supportFade*supportFade*(3.0-2.0*supportFade); - floorBelowWeight=rampSmooth*fadeSmooth; - } - // Preserve native terrain only along a capsule-scale worn lane. The - // former bore-wide alignment feather left a straight platform-width - // bridge across the FI mouth. - double mouthWalkLaneT=std::clamp((1.05-mouthEntryPlanDistance)/0.60,0.0,1.0); - if(passageProfile)++passageProfile->passageSmoothstepEvaluations; - mouthWalkLaneT=mouthWalkLaneT*mouthWalkLaneT*(3.0-2.0*mouthWalkLaneT); - const double mouthWalkLaneWeight=upperMouthFloorFade?mouthWalkLaneT:0.0; - const double floorCarveWeight=1.0-(1.0-mouthCarveFade) - *floorAlignment*floorAlignment*floorBelowWeight*mouthWalkLaneWeight; - const float fullyCarvedDensity=std::max(composed, - static_cast(-roughSignedDistance/Q)); - double carveReachWeight=1.0; - if(passageCarveReachEnabled) - { - constexpr double ReachBlendWidthMetres=0.5; - const double blendWidthQ=std::min(ReachBlendWidthMetres, - passageCarveReachMetres)*qPerMetre; - const double fade=std::clamp((passageCarveReachQ-bestSignedDistance) - /std::max(1.0,blendWidthQ),0.0,1.0); - if(passageProfile)++passageProfile->passageSmoothstepEvaluations; - carveReachWeight=fade*fade*(3.0-2.0*fade); - } - static const bool bL75TraceTnPassage=[] - { - const char* Value=std::getenv("VOXELFORGE_L75_TN_BLOCK_REGRESSION"); - return Value&&Value[0]=='1'&&Value[1]=='\0'; - }(); - const float passageInput=composed; - composed=std::lerp(composed,fullyCarvedDensity, - static_cast(floorCarveWeight*carveReachWeight)); - if(bL75TraceTnPassage&&X==-80.0f&&Y==-20.0f&&Z==-3218.0f - &&composed!=passageInput) - { - const auto& traceA=passage.controlPoints[static_cast(bestIndex)]; - const auto& traceB=passage.controlPoints[static_cast(bestIndex+1)]; - std::printf("[L75TNPassageTrace] passage=%zu segment=%td t=%.9g input=%.9g output=%.9g signed=%.9g rough=%.9g carve_weight=%.9g bounds=(%lld,%lld,%lld)..(%lld,%lld,%lld)\n", - passageIndex,bestIndex,bestT,passageInput,composed,bestSignedDistance, - roughSignedDistance,floorCarveWeight, - static_cast(std::min(traceA.positionSubvoxels[0],traceB.positionSubvoxels[0])), - static_cast(std::min(traceA.positionSubvoxels[1],traceB.positionSubvoxels[1])), - static_cast(std::min(traceA.positionSubvoxels[2],traceB.positionSubvoxels[2])), - static_cast(std::max(traceA.positionSubvoxels[0],traceB.positionSubvoxels[0])), - static_cast(std::max(traceA.positionSubvoxels[1],traceB.positionSubvoxels[1])), - static_cast(std::max(traceA.positionSubvoxels[2],traceB.positionSubvoxels[2]))); - } - const float composedAfterCarve=composed; - const auto considerSupportSegment=[&](std::ptrdiff_t index) - { - l90IterationTimer.recordTread(); - if(passageProfile)++passageProfile->passageSupportSegmentVisits; - const FPassageSegmentData& segment=GetPassageSegmentData( - passageIndex,static_cast(index)); - if(passageTileScopeMatches) - passageTileQueries->recordPreparedSegmentUse( - FScopedPassageTileQueries::EPreparedSegmentUse::Support); - const auto& segmentA=passage.controlPoints[static_cast(index)]; - const double dx=segment.delta[0],dy=segment.delta[1],dz=segment.delta[2]; - const double radiusA=segment.radiusA; - const double radiusB=segment.radiusB; - const bool entryMouthShoulder=index<=2; - // Keep the tread within the probe band and below the capsule's - // lowest sampled point. - const bool bridgeDeck=IsPassageShortSpanSegment(passageIndex, - static_cast(index)) - ||IsPassageColumnSegment(passageIndex,static_cast(index)); - // Keep a small capsule margin at regular treads and restore most of - // the nominal height smoothly as a tread approaches its landing. - double floorOffset=bridgeDeck - ?PassageBridgeDeckOffsetMetres(passageIndex,static_cast(index)) - :std::lerp(internalChainPassage?0.20:0.15,0.20,lowerMouthBlend); - const double horizontalLengthSq=segment.horizontalLengthSq; - const bool overlapSupportJoin=index+12(index)) - &&(index==0||(!IsPassageShortSpanSegment(passageIndex, - static_cast(index-1)))); - const bool smoothSupportJoin=index>0&&overlapSupportJoin - &&!IsPassageShortSpanSegment(passageIndex,static_cast(index+1)); - const double projection=horizontalLengthSq>0.0 - ?PassageXYProjectionNumerator(passageIndex, - static_cast(index),qx,qy)/horizontalLengthSq:bestT; - // Extend tread segments by a fixed distance through route knots. A - // fractional extension made the support width change with segment length. - const double overlapFraction=overlapSupportJoin&&horizontalLengthSq>0.0 - ?std::min(0.5,2.0*qPerMetre/segment.horizontalLength):0.0; - const double supportT=horizontalLengthSq>0.0 - ?std::clamp(projection,-overlapFraction,1.0+overlapFraction):bestT; - double centerX=segment.a[0]+supportT*dx; - double centerY=segment.a[1]+supportT*dy; - double centerZ=segment.a[2]+supportT*dz; - double radius=radiusA+supportT*segment.radiusDelta; - if(smoothSupportJoin) - { - if(passageProfile)++passageProfile->passageSmoothSupportJoins; - const double t2=supportT*supportT,t3=t2*supportT; - const auto interpolate=[&](double v0,double v1,double v2,double v3) - { - return 0.5*((2.0*v1)+(-v0+v2)*supportT - +(2.0*v0-5.0*v1+4.0*v2-v3)*t2 - +(-v0+3.0*v1-3.0*v2+v3)*t3); - }; - const double SmoothSupportHeightWeight=internalChainPassage?0.0:0.25; - centerZ+=(interpolate(segment.catmullBefore[2],segment.a[2], - segment.b[2],segment.catmullAfter[2])-centerZ) - *SmoothSupportHeightWeight; - radius+=(interpolate(segment.catmullRadiusBefore,radiusA, - radiusB,segment.catmullRadiusAfter)-radius) - *SmoothSupportHeightWeight; - } - double treadRelief=0.0; - if(entryMouthShoulder - ||(index>=lowerMouthIndex-2&&index<=lowerMouthIndex+2)) - { - const double horizontalLength=segment.horizontalLength; - if(horizontalLength>1.0e-6) - { - const double pathRelief=std::clamp(static_cast( - VF_FieldSurfaceRelief(static_cast(centerX/qPerMetre*1.5), - static_cast(centerY/qPerMetre*1.5), - static_cast(centerZ/qPerMetre*1.5), - static_cast(Owner?Owner->Seed:0)^0x4D4F5554u)), - -1.0,1.0); - if(passageProfile)++passageProfile->passageReliefFieldCalls; - treadRelief=pathRelief; - const double lateralOffset=pathRelief*0.18*qPerMetre; - centerX-=dy/horizontalLength*lateralOffset; - centerY+=dx/horizontalLength*lateralOffset; - } - } - const double horizontalX=qx-centerX,horizontalY=qy-centerY; - const double horizontalDistance=DeterministicSqrt(horizontalX*horizontalX - +horizontalY*horizontalY); - const double supportPlayerCenterZ=centerZ-radius+playerCenterAboveFloorQ; - const double supportQueryDepth=supportPlayerCenterZ-qz; - // Support belongs just below the avatar's foot plane. Queries within - // the capsule body, or a neighbouring coil's overlapping bore, must - // not turn that tread into a ceiling or mid-air shelf. - // Sparse authored routes use the full signed distance around the top; - // dense routes retain the legacy one-sided tread density. - const double supportSegmentLength=segment.lengthMetres; - const double sparseRouteThreshold=VoxelForgeCore::WorldAssemblyEvaluatorVersion>=188 - &&floatingIslandPassage&&passage.style==0?1.0:1.5; - const bool sparseRouteSupport=supportSegmentLength>sparseRouteThreshold; - const double minimumSupportQueryDepth=index==selectedSupportSegmentIndex - &&sparseRouteSupport?0.65:0.93; - if(supportQueryDepth1.30*qPerMetre) - return; - const bool fallbackSupport=qz>=supportPlayerCenterZ-1.50*qPerMetre; - const double supportThicknessVoxels=fallbackSupport - ?qPerMetre/Q:0.5*qPerMetre/Q; - // Keep the supported ramp to a comfortable walking width. Extending a - // full bore-radius shelf across overlapping helix coils can block the - // capsule on the neighbouring turn. - const double lowerMouthDx=centerX - -static_cast(passage.lowerMouthSubvoxels[0]); - const double lowerMouthDy=centerY - -static_cast(passage.lowerMouthSubvoxels[1]); - const double lowerMouthDz=centerZ-radius - -static_cast(passage.lowerMouthSubvoxels[2]); - const double lowerMouthBodyDistance=DeterministicSqrt( - lowerMouthDx*lowerMouthDx+lowerMouthDy*lowerMouthDy - +lowerMouthDz*lowerMouthDz); - const bool lowerMouthBodyOverlap=internalChainPassage - &&lowerMouthBodyDistance<=2.0*qPerMetre - &&supportQueryDepth<0.98*qPerMetre; - // Keep a narrow walk core, but place its top on the native surface - // so the support remains a worn ramp instead of a route-height slab. - const bool mouthTread=lowerMouthBodyOverlap - ||(entryMouthShoulder - &&(!floatingIslandPassage||passage.style==0||internalChainPassage)); - double distanceFromMouthMetres=std::numeric_limits::infinity(); - if(entryMouthShoulder) - { - double prefixMetres=0.0; - for(std::ptrdiff_t routeIndex=0;routeIndexrecordPreparedSegmentUse( - FScopedPassageTileQueries::EPreparedSegmentUse::Support); - prefixMetres+=PassageSegmentData[passageIndex][ - static_cast(routeIndex)].lengthMetres; - } - distanceFromMouthMetres=std::max(0.0, - prefixMetres+supportT*supportSegmentLength); - } - else if(lowerMouthBodyOverlap) - { - double suffixMetres=0.0; - for(std::ptrdiff_t routeIndex=index+1; - routeIndexrecordPreparedSegmentUse( - FScopedPassageTileQueries::EPreparedSegmentUse::Support); - suffixMetres+=PassageSegmentData[passageIndex][ - static_cast(routeIndex)].lengthMetres; - } - distanceFromMouthMetres=std::max(0.0, - suffixMetres+(1.0-supportT)*supportSegmentLength); - } - double mouthReliefT=std::clamp(distanceFromMouthMetres/8.0,0.0,1.0); - if(passageProfile)++passageProfile->passageSmoothstepEvaluations; - mouthReliefT=mouthReliefT*mouthReliefT*(3.0-2.0*mouthReliefT); - double mouthSupportT=std::clamp((distanceFromMouthMetres-0.25)/4.0,0.0,1.0); - if(passageProfile)++passageProfile->passageSmoothstepEvaluations; - mouthSupportT=mouthSupportT*mouthSupportT*(3.0-2.0*mouthSupportT); - const double mouthSupportWidth=std::lerp(0.82,1.00,mouthSupportT); - const double supportHalfWidthMetres=mouthTread?mouthSupportWidth - :lowerMouthBodyOverlap?0.90:1.25; - double supportHalfWidth=std::min(radius, - supportHalfWidthMetres*qPerMetre); - const double shoulderWarp=mouthTread - ?std::clamp(static_cast(getMouthSurfaceRelief()),-1.0,1.0) - *0.12*qPerMetre:0.0; - supportHalfWidth=mouthTread - ?std::clamp(supportHalfWidth+shoulderWarp, - std::lerp(0.52,0.62,mouthSupportT)*qPerMetre, - std::lerp(0.92,1.10,mouthSupportT)*qPerMetre) - :std::max(0.0,supportHalfWidth+shoulderWarp); - // Keep the walk core within the player footprint, then ease the outer - // edge into native ground over a long enough shoulder to avoid a berm. - const double supportEdgeCoreMetres=mouthTread?0.08 - :entryMouthShoulder?0.60:0.90; - const double supportEdgeBlendMetres=std::min( - mouthTread?1.40:entryMouthShoulder?0.85:0.35, - std::max(0.0,supportHalfWidth/qPerMetre-supportEdgeCoreMetres)); - const double supportEdgeT=supportEdgeBlendMetres>1.0e-6 - ?std::clamp((horizontalDistance - -(supportHalfWidth-supportEdgeBlendMetres*qPerMetre)) - /(supportEdgeBlendMetres*qPerMetre),0.0,1.0):0.0; - if(passageProfile)++passageProfile->passageSmoothstepEvaluations; - const double supportEdgeSmooth=supportEdgeT*supportEdgeT - *(3.0-2.0*supportEdgeT); - const double mouthSupportThicknessVoxels=std::lerp( - 0.35*supportThicknessVoxels,supportThicknessVoxels,mouthSupportT); - const double localSupportThicknessVoxels=(entryMouthShoulder - ||lowerMouthBodyOverlap) - ?mouthSupportThicknessVoxels*(1.0-0.72*supportEdgeSmooth) - :supportThicknessVoxels; - double mouthSupportBlend=1.0; - if(mouthTread&&std::isfinite(distanceFromMouthMetres)) - { - const double mouthBlendT=std::clamp( - distanceFromMouthMetres/0.75,0.0,1.0); - if(passageProfile)++passageProfile->passageSmoothstepEvaluations; - mouthSupportBlend=0.75+0.25*mouthBlendT*mouthBlendT - *(3.0-2.0*mouthBlendT); - } - const double supportEdgeDepth=mouthTread?0.25:0.35; - const double mouthFloorOffset=internalChainPassage?0.20 - :mouthTread?std::lerp(0.15,0.19,lowerMouthBlend):floorOffset; - const double baseFloorQ=centerZ-radius+mouthFloorOffset*qPerMetre - -supportEdgeSmooth*supportEdgeDepth*qPerMetre; - const double nativeSurfaceQ=static_cast(qz) - -static_cast(density)*Q; - // Keep support near the route floor; visible mouth preservation below - // blends the source field directly instead of extending this SDF top. - const double nativeFieldOffset=std::clamp(nativeSurfaceQ-baseFloorQ, - -0.80*qPerMetre,0.80*qPerMetre); - const double nativeSurfaceBlend=mouthTread - ?internalChainPassage?0.0:1.0:1.0-mouthReliefT; - const double nativeTreadOffset=std::clamp( - nativeFieldOffset*nativeSurfaceBlend+floorReliefOffset - -std::abs(treadRelief)*0.08*qPerMetre - *(1.0-0.25*mouthReliefT), - -0.80*qPerMetre,0.80*qPerMetre); - const double floorQ=baseFloorQ - +(mouthTread?std::clamp(nativeTreadOffset - +std::clamp(static_cast(getMouthTreadFieldRelief()),-1.0,1.0) - *0.40*qPerMetre,-0.80*qPerMetre,0.0):0.0); - const double floorVoxels=floorQ/Q; - const bool signedDistanceSupport=sparseRouteSupport||mouthTread; - const double supportPositiveRangeVoxels=signedDistanceSupport - ?0.35*qPerMetre/Q:1.0/Q; - if(ZfloorVoxels+supportPositiveRangeVoxels)return; - const double supportQueryHalfWidth=supportHalfWidth - +(mouthTread?0.45*qPerMetre:0.0); - if(horizontalDistance>supportQueryHalfWidth)return; - const double supportDistanceSquared=horizontalDistance*horizontalDistance - +(Z-floorVoxels)*(Z-floorVoxels); - if(supportDistanceSquared>=bestSupportDistanceSquared)return; - bestSupportDistanceSquared=supportDistanceSquared; - hasSupportFloor=true; - bestSupportSegmentIndex=index; - bestSupportIsMouthTread=mouthTread; - if(signedDistanceSupport) - { - // Sparse support profiles need both sides of a signed distance - // so the sampled zero crossing stays on the tread top. - const double topDistance=qz-floorQ; - const double bottomDistance=floorQ-localSupportThicknessVoxels*Q-qz; - const double verticalDistance=std::max(topDistance,bottomDistance); - const double sideDistance=horizontalDistance-supportHalfWidth; - bestSupportDensity=SmoothMaxDistance( - static_cast(sideDistance/Q), - static_cast(verticalDistance/Q), - entryMouthShoulder?0.80f:0.20f); - } - else - { - bestSupportDensity=std::clamp(Z-floorVoxels, - -localSupportThicknessVoxels,0.0); - } - bestSupportFloorQ=floorQ; - bestSupportUsesSignedDistance=signedDistanceSupport; - bestSupportMouthBlend=mouthSupportBlend; - bestSupportNativeBlend=mouthTread - ?(internalChainPassage?1.0:0.85) - *mouthSupportBlend*(1.0-supportEdgeSmooth):0.0; - }; - std::ptrdiff_t supportCenterIndex=bestIndex; - if(bestIndex( - supportProfile-floorProfileQ.begin(),0,lowerMouthIndex); - // At floor height the nearest 3D centerline can belong to the next - // coil below. The descending floor profile identifies the coil that - // owns this tread, even when it is more than eight control points away. - supportCenterIndex=profileIndex; - } - const std::ptrdiff_t supportBegin=std::max(0,supportCenterIndex-1); - const std::ptrdiff_t supportEnd=std::min(lastIndex-1, - supportCenterIndex+1); - selectedSupportSegmentIndex=supportCenterIndex>0 - ?supportCenterIndex-1:supportCenterIndex; - { - VoxelForgeCore::Linux77Profiler::FScopedPhase l77SupportSearchPhase( - VoxelForgeCore::Linux77Profiler::EPhase::Support); - for(std::ptrdiff_t index=supportBegin;index<=supportEnd;++index) - considerSupportSegment(index); - } - if(l90CandidateProfiled&&hasSupportFloor) - passageTileQueries->recordL90ProofCheck(1, - PassageCandidateBrickContains(l90CandidateBrick,1,passageIndex, - static_cast(bestSupportSegmentIndex))); - VoxelForgeCore::Linux77Profiler::FScopedPhase l77SupportApplyPhase( - VoxelForgeCore::Linux77Profiler::EPhase::Support); - // Keep route treads inside the native rock envelope. Carving may reopen the - // floor above this point, but a support cannot create a new surface in air. - const bool passageColumnFloorSupport=hasSupportFloor - &&IsPassageColumnSegment(passageIndex, - static_cast(bestSupportSegmentIndex)); - const bool shortSpanFloorSupport=hasSupportFloor - &&IsPassageShortSpanSegment(passageIndex, - static_cast(bestSupportSegmentIndex)); - const double capsuleClearanceMetres=bestSupportUsesSignedDistance?0.045:0.05; - const double capsuleQueryZ=bestSupportUsesSignedDistance?bestSupportFloorQ:qz; - const bool supportCapsuleProfileAvailable=passageIndexpassageSupportCapsuleChecks; - capsuleAllowsSupport=!PassagePlayerCapsuleBlocksSupport(passageIndex, - carveBegin,carveEnd,lowerMouthIndex,mouthSearchBegin,mouthSearchEnd, - lastIndex,qx,qy,capsuleQueryZ,qPerMetre,capsuleClearanceMetres); - } - else capsuleAllowsSupport= - bestPlayerCapsuleSignedDistance>=capsuleClearanceMetres*qPerMetre; - bool supportApplied=false; - bool supportNeedsDeferral=false; - // Outside bridge and short-span segments, add the tread only where the - // native field already provides a solid envelope; the capsule check keeps - // that support below the player's walk space. - if(hasSupportFloor&&(density<0.0f||passageColumnFloorSupport - ||shortSpanFloorSupport) - &&(capsuleAllowsSupport||bestSupportDensity>=0.0)) - { - supportNeedsDeferral=laterPassageMayCarve(bestSupportSegmentIndex, - qx,qy,qz); - if(bestSupportIsMouthTread) - { - // Preserve the owner's native ground through the shallow mouth - // carve. Blending back the native field keeps its crater curvature - // and noise. The capsule test keeps neighbouring coils open. - const bool nativeRestoreCapsuleClear=density<0.0f - &&bestSupportNativeBlend>0.0&&capsuleAllowsSupport - &&([&](){ - l90IterationTimer.recordClearance(); - if(passageProfile)++passageProfile->passageSupportCapsuleChecks; - return !PassagePlayerCapsuleBlocksSupport(passageIndex,carveBegin, - carveEnd,lowerMouthIndex,mouthSearchBegin,mouthSearchEnd, - lastIndex,qx,qy,qz,qPerMetre,capsuleClearanceMetres); - })(); - if(nativeRestoreCapsuleClear) - { - const double nativeSurfaceDetail=std::clamp( - static_cast(getMouthSurfaceRelief()),-1.0,1.0) - *0.18*qPerMetre/Q; - const float nativeGroundWithRelief=static_cast( - (supportNeedsDeferral?std::max(-1.0f,density):density) - -nativeSurfaceDetail); - composed=std::lerp(composed,nativeGroundWithRelief, - static_cast(bestSupportNativeBlend)); - supportApplied=composed(bestSupportDensity)); - supportApplied=composedpassageOtherCapsuleChecks; - if(PassageOtherCapsuleBlocksSupport(passageIndex, - bestSupportSegmentIndex,qx,qy,qz,qPerMetre,capsuleClearanceMetres)) - { - composed=composedAfterCarve; - supportApplied=false; - } - } - if(supportApplied&&supportNeedsDeferral) - { - deferredSupportDensity=std::min(deferredSupportDensity,composed); - // Preserve a tread only when a later passage bore reaches this - // sample; otherwise retain the ordinary composition order. - composed=composedAfterCarve; + const double floorAlongMetres=floorSegment.authoredAlongMetres + +nearest.floorT*floorSegment.authoredLengthMetres; + const double pastMouthMetres=std::max(0.0,floorAlongMetres + -constants.totalPathLengthMetres); + const double extensionFade=std::clamp(1.0 + -pastMouthMetres/MouthShellBlendMetres,0.0,1.0); + floorExtensionFade=extensionFade*extensionFade + *(3.0-2.0*extensionFade); } + const double floorShellThickness=smoothFloorBlend*shellThickness + *floorExtensionFade*smoothShellFade; + const double wallShellDistance=PassageRoundedWallShellDistance( + shapedDistance,wallElevationMetres*qPerMetre, + OpenAirSideWallHeightMetres*qPerMetre,mouthWallThickness); + const double floorShellDistance=std::max(-static_cast(shapedDistance), + static_cast(shapedDistance)-floorShellThickness); + unionDistance=std::min(unionDistance,static_cast(shapedDistance)); + const double localShellDistance=std::min(wallShellDistance, + floorShellDistance); + unionShellDistance=std::min(unionShellDistance, + std::min(localShellDistance,nearest.shellSignedDistance)); } - // Restore the surface route where the passage cut crossed otherwise solid - // native ground. The support stays native-solid-only, so it cannot float. - const std::size_t mouthSupportIterationCount=ResolvedLayout->passages.size(); - for(std::size_t passageIteration=0; - passageIterationpassages[passageIndex]; - if(passage.controlPoints.size()<2)continue; - const bool tileHasSupport=passageTileScopeMatches; - if(!tileHasSupport - ||ActivePassageTileQueries->hasMouthSupport(passageIndex)) - { - if(passageProfile)++passageProfile->passageMouthSupportCalls; - composeRouteMouthSupport(passageIndex); - } - } - composed=std::min(composed,deferredSupportDensity); - return composed; + + if(!std::isfinite(unionDistance))return density; + const float passageAirDistance=static_cast(-unionDistance/Q); + // Air is the union of the native graph and passage voids. Keeping the + // signed passage distance outside the void as well gives marching cubes + // a real negative distance through the floor instead of the terrain's + // saturated deep-rock value. + if(nativeTunnelFieldDensity>=0.0f) + return std::max(nativeTunnelFieldDensity,passageAirDistance); + if(nativeFloorSupport!=std::numeric_limits::lowest() + &&nativeFloorSupport<0.0f) + return std::min(nativeFloorSupport,unionDistance<=0.0 + ?passageAirDistance:density); + if(nativeTunnelFieldDensity!=std::numeric_limits::lowest()) + return std::max(density,passageAirDistance); + if(unionDistance>0.0&&unionShellDistance<0.0&&density>=0.0f) + return static_cast(unionShellDistance/Q); + return std::max(density,passageAirDistance); } float ApplyResolvedStrateComposition(float density,float X,float Y,float Z) const { float graphDensity=0.0f; + float nativeLatticeFloorSupport=std::numeric_limits::lowest(); { VoxelForgeCore::Linux77Profiler::FScopedPhase l77GraphPhase( VoxelForgeCore::Linux77Profiler::EPhase::CompositionGraph); FScopedLegacyFieldTermTimer TermTimer(ELegacyFieldTerm::ComposerCavern); - graphDensity=ApplyResolvedCavernGraph(density,X,Y,Z); + graphDensity=ApplyResolvedCavernGraph(density,X,Y,Z, + &nativeLatticeFloorSupport); } const auto* bound=FindBoundStratumForManagerZ(Z); const bool nativeLattice=bound&&bound->Resolved @@ -3054,18 +1556,7 @@ public: FScopedLegacyFieldTermTimer TermTimer(ELegacyFieldTerm::ComposerBoundary); boundary=ApplyResolvedStrateBoundaryBand(graphDensity,X,Y,Z); } - // The native lattice owns its resolved arrival/departure portals and their - // supported spine. Reapplying legacy passage carves here can erase the - // tread immediately above a broad legacy mouth or support column. float composed=boundary; - if(!nativeLattice&&!disablePassageComposition) - { - VoxelForgeCore::Linux77Profiler::FScopedPhase l77PassagePhase( - VoxelForgeCore::Linux77Profiler::EPhase::Passage); - FScopedLegacyFieldTermTimer TermTimer( - ELegacyFieldTerm::ComposerPassageAndSupport); - composed=ApplyResolvedStratePassageCarves(boundary,X,Y,Z); - } float stamped=composed; if(!StampRuntime.empty()) { @@ -3087,6 +1578,22 @@ public: ?bound->Resolved->passageCapabilities.hasNativeCaveField :bound->Resolved->passageCapabilities.hasNativeLatticeField)) { + if(!disablePassageComposition) + { + VoxelForgeCore::Linux77Profiler::FScopedPhase l77PassagePhase( + VoxelForgeCore::Linux77Profiler::EPhase::Passage); + FScopedLegacyFieldTermTimer TermTimer( + ELegacyFieldTerm::ComposerPassage); + const bool nativeTunnelField= + (VoxelForgeCore::IsNativeCaveFieldStratum(*bound->Resolved) + &&bound->Resolved->passageCapabilities.hasNativeCaveField) + ||(VoxelForgeCore::IsNativeLatticeFieldStratum(*bound->Resolved) + &&bound->Resolved->passageCapabilities.hasNativeLatticeField); + const float nativeTunnelFieldDensity=nativeTunnelField + ?graphDensity:std::numeric_limits::lowest(); + stamped=ApplyResolvedStratePassageCarves(stamped,X,Y,Z, + nativeTunnelFieldDensity,nativeLatticeFloorSupport); + } if(bTraceTnComposition) std::printf("[L75TNCompositionTrace] input=%.9g graph=%.9g boundary=%.9g passage=%.9g stamp=%.9g native=1\n", density,graphDensity,boundary,composed,stamped); @@ -3099,9 +1606,17 @@ public: VoxelForgeCore::Linux77Profiler::FScopedPhase l77CapsPhase( VoxelForgeCore::Linux77Profiler::EPhase::Caps); FScopedLegacyFieldTermTimer TermTimer( - ELegacyFieldTerm::ComposerPassageAndSupport); + ELegacyFieldTerm::ComposerPassage); final=ApplyResolvedCavernFloorCaps(stamped,X,Y,Z); } + if(!disablePassageComposition) + { + VoxelForgeCore::Linux77Profiler::FScopedPhase l77PassagePhase( + VoxelForgeCore::Linux77Profiler::EPhase::Passage); + FScopedLegacyFieldTermTimer TermTimer( + ELegacyFieldTerm::ComposerPassage); + final=ApplyResolvedStratePassageCarves(final,X,Y,Z); + } if(bTraceTnComposition) std::printf("[L75TNCompositionTrace] input=%.9g graph=%.9g boundary=%.9g passage=%.9g stamp=%.9g final=%.9g native=0\n", density,graphDensity,boundary,composed,stamped,final); @@ -3113,13 +1628,10 @@ public: if(!ResolvedLayout||ResolvedLayout->passages.empty())return false; if(PassageProofNodes.empty()) { - // Native-only readiness tiles have not built the passage BVH. Keep their - // exact conservative fallback instead of indexing an empty tree. - constexpr double Q=static_cast(VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel); - const double voxelsPerMetre=Owner&&Owner->CoreVoxelSizeMicrons>0 - ?1000000.0/Owner->CoreVoxelSizeMicrons:4.0; - const double bridgeHalfWidthVoxels=3.5*voxelsPerMetre; - const double bridgeFootDepthVoxels=(5.0-0.13)*voxelsPerMetre; + constexpr double Q=static_cast( + VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel); + const double qPerMetre=Q*1000000.0/ + std::max(1,ResolvedLayout->coreVoxelSizeMicrometres); const auto overlaps=[&](const double low[3],const double high[3]) { for(int axis=0;axis<3;++axis) @@ -3128,69 +1640,28 @@ public: }; for(const auto& passage:ResolvedLayout->passages) { - for(std::size_t i=1;i(std::max(a.radiusSubvoxels,b.radiusSubvoxels))/Q; - const double floorThicknessVoxels=voxelsPerMetre; - const double horizontalExtent=std::max(radius,bridgeHalfWidthVoxels); - const double footDepth=std::max(floorThicknessVoxels,bridgeFootDepthVoxels); - const double low[3]={ - std::min(a.positionSubvoxels[0],b.positionSubvoxels[0])/Q-horizontalExtent, - std::min(a.positionSubvoxels[1],b.positionSubvoxels[1])/Q-horizontalExtent, - std::min(a.positionSubvoxels[2],b.positionSubvoxels[2])/Q-radius-footDepth}; - const double high[3]={ - std::max(a.positionSubvoxels[0],b.positionSubvoxels[0])/Q+horizontalExtent, - std::max(a.positionSubvoxels[1],b.positionSubvoxels[1])/Q+horizontalExtent, - std::max(a.positionSubvoxels[2],b.positionSubvoxels[2])/Q+radius}; + const auto& a=passage.controlPoints[segment]; + const auto& b=passage.controlPoints[segment+1]; + const auto& p0=passage.controlPoints[segment==0?0:segment-1]; + const auto& p3=passage.controlPoints[ + std::min(segment+2,passage.controlPoints.size()-1)]; + const double radius=std::max(static_cast(a.radiusSubvoxels), + static_cast(b.radiusSubvoxels))/Q+1.0; + double low[3]{},high[3]{}; + for(int axis=0;axis<3;++axis) + { + const double values[4]={ + static_cast(p0.positionSubvoxels[axis])/Q, + static_cast(a.positionSubvoxels[axis])/Q, + static_cast(b.positionSubvoxels[axis])/Q, + static_cast(p3.positionSubvoxels[axis])/Q}; + low[axis]=*std::min_element(std::begin(values),std::end(values))-radius; + high[axis]=*std::max_element(std::begin(values),std::end(values))+radius; + } if(overlaps(low,high))return true; } - const auto upperStratum=std::find_if(ResolvedLayout->strates.begin(), - ResolvedLayout->strates.end(),[&passage](const auto& value) - {return value.strateIndex==passage.upperStrateIndex;}); - if(upperStratum!=ResolvedLayout->strates.end()) - { - std::array route{}; - std::size_t routeCount=0; - for(const auto& anchor:upperStratum->anchors) - if(anchor.kind=="route_point"&&anchor.values.size()>=3) - { - if(routeCount=2) - { - const double mouthReach=13.0*voxelsPerMetre*Q; - double minimumZ=std::numeric_limits::infinity(); - double maximumZ=-std::numeric_limits::infinity(); - for(std::size_t index=0;index(route[index]->values[2])); - maximumZ=std::max(maximumZ,static_cast(route[index]->values[2])); - } - const double mouthX=passage.upperMouthSubvoxels[0]; - const double mouthY=passage.upperMouthSubvoxels[1]; - const double low[3]={(mouthX-mouthReach)/Q,(mouthY-mouthReach)/Q, - (minimumZ-3.0*voxelsPerMetre*Q)/Q}; - const double high[3]={(mouthX+mouthReach)/Q,(mouthY+mouthReach)/Q, - (maximumZ+3.0*voxelsPerMetre*Q)/Q}; - if(overlaps(low,high))return true; - } - } - } - for(const auto& crossing:PassageVoidCrossings) - { - if(!crossing.needsColumn)continue; - const double radius=static_cast(crossing.maximumRadiusSubvoxels)/Q; - const double low[3]={crossing.centerXSubvoxels/Q-radius, - crossing.centerYSubvoxels/Q-radius,crossing.bottomZSubvoxels/Q}; - const double high[3]={crossing.centerXSubvoxels/Q+radius, - crossing.centerYSubvoxels/Q+radius,crossing.topZSubvoxels/Q}; - if(overlaps(low,high))return true; } return false; } @@ -3342,7 +1813,7 @@ public: OwnerNoiseAndWarp, ComposerCavern, ComposerBoundary, - ComposerPassageAndSupport, + ComposerPassage, ComposerStamps, EditBrushes, Count @@ -3814,10 +2285,10 @@ public: BuildPackedRockIntervals(Stats.RockIntervalLines); Stats.PackedSignBuildSeconds=std::chrono::duration(Clock::now()-Substage).count(); // Native density queries for non-heightfield strates use the exact interval - // evaluator. Build those native intervals before scanning passage support; - // the scan itself still completes before any resolved column is composed. + // evaluator. Build those native intervals before preparing the tunnel sweeps. Substage=Clock::now(); - BuildPassageVoidCrossingPlan(); + BuildResolvedBoundaryZIntervals(); + BuildPassageSpatialIndices(); Stats.PassageSweepPrepSeconds=std::chrono::duration(Clock::now()-Substage).count(); Substage=Clock::now(); BuildCandidateBands(Stats.CandidateAxisLines,Stats.CandidateMergeLines, @@ -4944,88 +3415,114 @@ public: private: struct FPassageTileFeature { - std::size_t passageIndex=0,segmentIndex=0; - bool bColumn=false,bMouthSupport=false; + std::size_t passageIndex=0,segmentIndex=0,segmentEndIndex=0; }; struct FPassageComposerConstants { - bool internalChainPassage=false; - bool floatingIslandPassage=false; - bool surfaceToTunnelSupport=false; - double firstFloorQ=0.0,lastFloorQ=0.0,carveSearchMargin=0.0; - std::ptrdiff_t lowerMouthIndex=1,lastIndex=1; - std::ptrdiff_t mouthSearchBegin=0,mouthSearchEnd=0; - std::vector controlFloorProfileQ; + double floorDepthMetres=0.0,totalPathLengthMetres=0.0; + double authoredTotalPathLengthMetres=0.0; + std::size_t routeProfileSegmentCount=0; + double upperMouthX=0.0,upperMouthY=0.0; + double upperMouthPlannedFloor=0.0; + double upperMouthTangentX=0.0,upperMouthTangentY=0.0; + std::vector> upperMouthReceivingRoute; + std::size_t routeEndControlIndex=0; }; struct FPassageSegmentData { - std::array a{},b{},delta{},catmullBefore{},catmullAfter{}; + std::array a{},b{},delta{}; std::array sweepMinimumSubvoxels{},sweepMaximumSubvoxels{}; + double authoredFloorZA=0.0,authoredFloorZDelta=0.0; + double authoredAlongMetres=0.0,authoredLengthMetres=0.0; double radiusA=0.0,radiusB=0.0,radiusDelta=0.0; - double catmullRadiusBefore=0.0,catmullRadiusAfter=0.0; double lengthSq=0.0,horizontalLengthSq=0.0; - double lengthSubvoxels=0.0,horizontalLength=0.0,lengthMetres=0.0; + double lengthSubvoxels=0.0,horizontalLength=0.0; + bool routeSegment=false; }; - struct FPreparedPassageCapsuleSegment + static double PassageFlatFloorDepthSubvoxels( + const FPassageComposerConstants& constants,std::size_t segmentIndex,double t, + double radiusSubvoxels,double qPerMetre) { - std::array a{},delta{}; - double horizontalLengthSq=0.0; - }; - const FPassageSegmentData& GetPassageSegmentData(std::size_t passageIndex, - std::size_t segmentIndex) const - {return PassageSegmentData[passageIndex][segmentIndex];} - - double PassageXYProjectionNumerator(std::size_t passageIndex, - std::size_t segmentIndex,double qx,double qy) const - { - const FPassageSegmentData& segment=GetPassageSegmentData( - passageIndex,segmentIndex); - const std::size_t flatIndex=PassageSegmentOffsets[passageIndex]+segmentIndex; - const auto* tileQueries=ActivePassageTileQueries; - if(tileQueries&&tileQueries->matches(*this)) - return tileQueries->projectionNumerator(flatIndex,qx,qy, - segment.a[0],segment.a[1],segment.delta[0],segment.delta[1]); - return (qx-segment.a[0])*segment.delta[0] - +(qy-segment.a[1])*segment.delta[1]; + (void)segmentIndex;(void)t; + if(!std::isfinite(qPerMetre)||qPerMetre<=0.0) + return std::max(0.0,radiusSubvoxels-0.23); + return std::min(constants.floorDepthMetres*qPerMetre, + std::max(0.0,radiusSubvoxels-0.23*qPerMetre)); } - double PassageCapsuleRouteXYProjectionNumerator(std::size_t stratumIndex, - std::size_t segmentIndex,double qx,double qy) const + static double PassageFlatFloorCenterZSubvoxels( + const FPassageComposerConstants& constants, + const std::vector& segments, + std::size_t segmentIndex,double floorT, + const FPassageSegmentData& segment,double queryXSubvoxels,double queryYSubvoxels, + double floorDepthSubvoxels,double qPerMetre) { - const FPreparedPassageCapsuleSegment& segment= - PassageStratumCapsuleSegments[stratumIndex][segmentIndex]; - const std::size_t flatIndex=PassageSegmentOffsets.back() - +PassageMouthSupportSegmentOffsets.back() - +PassageStratumCapsuleSegmentOffsets[stratumIndex]+segmentIndex; - const auto* tileQueries=ActivePassageTileQueries; - if(tileQueries&&tileQueries->matches(*this)) - return tileQueries->projectionNumerator(flatIndex,qx,qy, - segment.a[0],segment.a[1],segment.delta[0],segment.delta[1]); - return (qx-segment.a[0])*segment.delta[0] - +(qy-segment.a[1])*segment.delta[1]; + if(!segment.routeSegment||qPerMetre<=0.0) + return segment.a[2]+std::clamp(floorT,0.0,1.0)*segment.delta[2]; + const std::size_t profileCount=std::min( + constants.routeProfileSegmentCount,segments.size()); + double plannedFloor=segment.authoredFloorZA + +floorT*segment.authoredFloorZDelta; + if(profileCount>0) + { + if(floorT>=0.0&&floorT<=1.0) + plannedFloor=segment.authoredFloorZA + +floorT*segment.authoredFloorZDelta; + else + { + const double distance=segment.authoredAlongMetres + +floorT*segment.authoredLengthMetres; + const auto profileEnd=segments.begin()+profileCount; + const auto upper=std::lower_bound(segments.begin(),profileEnd,distance, + [](const FPassageSegmentData& candidate,double value) + {return candidate.authoredAlongMetres + +candidate.authoredLengthMetres1.0e-12 + ?std::clamp((distance-profileSegment.authoredAlongMetres) + /profileSegment.authoredLengthMetres,0.0,1.0):0.0; + plannedFloor=profileSegment.authoredFloorZA + +profileT*profileSegment.authoredFloorZDelta; + } + } + const double mouthBlendFloor=VoxelForgeCore::PassageSpline::BlendUpperMouthFloorAtXY( + constants.upperMouthReceivingRoute,queryXSubvoxels,queryYSubvoxels, + plannedFloor,constants.upperMouthX,constants.upperMouthY, + constants.upperMouthPlannedFloor, + constants.upperMouthTangentX,constants.upperMouthTangentY, + VoxelForgeCore::PassageSpline::UpperMouthFloorBlendRadiusMetres,1.13, + qPerMetre); + return mouthBlendFloor+floorDepthSubvoxels; } - struct FPassageMouthSupportSegment + static float PassageFlatBottomDistance(float roundDistanceSubvoxels, + double centerZSubvoxels,double queryZSubvoxels,double floorDepthSubvoxels, + double qPerMetre) { - std::array a{},b{}; - std::array preparedA{},preparedDelta{}; - double horizontalLengthSq=0.0; - bool hasRadius=false; - }; - double PassageMouthSupportXYProjectionNumerator(std::size_t passageIndex, - std::size_t routeIndex,double qx,double qy) const + constexpr double CornerBlendMetres=0.50; + const float floorDistance=static_cast(centerZSubvoxels + -floorDepthSubvoxels-queryZSubvoxels); + return SmoothMaxDistance(roundDistanceSubvoxels,floorDistance, + static_cast(CornerBlendMetres*qPerMetre)); + } + static double PassageRoundedWallShellDistance(double flatDistanceSubvoxels, + double wallElevationSubvoxels,double wallHeightSubvoxels, + double wallThicknessSubvoxels) { - const FPassageMouthSupportSegment& segment= - PassageMouthSupportRoutes[passageIndex][routeIndex]; - const std::size_t flatIndex=PassageSegmentOffsets.back() - +PassageMouthSupportSegmentOffsets[passageIndex]+routeIndex; - const auto* tileQueries=ActivePassageTileQueries; - if(tileQueries&&tileQueries->matches(*this)) - return tileQueries->projectionNumerator(flatIndex,qx,qy, - segment.preparedA[0],segment.preparedA[1], - segment.preparedDelta[0],segment.preparedDelta[1]); - return (qx-segment.preparedA[0])*segment.preparedDelta[0] - +(qy-segment.preparedA[1])*segment.preparedDelta[1]; + if(!(wallThicknessSubvoxels>1.0e-9)||!(wallHeightSubvoxels>0.0)) + return std::numeric_limits::infinity(); + const double radius=wallThicknessSubvoxels*0.5; + const double capCenter=wallHeightSubvoxels-radius; + if(!(capCenter>0.0))return std::numeric_limits::infinity(); + const double x=flatDistanceSubvoxels-radius; + const double boxHalfHeight=capCenter*0.5; + const double boxX=std::abs(x)-radius; + const double boxY=std::abs(wallElevationSubvoxels-boxHalfHeight) + -boxHalfHeight; + const double boxDistance=std::min(std::max(boxX,boxY),0.0) + +std::hypot(std::max(boxX,0.0),std::max(boxY,0.0)); + const double capDistance=std::hypot(x,wallElevationSubvoxels-capCenter)-radius; + return std::min(boxDistance,capDistance); } struct FPassageNearestNode { @@ -5040,46 +3537,6 @@ private: { std::array minimum{},maximum{}; }; - struct FPassageLaterBoreCandidate - { - std::array minimum{},maximum{}; - double reach=0.0; - }; - struct FPassageLaterBoreSource - { - std::array minimum{},maximum{}; - std::vector candidates; - std::vector capsuleCandidatePassages; - }; - struct FPassageCandidateBrickKey - { - std::int64_t x=0,y=0,z=0; - bool operator==(const FPassageCandidateBrickKey&) const=default; - }; - struct FPassageCandidateBrickKeyHash - { - std::size_t operator()(const FPassageCandidateBrickKey& key) const noexcept - { - const std::size_t hx=std::hash{}(key.x); - const std::size_t hy=std::hash{}(key.y); - const std::size_t hz=std::hash{}(key.z); - return hx^(hy+static_cast(0x9e3779b97f4a7c15ull)+(hx<<6)+(hx>>2)) - ^(hz+static_cast(0x9e3779b97f4a7c15ull)+(hy<<6)+(hy>>2)); - } - }; - struct FPassageCandidateRef - { - std::uint32_t passageIndex=0; - std::int32_t segmentIndex=-1; - std::uint8_t featureKind=0; - bool operator==(const FPassageCandidateRef&) const=default; - }; - struct FPassageCandidateBrick - { - // carve, tread, clearance, mouth/column. Lists are complete for the - // declared geometry and reach envelopes; vectors are never capped. - std::array,4> semantics; - }; struct FPassageProofNode { std::array minimum{},maximum{}; @@ -5857,24 +4314,21 @@ private: int BuildPassageNearestNode(std::size_t passageIndex,std::vector segments) { - const auto& points=ResolvedLayout->passages[passageIndex].controlPoints; FPassageNearestNode node; node.minimum.fill(std::numeric_limits::infinity()); node.maximum.fill(-std::numeric_limits::infinity()); for(const std::size_t segment:segments) { - const auto& a=points[segment];const auto& b=points[segment+1]; + const auto& prepared=PassageSegmentData[passageIndex][segment]; for(std::size_t axis=0;axis<3;++axis) { node.minimum[axis]=std::min({node.minimum[axis], - static_cast(a.positionSubvoxels[axis]), - static_cast(b.positionSubvoxels[axis])}); + prepared.a[axis],prepared.b[axis]}); node.maximum[axis]=std::max({node.maximum[axis], - static_cast(a.positionSubvoxels[axis]), - static_cast(b.positionSubvoxels[axis])}); + prepared.a[axis],prepared.b[axis]}); } node.maximumRadius=std::max({node.maximumRadius, - static_cast(a.radiusSubvoxels),static_cast(b.radiusSubvoxels)}); + prepared.radiusA,prepared.radiusB}); } node.minimumSegment=*std::min_element(segments.begin(),segments.end()); node.maximumSegment=*std::max_element(segments.begin(),segments.end()); @@ -5894,8 +4348,8 @@ private: -PassageNearestNodes[passageIndex][nodeIndex].minimum[splitAxis])splitAxis=axis; const std::size_t middle=segments.size()/2; const auto center=[&](std::size_t segment) - {return static_cast(points[segment].positionSubvoxels[splitAxis]) - +static_cast(points[segment+1].positionSubvoxels[splitAxis]);}; + {const auto& prepared=PassageSegmentData[passageIndex][segment]; + return prepared.a[splitAxis]+prepared.b[splitAxis];}; std::nth_element(segments.begin(),segments.begin()+middle,segments.end(), [&](std::size_t a,std::size_t b) {const double ca=center(a),cb=center(b);return ca==cb?a + void VisitNearestPassageSegmentRange(std::size_t passageIndex, + std::ptrdiff_t first,std::ptrdiff_t last,double qx,double qy,double qz, + int priority,double& bestDistance,double& bestFloorCenterDistanceSq, + FVisitor&& visitor) const + { + (void)priority; + if(first>last||passageIndex>=PassageNearestNodes.size() + ||PassageNearestNodes[passageIndex].empty())return; + const auto& nodes=PassageNearestNodes[passageIndex]; + const double qPerMetre=static_cast( + VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel)*1000000.0 + /std::max(1,ResolvedLayout + ?ResolvedLayout->coreVoxelSizeMicrometres:250000); + constexpr double SmoothDistanceSlackMetres=0.25; + const auto lowerBound=[&](const FPassageNearestNode& node) + { + const double dx=std::max({node.minimum[0]-qx,0.0,qx-node.maximum[0]}); + const double dy=std::max({node.minimum[1]-qy,0.0,qy-node.maximum[1]}); + const double dz=std::max({node.minimum[2]-qz,0.0,qz-node.maximum[2]}); + return DeterministicSqrt(dx*dx+dy*dy+dz*dz)-node.maximumRadius + -SmoothDistanceSlackMetres*qPerMetre; + }; + const auto centerDistanceLowerBoundSq=[&](const FPassageNearestNode& node) + { + const double dx=std::max({node.minimum[0]-qx,0.0,qx-node.maximum[0]}); + const double dy=std::max({node.minimum[1]-qy,0.0,qy-node.maximum[1]}); + const double dz=std::max({node.minimum[2]-qz,0.0,qz-node.maximum[2]}); + return dx*dx+dy*dy+dz*dz; + }; + const auto visit=[&](auto&& self,int nodeIndex)->void + { + if(nodeIndex<0)return; + const auto& node=nodes[static_cast(nodeIndex)]; + if(static_cast(node.maximumSegment)(node.minimumSegment)>last + ||(lowerBound(node)>bestDistance + &&(bestFloorCenterDistanceSq<0.0 + ||centerDistanceLowerBoundSq(node) + >bestFloorCenterDistanceSq)))return; + if(node.left<0) + { + for(const std::size_t segment:node.segments) + if(static_cast(segment)>=first + &&static_cast(segment)<=last) + visitor(segment,0); + return; + } + const double leftBound=lowerBound(nodes[static_cast(node.left)]); + const double rightBound=lowerBound(nodes[static_cast(node.right)]); + if(leftBound<=rightBound) + { + self(self,node.left); + self(self,node.right); + } + else + { + self(self,node.right); + self(self,node.left); + } + }; + visit(visit,0); + } + std::vector BuildPassageSegmentRangeNodeMask( std::size_t passageIndex,std::ptrdiff_t first,std::ptrdiff_t end) const { @@ -6077,12 +4595,10 @@ private: PassageComposerConstants.clear(); PassageSegmentData.clear(); PassageSegmentOffsets.clear(); - PassageStratumCapsuleSegments.clear(); - PassageStratumCapsuleSegmentOffsets.clear(); if(!ResolvedLayout) { if(tracePreparation) - std::printf("[L98PassagePrepare] passages=0 segments=0 bytes=0 prepare_ms=%.3f\n", + std::printf("[L113PassagePrepare] passages=0 control_spans=0 segments=0 max_spacing_m=8.00 max_chord_error_m=0.025 bytes=0 prepare_ms=%.3f\n", std::chrono::duration( std::chrono::steady_clock::now()-preparationStart).count()); return; @@ -6090,14 +4606,12 @@ private: PassageComposerConstants.resize(ResolvedLayout->passages.size()); PassageSegmentData.resize(ResolvedLayout->passages.size()); PassageSegmentOffsets.resize(ResolvedLayout->passages.size()+1,0); - PassageStratumCapsuleSegments.resize(ResolvedLayout->strates.size()); - PassageStratumCapsuleSegmentOffsets.resize(ResolvedLayout->strates.size()+1,0); constexpr double Q=static_cast(VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel); const double qPerMetre=Q*1000000.0/ std::max(1,ResolvedLayout->coreVoxelSizeMicrometres); - const double playerCenterAboveFloorQ=1.13*qPerMetre; - std::size_t preparedSegments=0; - std::size_t preparedFloorSamples=0; + constexpr double PassageSegmentSpacingMetres=8.0; + constexpr double PassageSegmentChordErrorMetres=0.100; + std::size_t preparedSegments=0,controlSpans=0; for(std::size_t passageIndex=0;passageIndexpassages.size(); ++passageIndex) { @@ -6108,1290 +4622,283 @@ private: PassageSegmentOffsets[passageIndex+1]=preparedSegments; continue; } - auto& segmentData=PassageSegmentData[passageIndex]; - segmentData.resize(passage.controlPoints.size()-1); - for(std::size_t segmentIndex=0;segmentIndex( + passage.lowerMouthControlIndex,1,passage.controlPoints.size()-1); + auto& constants=PassageComposerConstants[passageIndex]; + constants.routeEndControlIndex=routeEnd; + + using FRawPassageSegment=VoxelForgeCore::PassageSpline::FSegment; + std::vector controls; + controls.reserve(passage.controlPoints.size()); + std::vector plannedFloorProfile; + plannedFloorProfile.reserve(passage.controlPoints.size()); + for(const auto& point:passage.controlPoints) { - const auto& a=passage.controlPoints[segmentIndex]; - const auto& b=passage.controlPoints[segmentIndex+1]; - const auto& p0=passage.controlPoints[segmentIndex==0?0:segmentIndex-1]; - const auto& p3=passage.controlPoints[std::min(segmentIndex+2, - passage.controlPoints.size()-1)]; - FPassageSegmentData& data=segmentData[segmentIndex]; + controls.push_back({static_cast(point.positionSubvoxels[0]), + static_cast(point.positionSubvoxels[1]), + static_cast(point.positionSubvoxels[2]), + static_cast(point.radiusSubvoxels)}); + plannedFloorProfile.push_back(static_cast( + point.positionSubvoxels[2]-point.radiusSubvoxels)); + } + const double authoredUpperMouthFloorDepth=std::max(0.0, + static_cast(passage.controlPoints.front().positionSubvoxels[2] + -passage.upperMouthSubvoxels[2])/qPerMetre+1.13); + double upperMouthFloorDepth=authoredUpperMouthFloorDepth; + const auto upperStratum=std::find_if(ResolvedLayout->strates.begin(), + ResolvedLayout->strates.end(),[&](const auto& stratum) + {return stratum.strateIndex==passage.upperStrateIndex;}); + if(upperStratum!=ResolvedLayout->strates.end() + &&upperStratum->generatorKind=="FloatingIslands") + { + std::vector> route; + for(const auto& anchor:upperStratum->anchors) + if(anchor.kind=="route_point"&&anchor.values.size()>=3) + route.push_back({static_cast(anchor.values[0]), + static_cast(anchor.values[1]), + static_cast(anchor.values[2])}); + constants.upperMouthReceivingRoute=route; + double routeHeight=0.0,distanceSquared=0.0; + if(VoxelForgeCore::PassageSpline::ClosestRouteHeightAtXY(route, + controls.front()[0],controls.front()[1],routeHeight,distanceSquared) + &&distanceSquared<=std::pow(controls.front()[3]+2.0*qPerMetre,2.0)) + upperMouthFloorDepth=std::max(upperMouthFloorDepth, + std::max(0.0,(controls.front()[2]-routeHeight)/qPerMetre+1.13)); + } + controls.front()[3]=std::max(controls.front()[3], + upperMouthFloorDepth*qPerMetre); + const auto sampledSegments=VoxelForgeCore::PassageSpline::BuildSegments( + controls,controls.size()-1,PassageSegmentSpacingMetres,qPerMetre, + plannedFloorProfile,PassageSegmentChordErrorMetres); + constexpr double MaximumFloorGradeDegrees=15.0; + constexpr double DegreesPerRadian=180.0/3.14159265358979323846; + double maximumFloorGradeDegrees=0.0; + std::size_t floorGradeSamples=0,floorGradeViolations=0; + for(const auto& segment:sampledSegments) + { + if(segment.controlSpan>=routeEnd)continue; + const double dx=(segment.b[0]-segment.a[0])/qPerMetre; + const double dy=(segment.b[1]-segment.a[1])/qPerMetre; + const double dz=(segment.plannedFloorB-segment.plannedFloorA)/qPerMetre; + const double horizontal=std::hypot(dx,dy); + const double grade=horizontal>1.0e-9 + ?std::atan2(std::abs(dz),horizontal)*DegreesPerRadian + :(std::abs(dz)>1.0e-9?90.0:0.0); + maximumFloorGradeDegrees=std::max(maximumFloorGradeDegrees,grade); + ++floorGradeSamples; + if(grade>MaximumFloorGradeDegrees+1.0e-8)++floorGradeViolations; + } + std::printf("[PassagePlanGradeAudit] id=%s samples=%zu max_grade_deg=%.6f limit_deg=%.3f violations=%zu status=%s\n", + passage.stableId.c_str(),floorGradeSamples,maximumFloorGradeDegrees, + MaximumFloorGradeDegrees,floorGradeViolations, + floorGradeViolations==0?"PASS":"FAIL"); + constants.upperMouthX=controls.front()[0]; + constants.upperMouthY=controls.front()[1]; + constants.upperMouthPlannedFloor=plannedFloorProfile.front(); + if(!sampledSegments.empty()) + { + constants.upperMouthTangentX=sampledSegments.front().b[0] + -sampledSegments.front().a[0]; + constants.upperMouthTangentY=sampledSegments.front().b[1] + -sampledSegments.front().a[1]; + } + std::vector rawSegments=sampledSegments; + std::vector> routeRadiusSamples; + routeRadiusSamples.push_back({0.0,controls.front()[3]/qPerMetre}); + std::size_t preparedSpan=std::numeric_limits::max(); + double authoredTotalPathLengthMetres=0.0; + for(const auto& raw:rawSegments) + { + if(raw.controlSpan!=preparedSpan) + { + preparedSpan=raw.controlSpan; + ++controlSpans; + } + if(raw.controlSpan::infinity(); + double minimumRadius=std::numeric_limits::infinity(); + for(const auto& sample:routeRadiusSamples) + { + minimumRadius=std::min(minimumRadius,sample[1]); + if(sample[0]>=10.0&&authoredTotalPathLengthMetres-sample[0]>=10.0) + minimumBodyRadius=std::min(minimumBodyRadius,sample[1]); + } + if(!std::isfinite(minimumBodyRadius))minimumBodyRadius=minimumRadius; + // Keep a stable body depth and limit it smoothly by the local bore radius. + constants.floorDepthMetres=std::max(0.5,minimumBodyRadius-0.23); + constants.totalPathLengthMetres=authoredTotalPathLengthMetres; + auto& segmentData=PassageSegmentData[passageIndex]; + segmentData.clear(); + segmentData.reserve(rawSegments.size()); + for(const auto& raw:rawSegments) + { + FPassageSegmentData data; + data.authoredFloorZA=raw.plannedFloorA; + data.authoredFloorZDelta=raw.plannedFloorB-raw.plannedFloorA; + data.authoredAlongMetres=raw.alongMetres; + data.authoredLengthMetres=raw.lengthMetres; + data.routeSegment=raw.controlSpan(a.positionSubvoxels[axis]); - data.b[axis]=static_cast(b.positionSubvoxels[axis]); + data.a[axis]=raw.a[axis]; + data.b[axis]=raw.b[axis]; + if(axis==2) + { + data.a[axis]=effectiveCenterZ(raw.a[2],raw.a[3], + raw.plannedFloorA,raw.alongMetres); + data.b[axis]=effectiveCenterZ(raw.b[2],raw.b[3], + raw.plannedFloorB,alongB); + } data.delta[axis]=data.b[axis]-data.a[axis]; - data.catmullBefore[axis]=static_cast(p0.positionSubvoxels[axis]); - data.catmullAfter[axis]=static_cast(p3.positionSubvoxels[axis]); } - data.radiusA=static_cast(a.radiusSubvoxels); - data.radiusB=static_cast(b.radiusSubvoxels); - data.radiusDelta=static_cast(b.radiusSubvoxels)-a.radiusSubvoxels; - data.catmullRadiusBefore=static_cast(p0.radiusSubvoxels); - data.catmullRadiusAfter=static_cast(p3.radiusSubvoxels); const double dx=data.delta[0],dy=data.delta[1],dz=data.delta[2]; data.lengthSq=dx*dx+dy*dy+dz*dz; data.horizontalLengthSq=dx*dx+dy*dy; data.lengthSubvoxels=DeterministicSqrt(data.lengthSq); data.horizontalLength=DeterministicSqrt(data.horizontalLengthSq); - data.lengthMetres=data.lengthSubvoxels/qPerMetre; + segmentData.push_back(data); ++preparedSegments; } + constants.routeProfileSegmentCount=static_cast(std::count_if( + segmentData.begin(),segmentData.end(), + [](const FPassageSegmentData& segment){return segment.routeSegment;})); PassageSegmentOffsets[passageIndex+1]=preparedSegments; - const auto supportStratum=[&](std::int32_t strateIndex) - ->const VoxelForgeCore::ResolvedLayoutStratumV2* - { - const auto it=std::find_if(ResolvedLayout->strates.begin(), - ResolvedLayout->strates.end(),[strateIndex](const auto& stratum) - {return stratum.strateIndex==strateIndex;}); - return it==ResolvedLayout->strates.end()?nullptr:&*it; - }; - const auto* supportUpper=supportStratum(passage.upperStrateIndex); - const auto* supportLower=supportStratum(passage.lowerStrateIndex); - const auto mouthInsideContent=[&]( - const VoxelForgeCore::ResolvedLayoutStratumV2* stratum, - const std::array& mouth) - { - if(!stratum||!stratum->content.presentInCurrentField)return false; - const auto zMicrometres=static_cast(std::llround( - static_cast(mouth[2]) - *ResolvedLayout->coreVoxelSizeMicrometres/Q)); - return zMicrometres>=stratum->content.bottomMicrometres - &&zMicrometrescontent.topMicrometres; - }; - auto& constants=PassageComposerConstants[passageIndex]; - constants.internalChainPassage=supportUpper&&supportLower - &&!supportUpper->passageCapabilities.hasSurfaceLanding - &&!supportLower->passageCapabilities.hasSurfaceLanding - &&mouthInsideContent(supportUpper,passage.upperMouthSubvoxels) - &&mouthInsideContent(supportLower,passage.lowerMouthSubvoxels); - constants.floatingIslandPassage=supportUpper - &&supportUpper->passageCapabilities.hasFloatingIslandLanding; - constants.surfaceToTunnelSupport=supportUpper&&supportLower - &&supportUpper->lowerInterfaceCapabilities.surfaceToTunnelLandingSupport; - constants.controlFloorProfileQ.resize(passage.controlPoints.size()); - for(std::size_t pointIndex=0;pointIndex(passage.controlPoints.size())-1; - constants.lowerMouthIndex=std::clamp( - static_cast(passage.lowerMouthControlIndex),1, - constants.lastIndex); - constants.mouthSearchBegin=std::max(0, - constants.lowerMouthIndex-8); - constants.mouthSearchEnd=std::min(constants.lastIndex, - constants.lowerMouthIndex+8); - constants.carveSearchMargin=std::max(passage.mouthRadiusSubvoxels, - passage.midRadiusSubvoxels)+0.25*qPerMetre; - } - std::size_t preparedCapsuleSegments=0; - for(std::size_t stratumIndex=0;stratumIndexstrates.size(); - ++stratumIndex) - { - PassageStratumCapsuleSegmentOffsets[stratumIndex]=preparedCapsuleSegments; - const auto& stratum=ResolvedLayout->strates[stratumIndex]; - std::vector routePoints; - for(const auto& anchor:stratum.anchors) - if(anchor.kind=="route_point"&&anchor.values.size()>=3) - routePoints.push_back(&anchor); - auto& prepared=PassageStratumCapsuleSegments[stratumIndex]; - if(routePoints.size()>1)prepared.resize(routePoints.size()-1); - for(std::size_t segmentIndex=0;segmentIndexvalues[axis]; - segment.delta[axis]=routePoints[segmentIndex+1]->values[axis] - -segment.a[axis]; - } - const double dx=segment.delta[0],dy=segment.delta[1]; - segment.horizontalLengthSq=dx*dx+dy*dy; - ++preparedCapsuleSegments; - } - PassageStratumCapsuleSegmentOffsets[stratumIndex+1]=preparedCapsuleSegments; } if(tracePreparation) - std::printf("[L98PassagePrepare] passages=%zu segments=%zu floor_samples=%zu capsule_route_segments=%zu bytes=%zu prepare_ms=%.3f\n", - PassageSegmentData.size(),preparedSegments, - preparedFloorSamples, - preparedCapsuleSegments, - preparedSegments*sizeof(FPassageSegmentData) - +preparedFloorSamples*sizeof(double) - +preparedCapsuleSegments*sizeof(FPreparedPassageCapsuleSegment), + std::printf("[L113PassagePrepare] passages=%zu control_spans=%zu segments=%zu max_spacing_m=%.2f max_chord_error_m=%.3f bytes=%zu prepare_ms=%.3f\n", + PassageSegmentData.size(),controlSpans,preparedSegments, + PassageSegmentSpacingMetres,PassageSegmentChordErrorMetres, + preparedSegments*sizeof(FPassageSegmentData), std::chrono::duration( std::chrono::steady_clock::now()-preparationStart).count()); } void BuildPassageSpatialIndices() { - L90PassageCandidateProgramEnabled=VF_IsL90PassageCandidateCensusEnabled(); - L90PassageCandidateBricks.clear(); - L90PassageCandidateProgramValid=false; BuildStampSpatialIndex(); BuildCavernSpatialIndex(); - PassageTileFeatures.clear();PassageFeatureBounds.clear(); - PassageFeatureOrder.clear();PassageFeatureNodes.clear(); + PassageTileFeatures.clear(); + PassageFeatureBounds.clear(); + PassageFeatureOrder.clear(); + PassageFeatureNodes.clear(); PassageFeatureBoundsFailOpen=false; PassageNearestNodes.clear(); - PassageProofBounds.clear();PassageProofNodes.clear(); + PassageProofBounds.clear(); + PassageProofNodes.clear(); PassageNearestNodes.resize(ResolvedLayout?ResolvedLayout->passages.size():0); - PassageMouthSupportRoutes.clear(); - PassageMouthSupportRoutes.resize(ResolvedLayout?ResolvedLayout->passages.size():0); - PassageMouthSupportSegmentOffsets.assign(PassageMouthSupportRoutes.size()+1,0); - PassageLaterBoreSources.clear(); - PassageColumnSegmentFlags.clear();PassageShortSpanSegmentFlags.clear(); - PassageHasShortSpanFlags.clear(); if(!ResolvedLayout||ResolvedLayout->passages.empty())return; constexpr double Q=static_cast(VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel); - const double voxelsPerMetre=Owner&&Owner->CoreVoxelSizeMicrons>0 - ?1000000.0/Owner->CoreVoxelSizeMicrons:4.0; - const double qPerMetre=Q*voxelsPerMetre; - const double bridgeHalfWidthVoxels=3.5*voxelsPerMetre; - const double bridgeFootDepthVoxels=(5.0-0.13)*voxelsPerMetre; - // PassageWallRelief is bounded by 0.21 m along the route. Mouth floor - // relief is bounded by 0.20 m and only applies in the upper entry run. - const double passageWallReliefVoxels=0.21*voxelsPerMetre; - const double passageMouthFloorReliefVoxels=0.20*voxelsPerMetre; - PassageColumnSegmentFlags.resize(ResolvedLayout->passages.size()); - PassageShortSpanSegmentFlags.resize(ResolvedLayout->passages.size()); - for(std::size_t passageIndex=0;passageIndexpassages.size();++passageIndex) - { - const auto& passage=ResolvedLayout->passages[passageIndex]; - const std::size_t segmentCount=passage.controlPoints.size()>1 - ?passage.controlPoints.size()-1:0; - PassageColumnSegmentFlags[passageIndex].assign(segmentCount,0); - PassageShortSpanSegmentFlags[passageIndex].assign(segmentCount,0); - if(segmentCount>0) - { - std::vector segmentIds(segmentCount); - for(std::size_t i=0;i(std::max(a.radiusSubvoxels,b.radiusSubvoxels))/Q; - const std::ptrdiff_t lastControl=static_cast( - passage.controlPoints.size())-1; - const std::ptrdiff_t lowerMouthControl=std::clamp( - static_cast(passage.lowerMouthControlIndex),1,lastControl); - const double dx=static_cast(b.positionSubvoxels[0]) - -a.positionSubvoxels[0]; - const double dy=static_cast(b.positionSubvoxels[1]) - -a.positionSubvoxels[1]; - const double dz=static_cast(b.positionSubvoxels[2]) - -a.positionSubvoxels[2]; - const bool bMayUseSmoothCarve=segment>2 - &&static_cast(segment)+2( - std::min(3,lowerMouthControl)) - ?passageMouthFloorReliefVoxels:0.0; - constexpr int32 ProofSubdivisions=4; - constexpr double OutwardPaddingVoxels=1.0e-6; - const double footDepth=std::max(voxelsPerMetre,bridgeFootDepthVoxels); - std::array featureMinimum={ - std::numeric_limits::infinity(), - std::numeric_limits::infinity(), - std::numeric_limits::infinity()}; - std::array featureMaximum={ - -std::numeric_limits::infinity(), - -std::numeric_limits::infinity(), - -std::numeric_limits::infinity()}; - std::array tubeMinimum={ - std::numeric_limits::infinity(), - std::numeric_limits::infinity(), - std::numeric_limits::infinity()}; - std::array tubeMaximum={ - -std::numeric_limits::infinity(), - -std::numeric_limits::infinity(), - -std::numeric_limits::infinity()}; - const auto& p0=bMayUseSmoothCarve - ?passage.controlPoints[segment-1]:a; - const auto& p3=bMayUseSmoothCarve - ?passage.controlPoints[segment+2]:b; - for(int32 proofPart=0;proofPart(proofPart)/ProofSubdivisions; - const double t1=static_cast(proofPart+1)/ProofSubdivisions; - std::array centerMinimum{},centerMaximum{}; - for(std::size_t axis=0;axis<3;++axis) - { - const double v0=static_cast(p0.positionSubvoxels[axis])/Q; - const double v1=static_cast(a.positionSubvoxels[axis])/Q; - const double v2=static_cast(b.positionSubvoxels[axis])/Q; - const double v3=static_cast(p3.positionSubvoxels[axis])/Q; - const double c0=v1; - const double c1=0.5*(-v0+v2); - const double c2=0.5*(2.0*v0-5.0*v1+4.0*v2-v3); - const double c3=0.5*(-v0+3.0*v1-3.0*v2+v3); - const auto evaluate=[&](double t) - { - return bMayUseSmoothCarve - ?((c3*t+c2)*t+c1)*t+c0:v1+t*(v2-v1); - }; - double low=std::min(evaluate(t0),evaluate(t1)); - double high=std::max(evaluate(t0),evaluate(t1)); - const double qa=3.0*c3,qb=2.0*c2,qc=c1; - const auto includeRoot=[&](double t) - { - if(t<=t0||t>=t1||!std::isfinite(t))return; - const double value=evaluate(t); - low=std::min(low,value);high=std::max(high,value); - }; - if(bMayUseSmoothCarve) - { - if(std::abs(qa)<=1.0e-12) - { - if(std::abs(qb)>1.0e-12)includeRoot(-qc/qb); - } - else - { - const double discriminant=qb*qb-4.0*qa*qc; - if(discriminant>=0.0) - { - const double root=std::sqrt(discriminant); - includeRoot((-qb-root)/(2.0*qa)); - includeRoot((-qb+root)/(2.0*qa)); - } - } - } - centerMinimum[axis]=low-OutwardPaddingVoxels; - centerMaximum[axis]=high+OutwardPaddingVoxels; - } - const double radiusAt0=(static_cast(a.radiusSubvoxels) - +t0*(static_cast(b.radiusSubvoxels)-a.radiusSubvoxels))/Q; - const double radiusAt1=(static_cast(a.radiusSubvoxels) - +t1*(static_cast(b.radiusSubvoxels)-a.radiusSubvoxels))/Q; - const double partRadius=std::max(radiusAt0,radiusAt1); - const double relievedRadius=partRadius+passageWallReliefVoxels - +mouthFloorReliefVoxels+OutwardPaddingVoxels; - const double horizontalExtent=std::max(relievedRadius, - bridgeHalfWidthVoxels+OutwardPaddingVoxels); - FPassageProofBound proof; - proof.minimum={centerMinimum[0]-horizontalExtent, - centerMinimum[1]-horizontalExtent, - centerMinimum[2]-partRadius-footDepth-passageWallReliefVoxels - -mouthFloorReliefVoxels-OutwardPaddingVoxels}; - proof.maximum={centerMaximum[0]+horizontalExtent, - centerMaximum[1]+horizontalExtent, - centerMaximum[2]+partRadius+passageWallReliefVoxels - +mouthFloorReliefVoxels+OutwardPaddingVoxels}; - for(std::size_t axis=0;axis<3;++axis) - { - featureMinimum[axis]=std::min(featureMinimum[axis],proof.minimum[axis]); - featureMaximum[axis]=std::max(featureMaximum[axis],proof.maximum[axis]); - tubeMinimum[axis]=std::min(tubeMinimum[axis], - centerMinimum[axis]-relievedRadius); - tubeMaximum[axis]=std::max(tubeMaximum[axis], - centerMaximum[axis]+relievedRadius); - } - PassageProofBounds.push_back(proof); - } - auto& preparedSegment=PassageSegmentData[passageIndex][segment]; - for(std::size_t axis=0;axis<3;++axis) - { - preparedSegment.sweepMinimumSubvoxels[axis]= - static_cast(std::floor( - (tubeMinimum[axis]-4.0*voxelsPerMetre)*Q)); - preparedSegment.sweepMaximumSubvoxels[axis]= - static_cast(std::ceil( - (tubeMaximum[axis]+4.0*voxelsPerMetre)*Q)); - } - const std::array featureMin={ - static_cast(std::floor( - (featureMinimum[0]-4.0*voxelsPerMetre)*Q)), - static_cast(std::floor( - (featureMinimum[1]-4.0*voxelsPerMetre)*Q)), - static_cast(std::floor( - (featureMinimum[2]-4.0*voxelsPerMetre)*Q))}; - const std::array featureMax={ - static_cast(std::ceil( - (featureMaximum[0]+4.0*voxelsPerMetre)*Q)), - static_cast(std::ceil( - (featureMaximum[1]+4.0*voxelsPerMetre)*Q)), - static_cast(std::ceil( - (featureMaximum[2]+4.0*voxelsPerMetre)*Q))}; - PassageFeatureBounds.push_back({static_cast(PassageTileFeatures.size()), - featureMin,featureMax}); - PassageTileFeatures.push_back({passageIndex,segment,false}); - } - const auto upperStratum=std::find_if(ResolvedLayout->strates.begin(), - ResolvedLayout->strates.end(),[&passage](const auto& value) - {return value.strateIndex==passage.upperStrateIndex;}); - if(upperStratum!=ResolvedLayout->strates.end()) - { - std::array route{}; - std::size_t routeCount=0; - std::vector allRoutePoints; - allRoutePoints.reserve(upperStratum->anchors.size()); - for(const auto& anchor:upperStratum->anchors) - if(anchor.kind=="route_point"&&anchor.values.size()>=3) - { - allRoutePoints.push_back(&anchor); - if(routeCount=2) - { - auto& supportRoutes=PassageMouthSupportRoutes[passageIndex]; - supportRoutes.reserve(allRoutePoints.size()-1); - for(std::size_t index=0;index+1values[axis]; - segment.b[axis]=allRoutePoints[index+1]->values[axis]; - } - segment.hasRadius=allRoutePoints[index]->values.size()>=4 - &&allRoutePoints[index+1]->values.size()>=4; - if(segment.hasRadius) - { - segment.a[3]=allRoutePoints[index]->values[3]; - segment.b[3]=allRoutePoints[index+1]->values[3]; - } - supportRoutes.push_back(segment); - } - const double mouthReach=13.0*voxelsPerMetre*Q; - double minimumZ=std::numeric_limits::infinity(); - double maximumZ=-std::numeric_limits::infinity(); - for(std::size_t index=0;index(route[index]->values[2])); - maximumZ=std::max(maximumZ,static_cast(route[index]->values[2])); - } - const double mouthX=passage.upperMouthSubvoxels[0]; - const double mouthY=passage.upperMouthSubvoxels[1]; - FPassageProofBound supportProof; - supportProof.minimum={(mouthX-mouthReach)/Q,(mouthY-mouthReach)/Q, - (minimumZ-3.0*voxelsPerMetre*Q)/Q}; - supportProof.maximum={(mouthX+mouthReach)/Q,(mouthY+mouthReach)/Q, - (maximumZ+3.0*voxelsPerMetre*Q)/Q}; - PassageProofBounds.push_back(supportProof); - for(std::size_t index=0;index featureMinimum={ - std::min(segment.a[0],segment.b[0])-static_cast( - std::ceil(HorizontalReachMetres*qPerMetre)), - std::min(segment.a[1],segment.b[1])-static_cast( - std::ceil(HorizontalReachMetres*qPerMetre)), - static_cast(std::floor( - std::min(segment.a[2],segment.b[2]) - -MouthSupportBottomOffsetMetres*qPerMetre))}; - const std::array featureMaximum={ - std::max(segment.a[0],segment.b[0])+static_cast( - std::ceil(HorizontalReachMetres*qPerMetre)), - std::max(segment.a[1],segment.b[1])+static_cast( - std::ceil(HorizontalReachMetres*qPerMetre)), - static_cast(std::ceil( - std::max(segment.a[2],segment.b[2]) - -MouthSupportTopOffsetMetres*qPerMetre))}; - PassageFeatureBounds.push_back({static_cast( - PassageTileFeatures.size()),featureMinimum,featureMaximum}); - PassageTileFeatures.push_back({passageIndex,index,false,true}); - } - } - } - } - const bool traceMouthPreparation=VF_IsL98PassagePrepareTraceEnabled(); - const auto mouthPreparationStart=traceMouthPreparation - ?std::chrono::steady_clock::now():std::chrono::steady_clock::time_point{}; - std::size_t mouthSupportSegmentCount=0; - for(std::size_t passageIndex=0;passageIndexpassages.size(); ++passageIndex) { - PassageMouthSupportSegmentOffsets[passageIndex]=mouthSupportSegmentCount; - for(auto& segment:PassageMouthSupportRoutes[passageIndex]) + const std::size_t segmentCount=PassageSegmentData[passageIndex].size(); + if(segmentCount==0)continue; + std::vector segmentIds(segmentCount); + for(std::size_t i=0;i routeMinimum{ + std::numeric_limits::infinity(), + std::numeric_limits::infinity(), + std::numeric_limits::infinity()}; + std::array routeMaximum{ + -std::numeric_limits::infinity(), + -std::numeric_limits::infinity(), + -std::numeric_limits::infinity()}; + double maximumRadiusSubvoxels=0.0; + for(std::size_t localIndex=segmentIndex; + localIndex(segment.a[axis]); - segment.preparedDelta[axis]=axis<2 - ?static_cast(segment.b[axis]-segment.a[axis]) - :static_cast(segment.b[axis])-segment.a[axis]; - } - const double dx=segment.preparedDelta[0]; - const double dy=segment.preparedDelta[1]; - segment.horizontalLengthSq=dx*dx+dy*dy; - ++mouthSupportSegmentCount; - } - PassageMouthSupportSegmentOffsets[passageIndex+1]=mouthSupportSegmentCount; - } - if(traceMouthPreparation) - std::printf("[L98PassageMouthPrepare] segments=%zu bytes=%zu prepare_ms=%.3f\n", - mouthSupportSegmentCount, - mouthSupportSegmentCount*sizeof(FPassageMouthSupportSegment), - std::chrono::duration( - std::chrono::steady_clock::now()-mouthPreparationStart).count()); - // Precompute the later-bore leaves that can intersect each tread segment. - // Passage support samples normally stay within this source envelope, so the - // hot query can test a short list of physical bounds instead of walking a - // full spatial tree for every density sample. - PassageLaterBoreSources.resize(ResolvedLayout->passages.size()); - for(std::size_t sourcePassageIndex=0; - sourcePassageIndexpassages.size();++sourcePassageIndex) - { - const auto& sourcePassage=ResolvedLayout->passages[sourcePassageIndex]; - const std::size_t sourceSegmentCount=sourcePassage.controlPoints.size()>1 - ?sourcePassage.controlPoints.size()-1:0; - auto& sourceSegments=PassageLaterBoreSources[sourcePassageIndex]; - sourceSegments.resize(sourceSegmentCount); - for(std::size_t sourceSegment=0;sourceSegmentpassages.size();++laterPassageIndex) - { - for(const auto& node:PassageNearestNodes[laterPassageIndex]) + auto& prepared=PassageSegmentData[passageIndex][localIndex]; + maximumRadiusSubvoxels=std::max({maximumRadiusSubvoxels, + prepared.radiusA,prepared.radiusB}); + std::array localMinimum{},localMaximum{}; + for(std::size_t axis=0;axis<3;++axis) { - if(node.left>=0)continue; - const double reach=node.maximumRadius+0.35*qPerMetre+1.0e-6; - bool intersectsSource=true; - for(std::size_t axis=0;axis<3;++axis) - intersectsSource=intersectsSource - &&node.minimum[axis]-reach<=source.maximum[axis] - &&node.maximum[axis]+reach>=source.minimum[axis]; - if(!intersectsSource)continue; - source.candidates.push_back({node.minimum,node.maximum,reach}); + localMinimum[axis]=std::min(prepared.a[axis],prepared.b[axis])/Q; + localMaximum[axis]=std::max(prepared.a[axis],prepared.b[axis])/Q; + routeMinimum[axis]=std::min(routeMinimum[axis],localMinimum[axis]); + routeMaximum[axis]=std::max(routeMaximum[axis],localMaximum[axis]); + } + const double localExtent=requiredReach + +std::max(prepared.radiusA,prepared.radiusB)/Q+0.01; + FPassageProofBound proof; + for(std::size_t axis=0;axis<3;++axis) + { + proof.minimum[axis]=localMinimum[axis]-localExtent; + proof.maximum[axis]=localMaximum[axis]+localExtent; + } + PassageProofBounds.push_back(proof); + + for(std::size_t axis=0;axis<3;++axis) + { + prepared.sweepMinimumSubvoxels[axis]=static_cast( + std::floor((localMinimum[axis]-localExtent)*Q)); + prepared.sweepMaximumSubvoxels[axis]=static_cast( + std::ceil((localMaximum[axis]+localExtent)*Q)); } } - const double capsuleXYReach=0.39*qPerMetre; - for(std::size_t otherPassageIndex=0; - otherPassageIndexpassages.size();++otherPassageIndex) + const double routeExtent=maximumRadiusSubvoxels/Q+requiredReach+0.01; + const double tileExtent=routeExtent; + std::array featureMinimum{},featureMaximum{}; + for(std::size_t axis=0;axis<3;++axis) { - if(otherPassageIndex==sourcePassageIndex - ||PassageNearestNodes[otherPassageIndex].empty())continue; - const auto& otherRoot=PassageNearestNodes[otherPassageIndex].front(); - const std::array blockerMinimum={ - otherRoot.minimum[0]-capsuleXYReach, - otherRoot.minimum[1]-capsuleXYReach, - otherRoot.minimum[2]-otherRoot.maximumRadius+0.20*qPerMetre}; - const std::array blockerMaximum={ - otherRoot.maximum[0]+capsuleXYReach, - otherRoot.maximum[1]+capsuleXYReach, - otherRoot.maximum[2]+2.06*qPerMetre}; - bool intersectsSource=true; - for(std::size_t axis=0;axis<3;++axis) - intersectsSource=intersectsSource - &&blockerMinimum[axis]<=source.maximum[axis] - &&blockerMaximum[axis]>=source.minimum[axis]; - if(intersectsSource) - source.capsuleCandidatePassages.push_back(otherPassageIndex); + featureMinimum[axis]=static_cast(std::floor( + (routeMinimum[axis]-tileExtent)*Q)); + featureMaximum[axis]=static_cast(std::ceil( + (routeMaximum[axis]+tileExtent)*Q)); } + PassageFeatureBounds.push_back({ + static_cast(PassageTileFeatures.size()), + featureMinimum,featureMaximum}); + PassageTileFeatures.push_back( + {passageIndex,segmentIndex,segmentEndIndex}); } } - for(const auto& crossing:PassageVoidCrossings) - { - if(crossing.passageIndexpassages.size()) - { - const std::int32_t strate=ResolvedLayout->passages[ - crossing.passageIndex].upperStrateIndex; - const auto upper=std::find_if(ResolvedLayout->strates.begin(), - ResolvedLayout->strates.end(),[strate](const auto& value) - {return value.strateIndex==strate;}); - surfaceWorldUpper=upper!=ResolvedLayout->strates.end() - &&upper->passageCapabilities.hasSurfaceLanding; - } - const std::size_t shortSpanPadding=!crossing.needsColumn - &&surfaceWorldUpper&&!flags.empty()?2:0; - const std::size_t first=std::min(crossing.firstSegment>shortSpanPadding - ?crossing.firstSegment-shortSpanPadding:0,flags.size()); - const std::size_t last=std::min(crossing.lastSegment+shortSpanPadding, - flags.empty()?0:flags.size()-1); - if(!flags.empty()&&first<=last) - std::fill(flags.begin()+first,flags.begin()+last+1,1); - } - if(!crossing.needsColumn)continue; - FPassageProofBound proof; - const double radius=static_cast(crossing.maximumRadiusSubvoxels)/Q; - proof.minimum={crossing.centerXSubvoxels/Q-radius,crossing.centerYSubvoxels/Q-radius, - crossing.bottomZSubvoxels/Q}; - proof.maximum={crossing.centerXSubvoxels/Q+radius,crossing.centerYSubvoxels/Q+radius, - crossing.topZSubvoxels/Q}; - PassageProofBounds.push_back(proof); - const std::array featureMin={ - static_cast(std::floor(proof.minimum[0]*Q)), - static_cast(std::floor(proof.minimum[1]*Q)), - static_cast(std::floor(proof.minimum[2]*Q))}; - const std::array featureMax={ - static_cast(std::ceil(proof.maximum[0]*Q)), - static_cast(std::ceil(proof.maximum[1]*Q)), - static_cast(std::ceil(proof.maximum[2]*Q))}; - PassageFeatureBounds.push_back({static_cast(PassageTileFeatures.size()), - featureMin,featureMax}); - PassageTileFeatures.push_back({crossing.passageIndex,0,true}); - } - PassageHasShortSpanFlags.assign(PassageShortSpanSegmentFlags.size(),0); - for(std::size_t passageIndex=0;passageIndex( - std::any_of(PassageShortSpanSegmentFlags[passageIndex].begin(), - PassageShortSpanSegmentFlags[passageIndex].end(), - [](std::uint8_t flag){return flag!=0;})); for(std::size_t i=0;i(i)); for(const auto& feature:PassageFeatureBounds) for(std::size_t axis=0;axis<3;++axis) PassageFeatureBoundsFailOpen=PassageFeatureBoundsFailOpen ||feature.minimumSubvoxels[axis]>feature.maximumSubvoxels[axis]; - if(!PassageFeatureOrder.empty())BuildPassageFeatureNode(0,PassageFeatureOrder.size()); - if(!PassageProofBounds.empty())BuildPassageProofNode(0,PassageProofBounds.size()); - if(L90PassageCandidateProgramEnabled)BuildPassageCandidateProgram(); - } - - static FPassageCandidateBrickKey PassageCandidateBrickKeyFor(double qx,double qy, - double qz,double brickEdgeSubvoxels) - { - return {static_cast(std::floor(qx/brickEdgeSubvoxels)), - static_cast(std::floor(qy/brickEdgeSubvoxels)), - static_cast(std::floor(qz/brickEdgeSubvoxels))}; - } - - const FPassageCandidateBrick* FindPassageCandidateBrick(double qx,double qy, - double qz) const - { - if(!L90PassageCandidateProgramValid)return nullptr; - const auto key=PassageCandidateBrickKeyFor(qx,qy,qz, - L90PassageCandidateBrickEdgeSubvoxels); - const auto found=L90PassageCandidateBricks.find(key); - return found==L90PassageCandidateBricks.end()?nullptr:&found->second; - } - - static bool PassageCandidateRefLess(const FPassageCandidateRef& a, - const FPassageCandidateRef& b) - { - if(a.passageIndex!=b.passageIndex)return a.passageIndex=brick->semantics.size() - ||passageIndex>std::numeric_limits::max())return false; - const FPassageCandidateRef query{static_cast(passageIndex), - segmentIndex,featureKind}; - const auto& values=brick->semantics[semantic]; - return std::binary_search(values.begin(),values.end(),query,PassageCandidateRefLess); - } - - void BuildPassageCandidateProgram() - { - using FClock=std::chrono::steady_clock; - const auto buildStart=FClock::now(); - L90PassageCandidateBricks.clear(); - L90PassageCandidateProgramValid=false; - L90PassageCandidateBuildFailures=0; - const auto ReadPositiveEnv=[](const char* Name,double Default) - { - const char* Raw=std::getenv(Name); - if(!Raw||!*Raw)return Default; - char* End=nullptr; - const double Parsed=std::strtod(Raw,&End); - return End!=Raw&&*End=='\0'&&std::isfinite(Parsed)&&Parsed>0.0 - ?Parsed:Default; - }; - L90PassageCandidateReachMetres=ReadPositiveEnv( - "VOXELFORGE_L90_PASSAGE_REACH_METRES",10.0); - const double brickMetres=ReadPositiveEnv( - "VOXELFORGE_L90_PASSAGE_BRICK_METRES",4.0); - constexpr double Q=static_cast(VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel); - const double qPerMetre=Q*1000000.0/std::max(1, - ResolvedLayout->coreVoxelSizeMicrometres); - const double voxelsPerMetre=qPerMetre/Q; - L90PassageCandidateBrickEdgeSubvoxels=brickMetres*qPerMetre; - const double reachSubvoxels=L90PassageCandidateReachMetres*qPerMetre; - const double cubicPadding=1.0; - std::array emittedReferences{}; - const auto emit=[&](std::size_t semantic,const std::array& minimum, - const std::array& maximum,const FPassageCandidateRef& reference) - { - if(semantic>=4||!std::isfinite(L90PassageCandidateBrickEdgeSubvoxels) - ||L90PassageCandidateBrickEdgeSubvoxels<=0.0) - {++L90PassageCandidateBuildFailures;return;} - FPassageCandidateBrickKey first{},last{}; - for(std::size_t axis=0;axis<3;++axis) - { - if(!std::isfinite(minimum[axis])||!std::isfinite(maximum[axis]) - ||minimum[axis]>maximum[axis]) - {++L90PassageCandidateBuildFailures;return;} - const long double cellMinimum=std::floor(static_cast(minimum[axis]) - /L90PassageCandidateBrickEdgeSubvoxels); - const long double cellMaximum=std::floor(static_cast(maximum[axis]) - /L90PassageCandidateBrickEdgeSubvoxels); - if(cellMinimum(std::numeric_limits::min()) - ||cellMinimum>static_cast(std::numeric_limits::max()) - ||cellMaximum(std::numeric_limits::min()) - ||cellMaximum>static_cast(std::numeric_limits::max())) - {++L90PassageCandidateBuildFailures;return;} - const auto lo=static_cast(cellMinimum); - const auto hi=static_cast(cellMaximum); - if(axis==0){first.x=lo;last.x=hi;} - else if(axis==1){first.y=lo;last.y=hi;} - else {first.z=lo;last.z=hi;} - } - for(std::int64_t x=first.x;;++x) - { - for(std::int64_t y=first.y;;++y) - { - for(std::int64_t z=first.z;;++z) - { - auto& brick=L90PassageCandidateBricks[{x,y,z}]; - brick.semantics[semantic].push_back(reference); - ++emittedReferences[semantic]; - if(z==last.z)break; - } - if(y==last.y)break; - } - if(x==last.x)break; - } - }; - const auto pointBox=[&](const std::array& centerMinimum, - const std::array& centerMaximum,double extentX,double extentY, - double extentBelow,double extentAbove) - { - return std::pair,std::array>{ - {centerMinimum[0]-extentX,centerMinimum[1]-extentY, - centerMinimum[2]-extentBelow}, - {centerMaximum[0]+extentX,centerMaximum[1]+extentY, - centerMaximum[2]+extentAbove}}; - }; - - for(std::size_t passageIndex=0;passageIndexpassages.size(); - ++passageIndex) - { - const auto& passage=ResolvedLayout->passages[passageIndex]; - if(passage.controlPoints.size()<2)continue; - const std::ptrdiff_t lastIndex=static_cast( - passage.controlPoints.size())-1; - const auto& constants=PassageComposerConstants[passageIndex]; - const std::ptrdiff_t lowerMouthIndex=constants.lowerMouthIndex; - const auto pointArray=[&](std::ptrdiff_t index) - { - std::array result{}; - const auto& point=passage.controlPoints[static_cast(index)]; - for(std::size_t axis=0;axis<3;++axis) - result[axis]=static_cast(point.positionSubvoxels[axis]); - return result; - }; - for(std::size_t segment=0;segment+1(b.positionSubvoxels[0])-a.positionSubvoxels[0]; - const double dy=static_cast(b.positionSubvoxels[1])-a.positionSubvoxels[1]; - const double dz=static_cast(b.positionSubvoxels[2])-a.positionSubvoxels[2]; - const double length=DeterministicSqrt(dx*dx+dy*dy+dz*dz); - const bool smoothCarve=static_cast(segment)>2 - &&static_cast(segment) - +(constants.internalChainPassage?2:12)(segment)-1 - :static_cast(segment)); - const auto p1=pointArray(static_cast(segment)); - const auto p2=pointArray(static_cast(segment)+1); - const auto p3=pointArray(smoothCarve - ?static_cast(segment)+2 - :static_cast(segment)+1); - const auto supportP0=pointArray(segment>0 - ?static_cast(segment)-1 - :static_cast(segment)); - const auto supportP3=pointArray(segment+2(segment)+2 - :static_cast(segment)+1); - const auto catmullRange=[&](std::size_t axis,double t0,double t1) - { - const double c0=p1[axis]; - const double c1=0.5*(-supportP0[axis]+p2[axis]); - const double c2=0.5*(2.0*supportP0[axis]-5.0*p1[axis] - +4.0*p2[axis]-supportP3[axis]); - const double c3=0.5*(-supportP0[axis]+3.0*p1[axis] - -3.0*p2[axis]+supportP3[axis]); - const auto evaluate=[&](double t) - {return ((c3*t+c2)*t+c1)*t+c0;}; - double low=std::min(evaluate(t0),evaluate(t1)); - double high=std::max(evaluate(t0),evaluate(t1)); - const double qa=3.0*c3,qb=2.0*c2,qc=c1; - const auto includeRoot=[&](double t) - { - if(t<=t0||t>=t1||!std::isfinite(t))return; - const double value=evaluate(t); - low=std::min(low,value);high=std::max(high,value); - }; - if(std::abs(qa)<=1.0e-12) - {if(std::abs(qb)>1.0e-12)includeRoot(-qc/qb);} - else - { - const double discriminant=qb*qb-4.0*qa*qc; - if(discriminant>=0.0) - { - const double root=std::sqrt(discriminant); - includeRoot((-qb-root)/(2.0*qa)); - includeRoot((-qb+root)/(2.0*qa)); - } - } - return std::pair{low-cubicPadding,high+cubicPadding}; - }; - std::array curveMinimum{},curveMaximum{}; - for(std::size_t axis=0;axis<3;++axis) - { - const double c0=p1[axis]; - const double c1=0.5*(-p0[axis]+p2[axis]); - const double c2=0.5*(2.0*p0[axis]-5.0*p1[axis] - +4.0*p2[axis]-p3[axis]); - const double c3=0.5*(-p0[axis]+3.0*p1[axis] - -3.0*p2[axis]+p3[axis]); - const auto evaluate=[&](double t) - {return smoothCarve?((c3*t+c2)*t+c1)*t+c0:p1[axis]+t*(p2[axis]-p1[axis]);}; - double low=std::min(evaluate(0.0),evaluate(1.0)); - double high=std::max(evaluate(0.0),evaluate(1.0)); - const double qa=3.0*c3,qb=2.0*c2,qc=c1; - const auto includeRoot=[&](double t) - { - if(t<=0.0||t>=1.0||!std::isfinite(t))return; - const double value=evaluate(t); - low=std::min(low,value);high=std::max(high,value); - }; - if(smoothCarve) - { - if(std::abs(qa)<=1.0e-12) - {if(std::abs(qb)>1.0e-12)includeRoot(-qc/qb);} - else - { - const double discriminant=qb*qb-4.0*qa*qc; - if(discriminant>=0.0) - { - const double root=std::sqrt(discriminant); - includeRoot((-qb-root)/(2.0*qa)); - includeRoot((-qb+root)/(2.0*qa)); - } - } - } - curveMinimum[axis]=low-cubicPadding; - curveMaximum[axis]=high+cubicPadding; - } - const double radius=static_cast(std::max(a.radiusSubvoxels, - b.radiusSubvoxels)); - const double carveExtent=radius+reachSubvoxels - +(0.21+0.20)*qPerMetre+cubicPadding; - const auto carveBox=pointBox(curveMinimum,curveMaximum, - carveExtent,carveExtent,carveExtent,carveExtent); - const FPassageCandidateRef routeReference{ - static_cast(passageIndex), - static_cast(segment),0}; - emit(0,carveBox.first,carveBox.second,routeReference); - - // Treads extend by up to two metres through route knots, then project - // across a 1.55 m half-width with relief. Include Catmull support-height - // overshoot, extrapolated radius, and the full source-dependent floor band. - const auto supportZCurve=catmullRange(2,-0.5,1.5); - const double supportLinearMinimum=std::min(p1[2],p2[2])-0.5*std::abs(dz); - const double supportLinearMaximum=std::max(p1[2],p2[2])+0.5*std::abs(dz); - const double supportRadiusMaximum=radius - +0.5*std::abs(static_cast(b.radiusSubvoxels) - -static_cast(a.radiusSubvoxels))+cubicPadding; - std::array treadMinimum={ - std::min(p1[0],p2[0])-4.25*qPerMetre, - std::min(p1[1],p2[1])-4.25*qPerMetre, - std::min(supportLinearMinimum,supportZCurve.first) - -supportRadiusMaximum-2.5*qPerMetre}; - std::array treadMaximum={ - std::max(p1[0],p2[0])+4.25*qPerMetre, - std::max(p1[1],p2[1])+4.25*qPerMetre, - std::max(supportLinearMaximum,supportZCurve.second)+2.5*qPerMetre}; - emit(1,treadMinimum,treadMaximum,routeReference); - - // Player capsules use horizontal projection, a 0.34 m radius, and a - // 0.54 m axial half-length above the route floor. - std::array clearanceMinimum={ - std::min(p1[0],p2[0])-0.40*qPerMetre, - std::min(p1[1],p2[1])-0.40*qPerMetre, - std::min(p1[2],p2[2])-radius+0.20*qPerMetre}; - std::array clearanceMaximum={ - std::max(p1[0],p2[0])+0.40*qPerMetre, - std::max(p1[1],p2[1])+0.40*qPerMetre, - std::max(p1[2],p2[2])+2.06*qPerMetre}; - emit(2,clearanceMinimum,clearanceMaximum,routeReference); - - const std::ptrdiff_t index=static_cast(segment); - const bool mouthCarve=index(8,lowerMouthIndex) - ||(index>=constants.mouthSearchBegin&&index=lowerMouthIndex; - if(mouthCarve) - emit(3,carveBox.first,carveBox.second,{routeReference.passageIndex, - routeReference.segmentIndex,1}); - } - - // The upper-mouth support exception has a larger spatial envelope than the - // tunnel body and remains an explicit compiled operation. - const auto& upperMouth=passage.upperMouthSubvoxels; - const double upperReach=15.0*qPerMetre,upperZReach=8.0*qPerMetre; - emit(3,{upperMouth[0]-upperReach,upperMouth[1]-upperReach, - upperMouth[2]-upperZReach}, - {upperMouth[0]+upperReach,upperMouth[1]+upperReach, - upperMouth[2]+upperZReach}, - {static_cast(passageIndex),-1,0}); - - if(passageIndex(passageIndex), - static_cast(segment),2}); - } - } - } - - for(std::size_t crossingIndex=0;crossingIndex=ResolvedLayout->passages.size())continue; - if(crossing.needsColumn) - { - const double radius=static_cast(crossing.maximumRadiusSubvoxels) - +reachSubvoxels; - emit(3,{crossing.centerXSubvoxels-radius, - crossing.centerYSubvoxels-radius, - static_cast(crossing.bottomZSubvoxels)-reachSubvoxels}, - {crossing.centerXSubvoxels+radius, - crossing.centerYSubvoxels+radius, - static_cast(crossing.topZSubvoxels)+reachSubvoxels}, - {static_cast(crossing.passageIndex), - static_cast(crossing.firstSegment),3}); - } - else - { - const auto& passage=ResolvedLayout->passages[crossing.passageIndex]; - bool surfaceWorldUpper=false; - const std::int32_t upperStrate=passage.upperStrateIndex; - const auto upper=std::find_if(ResolvedLayout->strates.begin(), - ResolvedLayout->strates.end(),[upperStrate](const auto& value) - {return value.strateIndex==upperStrate;}); - surfaceWorldUpper=upper!=ResolvedLayout->strates.end() - &&upper->passageCapabilities.hasSurfaceLanding; - const std::size_t shortSpanPadding=surfaceWorldUpper?2:0; - const std::size_t first=std::min(crossing.firstSegment>shortSpanPadding - ?crossing.firstSegment-shortSpanPadding:0, - passage.controlPoints.size()-1); - const std::size_t last=std::min(crossing.lastSegment+shortSpanPadding, - passage.controlPoints.size()-2); - for(std::size_t segment=first;segment<=last;++segment) - { - const auto& a=passage.controlPoints[segment]; - const auto& b=passage.controlPoints[segment+1]; - const double radius=static_cast(std::max(a.radiusSubvoxels, - b.radiusSubvoxels))+3.8*qPerMetre; - emit(3,{std::min(a.positionSubvoxels[0],b.positionSubvoxels[0])-radius, - std::min(a.positionSubvoxels[1],b.positionSubvoxels[1])-radius, - std::min(a.positionSubvoxels[2],b.positionSubvoxels[2])-5.0*qPerMetre}, - {std::max(a.positionSubvoxels[0],b.positionSubvoxels[0])+radius, - std::max(a.positionSubvoxels[1],b.positionSubvoxels[1])+radius, - std::max(a.positionSubvoxels[2],b.positionSubvoxels[2])+1.0*qPerMetre}, - {static_cast(crossing.passageIndex), - static_cast(segment),4}); - } - } - } - - for(auto& [key,brick]:L90PassageCandidateBricks) - { - (void)key; - for(auto& list:brick.semantics) - { - std::sort(list.begin(),list.end(),PassageCandidateRefLess); - list.erase(std::unique(list.begin(),list.end()),list.end()); - } - } - std::array uniqueReferences{}; - std::size_t listCapacityBytes=0; - for(const auto& [key,brick]:L90PassageCandidateBricks) - { - (void)key; - for(std::size_t semantic=0;semantic( - FClock::now()-buildStart).count(); - std::printf("[L90PassageCandidateBuild] brick_m=%.3f reach_m=%.3f source_floor_vox=%.3f bricks=%zu emitted=(%llu,%llu,%llu,%llu) unique=(%llu,%llu,%llu,%llu) bytes_estimate=%zu build_ms=%.3f failures=%llu valid=%d\n", - brickMetres,L90PassageCandidateReachMetres,VF_L91PassageSourceFloorVoxels(), - L90PassageCandidateBricks.size(), - static_cast(emittedReferences[0]), - static_cast(emittedReferences[1]), - static_cast(emittedReferences[2]), - static_cast(emittedReferences[3]), - static_cast(uniqueReferences[0]), - static_cast(uniqueReferences[1]), - static_cast(uniqueReferences[2]), - static_cast(uniqueReferences[3]), - estimatedBytes,buildMilliseconds, - static_cast(L90PassageCandidateBuildFailures), - static_cast(L90PassageCandidateProgramValid)); - } - - double PassageNearestNodeLowerBound(const FPassageNearestNode& node, - double qx,double qy,double qz) const - { - const double dx=qxnode.maximum[0]?qx-node.maximum[0]:0.0; - const double dy=qynode.maximum[1]?qy-node.maximum[1]:0.0; - const double dz=qznode.maximum[2]?qz-node.maximum[2]:0.0; - return DeterministicSqrt(dx*dx+dy*dy+dz*dz)-node.maximumRadius-1.0e-6; - } - - template - void VisitNearestPassageSpatialNode(std::size_t passageIndex,int nodeIndex, - std::size_t first,std::size_t end,double qx,double qy,double qz,int priority, - const std::vector* activeNodes,double knownLowerBound, - double& bestDistance,FVisit& visit) const - { - if(passageIndex>=PassageNearestNodes.size()||nodeIndex<0)return; - const auto& nodes=PassageNearestNodes[passageIndex]; - const std::size_t nodeOffset=static_cast(nodeIndex); - if(activeNodes&&(nodeOffset>=activeNodes->size()||!(*activeNodes)[nodeOffset]))return; - const auto& node=nodes[nodeOffset]; - if(!activeNodes&&(node.maximumSegment=end))return; - auto candidate=node.segments.begin(); - if(!activeNodes) - { - const bool allSegmentsInRange=first<=node.minimumSegment - &&node.maximumSegment=end)return; - } - if(knownLowerBound>bestDistance)return; - if(node.left<0) - { - for(auto it=candidate;it!=node.segments.end();++it) - { - if(*it=end)continue; - visit(*it,priority); - } - return; - } - const bool leftActive=!activeNodes - ||(static_cast(node.left)size() - &&(*activeNodes)[static_cast(node.left)]); - const bool rightActive=!activeNodes - ||(static_cast(node.right)size() - &&(*activeNodes)[static_cast(node.right)]); - const double leftBound=leftActive?PassageNearestNodeLowerBound( - nodes[static_cast(node.left)],qx,qy,qz) - :std::numeric_limits::infinity(); - const double rightBound=rightActive?PassageNearestNodeLowerBound( - nodes[static_cast(node.right)],qx,qy,qz) - :std::numeric_limits::infinity(); - const int nearChild=leftBound<=rightBound?node.left:node.right; - const int farChild=leftBound<=rightBound?node.right:node.left; - VisitNearestPassageSpatialNode(passageIndex,nearChild,first,end,qx,qy,qz, - priority,activeNodes,leftBound<=rightBound?leftBound:rightBound, - bestDistance,visit); - VisitNearestPassageSpatialNode(passageIndex,farChild,first,end,qx,qy,qz, - priority,activeNodes,leftBound<=rightBound?rightBound:leftBound, - bestDistance,visit); - } - - template - void VisitNearestPassageSegmentRange(std::size_t passageIndex,std::ptrdiff_t first, - std::ptrdiff_t last,double qx,double qy,double qz,int priority, - double& bestDistance,FVisit&& visit) const - { - if(first>last||passageIndex>=PassageNearestNodes.size() - ||PassageNearestNodes[passageIndex].empty())return; - auto callback=std::forward(visit); - const auto* tileQueries=ActivePassageTileQueries; - const auto* activeNodes=tileQueries&&tileQueries->matches(*this) - ?tileQueries->segmentRangeNodeMask(passageIndex,first,last+1,priority):nullptr; - if(activeNodes&&(activeNodes->empty()||!(*activeNodes)[0]))return; - if(!activeNodes) - { - const auto& root=PassageNearestNodes[passageIndex][0]; - if(root.maximumSegment(first) - ||root.minimumSegment>=static_cast(last+1))return; - } - const double rootLowerBound=PassageNearestNodeLowerBound( - PassageNearestNodes[passageIndex][0],qx,qy,qz); - VisitNearestPassageSpatialNode(passageIndex,0,static_cast(first), - static_cast(last+1),qx,qy,qz,priority,activeNodes, - rootLowerBound,bestDistance,callback); - } - - bool PassagePotentialWithinNode(std::size_t passageIndex,int nodeIndex, - std::size_t first,std::size_t end,double qx,double qy,double qz, - double signedDistanceLimit) const - { - if(passageIndex>=PassageNearestNodes.size()||nodeIndex<0)return false; - const auto& nodes=PassageNearestNodes[passageIndex]; - const std::size_t nodeOffset=static_cast(nodeIndex); - if(nodeOffset>=nodes.size())return false; - const auto& node=nodes[nodeOffset]; - if(node.maximumSegment=end)return false; - if(!node.segmentRangeContiguous) - { - const bool allSegmentsInRange=first<=node.minimumSegment - &&node.maximumSegment=end)return false; - } - if(PassageNearestNodeLowerBound(node,qx,qy,qz)>signedDistanceLimit)return false; - if(node.left<0)return true; - const double leftBound=PassageNearestNodeLowerBound( - nodes[static_cast(node.left)],qx,qy,qz); - const double rightBound=PassageNearestNodeLowerBound( - nodes[static_cast(node.right)],qx,qy,qz); - const int nearChild=leftBound<=rightBound?node.left:node.right; - const int farChild=leftBound<=rightBound?node.right:node.left; - return PassagePotentialWithinNode(passageIndex,nearChild,first,end,qx,qy,qz, - signedDistanceLimit) - ||PassagePotentialWithinNode(passageIndex,farChild,first,end,qx,qy,qz, - signedDistanceLimit); - } - - bool PassageSupportMayBeCarvedByLaterBore(std::size_t passageIndex, - std::ptrdiff_t supportSegment,double qx,double qy,double qz, - double signedDistanceLimit) const - { - if(!ResolvedLayout||passageIndex+1>=ResolvedLayout->passages.size())return false; - if(passageIndex=0 - &&static_cast(supportSegment) - (supportSegment)]; - const bool insideSourceEnvelope=qx>=source.minimum[0]&&qx<=source.maximum[0] - &&qy>=source.minimum[1]&&qy<=source.maximum[1] - &&qz>=source.minimum[2]&&qz<=source.maximum[2]; - if(insideSourceEnvelope) - { - for(const auto& candidate:source.candidates) - { - double distanceSquared=0.0; - for(std::size_t axis=0;axis<3;++axis) - { - const double q=axis==0?qx:axis==1?qy:qz; - const double distance=qcandidate.maximum[axis]?q-candidate.maximum[axis]:0.0; - distanceSquared+=distance*distance; - } - const double reach=candidate.reach; - if(distanceSquared<=reach*reach)return true; - } - return false; - } - } - for(std::size_t otherPassageIndex=passageIndex+1; - otherPassageIndexpassages.size();++otherPassageIndex) - { - const auto& otherPassage=ResolvedLayout->passages[otherPassageIndex]; - if(otherPassage.controlPoints.size()<2)continue; - if(PassagePotentialWithinNode(otherPassageIndex,0,0, - otherPassage.controlPoints.size()-1,qx,qy,qz,signedDistanceLimit))return true; - } - return false; - } - - bool PassageOtherCapsuleBlocksSupport(std::size_t passageIndex, - std::ptrdiff_t supportSegment,double qx,double qy,double qz, - double qPerMetre,double minimumClearanceMetres) const - { - if(passageIndex=0 - &&static_cast(supportSegment) - (supportSegment)]; - const bool insideSourceEnvelope=qx>=source.minimum[0]&&qx<=source.maximum[0] - &&qy>=source.minimum[1]&&qy<=source.maximum[1] - &&qz>=source.minimum[2]&&qz<=source.maximum[2]; - if(insideSourceEnvelope) - { - for(const std::size_t otherPassageIndex:source.capsuleCandidatePassages) - { - const auto& otherPassage=ResolvedLayout->passages[otherPassageIndex]; - if(PassagePlayerCapsuleBlocksSupportNode(otherPassageIndex,0,0, - otherPassage.controlPoints.size()-1,qx,qy,qz,qPerMetre, - minimumClearanceMetres))return true; - } - return false; - } - } - for(std::size_t otherPassageIndex=0; - otherPassageIndexpassages.size();++otherPassageIndex) - { - if(otherPassageIndex==passageIndex)continue; - const auto& otherPassage=ResolvedLayout->passages[otherPassageIndex]; - if(otherPassage.controlPoints.size()<2)continue; - if(PassagePlayerCapsuleBlocksSupportNode(otherPassageIndex,0,0, - otherPassage.controlPoints.size()-1,qx,qy,qz,qPerMetre, - minimumClearanceMetres))return true; - } - return false; - } - - bool PassageMayAffectDensity(std::size_t passageIndex,std::ptrdiff_t carveBegin, - std::ptrdiff_t carveEnd,std::ptrdiff_t lowerMouthIndex, - std::ptrdiff_t mouthSearchBegin,std::ptrdiff_t mouthSearchEnd,std::ptrdiff_t lastIndex, - double qx,double qy,double qz,double signedDistanceLimit) const - { - const auto possible=[&](std::ptrdiff_t first,std::ptrdiff_t last) - { - if(first>last||passageIndex>=PassageNearestNodes.size() - ||PassageNearestNodes[passageIndex].empty())return false; - return PassagePotentialWithinNode(passageIndex,0, - static_cast(first),static_cast(last+1), - qx,qy,qz,signedDistanceLimit); - }; - return possible(carveBegin,carveEnd) - ||possible(0,std::min(8,lowerMouthIndex)-1) - ||possible(mouthSearchBegin,mouthSearchEnd-1) - ||possible(lowerMouthIndex,lastIndex-1); - } - - bool PassagePlayerCapsuleBlocksSupportNode(std::size_t passageIndex,int nodeIndex, - std::size_t first,std::size_t end,double qx,double qy,double qz,double qPerMetre, - double minimumClearanceMetres) const - { - if(passageIndex>=PassageNearestNodes.size()||nodeIndex<0)return false; - const auto& nodes=PassageNearestNodes[passageIndex]; - const auto& node=nodes[static_cast(nodeIndex)]; - if(node.maximumSegment=end)return false; - auto candidate=node.segments.begin(); - if(!node.segmentRangeContiguous) - { - const bool allSegmentsInRange=first<=node.minimumSegment - &&node.maximumSegment=end)return false; - } - const double xyReach=0.39*qPerMetre; - if(qx+xyReachnode.maximum[0] - ||qy+xyReachnode.maximum[1])return false; - const double minimumCenterZ=node.minimum[2]-node.maximumRadius+0.20*qPerMetre; - const double maximumCenterZ=node.maximum[2]+2.06*qPerMetre; - if(qzmaximumCenterZ)return false; - const auto& passage=ResolvedLayout->passages[passageIndex]; - if(node.left<0) - { - for(auto it=candidate;it!=node.segments.end()&&*itmatches(*this)) - l98TileQueries->recordPreparedSegmentUse( - FScopedPassageTileQueries::EPreparedSegmentUse::Capsule); - const double ax=segment.a[0],ay=segment.a[1],az=segment.a[2]; - const double dx=segment.delta[0],dy=segment.delta[1],dz=segment.delta[2]; - const double lengthSq=segment.lengthSq; - if(lengthSq<=0.0)continue; - const double horizontalLengthSq=segment.horizontalLengthSq; - const double t=horizontalLengthSq>0.0 - ?std::clamp(PassageXYProjectionNumerator(passageIndex,index,qx,qy) - /horizontalLengthSq,0.0,1.0):0.0; - const double centerX=ax+t*dx,centerY=ay+t*dy; - const double centerZ=az+t*dz-(segment.radiusA - +t*segment.radiusDelta)+1.13*qPerMetre; - const double horizontalX=qx-centerX,horizontalY=qy-centerY; - const double vertical=std::max(0.0,std::abs(qz-centerZ)-0.54*qPerMetre); - const double distance=DeterministicSqrt(horizontalX*horizontalX+horizontalY*horizontalY - +vertical*vertical)-0.34*qPerMetre; - if(distancematches(*this) - &&l90TileQueries->candidateCensusProfiled()) - l90TileQueries->recordL90ProofCheck(2, - PassageCandidateBrickContains(ActivePassageCandidateBrick,2, - passageIndex,static_cast(index))); - return true; - } - } - return false; - } - return PassagePlayerCapsuleBlocksSupportNode(passageIndex,node.left,first,end, - qx,qy,qz,qPerMetre,minimumClearanceMetres) - ||PassagePlayerCapsuleBlocksSupportNode(passageIndex,node.right,first,end, - qx,qy,qz,qPerMetre,minimumClearanceMetres); - } - - bool PassagePlayerCapsuleBlocksSupport(std::size_t passageIndex, - std::ptrdiff_t carveBegin,std::ptrdiff_t carveEnd,std::ptrdiff_t lowerMouthIndex, - std::ptrdiff_t mouthSearchBegin,std::ptrdiff_t mouthSearchEnd,std::ptrdiff_t lastIndex, - double qx,double qy,double qz,double qPerMetre,double minimumClearanceMetres) const - { - const auto blocked=[&](std::ptrdiff_t first,std::ptrdiff_t last) - { - return first<=last&&PassagePlayerCapsuleBlocksSupportNode(passageIndex,0, - static_cast(first),static_cast(last+1), - qx,qy,qz,qPerMetre,minimumClearanceMetres); - }; - return blocked(carveBegin,carveEnd) - ||blocked(0,std::min(8,lowerMouthIndex)-1) - ||blocked(mouthSearchBegin,mouthSearchEnd-1) - ||blocked(lowerMouthIndex,lastIndex-1); + if(!PassageFeatureOrder.empty()) + BuildPassageFeatureNode(0,PassageFeatureOrder.size()); + if(!PassageProofBounds.empty()) + BuildPassageProofNode(0,PassageProofBounds.size()); } bool PassageProofBoundsOverlapNode(int nodeIndex,const double minimum[3], @@ -7417,197 +4924,6 @@ private: ||PassageProofBoundsOverlapNode(node.right,minimum,maximum); } - bool IsPassageColumnSegment(std::size_t PassageIndex,std::size_t SegmentIndex) const - { - return PassageIndex=ResolvedLayout->passages.size()) - return std::numeric_limits::infinity(); - const auto& passage=ResolvedLayout->passages[PassageIndex]; - if(SegmentIndex+1>=passage.controlPoints.size()) - return std::numeric_limits::infinity(); - constexpr double Q=static_cast(VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel); - const double qPerMetre=Q*1000000.0/std::max(1, - ResolvedLayout->coreVoxelSizeMicrometres); - const auto upperStratum=std::find_if(ResolvedLayout->strates.begin(), - ResolvedLayout->strates.end(),[&passage](const auto& value) - {return value.strateIndex==passage.upperStrateIndex;}); - const bool surfaceWorldUpper=upperStratum!=ResolvedLayout->strates.end() - &&upperStratum->passageCapabilities.hasSurfaceLanding; - const FPassageSegmentData& segment=GetPassageSegmentData(PassageIndex,SegmentIndex); - const auto* l98TileQueries=ActivePassageTileQueries; - if(l98TileQueries&&l98TileQueries->matches(*this)) - l98TileQueries->recordPreparedSegmentUse( - FScopedPassageTileQueries::EPreparedSegmentUse::Support); - const double ax=segment.a[0],ay=segment.a[1]; - const double dx=segment.delta[0],dy=segment.delta[1]; - const double horizontalLengthSq=segment.horizontalLengthSq; - const double qx=static_cast(X)*Q,qy=static_cast(Y)*Q; - const double qz=static_cast(Z)*Q; - const double t=horizontalLengthSq>0.0 - ?std::clamp(PassageXYProjectionNumerator(PassageIndex,SegmentIndex,qx,qy) - /horizontalLengthSq,0.0,1.0):0.0; - const double centerX=ax+t*dx,centerY=ay+t*dy; - const double centerZ=segment.a[2]+t*segment.delta[2]; - const double radius=segment.radiusA+t*segment.radiusDelta; - // Embed the deck 13 cm above the bore bottom: within the 25 cm support - // probe, while leaving 16 cm between it and the capsule's lowest sample. - const double floorQ=centerZ-radius - +PassageBridgeDeckOffsetMetres(PassageIndex,SegmentIndex)*qPerMetre; - const double relief=std::clamp(static_cast(VF_FieldSurfaceRelief(X,Y,Z, - static_cast(Owner?Owner->Seed:0))),-1.0,1.0); - const double halfWidth=(surfaceWorldUpper?3.65+0.10*relief:3.30+0.20*relief) - *qPerMetre; - const double thickness=(4.0+1.0*relief)*qPerMetre; - const double horizontalDistance=DeterministicSqrt((qx-centerX)*(qx-centerX) - +(qy-centerY)*(qy-centerY)); - const double sideDistance=horizontalDistance-halfWidth; - const double topDistance=qz-floorQ; - const double bottomDistance=floorQ-thickness-qz; - const double verticalDistance=std::max(topDistance,bottomDistance); - const double outside=DeterministicSqrt( - std::max(sideDistance,0.0)*std::max(sideDistance,0.0) - +std::max(verticalDistance,0.0)*std::max(verticalDistance,0.0)); - const double inside=std::min(std::max(sideDistance,verticalDistance),0.0); - return outside+inside; - } - - double PassageColumnSignedDistance(const FStandalonePassageVoidCrossing& crossing, - float X,float Y,float Z) const - { - if(crossing.maximumRadiusSubvoxels<=0||crossing.topZSubvoxels - <=crossing.bottomZSubvoxels)return std::numeric_limits::infinity(); - constexpr double Q=static_cast(VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel); - const double qPerMetre=Q*1000000.0/std::max(1, - ResolvedLayout?ResolvedLayout->coreVoxelSizeMicrometres:250000u); - const double qx=static_cast(X)*Q,qy=static_cast(Y)*Q, - qz=static_cast(Z)*Q; - const double dx=qx-crossing.centerXSubvoxels; - const double dy=qy-crossing.centerYSubvoxels; - const double maximumRadius=static_cast(crossing.maximumRadiusSubvoxels); - const double horizontalSquared=dx*dx+dy*dy; - if(horizontalSquared>maximumRadius*maximumRadius) - return DeterministicSqrt(horizontalSquared)-maximumRadius; - if(qz>crossing.topZSubvoxels) - return qz-crossing.topZSubvoxels; - if(qzpassages.size() - &&qzpassages[crossing.passageIndex]; - const auto lower=std::find_if(ResolvedLayout->strates.begin(), - ResolvedLayout->strates.end(),[&](const auto& value) - {return value.strateIndex==passage.lowerStrateIndex;}); - if(lower!=ResolvedLayout->strates.end()) - { - const double capsuleRadius=0.37*qPerMetre; - const double capsuleHalfHeight=0.86*qPerMetre; - const double capsuleRadiusSquared=capsuleRadius*capsuleRadius; - const std::size_t lowerStratumIndex=static_cast( - lower-ResolvedLayout->strates.begin()); - const auto& routeSegments=PassageStratumCapsuleSegments[ - lowerStratumIndex]; - for(std::size_t segmentIndex=0;segmentIndexmatches(*this)) - l98TileQueries->recordPreparedSegmentUse( - FScopedPassageTileQueries::EPreparedSegmentUse::Capsule); - const double ax=segment.a[0],ay=segment.a[1]; - const double dx=segment.delta[0],dy=segment.delta[1]; - const double lengthSquared=segment.horizontalLengthSq; - const double t=lengthSquared>0.0?std::clamp( - PassageCapsuleRouteXYProjectionNumerator(lowerStratumIndex, - segmentIndex,qx,qy)/lengthSquared,0.0,1.0):0.0; - const double routeX=ax+t*dx,routeY=ay+t*dy; - const double routeZ=segment.a[2]+t*segment.delta[2]; - const double routeDx=qx-routeX,routeDy=qy-routeY; - if(routeDx*routeDx+routeDy*routeDy<=capsuleRadiusSquared - &&std::abs(qz-routeZ)<=capsuleHalfHeight) - return maximumRadius+qPerMetre; - } - } - } - - const double height=static_cast(crossing.topZSubvoxels - -crossing.bottomZSubvoxels); - const double t=std::clamp((crossing.topZSubvoxels-qz)/height,0.0,1.0); - const auto smoothStep=[](double value) - { - value=std::clamp(value,0.0,1.0); - return value*value*(3.0-2.0*value); - }; - const float z=static_cast(Z); - const float scaledZ=z*0.12f; - const float driftX=VF_FieldSurfaceRelief(0.0f,0.0f,scaledZ, - static_cast(Owner?Owner->Seed:0)^0x434f4c58u); - const float driftY=VF_FieldSurfaceRelief(0.0f,0.0f,scaledZ, - static_cast(Owner?Owner->Seed:0)^0x434f4c59u); - const double axisX=crossing.centerXSubvoxels - +std::clamp(static_cast(driftX),-1.0,1.0)*0.35*qPerMetre; - const double axisY=crossing.centerYSubvoxels - +std::clamp(static_cast(driftY),-1.0,1.0)*0.35*qPerMetre; - const double centerDx=qx-axisX,centerDy=qy-axisY; - const double radialDistance=DeterministicSqrt(centerDx*centerDx+centerDy*centerDy); - const float broadRelief=VF_FieldSurfaceRelief(X*0.12f,Y*0.12f,Z*0.12f, - static_cast(Owner?Owner->Seed:0)^0x434f4c52u); - const float surfaceRelief=VF_FieldSurfaceRelief(X,Y,Z, - static_cast(Owner?Owner->Seed:0)^0x434f4c53u); - const double baseFlare=6.0*qPerMetre*smoothStep((t-0.82)/0.18); - const double ceilingFlare=2.0*qPerMetre*(1.0-smoothStep(t/0.075)); - const double irregularity=1.25*qPerMetre - +std::clamp(static_cast(broadRelief),-1.0,1.0)*1.10*qPerMetre - +std::clamp(static_cast(surfaceRelief),-1.0,1.0)*0.35*qPerMetre; - // Add a subtle host-rock root only when the unmodified column lacks the - // vertical relief required for walkable passage support. - const double rootTaper=crossing.needsRootTaper - ?0.30*qPerMetre*smoothStep((t-0.35)/0.50):0.0; - const double radius=static_cast(crossing.minimumRadiusSubvoxels) - +std::max(0.15*qPerMetre,irregularity)+rootTaper+baseFlare+ceilingFlare; - const double radialDistanceField=radialDistance-radius; - const double topDistance=qz-crossing.topZSubvoxels; - const double bottomDistance=crossing.bottomZSubvoxels-qz; - const double verticalDistance=std::max(topDistance,bottomDistance); - const double outside=DeterministicSqrt( - std::max(radialDistanceField,0.0)*std::max(radialDistanceField,0.0) - +std::max(verticalDistance,0.0)*std::max(verticalDistance,0.0)); - const double inside=std::min(std::max(radialDistanceField,verticalDistance),0.0); - return outside+inside; - } - float NativePassageDensityAt(float X,float Y,float Z) const { float density=0.0f; @@ -7626,298 +4942,6 @@ private: return ApplyResolvedStrateBoundaryBand(density,X,Y,Z); } - double PassageColumnNaturalReliefMetres( - const FStandalonePassageVoidCrossing& crossing,double qPerMetre) const - { - constexpr double Q=static_cast(VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel); - constexpr std::array HeightFractions{{0.25,0.35,0.45,0.55,0.65,0.75}}; - constexpr std::size_t DirectionCount=16; - const auto smoothStep=[](double value) - { - value=std::clamp(value,0.0,1.0); - return value*value*(3.0-2.0*value); - }; - std::array meanRadii{}; - std::size_t heightCount=0; - const auto seed=static_cast(Owner?Owner->Seed:0); - const double height=static_cast(crossing.topZSubvoxels - -crossing.bottomZSubvoxels); - if(height<=0.0)return 0.0; - for(const double fraction:HeightFractions) - { - const double qz=crossing.topZSubvoxels-height*fraction; - const float z=static_cast(qz/Q); - const float scaledZ=z*0.12f; - const float driftX=VF_FieldSurfaceRelief(0.0f,0.0f,scaledZ,seed^0x434f4c58u); - const float driftY=VF_FieldSurfaceRelief(0.0f,0.0f,scaledZ,seed^0x434f4c59u); - const double axisX=crossing.centerXSubvoxels - +std::clamp(static_cast(driftX),-1.0,1.0)*0.35*qPerMetre; - const double axisY=crossing.centerYSubvoxels - +std::clamp(static_cast(driftY),-1.0,1.0)*0.35*qPerMetre; - const double t=(crossing.topZSubvoxels-qz)/height; - const double baseFlare=6.0*qPerMetre*smoothStep((t-0.82)/0.18); - const double ceilingFlare=2.0*qPerMetre*(1.0-smoothStep(t/0.075)); - double meanRadius=0.0; - for(std::size_t direction=0;direction((axisX+radius*std::cos(angle))/Q); - const float sampleY=static_cast((axisY+radius*std::sin(angle))/Q); - const float broadRelief=VF_FieldSurfaceRelief(sampleX*0.12f, - sampleY*0.12f,scaledZ,seed^0x434f4c52u); - const float surfaceRelief=VF_FieldSurfaceRelief(sampleX,sampleY,z, - seed^0x434f4c53u); - const double irregularity=1.25*qPerMetre - +std::clamp(static_cast(broadRelief),-1.0,1.0)*1.10*qPerMetre - +std::clamp(static_cast(surfaceRelief),-1.0,1.0)*0.35*qPerMetre; - radius=crossing.minimumRadiusSubvoxels - +std::max(0.15*qPerMetre,irregularity)+baseFlare+ceilingFlare; - } - meanRadius+=radius; - } - meanRadii[heightCount++]=meanRadius/DirectionCount/qPerMetre; - } - if(heightCount<2)return 0.0; - const auto begin=meanRadii.begin(); - const auto end=begin+static_cast(heightCount); - return *std::max_element(begin,end)-*std::min_element(begin,end); - } - - void BuildPassageVoidCrossingPlan() - { - BuildResolvedBoundaryZIntervals(); - PassageVoidCrossings.clear(); - if(!Owner||!ResolvedLayout||ResolvedLayout->passages.empty())return; - if(!Owner->PassageVoidCrossingCache) - {BuildPassageSpatialIndices();return;} - auto& cache=*Owner->PassageVoidCrossingCache; - std::lock_guard lock(cache.mutex); - const std::string cacheKey=ResolvedLayout->stableIdentity+"/passage-void-columns-v2-seed-" - +std::to_string(Owner->Seed); - const auto cached=cache.byLayout.find(cacheKey); - if(cached!=cache.byLayout.end()) - {PassageVoidCrossings=cached->second;BuildPassageSpatialIndices();return;} - - constexpr double Q=static_cast(VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel); - const double qPerMetre=Q*1000000.0/std::max(1, - ResolvedLayout->coreVoxelSizeMicrometres); - constexpr std::array,5> supportOffsets{{ - {{0.0,0.0}},{{0.45,0.0}},{{-0.45,0.0}},{{0.0,0.45}},{{0.0,-0.45}}}}; - constexpr std::array supportDepthsMetres{{0.125,0.25}}; - constexpr double shortSpanMaximumMetres=12.5; // 2.5 x the 5 m legacy support thickness. - struct FPathSample - { - std::size_t segment=0; - std::array point{}; - bool nativeSupported=false; - }; - const auto nativeSupportedAt=[&](const std::array& point) - { - const double floorQ=point[2]-point[3]+0.13*qPerMetre; - std::uint32_t supported=0; - for(const auto& offset:supportOffsets) - { - bool hasSolid=false; - for(const double depth:supportDepthsMetres) - { - const double sampleZ=floorQ-depth*qPerMetre; - const float density=NativePassageDensityAt( - static_cast((point[0]+offset[0]*qPerMetre)/Q), - static_cast((point[1]+offset[1]*qPerMetre)/Q), - static_cast(sampleZ/Q)); - if(density<0.0f){hasSolid=true;break;} - } - supported+=hasSolid; - } - return supported>=3; - }; - for(std::size_t passageIndex=0;passageIndexpassages.size(); - ++passageIndex) - { - const auto& passage=ResolvedLayout->passages[passageIndex]; - const auto upperStratum=std::find_if(ResolvedLayout->strates.begin(), - ResolvedLayout->strates.end(),[&passage](const auto& value) - {return value.strateIndex==passage.upperStrateIndex;}); - const bool surfaceWorldUpper=upperStratum!=ResolvedLayout->strates.end() - &&upperStratum->passageCapabilities.hasSurfaceLanding; - if(passage.controlPoints.size()<2)continue; - std::vector samples; - samples.reserve(passage.controlPoints.size()*2); - const auto pointAt=[&](std::size_t segment,double t) - { - const auto& a=passage.controlPoints[segment]; - const auto& b=passage.controlPoints[segment+1]; - FPathSample sample;sample.segment=segment; - for(std::size_t axis=0;axis<3;++axis) - sample.point[axis]=a.positionSubvoxels[axis]+t*( - static_cast(b.positionSubvoxels[axis]) - -a.positionSubvoxels[axis]); - sample.point[3]=a.radiusSubvoxels+t*( - static_cast(b.radiusSubvoxels)-a.radiusSubvoxels); - sample.nativeSupported=nativeSupportedAt(sample.point); - return sample; - }; - samples.push_back(pointAt(0,0.0)); - for(std::size_t segment=0;segment+1(b.positionSubvoxels[0])-a.positionSubvoxels[0]; - const double dy=static_cast(b.positionSubvoxels[1])-a.positionSubvoxels[1]; - const double dz=static_cast(b.positionSubvoxels[2])-a.positionSubvoxels[2]; - const double lengthMetres=DeterministicSqrt(dx*dx+dy*dy+dz*dz)/qPerMetre; - const std::size_t intervals=std::max(1, - static_cast(std::ceil(lengthMetres/0.5))); - for(std::size_t step=1;step<=intervals;++step) - samples.push_back(pointAt(segment,static_cast(step)/intervals)); - } - std::size_t cursor=0; - while(cursor0?gapBegin-1:gapBegin; - const std::size_t endSample=cursor0&&samples[startSample].nativeSupported; - crossing.connectedAtEnd=cursorshortSpanMaximumMetres; - if(crossing.needsColumn&&passage.controlPoints.size()>1) - crossing.lastSegment=std::min(crossing.lastSegment+1, - passage.controlPoints.size()-2); - if(crossing.needsColumn) - { - std::int64_t sumX=0,sumY=0; - std::uint64_t centerSamples=0; - for(std::size_t index=gapBegin;index<=gapEnd;++index) - { - sumX+=static_cast(std::llround(samples[index].point[0])); - sumY+=static_cast(std::llround(samples[index].point[1])); - ++centerSamples; - } - crossing.centerXSubvoxels=centerSamples>0 - ?static_cast(std::llround(static_cast(sumX)/centerSamples)):0; - crossing.centerYSubvoxels=centerSamples>0 - ?static_cast(std::llround(static_cast(sumY)/centerSamples)):0; - for(const auto& stratum:ResolvedLayout->strates) - if(stratum.strateIndex==passage.upperStrateIndex - &&stratum.passageCapabilities.usePassageAnchorForColumns) - for(const auto& anchor:stratum.anchors) - if(anchor.kind=="passage_anchor"&&anchor.values.size()>=2) - { - crossing.centerXSubvoxels=anchor.values[0]; - crossing.centerYSubvoxels=anchor.values[1]; - break; - } - double maximumOffsetSubvoxels=0.0; - double maximumBoreSubvoxels=0.0; - double minimumCrossingZ=std::min(crossing.startPoint[2],crossing.endPoint[2]); - double maximumCrossingZ=std::max(crossing.startPoint[2],crossing.endPoint[2]); - for(std::size_t sampleIndex=0;sampleIndexcrossing.lastSegment)continue; - } - else if(sampleIndexendSample)continue; - const auto& point=sample.point; - const double dx=point[0]-crossing.centerXSubvoxels; - const double dy=point[1]-crossing.centerYSubvoxels; - maximumOffsetSubvoxels=std::max(maximumOffsetSubvoxels, - DeterministicSqrt(dx*dx+dy*dy)); - maximumBoreSubvoxels=std::max(maximumBoreSubvoxels,point[3]); - if(surfaceWorldUpper) - { - minimumCrossingZ=std::min(minimumCrossingZ,point[2]); - maximumCrossingZ=std::max(maximumCrossingZ,point[2]); - } - } - const double maximumOffsetMetres=maximumOffsetSubvoxels/qPerMetre; - const double maximumBoreMetres=maximumBoreSubvoxels/qPerMetre; - const double minimumRadiusMetres=maximumOffsetMetres+maximumBoreMetres+2.0; - const double nominalRadiusMetres=minimumRadiusMetres+1.25; - crossing.maximumRouteOffsetMetres=maximumOffsetMetres; - crossing.maximumBoreRadiusMetres=maximumBoreMetres; - crossing.minimumRadiusSubvoxels=static_cast(std::ceil( - minimumRadiusMetres*qPerMetre)); - crossing.nominalRadiusSubvoxels=static_cast(std::llround( - nominalRadiusMetres*qPerMetre)); - crossing.maximumRadiusSubvoxels=crossing.minimumRadiusSubvoxels - +static_cast(std::ceil(11.25*qPerMetre)); - crossing.topZSubvoxels=static_cast(std::llround( - maximumCrossingZ+5.0*qPerMetre)); - crossing.bottomZSubvoxels=static_cast(std::llround( - minimumCrossingZ-6.0*qPerMetre)); - crossing.naturalSurfaceReliefMetres=PassageColumnNaturalReliefMetres( - crossing,qPerMetre); - // The support-column audit requires 20 cm of vertical relief. - // Add a shallow root flare only when the existing field profile - // falls short, so naturally varied legacy columns remain intact. - crossing.needsRootTaper=crossing.naturalSurfaceReliefMetres<0.20; - } - PassageVoidCrossings.push_back(crossing); - if(crossing.needsColumn) - { - const double coreRadius=crossing.nominalRadiusSubvoxels/qPerMetre; - const double minimumWall=coreRadius-crossing.maximumRouteOffsetMetres - -crossing.maximumBoreRadiusMetres; - std::printf("[PassageVoidColumnPlan] id=%s segments=%zu..%zu unsupported_samples=%llu span_m=%.3f threshold_m=%.3f connected=%d/%d axis_m=(%.3f,%.3f) z_m=%.3f..%.3f route_radius_m=%.3f bore_radius_m=%.3f min_radius_m=%.3f nominal_radius_m=%.3f max_radius_m=%.3f nominal_wall_m=%.3f natural_relief_m=%.3f root_taper=%d flare_m=6.000 status=%s\n", - passage.stableId.c_str(),crossing.firstSegment,crossing.lastSegment, - static_cast(crossing.unsupportedSamples),gapLength, - shortSpanMaximumMetres,static_cast(crossing.connectedAtStart), - static_cast(crossing.connectedAtEnd), - crossing.centerXSubvoxels/qPerMetre,crossing.centerYSubvoxels/qPerMetre, - crossing.topZSubvoxels/qPerMetre,crossing.bottomZSubvoxels/qPerMetre, - crossing.maximumRouteOffsetMetres,crossing.maximumBoreRadiusMetres, - crossing.minimumRadiusSubvoxels/qPerMetre,coreRadius, - crossing.maximumRadiusSubvoxels/qPerMetre,minimumWall, - crossing.naturalSurfaceReliefMetres,static_cast(crossing.needsRootTaper), - crossing.connectedAtStart&&crossing.connectedAtEnd?"PLANNED":"UNATTACHED"); - } - else - std::printf("[PassageShortGroundedSpanPlan] id=%s segments=%zu..%zu span_m=%.3f threshold_m=%.3f connected=%d/%d width_m=7.300 thickness_m=3.000..5.000 status=%s\n", - passage.stableId.c_str(),crossing.firstSegment,crossing.lastSegment, - gapLength,shortSpanMaximumMetres,static_cast(crossing.connectedAtStart), - static_cast(crossing.connectedAtEnd), - crossing.connectedAtStart&&crossing.connectedAtEnd?"PLANNED":"UNATTACHED"); - } - if(std::none_of(PassageVoidCrossings.begin(),PassageVoidCrossings.end(), - [passageIndex](const auto& range){return range.passageIndex==passageIndex;})) - std::printf("[PassageVoidColumnPlan] id=%s crossings=0 status=NOT_REQUIRED\n", - passage.stableId.c_str()); - } - cache.byLayout.emplace(cacheKey,PassageVoidCrossings); - BuildPassageSpatialIndices(); - } - static uint64 PackLatticeKey(int32 X,int32 Y,int32 Z) { constexpr uint64 Mask=0x1FFFFFull; @@ -10181,8 +7205,11 @@ private: apply(static_cast(index)); return composed; } - float ApplyResolvedCavernGraph(float density,float X,float Y,float Z) const + float ApplyResolvedCavernGraph(float density,float X,float Y,float Z, + float* nativeFloorSupport=nullptr) const { + if(nativeFloorSupport) + *nativeFloorSupport=std::numeric_limits::lowest(); if(CavernRuntime.empty()||!Owner||Owner->CoreVoxelSizeMicrons==0)return density; const auto* tileQueries=ActivePassageTileQueries; const bool scoped=tileQueries&&tileQueries->matches(*this); @@ -10194,7 +7221,8 @@ private: &&(VoxelForgeCore::IsNativeCaveFieldStratum(*bound->Resolved) ?bound->Resolved->passageCapabilities.hasNativeCaveField :bound->Resolved->passageCapabilities.hasNativeLatticeField)) - return ApplyResolvedNativeCavesField(density,X,Y,Z,*bound,tileQueries,scoped); + return ApplyResolvedNativeCavesField(density,X,Y,Z,*bound,tileQueries,scoped, + nativeFloorSupport); const double micronsPerVoxel=Owner->CoreVoxelSizeMicrons; const std::array worldMicrometres={X*micronsPerVoxel, Y*micronsPerVoxel,Z*micronsPerVoxel}; @@ -10340,8 +7368,10 @@ private: float ApplyResolvedNativeCavesField(float density,float X,float Y,float Z, const FBoundStratumField& bound,const FScopedPassageTileQueries* tileQueries, - bool scoped) const + bool scoped,float* nativeFloorSupport=nullptr) const { + if(nativeFloorSupport) + *nativeFloorSupport=std::numeric_limits::lowest(); (void)density; const double metresPerVoxel=Owner->CoreVoxelSizeMicrons/1000000.0; const std::array point={X*metresPerVoxel,Y*metresPerVoxel, @@ -10508,6 +7538,8 @@ private: // explicit support depth so separated helix turns remain independent. if(std::isfinite(latticeFloorSupportMinimum)) composed=std::min(composed,latticeFloorSupportMinimum); + if(nativeFloorSupport&&std::isfinite(latticeFloorSupportMinimum)) + *nativeFloorSupport=static_cast(latticeFloorSupportMinimum/metresPerVoxel); return static_cast(composed/metresPerVoxel); } @@ -13636,7 +10668,6 @@ public: return; } if(Count<=0||OutDensity==nullptr)return; - FScopedPassageColumnXYReuse passageColumnXYReuse(*this); FScopedRoute l77DispatchRoute(ERoute::Dispatch); FScopedPhase l77DispatchPhase(EPhase::Dispatch); FScopedDensityQueryProfile queryProfile(EDensityQueryKind::Lattice, @@ -14366,7 +11397,6 @@ private: std::vector FarConnectorSegments; std::unordered_map,FBinHash> FarConnectorSpatialBins; std::vector EditBrushes; - std::vector PassageVoidCrossings; std::array AxisBins; std::unordered_map SpatialBins; std::vector UnbinnedSpatialPrimitiveIds; @@ -14401,27 +11431,11 @@ private: std::vector PassageFeatureNodes; bool PassageFeatureBoundsFailOpen=false; std::vector> PassageNearestNodes; - std::vector> PassageMouthSupportRoutes; - std::vector PassageMouthSupportSegmentOffsets; std::vector PassageComposerConstants; std::vector> PassageSegmentData; std::vector PassageSegmentOffsets; - std::vector> - PassageStratumCapsuleSegments; - std::vector PassageStratumCapsuleSegmentOffsets; - std::vector> PassageLaterBoreSources; std::vector PassageProofBounds; std::vector PassageProofNodes; - std::vector> PassageColumnSegmentFlags,PassageShortSpanSegmentFlags; - std::vector PassageHasShortSpanFlags; - bool L90PassageCandidateProgramEnabled=false; - bool L90PassageCandidateProgramValid=false; - double L90PassageCandidateBrickEdgeSubvoxels=0.0; - double L90PassageCandidateReachMetres=0.0; - std::uint64_t L90PassageCandidateBuildFailures=0; - std::unordered_map L90PassageCandidateBricks; - inline static thread_local const FPassageCandidateBrick* ActivePassageCandidateBrick=nullptr; }; inline void FStandaloneShapeWorld::FScopedPassageTileQueries::prepareSweptTubeBase( @@ -14429,8 +11443,12 @@ inline void FStandaloneShapeWorld::FScopedPassageTileQueries::prepareSweptTubeBa { constexpr std::int64_t Q=VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel; constexpr double InfluenceMetres=4.0; + constexpr double OpenAirSideWallHeightMetres=1.0; if(!shape_||step<=0||cells<=0||!std::isfinite(passageCarveReachMetres_) ||std::abs(passageCarveReachMetres_-InfluenceMetres)>1.0e-9)return; + const bool profile=profileStats_!=nullptr; + const auto prepareStart=profile?std::chrono::steady_clock::now() + :std::chrono::steady_clock::time_point{}; auto sweep=std::make_shared(); sweep->gridMinimumSubvoxels={ @@ -14446,12 +11464,20 @@ inline void FStandaloneShapeWorld::FScopedPassageTileQueries::prepareSweptTubeBa ?shape_->ResolvedLayout->coreVoxelSizeMicrometres:250000); sweep->passageToSweep.assign(passageRouteSegments_.size(),-1); std::vector anyPassageInfluence(gridSampleCount,0); + std::vector anyPreparedSample(profile?gridSampleCount:0,0); + std::vector anyCacheValidSample(profile?gridSampleCount:0,0); + std::vector anyExactBandSample(profile?gridSampleCount:0,0); + std::uint64_t preparedSampleCount=0,stampedOutsideSampleCount=0, + cacheValidSampleCount=0,contributingPairCount=0, + bodyBandSampleCount=0,shellBandSampleCount=0; const double qPerMetre=static_cast(Q)*1000000.0/ std::max(1,shape_->ResolvedLayout ?shape_->ResolvedLayout->coreVoxelSizeMicrometres:250000); + const double shellThickness=0.75*qPerMetre; + const double stampedOutsideDistance=sweep->influenceSubvoxels+1.0; + constexpr double MouthShellBlendMetres=5.0; const double wallReliefShell=0.41*qPerMetre; const double floorDetailShell=1.0*qPerMetre; - const bool profile=profileStats_!=nullptr; if(profile) { profileStats_->passageSweepRouteSegmentCandidates=routeSegmentCandidateCount_; @@ -14480,77 +11506,86 @@ inline void FStandaloneShapeWorld::FScopedPassageTileQueries::prepareSweptTubeBa passageSamples.passageIndex=passageIndex; passageSamples.samples.resize(gridSampleCount); const auto& constants=shape_->PassageComposerConstants[passageIndex]; - struct FCarveWindow - { - std::ptrdiff_t begin=1,end=0; - }; - std::vector carveWindows(static_cast(sweep->dimension)); - const auto& floorProfileQ=constants.controlFloorProfileQ; - const std::ptrdiff_t lowerMouthIndex=constants.lowerMouthIndex; - if(lowerMouthIndex>=0 - &&static_cast(lowerMouthIndex)value;}; - const auto profileBegin=floorProfileQ.begin(); - const auto profileEnd=profileBegin+lowerMouthIndex+1; - for(std::int32_t gz=0;gzdimension;++gz) - { - const double qz=static_cast(sweep->gridMinimumSubvoxels[2] - +static_cast(gz)*sweep->stepSubvoxels); - const auto carveHigh=std::lower_bound(profileBegin,profileEnd, - qz+constants.carveSearchMargin,compareFloorProfile); - const auto carveLow=std::lower_bound(profileBegin,profileEnd, - qz-constants.carveSearchMargin,compareFloorProfile); - auto& window=carveWindows[static_cast(gz)]; - window.begin=std::max(0, - (carveHigh-profileBegin)-1); - window.end=std::min(lowerMouthIndex-1, - (carveLow-profileBegin)+1); - } - } - const auto scanPhaseForSegment=[&](std::ptrdiff_t segmentIndex, - const FCarveWindow& window) - { - if(segmentIndex>=window.begin&&segmentIndex<=window.end)return 0; - if(segmentIndex(8,lowerMouthIndex))return 1; - if(segmentIndex>=constants.mouthSearchBegin - &&segmentIndex=lowerMouthIndex&&segmentIndexPassageSegmentData[passageIndex]; for(const auto& candidate:candidates) { - if(candidate.segmentIndex>=shape_->PassageSegmentData[passageIndex].size())continue; + if(candidate.segmentIndex>=segments.size())continue; + const std::size_t segmentEndIndex=std::min(candidate.segmentEndIndex, + segments.size()); + if(candidate.segmentIndex>=segmentEndIndex)continue; std::array first{},last{}; for(std::size_t axis=0;axis<3;++axis) gridRange(axis,candidate.sweepMinimumSubvoxels[axis], candidate.sweepMaximumSubvoxels[axis],first[axis],last[axis]); if(first[0]>last[0]||first[1]>last[1]||first[2]>last[2])continue; - const auto& segment=shape_->PassageSegmentData[passageIndex][candidate.segmentIndex]; - if(segment.lengthSq<=0.0)continue; - const std::ptrdiff_t segmentIndex=static_cast(candidate.segmentIndex); - const bool smoothCarveJoin=segmentIndex>2 - &&segmentIndex+(constants.internalChainPassage?2:12)IsPassageShortSpanSegment(passageIndex,candidate.segmentIndex-1) - &&!shape_->IsPassageShortSpanSegment(passageIndex,candidate.segmentIndex) - &&!shape_->IsPassageShortSpanSegment(passageIndex,candidate.segmentIndex+1); + // Stamp the conservative route feature slab once. Segment geometry below + // visits its own tight expanded bounds, avoiding the old feature-box x + // segment-count scan. for(std::int32_t gz=first[2];gz<=last[2];++gz) { - const int scanPhase=scanPhaseForSegment(segmentIndex, - carveWindows[static_cast(gz)]); - if(scanPhase<0)continue; for(std::int32_t gy=first[1];gy<=last[1];++gy) for(std::int32_t gx=first[0];gx<=last[0];++gx) { + const double qz=static_cast(sweep->gridMinimumSubvoxels[2] + +static_cast(gz)*sweep->stepSubvoxels); + const std::size_t sampleIndex=(static_cast(gz) + *static_cast(sweep->dimension)+static_cast(gy)) + *static_cast(sweep->dimension)+static_cast(gx); + auto& sample=passageSamples.samples[sampleIndex]; + // Every grid sample inside a conservative feature slab has a known + // outside value unless a segment contributes within the prepared + // influence. This makes slab gaps cheap rock instead of cache misses. + if(!sample.valid) + { + sample.signedDistance=stampedOutsideDistance; + sample.shellSignedDistance=stampedOutsideDistance; + sample.roundSignedDistance=stampedOutsideDistance; + sample.centerZSubvoxels=qz; + sample.floorCenterZSubvoxels=qz; + sample.radiusSubvoxels=0.0; + sample.floorDepthSubvoxels=0.0; + sample.floorCenterDistanceSq=std::numeric_limits::infinity(); + sample.t=0.0; + sample.floorT=0.0; + sample.segmentIndex=static_cast(candidate.segmentIndex); + sample.floorSegmentIndex=static_cast(candidate.segmentIndex); + sample.wallRelief=0.0f; + sample.valid=true; + sample.hasWallRelief=false; + sample.hasExactContribution=false; + } + } + } + + for(std::size_t segmentIndex=candidate.segmentIndex; + segmentIndex segmentFirst{},segmentLast{}; + for(std::size_t axis=0;axis<3;++axis) + gridRange(axis,segment.sweepMinimumSubvoxels[axis], + segment.sweepMaximumSubvoxels[axis], + segmentFirst[axis],segmentLast[axis]); + if(segmentFirst[0]>segmentLast[0] + ||segmentFirst[1]>segmentLast[1] + ||segmentFirst[2]>segmentLast[2])continue; + for(std::int32_t gz=segmentFirst[2];gz<=segmentLast[2];++gz) + { + for(std::int32_t gy=segmentFirst[1];gy<=segmentLast[1];++gy) + for(std::int32_t gx=segmentFirst[0];gx<=segmentLast[0];++gx) + { const double qx=static_cast(sweep->gridMinimumSubvoxels[0] +static_cast(gx)*sweep->stepSubvoxels); const double qy=static_cast(sweep->gridMinimumSubvoxels[1] +static_cast(gy)*sweep->stepSubvoxels); const double qz=static_cast(sweep->gridMinimumSubvoxels[2] +static_cast(gz)*sweep->stepSubvoxels); + const std::size_t sampleIndex=(static_cast(gz) + *static_cast(sweep->dimension)+static_cast(gy)) + *static_cast(sweep->dimension)+static_cast(gx); + auto& sample=passageSamples.samples[sampleIndex]; const double projectionXY=(qx-segment.a[0])*segment.delta[0] +(qy-segment.a[1])*segment.delta[1]; const double t=std::clamp((projectionXY @@ -14558,54 +11593,122 @@ inline void FStandaloneShapeWorld::FScopedPassageTileQueries::prepareSweptTubeBa double cx=segment.a[0]+t*segment.delta[0]; double cy=segment.a[1]+t*segment.delta[1]; double cz=segment.a[2]+t*segment.delta[2]; - if(smoothCarveJoin) - { - const double t2=t*t,t3=t2*t; - for(std::size_t axis=0;axis<3;++axis) - { - const double v0=segment.catmullBefore[axis]; - const double v1=segment.a[axis]; - const double v2=segment.b[axis]; - const double v3=segment.catmullAfter[axis]; - const double curve=0.5*((2.0*v1)+(-v0+v2)*t - +(2.0*v0-5.0*v1+4.0*v2-v3)*t2 - +(-v0+3.0*v1-3.0*v2+v3)*t3); - const double line=axis==0?cx:axis==1?cy:cz; - const double value=line+(curve-line); - if(axis==0)cx=value; - else if(axis==1)cy=value; - else cz=value; - } - } const double radius=segment.radiusA+t*segment.radiusDelta; const double ex=qx-cx,ey=qy-cy,ez=qz-cz; const double signedDistance=FStandaloneShapeWorld::DeterministicSqrt( ex*ex+ey*ey+ez*ez)-radius; + if(profile&&signedDistanceinfluenceSubvoxels+1.0) + ++contributingPairCount; + const double floorT=segment.horizontalLengthSq>1.0e-12 + ?projectionXY/segment.horizontalLengthSq:t; + const double floorTClamped=std::clamp(floorT,0.0,1.0); + const double floorCenterDistanceSq=ex*ex+ey*ey+ez*ez; + const double floorRadius=segment.radiusA + +floorTClamped*segment.radiusDelta; + const double floorDepth=FStandaloneShapeWorld::PassageFlatFloorDepthSubvoxels( + constants,segmentIndex,floorTClamped,floorRadius,qPerMetre); + const double floorCenterZ= + FStandaloneShapeWorld::PassageFlatFloorCenterZSubvoxels( + constants,segments,segmentIndex,floorT,segment, + qx,qy,floorDepth,qPerMetre); if(profile)++profileStats_->passageSweepSegmentSamplePairs; if(signedDistance>sweep->influenceSubvoxels) { if(profile)++profileStats_->passageSweepOutsideInfluencePairs; } - const std::size_t sampleIndex=(static_cast(gz) - *static_cast(sweep->dimension)+static_cast(gy)) - *static_cast(sweep->dimension)+static_cast(gx); - auto& sample=passageSamples.samples[sampleIndex]; - if(!sample.valid||signedDistance( + segmentIndex); + } + // A negative shell distance is possible only when the flattened tube + // distance lies in [0, shellThickness]. SmoothMaxDistance is at least + // max(roundDistance, floorDistance) and can raise that maximum by no + // more than cornerWidth/6. Skip its work for pairs outside this exact + // support, with a small subvoxel guard for float rounding. The final + // shell union only consumes negative distances. + constexpr double CornerBlendMetres=0.50; + const float roundDistanceFloat=static_cast(signedDistance); + const float floorDistanceFloat=static_cast(floorCenterZ-floorDepth-qz); + const double flatDistanceLowerBound=std::max( + static_cast(roundDistanceFloat), + static_cast(floorDistanceFloat)); + const double cornerWidth=static_cast(static_cast( + CornerBlendMetres*qPerMetre)); + const bool shellSupportPossible=flatDistanceLowerBound + >=-cornerWidth/6.0-1.0 + &&flatDistanceLowerBound<=shellThickness+1.0; + if(shellSupportPossible) + { + const double flatDistance=FStandaloneShapeWorld::PassageFlatBottomDistance( + roundDistanceFloat,floorCenterZ,qz,floorDepth,qPerMetre); + const double alongMetres=segment.authoredAlongMetres + +t*segment.authoredLengthMetres; + const double mouthDistanceMetres=std::max(0.0,std::min(alongMetres, + constants.totalPathLengthMetres-alongMetres)); + const double shellFade=std::clamp(mouthDistanceMetres/ + MouthShellBlendMetres,0.0,1.0); + const double smoothShellFade=shellFade*shellFade + *(3.0-2.0*shellFade); + const double floorDistanceMetres=(floorCenterZ-floorDepth-qz)/qPerMetre; + const double floorBlend=std::clamp(floorDistanceMetres/0.25,0.0,1.0); + const double smoothFloorBlend=floorBlend*floorBlend + *(3.0-2.0*floorBlend); + const double wallElevationMetres=(qz-(floorCenterZ-floorDepth)) + /qPerMetre; + const double mouthWallThickness=segment.routeSegment + ?smoothShellFade*shellThickness:0.0; + double floorExtensionFade=1.0; + if(!segment.routeSegment) + { + const double pastMouthMetres=std::max(0.0,alongMetres + -constants.totalPathLengthMetres); + const double extensionFade=std::clamp(1.0 + -pastMouthMetres/MouthShellBlendMetres,0.0,1.0); + floorExtensionFade=extensionFade*extensionFade + *(3.0-2.0*extensionFade); + } + const double floorShellThickness=smoothFloorBlend*shellThickness + *floorExtensionFade*smoothShellFade; + const double wallShellDistance= + FStandaloneShapeWorld::PassageRoundedWallShellDistance( + flatDistance,wallElevationMetres*qPerMetre, + OpenAirSideWallHeightMetres*qPerMetre,mouthWallThickness); + const double floorShellDistance=std::max( + -static_cast(flatDistance), + static_cast(flatDistance)-floorShellThickness); + const double localShellDistance=std::min(wallShellDistance, + floorShellDistance); + sample.shellSignedDistance=std::min(sample.shellSignedDistance, + localShellDistance); + } + else if(profile) + ++profileStats_->passageSweepShellSupportSkips; + // Rank the tube body by round SDF. Its floor plane is selected + // independently above from the nearest centerline position. + if(signedDistance(candidate.segmentIndex); - sample.scanPhase=static_cast(scanPhase); + sample.segmentIndex=static_cast(segmentIndex); sample.valid=true; sample.hasWallRelief=false; - sample.hasMouthSurfaceRelief=false; - sample.hasMouthTreadFieldRelief=false; + sample.hasExactContribution=true; if(profile)++profileStats_->passageSweepMinimumUpdates; } + } } } } @@ -14620,6 +11723,23 @@ inline void FStandaloneShapeWorld::FScopedPassageTileQueries::prepareSweptTubeBa { auto& sample=passageSamples.samples[sampleIndex]; if(!sample.valid)continue; + if(profile) + { + ++cacheValidSampleCount; + anyCacheValidSample[sampleIndex]=1; + } + if(!sample.hasExactContribution) + { + if(profile)++stampedOutsideSampleCount; + sample.signedDistance=stampedOutsideDistance; + sample.shellSignedDistance=stampedOutsideDistance; + continue; + } + if(profile) + { + ++preparedSampleCount; + anyPreparedSample[sampleIndex]=1; + } const std::int32_t gx=static_cast(sampleIndex %static_cast(sweep->dimension)); const std::int32_t gy=static_cast((sampleIndex @@ -14634,15 +11754,28 @@ inline void FStandaloneShapeWorld::FScopedPassageTileQueries::prepareSweptTubeBa +static_cast(gy)*sweep->stepSubvoxels); const double qz=static_cast(sweep->gridMinimumSubvoxels[2] +static_cast(gz)*sweep->stepSubvoxels); - const auto& segment=segments[sample.segmentIndex]; - const double radius=segment.radiusA+sample.t*segment.radiusDelta; - const double centerZ=segment.a[2]+sample.t*segment.delta[2]; + sample.signedDistance=FStandaloneShapeWorld::PassageFlatBottomDistance( + static_cast(sample.roundSignedDistance), + sample.floorCenterZSubvoxels,qz,sample.floorDepthSubvoxels,qPerMetre); + if(profile&&std::abs(sample.signedDistance)<=sweep->stepSubvoxels) + { + ++bodyBandSampleCount; + anyExactBandSample[sampleIndex]=1; + } + if(profile&&std::isfinite(sample.shellSignedDistance) + &&std::abs(sample.shellSignedDistance)<=sweep->stepSubvoxels) + { + ++shellBandSampleCount; + anyExactBandSample[sampleIndex]=1; + } + const double radius=sample.radiusSubvoxels; + const double centerZ=sample.centerZSubvoxels; if(sample.signedDistance<=sweep->influenceSubvoxels) { anyPassageInfluence[sampleIndex]=1; if(profile)++profileStats_->passageSweepBaseInfluenceSamples; } - if(std::abs(sample.signedDistance)<=wallReliefShell) + if(std::abs(sample.roundSignedDistance)<=wallReliefShell) { const float x=static_cast(qx/Q); const float y=static_cast(qy/Q); @@ -14655,36 +11788,6 @@ inline void FStandaloneShapeWorld::FScopedPassageTileQueries::prepareSweptTubeBa ++profileStats_->passageReliefFieldCalls; } } - const std::size_t segmentIndex=sample.segmentIndex; - const double floorDistance=std::abs(qz-(centerZ-radius)); - const double dx=qx-(segment.a[0]+sample.t*segment.delta[0]); - const double dy=qy-(segment.a[1]+sample.t*segment.delta[1]); - const double horizontalDistance=FStandaloneShapeWorld::DeterministicSqrt( - dx*dx+dy*dy); - const bool upperMouthSegment=segmentIndex<=2; - const auto lowerMouth=static_cast( - std::max(0,constants.lowerMouthIndex)); - const bool lowerMouthSegment=segmentIndex+2>=lowerMouth - &&segmentIndex<=lowerMouth+2; - const float x=static_cast(qx/Q); - const float y=static_cast(qy/Q); - const float z=static_cast(qz/Q); - if(upperMouthSegment&&floorDistance<=4.0*qPerMetre - &&horizontalDistance<=3.0*qPerMetre) - { - sample.mouthSurfaceRelief=VF_FieldSurfaceRelief(x*1.5f,y*1.5f,z*1.5f, - seed^0x4D4F5554u); - sample.hasMouthSurfaceRelief=true; - if(profile)++profileStats_->passageReliefFieldCalls; - } - if((upperMouthSegment||lowerMouthSegment) - &&floorDistance<=floorDetailShell&&horizontalDistance<=2.5*qPerMetre) - { - sample.mouthTreadFieldRelief=VF_FieldSurfaceRelief(x*0.75f,y*0.75f, - z*0.75f,seed^0x54485244u); - sample.hasMouthTreadFieldRelief=true; - if(profile)++profileStats_->passageReliefFieldCalls; - } } } @@ -14693,6 +11796,41 @@ inline void FStandaloneShapeWorld::FScopedPassageTileQueries::prepareSweptTubeBa profileStats_->passageSweepNoInfluenceGridSamples= static_cast(std::count(anyPassageInfluence.begin(), anyPassageInfluence.end(),static_cast(0))); + profileStats_->passageSweepTouchedSamples=preparedSampleCount; + profileStats_->passageSweepStampedOutsideSamples=stampedOutsideSampleCount; + profileStats_->passageSweepCacheValidSamples=cacheValidSampleCount; + profileStats_->passageSweepCacheValidUniqueSamples= + static_cast(std::count(anyCacheValidSample.begin(), + anyCacheValidSample.end(),static_cast(1))); + profileStats_->passageSweepUniqueTouchedSamples= + static_cast(std::count(anyPreparedSample.begin(), + anyPreparedSample.end(),static_cast(1))); + profileStats_->passageSweepBodyBandSamples=bodyBandSampleCount; + profileStats_->passageSweepShellBandSamples=shellBandSampleCount; + profileStats_->passageSweepUniqueBandSamples= + static_cast(std::count(anyExactBandSample.begin(), + anyExactBandSample.end(),static_cast(1))); + profileStats_->passageSweepContributingPairs=contributingPairCount; + profileStats_->passageSweepOverlapPairs=contributingPairCount + >=preparedSampleCount + ?contributingPairCount-preparedSampleCount:0; + profileStats_->passageSweepCrossPassageOverlaps=preparedSampleCount + >=profileStats_->passageSweepUniqueTouchedSamples + ?preparedSampleCount-profileStats_->passageSweepUniqueTouchedSamples:0; + profileStats_->passageSweepFloorProfileCalls= + profileStats_->passageSweepSegmentSamplePairs; + std::uint64_t allocatedBytes=sizeof(*sweep) + +sweep->passageToSweep.capacity()*sizeof(std::int32_t) + +sweep->passages.capacity()*sizeof(FPassageTileSweepData::FPassageSamples); + for(const auto& passageSamples:sweep->passages) + allocatedBytes+=passageSamples.samples.capacity() + *sizeof(FPassageSweepSample); + profileStats_->passageSweepAllocatedBytes=allocatedBytes; + profileStats_->passageSweepPrepareScratchBytes=gridSampleCount + *(sizeof(std::uint8_t)*4); + profileStats_->passageSweepPrepareNanoseconds+=static_cast( + std::max(0,std::chrono::duration_cast( + std::chrono::steady_clock::now()-prepareStart).count())); } passageSweepData_=std::move(sweep); } @@ -14715,12 +11853,14 @@ FStandaloneShapeWorld::FScopedPassageTileQueries::sweptSample( }; if(passageIndex>=sweep->passageToSweep.size()) { + sweep->unpreparedMisses.fetch_add(1,std::memory_order_relaxed); recordMissing(); return nullptr; } const std::int32_t passageSweepIndex=sweep->passageToSweep[passageIndex]; if(passageSweepIndex<0||static_cast(passageSweepIndex)>=sweep->passages.size()) { + sweep->unpreparedMisses.fetch_add(1,std::memory_order_relaxed); recordMissing(); return nullptr; } @@ -14734,6 +11874,7 @@ FStandaloneShapeWorld::FScopedPassageTileQueries::sweptSample( if(rounded<0||rounded>=sweep->dimension ||std::abs(coordinate-static_cast(rounded))>1.0e-5) { + sweep->offGridMisses.fetch_add(1,std::memory_order_relaxed); recordMissing(); return nullptr; } @@ -14745,6 +11886,7 @@ FStandaloneShapeWorld::FScopedPassageTileQueries::sweptSample( const auto& samples=sweep->passages[static_cast(passageSweepIndex)].samples; if(index>=samples.size()||!samples[index].valid) { + sweep->unpreparedMisses.fetch_add(1,std::memory_order_relaxed); recordMissing(); return nullptr; } diff --git a/Standalone/Core/src/VoxelForgeCore.cpp b/Standalone/Core/src/VoxelForgeCore.cpp index 0a5d451..b139ec4 100644 --- a/Standalone/Core/src/VoxelForgeCore.cpp +++ b/Standalone/Core/src/VoxelForgeCore.cpp @@ -1284,103 +1284,104 @@ namespace VoxelForgeCore constexpr double Q=static_cast(WorldAssemblySubvoxelsPerVoxel); const double voxelsPerMetre=coreVoxelSizeMicrons>0 ?1000000.0/coreVoxelSizeMicrons:4.0; - const double bridgeHalfWidthVoxels=3.5*voxelsPerMetre; - const double bridgeFootDepthVoxels=(5.0-0.13)*voxelsPerMetre; + constexpr double WallReliefMetres=0.21; + constexpr double ShellThicknessMetres=0.75; + const double tubeExtentMetres=(WallReliefMetres+ShellThicknessMetres) + *voxelsPerMetre; + const double qPerMetre=Q*voxelsPerMetre; const double tileMinimum[3]={static_cast(minimum.X), static_cast(minimum.Y),static_cast(minimum.Z)}; const double tileMaximum[3]={static_cast(maximum.X), static_cast(maximum.Y),static_cast(maximum.Z)}; for(const auto& passage:layout.passages) { + if(passage.controlPoints.size()<2)continue; + const std::size_t routeEnd=std::clamp( + passage.lowerMouthControlIndex,1,passage.controlPoints.size()-1); + std::vector routeDistanceMetres(routeEnd+1,0.0); + for(std::size_t pointIndex=1;pointIndex<=routeEnd;++pointIndex) + { + const auto& a=passage.controlPoints[pointIndex-1].positionSubvoxels; + const auto& b=passage.controlPoints[pointIndex].positionSubvoxels; + const double dx=static_cast(b[0]-a[0])/qPerMetre; + const double dy=static_cast(b[1]-a[1])/qPerMetre; + const double dz=static_cast(b[2]-a[2])/qPerMetre; + routeDistanceMetres[pointIndex]=routeDistanceMetres[pointIndex-1] + +std::sqrt(dx*dx+dy*dy+dz*dz); + } + const double totalRouteMetres=routeDistanceMetres[routeEnd]; + double minimumRadiusMetres=std::numeric_limits::infinity(); + double minimumBodyRadiusMetres=minimumRadiusMetres; + for(std::size_t pointIndex=0;pointIndex<=routeEnd;++pointIndex) + { + const double radius=static_cast( + passage.controlPoints[pointIndex].radiusSubvoxels)/qPerMetre; + minimumRadiusMetres=std::min(minimumRadiusMetres,radius); + if(routeDistanceMetres[pointIndex]>=10.0 + &&totalRouteMetres-routeDistanceMetres[pointIndex]>=10.0) + minimumBodyRadiusMetres=std::min(minimumBodyRadiusMetres,radius); + } + if(!std::isfinite(minimumBodyRadiusMetres)) + minimumBodyRadiusMetres=minimumRadiusMetres; + const double bodyFloorDepthMetres=std::max(0.5, + minimumBodyRadiusMetres-0.23); + const double upperMouthDepthMetres=std::max(0.0, + static_cast(passage.controlPoints.front().positionSubvoxels[2] + -passage.upperMouthSubvoxels[2])/qPerMetre+0.90); + const double lowerMouthDepthMetres=std::max(0.0, + static_cast(passage.controlPoints[routeEnd].positionSubvoxels[2] + -passage.lowerMouthSubvoxels[2])/qPerMetre+0.90); + const auto routeFloorDepth=[&](double alongMetres,double radiusMetres) + { + const double localRadiusDepth=std::max(0.0,radiusMetres-0.23); + const double mouthDistance=std::max(0.0,std::min(alongMetres, + totalRouteMetres-alongMetres)); + const double linear=std::clamp(mouthDistance/5.0,0.0,1.0); + const double ramp=linear*linear*(3.0-2.0*linear); + const double target=alongMetres<=totalRouteMetres*0.5 + ?upperMouthDepthMetres:lowerMouthDepthMetres; + return std::lerp(std::clamp(target,0.0,localRadiusDepth), + localRadiusDepth,ramp); + }; + std::vector effectiveCenterZVoxels( + passage.controlPoints.size(),0.0); + for(std::size_t pointIndex=0;pointIndex( + passage.controlPoints[radiusIndex].radiusSubvoxels)/qPerMetre; + const double localTubeDepth=std::min(bodyFloorDepthMetres, + std::max(0.0,radius-0.23)); + const double routeDepth=pointIndex<=routeEnd + ?routeFloorDepth(routeDistanceMetres[pointIndex],radius) + :std::max(0.0,radius-0.23); + effectiveCenterZVoxels[pointIndex]= + static_cast(passage.controlPoints[pointIndex] + .positionSubvoxels[2])/Q + +(-routeDepth+localTubeDepth)*voxelsPerMetre; + } for(std::size_t segment=1;segment(std::max( - a.radiusSubvoxels,b.radiusSubvoxels))/Q; - const double horizontalExtent=std::max(radius,bridgeHalfWidthVoxels); - const double low[3]={ - std::min(a.positionSubvoxels[0],b.positionSubvoxels[0])/Q-horizontalExtent, - std::min(a.positionSubvoxels[1],b.positionSubvoxels[1])/Q-horizontalExtent, - std::min(a.positionSubvoxels[2],b.positionSubvoxels[2])/Q-radius - -bridgeFootDepthVoxels}; - const double high[3]={ - std::max(a.positionSubvoxels[0],b.positionSubvoxels[0])/Q+horizontalExtent, - std::max(a.positionSubvoxels[1],b.positionSubvoxels[1])/Q+horizontalExtent, - std::max(a.positionSubvoxels[2],b.positionSubvoxels[2])/Q+radius}; + const double extent=std::max(static_cast(a.radiusSubvoxels), + static_cast(b.radiusSubvoxels))/Q+tubeExtentMetres; + double low[3]{},high[3]{}; + for(int axis=0;axis<3;++axis) + { + const double aPosition=axis==2?effectiveCenterZVoxels[segment-1] + :static_cast(a.positionSubvoxels[axis])/Q; + const double bPosition=axis==2?effectiveCenterZVoxels[segment] + :static_cast(b.positionSubvoxels[axis])/Q; + low[axis]=std::min(aPosition,bPosition)-extent; + high[axis]=std::max(aPosition,bPosition)+extent; + } bool overlap=true; for(int axis=0;axis<3;++axis) overlap&=high[axis]>=tileMinimum[axis]&&low[axis]<=tileMaximum[axis]; if(overlap)return true; } - - // L27 can add a long support column around an unsupported passage span. Its - // radius can exceed the route and bridge bounds above by the column wall and - // flare allowance. The precompile shape-free proof runs before that crossing - // plan exists, so conservatively bound every possible column from the resolved - // route itself. The center is either the passage anchor or an average of route - // samples; in the latter case it lies inside the route's XY bounds. - if(passage.controlPoints.size()>=2) - { - double routeMinimum[3]={std::numeric_limits::infinity(), - std::numeric_limits::infinity(), - std::numeric_limits::infinity()}; - double routeMaximum[3]={-std::numeric_limits::infinity(), - -std::numeric_limits::infinity(), - -std::numeric_limits::infinity()}; - double maximumBoreRadius=0.0; - for(const auto& point:passage.controlPoints) - { - for(int axis=0;axis<3;++axis) - { - const double value=static_cast(point.positionSubvoxels[axis])/Q; - routeMinimum[axis]=std::min(routeMinimum[axis],value); - routeMaximum[axis]=std::max(routeMaximum[axis],value); - } - maximumBoreRadius=std::max(maximumBoreRadius, - static_cast(point.radiusSubvoxels)/Q); - } - - double centerMinimumX=routeMinimum[0],centerMaximumX=routeMaximum[0]; - double centerMinimumY=routeMinimum[1],centerMaximumY=routeMaximum[1]; - double maximumRouteOffset=std::hypot( - routeMaximum[0]-routeMinimum[0],routeMaximum[1]-routeMinimum[1]); - const auto upper=std::find_if(layout.strates.begin(),layout.strates.end(), - [&passage](const auto& stratum) - {return stratum.strateIndex==passage.upperStrateIndex;}); - if(upper!=layout.strates.end() - &&upper->passageCapabilities.usePassageAnchorForColumns) - { - const auto anchor=std::find_if(upper->anchors.begin(),upper->anchors.end(), - [](const auto& value) - {return value.kind=="passage_anchor"&&value.values.size()>=2;}); - if(anchor!=upper->anchors.end()) - { - const double centerX=static_cast(anchor->values[0])/Q; - const double centerY=static_cast(anchor->values[1])/Q; - centerMinimumX=centerMaximumX=centerX; - centerMinimumY=centerMaximumY=centerY; - maximumRouteOffset=0.0; - for(const auto& point:passage.controlPoints) - maximumRouteOffset=std::max(maximumRouteOffset,std::hypot( - static_cast(point.positionSubvoxels[0])/Q-centerX, - static_cast(point.positionSubvoxels[1])/Q-centerY)); - } - } - // The generated maximum column radius is the route offset, bore radius, - // and 13.25 m of wall/irregularity/flare allowance. - const double columnRadius=maximumRouteOffset+maximumBoreRadius - +13.25*voxelsPerMetre; - const double columnMinimum[3]={centerMinimumX-columnRadius, - centerMinimumY-columnRadius,routeMinimum[2]-6.0*voxelsPerMetre}; - const double columnMaximum[3]={centerMaximumX+columnRadius, - centerMaximumY+columnRadius,routeMaximum[2]+5.0*voxelsPerMetre}; - bool overlap=true; - for(int axis=0;axis<3;++axis) - overlap=overlap&&columnMaximum[axis]>=tileMinimum[axis] - &&columnMinimum[axis]<=tileMaximum[axis]; - if(overlap)return true; - } } return false; } @@ -1866,44 +1867,6 @@ namespace VoxelForgeCore static_cast(weighted)/65535.0*sampleVolume}); return result; } - std::vector World::passageVoidCrossings() const - { - std::vector result; - if(!impl_||!impl_->shapeReady.load(std::memory_order_acquire)||!impl_->shape)return result; - const auto& crossings=impl_->shape->GetPassageVoidCrossings(); - result.reserve(crossings.size()); - for(const auto& crossing:crossings) - { - PassageVoidCrossingAuditV1 value; - value.passageIndex=crossing.passageIndex;value.firstSegment=crossing.firstSegment; - value.lastSegment=crossing.lastSegment;value.unsupportedSamples=crossing.unsupportedSamples; - value.unsupportedLengthMetres=crossing.unsupportedLengthMetres; - value.startPointSubvoxels=crossing.startPoint;value.endPointSubvoxels=crossing.endPoint; - value.needsColumn=crossing.needsColumn; - value.connectedAtStart=crossing.connectedAtStart; - value.connectedAtEnd=crossing.connectedAtEnd; - value.columnAxisSubvoxels={crossing.centerXSubvoxels,crossing.centerYSubvoxels}; - value.columnTopZSubvoxels=crossing.topZSubvoxels; - value.columnBottomZSubvoxels=crossing.bottomZSubvoxels; - value.columnMinimumRadiusSubvoxels=crossing.minimumRadiusSubvoxels; - value.columnNominalRadiusSubvoxels=crossing.nominalRadiusSubvoxels; - value.columnMaximumRadiusSubvoxels=crossing.maximumRadiusSubvoxels; - value.maximumRouteOffsetMetres=crossing.maximumRouteOffsetMetres; - value.maximumBoreRadiusMetres=crossing.maximumBoreRadiusMetres; - result.push_back(value); - } - return result; - } - bool World::isPassageColumnSample(std::size_t passageIndex,std::size_t segmentIndex, - Vec3d position) const - {return impl_&&impl_->shapeReady.load(std::memory_order_acquire)&&impl_->shape - &&impl_->shape->IsResolvedPassageColumnSample(passageIndex,segmentIndex, - {position.x,position.y,position.z});} - bool World::isPassageShortSpanSample(std::size_t passageIndex,std::size_t segmentIndex, - Vec3d position) const - {return impl_&&impl_->shapeReady.load(std::memory_order_acquire)&&impl_->shape - &&impl_->shape->IsResolvedPassageShortSpanSample(passageIndex,segmentIndex, - {position.x,position.y,position.z});} std::string World::densityDispatchPathAt(Vec3d position) const { return impl_&&impl_->shapeReady.load(std::memory_order_acquire)&&impl_->shape ?impl_->shape->DensityDispatchPathAt(static_cast(position.x),static_cast(position.y),static_cast(position.z)) @@ -2672,30 +2635,6 @@ namespace VoxelForgeCore RelevantMinimum=std::min(RelevantMinimum,FeatureMinimum); RelevantMaximum=std::max(RelevantMaximum,FeatureMaximum); } - // A resolved passage void column can add solid support above or - // below the native heightfield's local Z range. Its finite radial - // and vertical bounds must participate before the mesh band is clipped. - for(const auto& Crossing:tileShape.GetPassageVoidCrossings()) - { - if(!Crossing.needsColumn||Crossing.maximumRadiusSubvoxels<=0 - ||Crossing.topZSubvoxels<=Crossing.bottomZSubvoxels)continue; - const double Radius=static_cast(Crossing.maximumRadiusSubvoxels) - /static_cast(SubvoxelScale); - const double CenterX=static_cast(Crossing.centerXSubvoxels) - /static_cast(SubvoxelScale); - const double CenterY=static_cast(Crossing.centerYSubvoxels) - /static_cast(SubvoxelScale); - if(CenterX+Radius(SubvoxelScale) - ||CenterX-Radius>TileMaximum[0]/static_cast(SubvoxelScale) - ||CenterY+Radius(SubvoxelScale) - ||CenterY-Radius>TileMaximum[1]/static_cast(SubvoxelScale))continue; - RelevantMinimum=std::min(RelevantMinimum, - static_cast(Crossing.bottomZSubvoxels) - /static_cast(SubvoxelScale)); - RelevantMaximum=std::max(RelevantMaximum, - static_cast(Crossing.topZSubvoxels) - /static_cast(SubvoxelScale)); - } // The native heightfield band only covers the owner terrain and its // manifest features. Resolved SDF stamps can carve below that band or // add a floor there, so include every overlapping stamp's bounded Z @@ -2804,7 +2743,6 @@ namespace VoxelForgeCore FStandaloneShapeWorld::FScopedPassageTileQueries passageFeatureScope( tileShape,queryMinimum,queryMaximum, options.profilePassageComposer?&out.diagnostics:nullptr,key.lod, - options.diagnosticPassageSourceFloorVoxels, options.diagnosticPassageCarveReachMetres); passageFeatureScope.prepareSweptTubeBase(origin,MeshStep,MeshCells, static_cast(world.Seed)); @@ -2904,10 +2842,6 @@ namespace VoxelForgeCore { out.diagnostics.passageTileRouteSegmentCandidates= passageFeatureScope.routeSegmentCandidateCount(); - for(std::size_t passageIndex=0; - passageIndexresolvedLayout->passages.size();++passageIndex) - out.diagnostics.passageTileMouthSegmentCandidates+= - passageFeatureScope.mouthSupportSegments(passageIndex).size(); } } FGridFillWorkerContext GridFillWorkerContext; diff --git a/Standalone/Research/WorldAssemblerM3/Astra2/PROMPT.md b/Standalone/Research/WorldAssemblerM3/Astra2/PROMPT.md new file mode 100644 index 0000000..84c1b09 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Astra2/PROMPT.md @@ -0,0 +1,60 @@ +# VoxelForge — read-only design review: stamp tunnels along the curve instead of searching the curve per sample + +You are reviewing a design idea against real code. **Do not edit, create or delete any file, and do not build or run +anything.** Read code and reason. Be thorough; mark each claim as [CODE] (with file:line), [MEASURED] (from a report), +or [INFERENCE]. + +## Context + +VoxelForge Core (`Standalone/Core`) generates a density field: negative = solid, positive = air, 25 cm voxels, 32³ tiles, +LOD0–8 clipmap, marching cubes. Same seed must give the same world on every machine and worker count; byte-identity with +older versions is NOT required. + +Inter-strate tunnels ("passages") on branch `wip/l111-halfpipe-spline` (HEAD `707bc61`) are a smooth spline swept tube: +- a D-shaped walkable floor with a continuous floor height h(s), max grade 15°; +- a rounded crest; +- an open-air half-pipe where there is no rock; +- a thin solid shell ("plain shell rule": interior always air, a thin shell always solid); +- smooth-min where tunnels meet; +- mouths that ramp into the ground. + +Key code: `Standalone/Core/src/ShapeWorldInternal.h` (`FScopedPassageTileQueries`, `prepareSweptTubeBase`, around +lines 374 and 11436), `Standalone/Core/src/VoxelForgeCore.cpp:~2747`. Reports: `Standalone/Research/WorldAssemblerM3/Linux109` +… `Linux119` (REPORT.md each). + +Cost today [MEASURED, L117–L119]: the smooth tunnel is 13–22% slower than the coarse L109 tunnel at LOD0–2 readiness. +About 95% of the extra cost is in passage-feature tiles. The causes: sweep pairs (sample × curve segment), exact +fallbacks that re-scan segments for off-grid queries, segment visits, per-tile prepare, and smooth-min. + +## The idea to review (owner + orchestrator) + +Today each sample "pulls": it searches for the nearest curve segment and computes a distance. Proposed: "push"/stamp. +For each tile, walk the curve in rings (frames: position, forward, up, as with an Unreal spline mesh) and write the +tube's signed distance into only the lattice samples near each ring. Only a narrow band of about one voxel around the +wall needs an exact value; deep rock only needs "rock" and the tunnel interior only needs "air". Off-grid queries +(normals/gradients at seams, gameplay point queries) would read the stamped lattice, interpolating, instead of +re-searching the curve. Also: accept curve accuracy at one voxel (25 cm) rather than 2.5–10 cm, and build the curve +frames once per route rather than per tile. + +## Questions + +1. Is the cost model right? From the code, what does a passage-feature tile do per sample today, and what would stamping + replace? Estimate the work ratio (samples touched × ops) for a typical LOD0 tile and for LOD1–2. +2. What breaks or gets harder, concretely in this code? + - box verdicts/tile skipping (`ClassifyTile`-style proofs that a tile is all solid/air); + - seams between tiles: both neighbours must stamp identical values at shared samples, deterministically; + - LOD levels (coarser lattices); + - off-grid `DensityAtUnclamped` queries and gradients; + - min/smooth-min with the rest of the field and with other tunnels; + - the floor h(s), half-pipe, shell, mouths; + - walk audits; + - thread safety. +3. Is "write into the lattice" compatible with how density is evaluated (lattice fill vs point evaluation)? If the + pipeline is pull-only, what is the smallest change that gets the push benefit? For example, a per-tile sparse + band list built by walking rings, then lookups during fill. +4. Is there a simpler or cheaper alternative we're missing? For example, an analytic local frame per sample from the + spline parameter, or a coarse per-tile segment window that is already almost free. +5. Recommendation: the design you would build, in steps, with the evidence bar (what measurement would prove or kill + it). Keep it short. + +Write your answer as plain Markdown, at most ~1,200 words. diff --git a/Standalone/Research/WorldAssemblerM3/Astra2/REVIEW.md b/Standalone/Research/WorldAssemblerM3/Astra2/REVIEW.md new file mode 100644 index 0000000..8f2163b --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Astra2/REVIEW.md @@ -0,0 +1,53 @@ +[INFERENCE] **Build a tighter passage cache first.** Ring stamping is promising, but the code already pushes segment contributions into a tile lattice. The main opportunity is reducing coverage, overlap, and off-grid fallback work—not reversing a purely pull-based architecture. + +References below: `H` = `Standalone/Core/src/ShapeWorldInternal.h`; `C` = `Standalone/Core/src/VoxelForgeCore.cpp`; `M` = `Standalone/Source/VoxelForge/Private/VoxelMarchingCubesMesher.cpp`. Report references mean `Standalone/Research/WorldAssemblerM3/LinuxNNN/REPORT.md`. + +**1. Cost model** + +[CODE] `prepareSweptTubeBase` allocates per-passage `(cells+3)³` sample records, including a one-step halo. It walks candidate bounding boxes, lattice samples, then fine segments; individual segment bounds reject some pairs. Accepted pairs compute projection, deterministic square root, radius, floor profile, and potentially shell distance. A final pass flattens the selected tube and caches relief (`H:11436`, `H:11489`, `H:11521`, `H:11659`). + +[CODE] During density evaluation, aligned samples retrieve that cache, then still perform relief weighting, floor shaping, mouth fades, shell composition, and host-field composition. Misses invoke two hierarchy searches: nearest body/floor and nearby shells—not necessarily a linear whole-route scan (`H:1247`, `H:1346`, `H:1427`, `H:1435`). + +[MEASURED] L119 reports 29.40M preparation pairs and 24.46M segment visits across its four LOD0–2 profiles. Preparation fell 59.8% versus L118, while fallbacks increased 55–58%. L117 attributes about 95% of the tile-worker regression to passage-feature tiles. Thus the diagnosis is sound, but those counters do not establish equivalent costs per operation. + +[INFERENCE] For an illustrative straight crossing, assume exposed surface perimeter \(P=16\) m, tile crossing length \(L=32\Delta\), and exact band ±one lattice step. Unique band samples are approximately \(2PL/\Delta^2\): + +| [INFERENCE] Normal tile | LOD0 | LOD1 | LOD2 | +|---|---:|---:|---:| +| Spacing Δ | 0.25 m | 0.5 m | 1 m | +| Band samples | 4,096 | 2,048 | 1,024 | +| Fraction of 35³ prepared grid | 9.6% | 4.8% | 2.4% | + +[INFERENCE] These are geometric estimates, not measured “typical tiles”; clipping, floor/outer-shell surfaces, bends, and crossings change them. If today fraction \(f\) of the grid receives \(k\) segment evaluations, and stamping averages \(m\) contributions per band sample, the expensive-work ratio is approximately `(table fraction × m)/(f × k)`, multiplied by relative operation cost. For `f=0.5, k=2, m=2`, that is 19%, 9.6%, 4.8%. Allocation, classification, host evaluation, and composition remain. Dense rings can make \(m\) large and erase this advantage. + +**2. Concrete difficulties** + +- [CODE] **Skipping:** passage-bound overlap currently vetoes a uniform proof and returns `Mixed` (`H:5684`). [INFERENCE] Retain conservative bounds, expanded for approximation and reconstruction support. “No band samples written” proves neither solid nor air: a thin shell can lie between samples. + +- [CODE] **Seams:** cache coordinates derive from integer world coordinates; nearest ties use segment index (`H:11448`, `H:11564`, `H:11640`). [INFERENCE] Generate rings from route-global parameters, never tile-local stepping. Include every contributor affecting shared samples and halos; use stable ordering and arithmetic. Independently clipping ring generation at tile boundaries risks disagreement. + +- [INFERENCE] **LOD:** distinguish 25 cm curve error from lattice spacing. A fixed 25 cm band is insufficient around 1 m cells; cover interpolation corners and gradient support. A 0.75 m shell can disappear at coarse resolution. Independently reconstructed LOD fields also disagree off-grid; define one canonical point-query field. + +- [CODE] **Off-grid:** `sweptSample` rejects non-lattice coordinates; public point queries call `DensityAtUnclamped` without requiring a tile cache (`H:11721`; `C:1875`). Gradients normally use density-grid values, with unclamped fallback (`M:1972`). [INFERENCE] Interpolation needs all eight valid corners, including outside loaded tiles. It changes gradients and zero crossings; interpolating only passage channels also differs from interpolating the fully composed field. + +- [CODE] **Composition:** passage bodies and shells use separate hard minima; final composition includes host/native-floor exceptions (`H:1496–1519`). The floor corner uses smooth-max, implemented through smooth-min (`H:3493`, `H:6940`). [INFERENCE] Do not assume the measured smooth-min cost is tunnel-to-tunnel joining. Preserve separate void/shell channels and composition order. Arbitrary “rock/air” magnitudes can move interpolated crossings and smooth blends. + +- [CODE] **Shape:** floor selection is independent of minimum round distance; the code explicitly warns that minimizing flattened segment distances makes downhill floors jump (`H:1328`). Floor evaluation uses horizontal projection, authored `h(s)`, and XY mouth blending (`H:3448`). Shells have rounded crests and five-metre mouth fades (`H:1461`, `H:3503`). [INFERENCE] A conventional spline-normal D-section changes this geometry. Stamped isolated rings can scallop; rasterize bounded slabs between frames while preserving gravity-relative floors, shell unions, and interior priority. + +- [MEASURED] **Walkability:** L119’s maximum sampled floor-root offset was 7.884 mm; L113 documented voxel-aligned floor ribs. [INFERENCE] A 25 cm curve tolerance does not authorize 25 cm floor error or guarantee ≤15° grade. Audit reconstructed density and meshes, including mouths, overlaps, support, and headroom—not only planner `h(s)`. + +- [CODE] **Threads:** copied worker scopes share prepared data through a shared pointer; active scope is thread-local (`H:353`, `H:11411`; `C:2854`). [INFERENCE] Finish stamping before publication. Parallel ring writes require deterministic reductions; mutable shared lazy caches introduce synchronization and lifetime problems. + +**3. Smallest useful change** + +[CODE] Preparation already precedes `GenerateMesh`, whose fill calls lattice evaluators (`C:2747`, `C:2892`; `M:1488`). Route segments are already prepared globally with 10 cm chord tolerance and an 8 m spacing cap (`H:4601`). + +[INFERENCE] Replace preparation’s broad pair enumeration with conservative slab-to-grid spans or small spatial bins. Keep indexed lookups during pull-based fill. Store body/floor ownership and shell contributions separately; use explicit outside/interior/band states. A dense index plus compact records may beat a sparse hash map. Additional frames can be route-global, but this does not eliminate existing per-tile rasterization. + +**4. Alternatives and recommendation** + +[MEASURED] L115 already reduced coarse candidates 74.1% without reducing fine pairs. L118’s restriction of fallbacks to prepared spans changed output; L116’s 20.8% pair reduction did not recover readiness. + +[INFERENCE] An analytic local frame still needs a parameter lookup, especially near folds. Prefer globally indexed conservative segment bins, shared by preparation and exact point queries. + +[INFERENCE] Build in three steps: instrument unique samples, overlap, misses by caller, memory, and per-LOD time; implement tighter bins/slabs while preserving geometry; then separately trial 25 cm curve tolerance and canonical interpolation. Accept only reproducible near-readiness gains against L119/L109 plus unchanged walk/seam requirements and cross-compiler/worker determinism. Kill the approach if saved distance work becomes rasterization, memory, or reconstruction cost. \ No newline at end of file diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/MeasureL109FloorRamp.py b/Standalone/Research/WorldAssemblerM3/Linux109/MeasureL109FloorRamp.py new file mode 100644 index 0000000..f080797 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux109/MeasureL109FloorRamp.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python3 +"""Measure the fixed-depth floor and derived centreline against the authored grade.""" +from __future__ import annotations + +import json +import math +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +LAYOUT = ROOT / "Saved/Linux/l109/audit-layout-final-stamp.json" +OUT = ROOT / "Saved/Linux/l109/floor-ramp-grade-final.json" +MOUTH_RAMP_METRES = 5.0 + + +def route_m(layout: dict, passage: dict): + scale = layout["core_voxel_size_um"] / 256.0 / 1_000_000.0 + controls = [(tuple(float(v) * scale for v in row["position_q"]), + float(row["radius_q"]) * scale) for row in passage["control_points"]] + lower_q = passage["lower_mouth_q"] + player_center_above_floor_q = round( + 1.13 * 256.0 * 1_000_000.0 / layout["core_voxel_size_um"]) + lower_index = next((index for index, row in enumerate(passage["control_points"]) + if row["position_q"][0] == lower_q[0] + and row["position_q"][1] == lower_q[1] + and row["position_q"][2] - row["radius_q"] + + player_center_above_floor_q == lower_q[2]), None) + if lower_index is None: + raise RuntimeError(f"{passage['stable_id']}: lower mouth control is unbound") + return controls[:lower_index + 1] + + +def maximum_grade(profile): + grades = [] + for (p0, z0), (p1, z1) in zip(profile, profile[1:]): + horizontal = math.hypot(p1[0] - p0[0], p1[1] - p0[1]) + if horizontal > 1.0e-8: + grades.append(math.degrees(math.atan2(abs(z1 - z0), horizontal))) + return max(grades, default=0.0) + + +def main() -> int: + layout = json.loads(LAYOUT.read_text(encoding="utf-8")) + rows = [] + for passage in layout["passages"]: + route = route_m(layout, passage) + segment_lengths = [math.dist(a[0], b[0]) for a, b in zip(route, route[1:])] + prefix = [0.0] + for length in segment_lengths: + prefix.append(prefix[-1] + length) + interior_radii = [radius for distance, (_, radius) in zip(prefix, route) + if distance >= 10.0 and prefix[-1] - distance >= 10.0] + minimum_body_radius = min(interior_radii or [radius for _, radius in route]) + body_depth = max(0.5, minimum_body_radius - 0.23) + scale = layout["core_voxel_size_um"] / 256.0 / 1_000_000.0 + upper_target = max(0.0, route[0][0][2] + - passage["upper_mouth_q"][2] * scale + 1.13) + lower_target = max(0.0, route[-1][0][2] + - passage["lower_mouth_q"][2] * scale + 1.13) + floor_profile = [] + raw_fixed_depth_profile = [] + maximum_centerline_shift = 0.0 + for segment_index, (a, b, length) in enumerate( + zip(route, route[1:], segment_lengths)): + steps = max(1, math.ceil(length / 0.05)) + for step in range(steps + 1): + if floor_profile and step == 0: + continue + t = step / steps + position = tuple(a[0][axis] + (b[0][axis] - a[0][axis]) * t + for axis in range(3)) + radius = a[1] + (b[1] - a[1]) * t + along = prefix[segment_index] + length * t + mouth_distance = max(0.0, min(along, prefix[-1] - along)) + u = max(0.0, min(1.0, mouth_distance / MOUTH_RAMP_METRES)) + ramp = u * u * (3.0 - 2.0 * u) + local_radius_depth = max(0.0, radius - 0.23) + mouth_target = upper_target if along <= prefix[-1] * 0.5 else lower_target + mouth_depth = max(0.0, min(radius, mouth_target)) + route_depth = mouth_depth + (local_radius_depth - mouth_depth) * ramp + tube_depth = min(body_depth, local_radius_depth) + effective_center = position[2] - route_depth + tube_depth + floor_profile.append((position, effective_center - tube_depth)) + raw_fixed_depth_profile.append((position, position[2] - tube_depth)) + maximum_centerline_shift = max(maximum_centerline_shift, + abs(effective_center - position[2])) + rows.append({ + "passage": passage["stable_id"], + "path_m": prefix[-1], + "body_floor_depth_m": body_depth, + "mouth_blend_m": MOUTH_RAMP_METRES, + "preserved_route_floor_max_grade_deg": maximum_grade(floor_profile), + "unshifted_fixed_depth_floor_max_grade_deg": maximum_grade( + raw_fixed_depth_profile), + "maximum_derived_centerline_shift_m": maximum_centerline_shift, + }) + OUT.write_text(json.dumps({ + "method": "0.05 m route samples; fixed body depth from the minimum interior radius; " + "cubic smoothstep mouth blend", + "passages": rows, + }, indent=2) + "\n", encoding="utf-8") + for row in rows: + print(f"[L109FloorRamp] {row['passage']} " + f"depth_m={row['body_floor_depth_m']:.3f} " + f"preserved_grade_deg={row['preserved_route_floor_max_grade_deg']:.3f} " + f"unshifted_fixed_depth_grade_deg={row['unshifted_fixed_depth_floor_max_grade_deg']:.3f} " + f"max_center_shift_m={row['maximum_derived_centerline_shift_m']:.3f}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/REPORT.md b/Standalone/Research/WorldAssemblerM3/Linux109/REPORT.md new file mode 100644 index 0000000..953cbe0 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux109/REPORT.md @@ -0,0 +1,70 @@ +# Linux 109 — tunnel floor and shell + +Baseline: `assembler/world` HEAD `95cf8de10723f2dffe7b3dfc116ecf350c7114ae`. Candidate source stamp: `9457b9bed7d57a4a387828961f9dd53632ec602eb5ea8f247b087be6ca5cc312` (evaluator v217). + +## Shape + +The per-tile swept tube now uses a horizontal flat floor, a 0.50 m smooth floor-to-wall corner, and a 0.75 m shell. Body floor depth is fixed per passage at the minimum interior radius minus 0.23 m, capped at the local radius. Five-metre cubic blends ramp both mouths into their ground; the lower mouth follows the matching authored native-cave floor where one exists. The route centreline shifts through radius tapers to keep that floor walkable. A small wall relief remains for naturalness. + +The passage interiors are unioned first and always win over every passage shell, including at coiled crossings. The shell writes solid only where the host field is air; rock remains unchanged. There is no rock classification. Open-air shell and interior samples pass in the owner audit. + +## Removed and retained + +Removed route support restoration, deferred support after later bores, support columns, mouth-support restoration, and their floor-specific capsule checks and profiling records. Replaced the old open-air/column audit gates with the shell audit and removed the no-long-bridge and rock-column gates, which measured the deleted support mechanism. Walkability, capsule, headroom, grade, mouth, naturalness, and ripple gates remain. Floor-ripple probes fully masked by another passage's interior air are skipped only when the overlap is explicit; capsule walkability still has to pass. + +Kept the native Lattice field's explicitly authored below-floor substrate because its spine needs it for walkability; this is part of that native field, not route support restoration. The legacy landmark demo retains its compatibility floor-cap path, which is separate from the resolved route sweep. Native Caves and Lattice fast checks pass. + +## Performance + +Five interleaved L80 pairs per cell, after one warmup for each binary; seconds are median `LOD0–2 near-ready / whole-view-ready`. Baseline binary is from `assembler/world` HEAD. Tile counts matched within each cell. + +| Strate | W8 near | W8 whole | W12 near | W12 whole | +|---|---:|---:|---:|---:| +| SW | 0.680 → 0.737 (+8.3%) | 1.686 → 1.674 (−0.7%) | 0.700 → 0.761 (+8.8%) | 1.643 → 1.644 (+0.1%) | +| FI | 1.455 → 0.911 (−37.4%) | 2.419 → 1.772 (−26.8%) | 1.394 → 0.863 (−38.0%) | 2.288 → 1.664 (−27.3%) | +| TN | 1.423 → 0.956 (−32.8%) | 2.310 → 1.778 (−23.0%) | 1.294 → 0.895 (−30.9%) | 2.132 → 1.661 (−22.1%) | +| VS | 1.008 → 0.789 (−21.8%) | 1.917 → 1.639 (−14.5%) | 0.854 → 0.738 (−13.5%) | 1.716 → 1.541 (−10.2%) | + +There is no broad regression. SW near-ready is about 0.06 s slower; its whole-view time is flat. **Measured:** SW LOD0–2 skirt triangles rise from 133,894 to 196,602, and summed skirt work rises from 455 to 743 ms at W8 and 650 to 1,044 ms at W12. **Inference:** the added open-air shell surface and skirts explain the small SW near-ready cost. FI, TN, and VS improve at both readiness marks. + +## L77 phase census + +Two samples per case. Entries are `share / estimated worker-s`; estimates use weighted L77 samples times `WorldAssemblerLODWorker` CPU, so they are not direct phase timers. + +| Case | Base passage | Base support | Candidate passage | Candidate support | +|---|---:|---:|---:|---:| +| FI near | 44.62% / 4.108 | 14.84% / 1.366 | 22.90% / 1.133 | 0% / 0 | +| FI whole | 29.31% / 4.874 | 8.08% / 1.344 | 10.59% / 1.206 | 0% / 0 | +| TN near | 38.57% / 3.318 | 14.74% / 1.267 | 19.43% / 1.019 | 0% / 0 | +| TN whole | 24.48% / 3.824 | 7.59% / 1.186 | 9.25% / 1.074 | 0% / 0 | + +The sampled support share disappears. Baseline estimates were 1.19–1.37 worker-s across these cases, below the 1.6–1.9 s expectation. + +## Audits and determinism + +The full-view all-LOD audit passes: 21,425/21,425 canonical passage centreline samples are open. All three interfaces pass capsule and support checks with zero blocked or unsupported samples, zero grade failures, and both mouths bound (2/2). Capsule samples: 266,175 (0–1), 15,120 (1–2), 64,764 (2–3). The shell audit sampled 89,365 floor points, 8,423 wall points, and 10,527 interior points: zero floor, wall, or interior violations; 22,755 open-air shell samples. Naturalness, mouth profile, and ripple summaries pass 3/3, with negative controls detected. Derived floor grade peaks at 14.49°; fast native Caves headroom is 0.30 m and native Lattice headroom is 2.20 m. + +Fast tier: PASS, 259 PASS checks plus 5 diagnostics across 80 runs. The Clang/GCC hash matrix matches at W1/W8/W12 for the owner four-strata layout and both two-strata canonical recipes. The v217 canonical pins were written for Surface World style 1 and Floating Islands style 2. + +Because Core sources are Unreal-compiled, the Linux VFHostEditor build passed with `-NoUBA -MaxParallelActions=4` (27 actions, 67.4 s). Three FI and three SW `after` arrival traces also passed, each settling its full requested LOD0–2 set. Unreal processes had no `prlimit`. + +## Change metrics + +LOD0–2 camera mesh windows; “moved” means a shared global lattice crossing displaced by more than 0.01 cm. Coverage is the paired edge-classifier coverage. + +| Strate | Added | Removed | Moved | Coverage | +|---|---:|---:|---:|---:| +| SW | 78,201 | 14,530 | 2,758 | 99.75% | +| FI | 37,810 | 42,398 | 78,215 | 98.31% | +| TN | 44,694 | 48,925 | 48,816 | 98.29% | +| VS | 7,055 | 7,096 | 8,790 | 97.38% | + +## Captures + +84 PNGs: before and after, each with both mouths and 25/50/75% stations for all three passages. Each of the nine open-air sections has three views in each set. The [capture index](captures/INDEX.md) lists every image and flags every **OPEN AIR** view. All 84 source meshes and rendered views contain geometry; minimum visible triangles are 55,420 before and 55,484 after. Six before and seven after images met the pixel floor but were flagged low contrast for review. + +Open-air sections (route distance in metres): `0–1`: 7.226–10.217, 13.456–17.443, 23.174–24.918, 1036.913–1489.321; `1–2`: 101.820–104.499; `2–3`: 7.677–34.747, 368.909–376.660, 393.828–396.510, 444.932–447.654. + +## Failed runs + +Early fast runs found a 0.79 m lower-mouth mismatch at native Caves and loss of the native Lattice route substrate; the mouth now matches the authored cave edge floor, and the explicitly authored Lattice floor field is retained. A sentinel check also initially treated the “no native floor” value as support; this was fixed. The first Unreal build stopped before compilation because UnrealBuildTool could not rotate its log under read-only `~/.config`; redirecting `XDG_CONFIG_HOME` to `/tmp` fixed it. Final audits, timings, hash runs, crossings, captures, build, and six traces passed. No run exceeded 30 minutes. diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/RunL109Captures.py b/Standalone/Research/WorldAssemblerM3/Linux109/RunL109Captures.py new file mode 100644 index 0000000..fa63821 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux109/RunL109Captures.py @@ -0,0 +1,511 @@ +#!/usr/bin/env python3 +"""Capture before/after passage mouths, route stations, and exposed shell sections.""" +from __future__ import annotations + +import json +import math +import re +from array import array +import struct +import subprocess +import time +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +RESEARCH = Path(__file__).resolve().parent +CAPTURES = RESEARCH / "captures" +SAVED = ROOT / "Saved/Linux/l109/captures" +DATA = ROOT / "Standalone/data/owner_world.json" +BINARIES = { + "before": ROOT / "Saved/Linux/l109/bin-baseline/VoxelForgeCoreHeadless-l109-baseline", + "after": ROOT / "Saved/Linux/l109/bin-final/VoxelForgeCoreHeadless-l109-clang", +} +LAYOUTS = { + "before": ROOT / "Saved/Linux/l109/audit-layout-baseline.json", + "after": ROOT / "Saved/Linux/l109/audit-layout-final-stamp.json", +} +AUDIT_LOG = ROOT / "Saved/Linux/l109/audit-owner4-final-stamp.log" +RENDERERS = { + "before": ROOT / "Saved/Linux/l109/bin-baseline/VoxelForgeOffscreenCapture-l109-baseline", + "after": ROOT / "Saved/Linux/l109/bin-final/VoxelForgeOffscreenCapture-l109-clang", +} +SECTION = re.compile( + r"^\[PassageOpenAirSection\] id=(\S+) section=(\d+) start_m=([\d.]+) " + r"end_m=([\d.]+) samples=(\d+) midpoint_xyz_m=\(([^)]*)\) " + r"midpoint_radius_m=([\d.]+)", re.M) +DRAWN = re.compile(r"drawn_triangles=(\d+)") +QUALITY_METRICS = re.compile(r"stddev_luma=([\d.]+).*coverage_luma_gt12=([\d.]+)") + + +def vector(text: str) -> tuple[float, float, float]: + return tuple(float(value) for value in text.split(",")) + + +def add(a, b): + return tuple(x + y for x, y in zip(a, b)) + + +def sub(a, b): + return tuple(x - y for x, y in zip(a, b)) + + +def mul(a, scale): + return tuple(x * scale for x in a) + + +def norm(a): + length = math.sqrt(sum(x * x for x in a)) + if length <= 1.0e-9: + return (0.0, 1.0, 0.0) + return tuple(value / length for value in a) + + +def angles(camera, target): + delta = sub(target, camera) + horizontal = math.hypot(delta[0], delta[1]) + return (math.degrees(math.atan2(delta[0], delta[1])), + math.degrees(math.atan2(delta[2], horizontal))) + + +def fmt(values) -> str: + return ",".join(f"{value:.6f}" for value in values) + + +def mesh_triangle_count(mesh: Path) -> int: + """Read only the VFMSH headers and count indexed triangles.""" + with mesh.open("rb") as stream: + magic = stream.read(8) + materials = magic == b"VFMSH002" + if magic not in (b"VFMSH001", b"VFMSH002"): + raise RuntimeError(f"unsupported mesh scene header: {mesh}") + version, _voxel_um, tile_count = struct.unpack("<3I", stream.read(12)) + if version != (2 if materials else 1): + raise RuntimeError(f"mesh scene version mismatch: {mesh}") + stream.seek(40, 1) + triangles = 0 + for _ in range(tile_count): + stream.seek(16, 1) + surface_count, _skirts, vertex_count, index_count, mask_count = struct.unpack( + "<5I", stream.read(20)) + triangles += index_count // 3 + stream.seek(vertex_count * 24 + (10 * vertex_count if materials else 0) + + index_count * 4 + mask_count, 1) + if stream.read(1): + raise RuntimeError(f"trailing data in mesh scene: {mesh}") + return triangles + + +def dot(a, b): + return sum(x * y for x, y in zip(a, b)) + + +def nearest_surface_anchor(mesh: Path, point, margin_m=200.0) -> dict: + """Return a nearby VFMSH surface vertex and its normal.""" + best_distance_sq = float("inf") + best_position = best_normal = None + with mesh.open("rb") as stream: + magic = stream.read(8) + materials = magic == b"VFMSH002" + if magic not in (b"VFMSH001", b"VFMSH002"): + raise RuntimeError(f"unsupported mesh scene header: {mesh}") + version, voxel_um, tile_count = struct.unpack("<3I", stream.read(12)) + if version != (2 if materials else 1): + raise RuntimeError(f"mesh scene version mismatch: {mesh}") + stream.seek(40, 1) + for _ in range(tile_count): + key = struct.unpack("<4i", stream.read(16)) + surface_count, _skirts, vertex_count, index_count, mask_count = struct.unpack( + "<5I", stream.read(20)) + extent = (32 << key[3]) * voxel_um / 1_000_000.0 + origin = (key[0] * extent, key[1] * extent, key[2] * extent) + if any(point[axis] < origin[axis] - margin_m or + point[axis] > origin[axis] + extent + margin_m for axis in range(3)): + stream.seek(vertex_count * 24 + (10 * vertex_count if materials else 0) + + index_count * 4 + mask_count, 1) + continue + positions = array("f") + positions.frombytes(stream.read(vertex_count * 12)) + normals = array("f") + normals.frombytes(stream.read(vertex_count * 12)) + if materials: + stream.seek(vertex_count * 10, 1) + stream.seek(index_count * 4 + mask_count, 1) + if struct.pack("=I", 1) != struct.pack("= best_distance_sq: + continue + raw_normal = tuple(float(normals[offset + axis]) for axis in range(3)) + if dot(raw_normal, raw_normal) < 1.0e-10: + continue + best_distance_sq = distance_sq + best_position = position + best_normal = norm(raw_normal) + if best_position is None: + raise RuntimeError(f"no nearby surface vertices in mesh scene: {mesh}") + return {"position_m": best_position, "normal": best_normal, + "distance_m": math.sqrt(best_distance_sq)} + + +def sanitize(value: str) -> str: + return re.sub(r"[^A-Za-z0-9_-]+", "-", value).strip("-").replace("/", "-") + + +def route_for(layout: dict, passage: dict) -> list[tuple[tuple[float, float, float], float]]: + scale = layout["core_voxel_size_um"] / 256.0 / 1_000_000.0 + controls = [(tuple(value * scale for value in row["position_q"]), + row["radius_q"] * scale) for row in passage["control_points"]] + lower_q = passage["lower_mouth_q"] + player_center_above_floor_q = round( + 1.13 * 256.0 * 1_000_000.0 / layout["core_voxel_size_um"]) + lower_index = next((index for index, row in enumerate(passage["control_points"]) + if row["position_q"][0] == lower_q[0] + and row["position_q"][1] == lower_q[1] + and row["position_q"][2] - row["radius_q"] + + player_center_above_floor_q == lower_q[2]), None) + if lower_index is None: + raise RuntimeError(f"{passage['stable_id']}: lower mouth control is unbound") + result = controls[:lower_index + 1] + if len(result) < 2: + raise RuntimeError(f"{passage['stable_id']}: incomplete route controls") + return result + + +def route_lengths(route): + lengths = [math.dist(a[0], b[0]) for a, b in zip(route, route[1:])] + prefix = [0.0] + for length in lengths: + prefix.append(prefix[-1] + length) + return lengths, prefix + + +def at_distance(route, lengths, prefix, distance): + distance = max(0.0, min(distance, prefix[-1])) + for index, length in enumerate(lengths): + if distance <= prefix[index + 1] or index + 1 == len(lengths): + t = 0.0 if length <= 1.0e-9 else (distance - prefix[index]) / length + a, b = route[index], route[index + 1] + return (tuple(a[0][axis] + (b[0][axis] - a[0][axis]) * t + for axis in range(3)), + a[1] + (b[1] - a[1]) * t) + return route[-1] + + +def tangent_at(route, lengths, prefix, distance): + before = at_distance(route, lengths, prefix, max(0.0, distance - 0.25))[0] + after = at_distance(route, lengths, prefix, min(prefix[-1], distance + 0.25))[0] + return norm(sub(after, before)) + + +def derived_route(route, passage, layout): + """Apply L109's fixed-depth floor offset to raw layout controls.""" + lengths, prefix = route_lengths(route) + total = prefix[-1] + body_radii = [radius for index, (_, radius) in enumerate(route) + if prefix[index] >= 10.0 and total - prefix[index] >= 10.0] + body_depth = max(0.5, min(body_radii or [radius for _, radius in route]) - 0.23) + scale = layout["core_voxel_size_um"] / 256.0 / 1_000_000.0 + upper_z = passage["upper_mouth_q"][2] * scale + lower_z = passage["lower_mouth_q"][2] * scale + upper_target = max(0.0, route[0][0][2] - upper_z + 1.13) + lower_target = max(0.0, route[-1][0][2] - lower_z + 1.13) + transformed = [] + for index, (point, radius) in enumerate(route): + local_radius_depth = max(0.0, radius - 0.23) + mouth_distance = max(0.0, min(prefix[index], total - prefix[index])) + u = max(0.0, min(1.0, mouth_distance / 5.0)) + ramp = u * u * (3.0 - 2.0 * u) + target = upper_target if prefix[index] <= total * 0.5 else lower_target + mouth_depth = max(0.0, min(radius, target)) + route_depth = mouth_depth + (local_radius_depth - mouth_depth) * ramp + tube_depth = min(body_depth, local_radius_depth) + transformed.append(((point[0], point[1], point[2] - route_depth + tube_depth), + radius)) + return transformed, body_depth + + +def make_views(layout: dict, audit_sections: list[dict], *, use_derived_shape: bool, + include_open_air: bool = True) -> list[dict]: + views = [] + passages = sorted(layout["passages"], key=lambda item: item["stable_id"]) + for passage in passages: + raw_route = route_for(layout, passage) + if use_derived_shape: + route, body_depth = derived_route(raw_route, passage, layout) + else: + route = raw_route + body_depth = max(point[1] for point in route) + def floor_depth(radius: float) -> float: + if not use_derived_shape: + return radius + return min(body_depth, max(0.0, radius - 0.23)) + lengths, prefix = route_lengths(route) + total = prefix[-1] + passage_id = passage["stable_id"] + safe_id = sanitize(passage_id) + + for end_name, distance, outward_sign in ( + ("upper-mouth", 0.0, -1.0), ("lower-mouth", total, 1.0)): + center, radius = at_distance(route, lengths, prefix, distance) + tangent = tangent_at(route, lengths, prefix, distance) + outward = mul(tangent, outward_sign) + floor_z = center[2] - floor_depth(radius) + eye = (center[0] + outward[0] * 4.5, + center[1] + outward[1] * 4.5, + floor_z + 1.55) + if end_name == "lower-mouth": + eye = add(eye, add(mul(outward, 5.0), (0.0, 0.0, 2.0))) + target = (center[0] - outward[0] * 2.0, + center[1] - outward[1] * 2.0, + floor_z + 1.45) + yaw, pitch = angles(eye, target) + views.append({"name": f"{safe_id}-{end_name}", "passage": passage_id, + "kind": "mouth", "station": end_name, + "camera": eye, "target": target, "yaw": yaw, "pitch": pitch, + "focus": center, "center_z": center[2]}) + + for fraction in (0.25, 0.50, 0.75): + distance = total * fraction + center, radius = at_distance(route, lengths, prefix, distance) + tangent = tangent_at(route, lengths, prefix, distance) + depth = floor_depth(radius) + floor_z = center[2] - depth + horizontal = norm((-tangent[1], tangent[0], 0.0)) + eye = (center[0] + horizontal[0] * 0.75, + center[1] + horizontal[1] * 0.75, floor_z + 1.60) + target_center, target_radius = at_distance(route, lengths, prefix, + min(total, distance + 14.0)) + target_depth = floor_depth(target_radius) + target = (target_center[0] + horizontal[0] * 2.35, + target_center[1] + horizontal[1] * 2.35, + target_center[2] - target_depth + 1.80) + yaw, pitch = angles(eye, target) + views.append({"name": f"{safe_id}-station-{int(fraction * 100)}", + "passage": passage_id, "kind": "station", + "station": f"{int(fraction * 100)}%", "camera": eye, + "target": target, "yaw": yaw, "pitch": pitch, + "focus": center, "center_z": center[2], + "route_distance_m": distance, + "route_length_m": total, + "requested_route_distance_m": distance}) + + if not include_open_air: + continue + for section in (item for item in audit_sections if item["passage"] == passage_id): + distance = 0.5 * (section["start_m"] + section["end_m"]) + center, radius = (section["midpoint"], section["radius_m"]) + tangent = tangent_at(route, lengths, prefix, distance) + side = norm((-tangent[1], tangent[0], 0.0)) + depth = floor_depth(radius) + section_id = section["section"] + interior_eye = (center[0], center[1], center[2] - depth + 1.25) + interior_target = add(interior_eye, mul(tangent, 7.0)) + side_eye = add(center, add(mul(side, radius + 5.0), (0.0, 0.0, 1.2))) + oblique_eye = add(center, add(mul(side, -(radius + 3.5)), (0.0, 0.0, 4.0))) + targets = (add(center, (0.0, 0.0, 0.1)), + add(center, mul(tangent, 2.0)), interior_target) + for view_index, (eye, target) in enumerate(zip( + (side_eye, oblique_eye, interior_eye), targets), start=1): + yaw, pitch = angles(eye, target) + views.append({"name": f"{safe_id}-openair-{section_id}-view-{view_index}", + "passage": passage_id, "kind": "open-air", + "station": f"section-{section_id}/view-{view_index}", + "camera": eye, "target": target, "yaw": yaw, + "pitch": pitch, "focus": center, + "center_z": center[2], "open_air_section": section_id, + "route_distance_m": distance, + "requested_route_distance_m": distance, + "route_length_m": total}) + return views + + +def run_process(name: str, command: list[str], log: Path, *, allow_failure=False) -> str: + wrapped = ["taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1740s", *map(str, command)] + started = time.monotonic() + with log.open("w", encoding="utf-8") as stream: + result = subprocess.run(wrapped, cwd=ROOT, stdout=stream, + stderr=subprocess.STDOUT, check=False, timeout=1740) + if result.returncode and not allow_failure: + raise RuntimeError(f"{name}: exit={result.returncode} log={log}") + print(f"[L109CaptureProcess] name={name} elapsed_s={time.monotonic()-started:.2f} " + f"exit={result.returncode} log={log.relative_to(ROOT)}", flush=True) + return log.read_text(encoding="utf-8", errors="replace") + + +def capture(variant: str, view: dict, layout: dict) -> dict: + variant_saved = SAVED / variant + variant_saved.mkdir(parents=True, exist_ok=True) + variant_capture = CAPTURES / variant + variant_capture.mkdir(parents=True, exist_ok=True) + scene = variant_saved / f"{view['name']}.vfmesh" + image = variant_capture / f"{view['name']}.png" + candidates = [(view["camera"], view["target"], view["focus"], + view.get("route_distance_m"), 0.0, "requested")] + if variant == "before" and view["kind"] != "mouth": + passage = next(item for item in layout["passages"] + if item["stable_id"] == view["passage"]) + route = route_for(layout, passage) + lengths, prefix = route_lengths(route) + total = prefix[-1] + eye_offset = sub(view["camera"], view["focus"]) + target_offset = sub(view["target"], view["focus"]) + requested = view["route_distance_m"] + for delta in (5, -5, 10, -10, 20, -20, 35, -35, 50, -50, 75, -75, + 100, -100, 150, -150, 200, -200): + distance = max(0.0, min(total, requested + delta)) + if abs(distance - requested) < 0.01: + continue + center, _radius = at_distance(route, lengths, prefix, distance) + candidates.append((add(center, eye_offset), add(center, target_offset), center, + distance, distance - requested, "route-offset")) + + attempt_errors = [] + for attempt_index, (probe_camera, probe_target, probe_focus, route_distance, + route_adjustment, attempt_kind) in enumerate(candidates): + suffix = "" if attempt_index == 0 else f"-attempt-{attempt_index:02d}" + headless_log = variant_saved / f"{view['name']}{suffix}-mesh.log" + render_log = variant_saved / f"{view['name']}{suffix}-render.log" + quality_log = variant_saved / f"{view['name']}{suffix}-quality.log" + yaw, pitch = angles(probe_camera, probe_target) + camera = (*probe_camera, yaw, pitch) + export_command = [ + str(BINARIES[variant]), str(DATA), "--world-assembler-prototype", + "--stream-benchmark", "--stream-pipeline", "--workers=12", + "--clip-radius=3", "--max-clip-level=0", "--max-level=0", "--force-generate", + "--recipe=surface-world", f"--camera={fmt(camera)}", + "--render-distance-chunks=1", f"--mesh-export={scene}", + ] + export_output = run_process(f"{variant}-{view['name']}{suffix}-mesh", export_command, + headless_log) + if "status=PASS" not in export_output or not scene.is_file(): + raise RuntimeError(f"{variant}-{view['name']}: missing successful scene export") + source_triangles = mesh_triangle_count(scene) + if source_triangles <= 0: + attempt_errors.append(f"{attempt_kind}@{route_distance}: empty mesh") + if variant == "after" or view["kind"] == "mouth": + break + continue + + actual_camera, actual_target = probe_camera, probe_target + actual_focus = probe_focus + surface_distance = None + if attempt_kind == "route-offset": + anchor = nearest_surface_anchor(scene, probe_focus) + surface_distance = anchor["distance_m"] + actual_camera = add(anchor["position_m"], mul(anchor["normal"], 12.0)) + actual_target = anchor["position_m"] + actual_focus = anchor["position_m"] + actual_yaw, actual_pitch = angles(actual_camera, actual_target) + render_command = [ + str(RENDERERS[variant]), str(scene), str(image), "--size=1920x1080", + f"--camera-m={fmt(actual_camera)}", f"--yaw-deg={actual_yaw:.6f}", + f"--pitch-deg={actual_pitch:.6f}", "--shade=readable", "--headlamp=on", + "--height-tint=on", f"--height-center-m={actual_focus[2]:.6f}", + "--height-range-m=32", + ] + render_output = run_process(f"{variant}-{view['name']}{suffix}-render", render_command, + render_log) + drawn = DRAWN.search(render_output) + if drawn is None or int(drawn.group(1)) <= 0 or not image.is_file(): + attempt_errors.append(f"{attempt_kind}@{route_distance}: no drawn geometry") + if variant == "after" or view["kind"] == "mouth": + break + continue + quality = run_process(f"{variant}-{view['name']}{suffix}-quality", [ + "python3", "-B", str(ROOT / "Standalone/Tools/verify/capture_quality.py"), + str(image)], quality_log, allow_failure=True) + quality_status = "pass" + if "status=PASS" not in quality: + metrics = QUALITY_METRICS.search(quality) + coverage = float(metrics.group(2)) if metrics else 0.0 + if coverage >= 0.001: + quality_status = "low_contrast_geometry_visible" + else: + attempt_errors.append(f"{attempt_kind}@{route_distance}: no visible pixel coverage") + if variant == "after" or view["kind"] == "mouth": + break + continue + + row = {**view, "variant": variant, "capture": str(image.relative_to(RESEARCH)), + "scene": str(scene.relative_to(ROOT)), "drawn_triangles": int(drawn.group(1)), + "source_triangles": source_triangles, "verified": True, + "pixel_quality_status": quality_status, + "route_distance_actual_m": route_distance, + "route_station_adjustment_m": route_adjustment, + "fallback_kind": attempt_kind if attempt_kind != "requested" else None, + "fallback_surface_distance_m": surface_distance, + "camera_actual_m": actual_camera, "target_actual_m": actual_target, + "logs": [str(headless_log.relative_to(ROOT)), + str(render_log.relative_to(ROOT)), + str(quality_log.relative_to(ROOT))]} + print("[L109Capture] " + json.dumps(row, sort_keys=True), flush=True) + return row + raise RuntimeError(f"{variant}-{view['name']}: no verified image; " + + "; ".join(attempt_errors)) + + +def main() -> int: + if any(not path.is_file() for path in (*BINARIES.values(), *RENDERERS.values(), + *LAYOUTS.values(), AUDIT_LOG)): + raise SystemExit("missing L109 capture binary, layout, or audit log") + sections = [] + for passage, section, start, end, samples, midpoint, radius in SECTION.findall( + AUDIT_LOG.read_text(encoding="utf-8", errors="replace")): + sections.append({"passage": passage, "section": int(section), + "start_m": float(start), "end_m": float(end), + "samples": int(samples), "midpoint": vector(midpoint), + "radius_m": float(radius)}) + if not sections: + raise SystemExit("no open-air sections found in the final passage audit") + all_rows = [] + for variant in ("before", "after"): + layout = json.loads(LAYOUTS[variant].read_text(encoding="utf-8")) + include_open_air = True + views = make_views(layout, sections, use_derived_shape=variant == "after", + include_open_air=include_open_air) + expected = 5 * len(layout["passages"]) + if include_open_air: + expected += 3 * len(sections) + if len(views) != expected: + raise RuntimeError(f"unexpected camera count: {len(views)} != {expected}") + print(f"[L109CapturePlan] variant={variant} passage_views={5*len(layout['passages'])} " + f"open_air_sections={len(sections) if include_open_air else 0} " + f"open_air_views={3*len(sections) if include_open_air else 0} " + f"total={len(views)}", flush=True) + for view in views: + all_rows.append(capture(variant, view, layout)) + CAPTURES.mkdir(parents=True, exist_ok=True) + (CAPTURES / "capture-index.json").write_text( + json.dumps({"open_air_sections": sections, "captures": all_rows}, indent=2) + "\n", + encoding="utf-8") + lines = ["# L109 passage captures", "", + "Each PNG was rendered from its own exported mesh. The renderer reported visible " + "triangles, and each decoded image met the pixel coverage floor. " + "`low_contrast_geometry_visible` marks images that met this floor below the " + "preferred contrast target.", ""] + for variant in ("before", "after"): + lines.extend([f"## {variant.title()}", ""]) + for row in all_rows: + if row["variant"] != variant: + continue + flag = " **OPEN AIR**" if row["kind"] == "open-air" else "" + quality_note = (f"; {row['pixel_quality_status']}" + if row["pixel_quality_status"] != "pass" else "") + lines.append(f"- [{row['station']}]({variant}/{Path(row['capture']).name}) — " + f"{row['passage']}{flag}; {row['drawn_triangles']} visible triangles" + f"{quality_note}") + lines.append("") + (CAPTURES / "INDEX.md").write_text("\n".join(lines), encoding="utf-8") + failures = [row for row in all_rows if not row["verified"]] + print(f"[L109CaptureSummary] captures={len(all_rows)} verified={len(all_rows)-len(failures)} " + f"failed={len(failures)} open_air_sections={len(sections)}", flush=True) + return 1 if failures else 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/RunL109CrossingDelta.py b/Standalone/Research/WorldAssemblerM3/Linux109/RunL109CrossingDelta.py new file mode 100644 index 0000000..4c37a93 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux109/RunL109CrossingDelta.py @@ -0,0 +1,140 @@ +#!/usr/bin/env python3 +"""Compare LOD0-2 owner mesh edge crossings before and after L109.""" +from __future__ import annotations + +import json +import math +import statistics +import struct +import subprocess +import time +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / "Saved/Linux/l109/crossings" +DATA = ROOT / "Standalone/data/owner_world.json" +BINARIES = { + "before": ROOT / "Saved/Linux/l109/bin-baseline/VoxelForgeCoreHeadless-l109-baseline", + "after": ROOT / "Saved/Linux/l109/bin-final/VoxelForgeCoreHeadless-l109-clang", +} +CAMERAS = { + "SW": (8.0, 16.0, -372.2626953125), + "FI": (25.8369140625, 3.19921875, -737.0), + "TN": (19.166015625, -14.2001953125, -753.3740234375), + "VS": (-20.0625, -5.068359375, -900.353515625), +} + + +def read_exact(stream, size): + data = stream.read(size) + if len(data) != size: + raise RuntimeError("truncated VFMSH export") + return data + + +def crossing_map(path: Path) -> tuple[dict, dict]: + crossings = {} + meta = {"tiles": 0, "surface_vertices": 0, "classified": 0} + with path.open("rb") as stream: + magic = read_exact(stream, 8) + materials = magic == b"VFMSH002" + if magic not in (b"VFMSH001", b"VFMSH002"): + raise RuntimeError(f"invalid mesh export {path}") + version, voxel_um, tile_count = struct.unpack("<3I", read_exact(stream, 12)) + if version != (2 if materials else 1): + raise RuntimeError("VFMSH version mismatch") + read_exact(stream, 40) + voxel_m = voxel_um / 1_000_000.0 + for _ in range(tile_count): + key = struct.unpack("<4i", read_exact(stream, 16)) + surface_count, _skirts, vertex_count, index_count, mask_count = struct.unpack( + "<5I", read_exact(stream, 20)) + positions = struct.iter_unpack("<3f", read_exact(stream, vertex_count * 12)) + values = list(positions) + read_exact(stream, vertex_count * 12) # normals + if materials: + read_exact(stream, vertex_count * 10) + read_exact(stream, index_count * 4 + mask_count) + meta["tiles"] += 1 + meta["surface_vertices"] += min(surface_count, vertex_count) + unit = voxel_m * (1 << key[3]) + for position in values[:min(surface_count, vertex_count)]: + grid = tuple(value / unit for value in position) + fractions = tuple(abs(value - round(value)) for value in grid) + axis = max(range(3), key=fractions.__getitem__) + if fractions[axis] < 1.0e-4: + continue + fixed = [index for index in range(3) if index != axis] + if any(fractions[index] > 0.01 for index in fixed): + continue + edge = [0, 0, 0] + for index in fixed: + edge[index] = int(round(grid[index])) + edge[axis] = math.floor(grid[axis]) + identity = (key[3], axis, *edge) + crossings.setdefault(identity, tuple(float(v) for v in position)) + meta["classified"] += 1 + if stream.read(1): + raise RuntimeError("trailing data in mesh export") + meta["classified_pct"] = (100.0 * meta["classified"] / meta["surface_vertices"] + if meta["surface_vertices"] else 0.0) + return crossings, meta + + +def export(strate: str, variant: str) -> Path: + OUT.mkdir(parents=True, exist_ok=True) + mesh = OUT / f"{strate.lower()}-{variant}.vfmesh" + log = OUT / f"{strate.lower()}-{variant}.log" + camera = ",".join(f"{v:.12f}" for v in CAMERAS[strate]) + ",0,0" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1740s", str(BINARIES[variant]), str(DATA), + "--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline", + "--workers=8", "--clip-radius=3", "--max-clip-level=2", "--max-level=2", + "--force-generate", "--recipe=surface-world", f"--camera={camera}", + "--render-distance-chunks=0", + f"--mesh-export={mesh}", + ] + started = time.monotonic() + with log.open("w", encoding="utf-8") as stream: + result = subprocess.run(command, cwd=ROOT, stdout=stream, + stderr=subprocess.STDOUT, timeout=1740, check=False) + output = log.read_text(encoding="utf-8", errors="replace") + if result.returncode or not mesh.is_file() or "status=PASS" not in output: + raise RuntimeError(f"mesh export failed: {strate}/{variant} exit={result.returncode} {log}") + return mesh + + +def main() -> int: + summaries = [] + for strate in CAMERAS: + paths = {variant: export(strate, variant) for variant in ("before", "after")} + maps = {variant: crossing_map(path) for variant, path in paths.items()} + old, old_meta = maps["before"] + new, new_meta = maps["after"] + old_keys, new_keys = set(old), set(new) + shared = old_keys & new_keys + moved_cm = [100.0 * math.dist(old[key], new[key]) for key in shared + if math.dist(old[key], new[key]) > 0.0001] + row = { + "strate": strate, "scope": "camera LOD0-2 mesh window; global lattice edge IDs", + "added_crossings": len(new_keys - old_keys), + "removed_crossings": len(old_keys - new_keys), + "shared_crossings": len(shared), "moved_crossings": len(moved_cm), + "mean_moved_cm": statistics.mean(moved_cm) if moved_cm else 0.0, + "max_moved_cm": max(moved_cm, default=0.0), + "before": old_meta, "after": new_meta, + "classified_pair_coverage_pct": min(old_meta["classified_pct"], + new_meta["classified_pct"]), + "exports": {key: str(value.relative_to(ROOT)) for key, value in paths.items()}, + } + summaries.append(row) + print("[L109CrossingDelta] " + json.dumps(row, sort_keys=True), flush=True) + (OUT / "summary.json").write_text( + json.dumps({"measurement": "per-vertex marching-cubes edge classifier; compare shared global lattice edges; positions >0.01cm count as moved", + "strata": summaries}, indent=2) + "\n", encoding="utf-8") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/RunL109HashMatrix.py b/Standalone/Research/WorldAssemblerM3/Linux109/RunL109HashMatrix.py new file mode 100644 index 0000000..d3344a0 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux109/RunL109HashMatrix.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python3 +"""Check Clang/GCC hash identity at W1/W8/W12 and repin v217 owner hashes.""" +from __future__ import annotations + +import json +import re +import subprocess +import time +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / "Saved/Linux/l109/hashes" +DATASETS = { + "owner4": ROOT / "Standalone/data/owner_world.json", + "owner2": ROOT / "Standalone/data/regression/owner_world_2strate_l61.json", +} +BINARIES = { + "clang": ROOT / "Saved/Linux/l109/bin-final/VoxelForgeCoreHeadless-l109-clang", + "gcc": ROOT / "Saved/Linux/l109/bin-final/VoxelForgeCoreHeadless-l109-gcc", +} +HASH = re.compile(r"^\[Pipeline(?:FullDetailHash|WholeViewHash|LODHash|ExactQueryHash)\].*$", re.M) +STAMP = re.compile(r"^\[VoxelForgeSourceStamp\] sha256=(\S+)$", re.M) + + +def run(dataset: str, recipe: str, workers: int, compiler: str) -> dict: + OUT.mkdir(parents=True, exist_ok=True) + label = f"{dataset}-{recipe}-w{workers}-{compiler}" + log = OUT / f"{label}.log" + layout = OUT / f"{label}.layout.json" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1740s", str(BINARIES[compiler]), str(DATASETS[dataset]), + f"--workers={workers}", "--world-assembler-prototype", "--stream-benchmark", + "--stream-pipeline", "--force-generate", "--clip-radius=3", + "--max-clip-level=8", "--max-level=8", f"--recipe={recipe}", + "--stream-hash", f"--resolved-layout-output={layout}", + ] + started = time.monotonic() + with log.open("w", encoding="utf-8") as stream: + result = subprocess.run(command, cwd=ROOT, stdout=stream, + stderr=subprocess.STDOUT, check=False, timeout=1740) + output = log.read_text(encoding="utf-8", errors="replace") + hashes = HASH.findall(output) + if result.returncode or len(hashes) != 12: + raise SystemExit(f"hash run failed or incomplete: {label}; exit={result.returncode} " + f"hashes={len(hashes)} log={log}") + row = {"dataset": dataset, "recipe": recipe, "workers": workers, + "compiler": compiler, "exit_code": result.returncode, + "hashes": hashes, "source_stamp": (STAMP.search(output).group(1) + if STAMP.search(output) else None), + "elapsed_s": round(time.monotonic() - started, 3), + "log": str(log.relative_to(ROOT))} + print("[L109HashRun] " + json.dumps(row, sort_keys=True), flush=True) + return row + + +def main() -> int: + if any(not path.is_file() for path in (*DATASETS.values(), *BINARIES.values())): + raise SystemExit("missing L109 hash input") + rows = [] + recipes = {"owner4": ("surface-world",), + "owner2": ("surface-world", "floating-islands")} + for dataset, dataset_recipes in recipes.items(): + for recipe in dataset_recipes: + for workers in (1, 8, 12): + for compiler in ("clang", "gcc"): + rows.append(run(dataset, recipe, workers, compiler)) + (OUT / "runs-partial.json").write_text( + json.dumps(rows, indent=2) + "\n", encoding="utf-8") + groups = {} + for dataset, dataset_recipes in recipes.items(): + for recipe in dataset_recipes: + key = f"{dataset}/{recipe}" + group = [row for row in rows if row["dataset"] == dataset + and row["recipe"] == recipe] + reference = group[0]["hashes"] + groups[key] = {"all_worker_compiler_hashes_match": all( + row["hashes"] == reference for row in group), + "source_stamps": sorted({row["source_stamp"] for row in group}), + "runs": [{"workers": row["workers"], "compiler": row["compiler"], + "log": row["log"]} for row in group]} + if not groups[key]["all_worker_compiler_hashes_match"]: + raise SystemExit(f"determinism mismatch: {key}") + if dataset == "owner2": + canonical = next(row for row in group if row["workers"] == 12 + and row["compiler"] == "clang") + recipe_name = "floating-islands" if recipe == "floating-islands" else "surface-world" + style = 1 if recipe_name == "surface-world" else 2 + baseline = (ROOT / "Standalone/Tools/verify/baselines/owner-hash/canonical" + / f"owner-hash-{recipe_name}-style{style}-v217.baseline") + baseline.write_text("\n".join(canonical["hashes"]) + "\n", + encoding="utf-8") + summary = {"runs": rows, "groups": groups, + "owner4_all_four_strata": "owner4/surface-world", + "owner2_canonical_pins": ["owner2/surface-world", + "owner2/floating-islands"]} + (OUT / "summary.json").write_text(json.dumps(summary, indent=2) + "\n", + encoding="utf-8") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/RunL109PhaseCensus.py b/Standalone/Research/WorldAssemblerM3/Linux109/RunL109PhaseCensus.py new file mode 100644 index 0000000..7c181d0 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux109/RunL109PhaseCensus.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python3 +"""Estimate L77 passage/support worker shares before and after L109.""" +from __future__ import annotations + +import json +import re +import statistics +import subprocess +import time +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / "Saved/Linux/l109/l77-phase-census" +DATA = ROOT / "Standalone/data/owner_world.json" +BINARIES = { + "base": ROOT / "Saved/Linux/l109/bin-baseline-profile/VoxelForgeCoreHeadless-l109-base-profile", + "candidate": ROOT / "Saved/Linux/l109/bin-final-profile/VoxelForgeCoreHeadless-l109-candidate-profile", +} +CAMERAS = { + "FI": (25.8369140625, 3.19921875, -737.0), + "TN": (19.166015625, -14.2001953125, -753.3740234375), +} +WORKER = re.compile(r"^\[WorldAssemblerLODWorker\] (.*)$", re.M) +SAMPLE = re.compile(r"^\[L77Sample\] (.*)$", re.M) +SAMPLER = re.compile(r"^\[L77Sampler\] action=stop (.*)$", re.M) +FIELDS = re.compile(r"([a-zA-Z0-9_]+)=([^ ]+)") + + +def run(stratum: str, variant: str, replicate: int) -> dict: + OUT.mkdir(parents=True, exist_ok=True) + label = f"{stratum.lower()}-{variant}-r{replicate}" + log = OUT / f"{label}.log" + camera = ",".join(f"{value:.12f}" for value in CAMERAS[stratum]) + ",0,0" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1740s", str(BINARIES[variant]), str(DATA), + "--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline", + "--workers=8", "--clip-radius=3", "--max-clip-level=8", "--max-level=8", + f"--camera={camera}", "--profile-lod-work", "--stream-scheduler-policy=3", + "--linux77-profile", + ] + started = time.monotonic() + with log.open("w", encoding="utf-8") as stream: + result = subprocess.run(command, cwd=ROOT, stdout=stream, + stderr=subprocess.STDOUT, check=False, timeout=1740) + content = log.read_text(encoding="utf-8", errors="replace") + sampler_match = SAMPLER.search(content) + workers = [dict(FIELDS.findall(match.group(1))) for match in WORKER.finditer(content)] + samples = [dict(FIELDS.findall(match.group(1))) for match in SAMPLE.finditer(content)] + if result.returncode or sampler_match is None or len(workers) < 9 or not samples: + raise SystemExit(f"phase census failed or markers missing: {log}; exit={result.returncode}") + sampler = dict(FIELDS.findall(sampler_match.group(1))) + if sampler.get("status") != "PASS": + raise SystemExit(f"L77 sampler failed: {log}: {sampler}") + lod_seconds = {int(row["lod"]): float(row["worker_sum_s"]) for row in workers} + + def estimate(scope: str) -> dict: + lods = set(range(3)) if scope == "lod0-2" else set(range(9)) + eligible = [row for row in samples if int(row["lod"]) in lods] + weights = {phase: sum(int(row.get("weight", "1")) for row in eligible + if row.get("phase") == phase) + for phase in ("passages", "support")} + total_weight = sum(int(row.get("weight", "1")) for row in eligible) + cpu_seconds = sum(value for lod, value in lod_seconds.items() if lod in lods) + result_row = {"worker_cpu_s": round(cpu_seconds, 4), + "weighted_samples": total_weight} + for phase, weight in weights.items(): + share = weight / total_weight if total_weight else 0.0 + result_row[f"{phase}_share_pct"] = round(share * 100.0, 3) + result_row[f"{phase}_worker_s_estimate"] = round(cpu_seconds * share, 4) + return result_row + + row = { + "stratum": stratum, "variant": variant, "replicate": replicate, + "exit_code": result.returncode, + "sampler": sampler, + "lod0_2": estimate("lod0-2"), "whole_view": estimate("whole"), + "log": str(log.relative_to(ROOT)), + "runner_wall_s": round(time.monotonic() - started, 3), + } + print("[L109PhaseCensusRun] " + json.dumps(row, sort_keys=True), flush=True) + return row + + +def main() -> int: + if any(not path.is_file() for path in BINARIES.values()): + raise SystemExit("missing L77 profile binary") + rows = [run(stratum, variant, replicate) + for stratum in ("FI", "TN") + for replicate in (1, 2) + for variant in ("base", "candidate")] + summary = [] + for stratum in ("FI", "TN"): + for variant in ("base", "candidate"): + entry = {"stratum": stratum, "variant": variant, "replicates": 2} + group = [row for row in rows if row["stratum"] == stratum + and row["variant"] == variant] + for scope in ("lod0_2", "whole_view"): + for key in ("worker_cpu_s", "passages_share_pct", "passages_worker_s_estimate", + "support_share_pct", "support_worker_s_estimate"): + values = [row[scope][key] for row in group] + entry[f"{scope}_{key}_runs"] = values + entry[f"{scope}_{key}_median"] = statistics.median(values) + summary.append(entry) + (OUT / "summary.json").write_text( + json.dumps({"runs": rows, "summary": summary}, indent=2) + "\n", + encoding="utf-8") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/RunL109Timing.py b/Standalone/Research/WorldAssemblerM3/Linux109/RunL109Timing.py new file mode 100644 index 0000000..3482f87 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux109/RunL109Timing.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python3 +"""Five interleaved L80 readiness pairs for L109, at W8 and W12.""" +from __future__ import annotations + +import json +import re +import statistics +import subprocess +import time +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / "Saved/Linux/l109/timing" +DATA = ROOT / "Standalone/data/owner_world.json" +BINARIES = { + "base": ROOT / "Saved/Linux/l109/bin-baseline/VoxelForgeCoreHeadless-l109-baseline", + "candidate": ROOT / "Saved/Linux/l109/bin-final/VoxelForgeCoreHeadless-l109-clang", +} +CAMERAS = { + 0: (8.0, 16.0, -372.2626953125), + 1: (25.8369140625, 3.19921875, -737.0), + 2: (19.166015625, -14.2001953125, -753.3740234375), + 3: (-20.0625, -5.068359375, -900.353515625), +} +PIPELINE = re.compile(r"^\[StreamPipeline\] (.*)$", re.M) +FIELDS = re.compile(r"([a-zA-Z0-9_]+)=([^ ]+)") +NEAR = re.compile( + r"^\[WorldAssemblerNearLODReady\] lods=0-2 tiles=(\d+)/(\d+) cold_ready_s=([0-9.]+)$", + re.M, +) + + +def run(strate: int, workers: int, variant: str, phase: str, replicate: int) -> dict: + OUT.mkdir(parents=True, exist_ok=True) + label = f"s{strate}-w{workers}-{variant}-{phase}{replicate}" + log = OUT / f"{label}.log" + camera = ",".join(f"{v:.12f}" for v in CAMERAS[strate]) + ",0,0" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1740s", str(BINARIES[variant]), str(DATA), + "--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline", + f"--workers={workers}", "--clip-radius=3", "--max-clip-level=8", "--max-level=8", + f"--camera={camera}", "--profile-lod-work", "--stream-scheduler-policy=3", + ] + start = time.monotonic() + with log.open("w", encoding="utf-8") as output: + result = subprocess.run(command, cwd=ROOT, stdout=output, + stderr=subprocess.STDOUT, check=False, timeout=1740) + content = log.read_text(encoding="utf-8", errors="replace") + pipeline_match = PIPELINE.search(content) + near_match = NEAR.search(content) + if result.returncode or pipeline_match is None or near_match is None: + raise SystemExit(f"readiness run failed or trace missing: {log}; exit={result.returncode}") + pipeline = dict(FIELDS.findall(pipeline_match.group(1))) + row = { + "strate": strate, "workers": workers, "variant": variant, + "phase": phase, "replicate": replicate, "exit_code": result.returncode, + "wall_s": round(time.monotonic() - start, 3), + "lod02_ready_s": float(near_match.group(3)), + "whole_view_ready_s": float(pipeline["whole_view_ready"].removesuffix("s")), + "whole_tiles": int(pipeline["whole_tiles"].split("/")[0]), + "log": str(log.relative_to(ROOT)), + } + print("[L109TimingRun] " + json.dumps(row, sort_keys=True), flush=True) + return row + + +def main() -> int: + if not DATA.is_file() or any(not binary.is_file() for binary in BINARIES.values()): + raise SystemExit("missing data or timing binary") + rows = [] + for strate in range(4): + for workers in (8, 12): + run(strate, workers, "base", "warmup", 0) + run(strate, workers, "candidate", "warmup", 0) + for replicate in range(1, 6): + order = ("base", "candidate") if replicate % 2 else ("candidate", "base") + for variant in order: + rows.append(run(strate, workers, variant, "measured", replicate)) + (OUT / "runs-partial.json").write_text( + json.dumps(rows, indent=2) + "\n", encoding="utf-8") + summary = [] + for strate in range(4): + for workers in (8, 12): + item = {"strate": strate, "workers": workers, "pairs": 5} + for variant in ("base", "candidate"): + group = [row for row in rows if row["strate"] == strate + and row["workers"] == workers and row["variant"] == variant] + for key in ("lod02_ready_s", "whole_view_ready_s"): + values = [row[key] for row in group] + item[f"{variant}_{key}"] = values + item[f"{variant}_{key}_median"] = statistics.median(values) + for key in ("lod02_ready_s", "whole_view_ready_s"): + base = item[f"base_{key}_median"] + candidate = item[f"candidate_{key}_median"] + item[f"{key}_delta_pct"] = round(100 * (candidate / base - 1), 2) + summary.append(item) + (OUT / "summary.json").write_text( + json.dumps({"runs": rows, "summary": summary}, indent=2) + "\n", + encoding="utf-8") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/RunL109UnrealArrival.py b/Standalone/Research/WorldAssemblerM3/Linux109/RunL109UnrealArrival.py new file mode 100644 index 0000000..ca68ae4 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux109/RunL109UnrealArrival.py @@ -0,0 +1,484 @@ +#!/usr/bin/env python3 +"""Run one pinned null-RHI SW/FI arrival for Linux 107.""" +from __future__ import annotations + +import argparse +from collections import Counter +from datetime import datetime +import json +import re +import subprocess +import time +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +HOST = Path("/home/jahni/VFHost") +HOST_PLUGIN_SAVED = HOST / "Plugins/VoxelForge/Saved/Linux/l109" +HOST_SAVED = HOST / "Saved/Linux/l109" +EDITOR = Path("/home/jahni/UnrealEngine/Engine/Binaries/Linux/UnrealEditor-Cmd") +OUT = ROOT / "Saved/Linux/l109/unreal-arrival" +SPAWNS_M = { + "FI": (25.8369140625, 3.19921875, -737.0), + "SW": (25.8369140625, 3.19921875, -200.0), +} +MOVE_START_S = 20.0 +MOVE_DURATION_S = 12.0 +EXIT_S = MOVE_START_S + MOVE_DURATION_S + 5.0 +RUN_TIMEOUT_S = 1740 + + +def read_events(path: Path) -> list[dict]: + events = [] + if path.is_file(): + for line in path.read_text(encoding="utf-8", errors="replace").splitlines(): + if line.startswith("{"): + try: + events.append(json.loads(line)) + except json.JSONDecodeError: + pass + return events + + +def percentile(values: list[float], fraction: float) -> float | None: + if not values: + return None + ordered = sorted(values) + return ordered[min(len(ordered) - 1, int(round((len(ordered) - 1) * fraction)))] + + +def sample_unreal_peak_rss() -> tuple[int, int] | None: + executable = str(EDITOR).encode() + project = str(HOST / "VFHost.uproject").encode() + peak: tuple[int, int] | None = None + for process in Path("/proc").glob("[0-9]*"): + try: + command_line = (process / "cmdline").read_bytes() + if executable not in command_line or project not in command_line: + continue + status = (process / "status").read_text(encoding="ascii", errors="ignore") + match = re.search(r"^VmHWM:\s+(\d+)\s+kB$", status, re.MULTILINE) + if match: + rss_kib = int(match.group(1)) + if peak is None or rss_kib > peak[0]: + peak = (rss_kib, int(process.name)) + except (FileNotFoundError, PermissionError, ProcessLookupError, OSError): + continue + return peak + + +def endphysics_gap(stdout: Path) -> tuple[float | None, int | None]: + release_times: dict[int, dict[int, datetime]] = {} + pattern = re.compile( + r"^\[(\d{4}\.\d{2}\.\d{2}-\d{2}\.\d{2}\.\d{2}:\d{3})\].*" + r"LogTick: tick\s+(\d+)\s+-+\s+Release tick group ([34])") + with stdout.open(encoding="utf-8", errors="replace") as stream: + for line in stream: + match = pattern.match(line) + if not match: + continue + timestamp = datetime.strptime(match.group(1), "%Y.%m.%d-%H.%M.%S:%f") + frame = int(match.group(2)) + group = int(match.group(3)) + release_times.setdefault(frame, {})[group] = timestamp + gaps = [(round((times[4] - times[3]).total_seconds() * 1000.0, 3), frame) + for frame, times in release_times.items() if 3 in times and 4 in times] + return max(gaps, default=(None, None)) + + +def run(stratum: str, repeat: int, phase: str, ready_depth: int, + background_cap: int, worker_reserve: int, helper_background: int, + tile_background_low: int, tile_background_normal: int, startup_boost: int, + tick_logs: bool, insights: bool) -> dict: + label = (f"{phase}-{stratum.lower()}-rd{ready_depth}-bg{background_cap}" + f"-reserve{worker_reserve}-helperbg{helper_background}" + f"-tilelow{tile_background_low}-tilenormal{tile_background_normal}" + f"-ticklog{int(tick_logs)}" + f"-boost{startup_boost}-{repeat}") + trace = OUT / f"{label}.trace.jsonl" + utrace = OUT / f"{label}.utrace" + abslog = OUT / f"{label}.log" + stdout = OUT / f"{label}.stdout.log" + output = HOST_PLUGIN_SAVED / "output" / label + userdir = HOST_SAVED / "user" / label + zendata = HOST_SAVED / "zen" / label + ddc = HOST_SAVED / "DDC" + for directory in (OUT, output, userdir, zendata, ddc): + directory.mkdir(parents=True, exist_ok=True) + trace.unlink(missing_ok=True) + utrace.unlink(missing_ok=True) + spawn_cm = ",".join(f"{value * 100.0:.3f}" for value in SPAWNS_M[stratum]) + command = [ + str(EDITOR), str(HOST / "VFHost.uproject"), "-nullrhi", "-unattended", + "-nop4", "-nosplash", "-NoSound", "-corelimit=12", "-NoZenAutoLaunch", + "-notraceserver", "-nocrashreports", + "-DisablePlugins=AndroidFileServer", + "-ddc=NoZenLocalFallback", f"-userdir={userdir}", f"-ZenDataPath={zendata}", + f"-LocalDataCachePath={ddc}", "-run=VoxelForgeExplore", "-seed=0", + "-archetype=TunnelNetwork", f"-slot={1 if stratum == 'FI' else 0}", + "-modes=export", "-gameconfig=1", "-coreworldtest=1", + "-ownerfourstrateplan=1", "-corevoxelsizecm=25", "-coreislandtest=0", + "-corefallbacktest=0", "-coreofftest=0", "-coreplantest=0", + "-settingsref=/Game/VoxelForge/DA_Settings.DA_Settings", "-corehybridmesher=0", + f"-out={output}", "-voxel.StreamingCoarseFirst=1", + "-voxel.StreamingDynamicNearReserve=1", + "-voxel.StreamingLegacyPendingResultCap=0", + "-voxel.CoreRegionConcurrentAdmission=1", + "-voxel.StreamingResultBacklogCap=256", + f"-voxel.StreamingReadyQueueDepth={ready_depth}", + f"-voxel.StreamingBackgroundWorkerCap={background_cap}", + f"-voxel.StreamingBackgroundWorkerReserve={worker_reserve}", + f"-voxel.CoreParallelForBackgroundPriority={helper_background}", + f"-voxel.StreamingTileBackgroundLow={tile_background_low}", + f"-voxel.StreamingTileBackgroundNormal={tile_background_normal}", + f"-voxel.TestLogTickFunctions={int(tick_logs)}", + "-voxel.CoreColumnCacheDirectMapped=0", "-voxel.CoreMCGradientMemoization=1", + "-voxel.StreamingCollisionLookahead=1", + f"-voxel.StreamingStartupApplyBoost={startup_boost}", + "-voxel.TestMove=1", "-voxel.TestMoveSpeedCmPerSecond=140.0", + f"-voxel.TestMoveStartSeconds={MOVE_START_S:.1f}", + f"-voxel.TestMoveDurationSeconds={MOVE_DURATION_S:.1f}", + f"-voxel.TestExitSeconds={EXIT_S:.1f}", "-voxel.TestMoveDirection=1,0,0", + "-voxel.StreamingSchedulerPolicy=3", "-voxel.TestExitOnSteady=0", + "-coreworldstreamtrace=1", f"-voxel.StartupTraceSpawnCm={spawn_cm}", + "-voxel.StartupTraceUntilEndPlay=1", "-voxel.StartupTraceThroughCrossing=1", + "-voxel.StartupTraceMaxTiles=16384", f"-voxel.StartupTraceFile={trace}", + f"-abslog={abslog}", + ] + if insights: + command += ["-trace=cpu,task,frame", "-statnamedevents", + f"-tracefile={utrace}", "-tracefiletrunc"] + wrapped = ["taskset", "-c", "0-11", "timeout", f"{RUN_TIMEOUT_S}s", *command] + started = time.monotonic() + with stdout.open("w", encoding="utf-8") as stream: + process = subprocess.Popen(wrapped, cwd=ROOT, stdout=stream, + stderr=subprocess.STDOUT) + peak_rss = None + while process.poll() is None: + observed = sample_unreal_peak_rss() + if observed and (peak_rss is None or observed[0] > peak_rss[0]): + peak_rss = observed + time.sleep(0.25) + exit_code = process.wait() + observed = sample_unreal_peak_rss() + if observed and (peak_rss is None or observed[0] > peak_rss[0]): + peak_rss = observed + + events = read_events(trace) + worker_backend_config = next( + (e for e in events if e.get("type") == "worker_backend_config"), {}) + worker_cap_readback = next( + (e for e in events if e.get("type") == "streaming_worker_cap_readback"), {}) + samples = [e for e in events if e.get("type") == "streaming_sample"] + arrival = [e for e in samples if float(e.get("t_s", 0.0)) < MOVE_START_S] + full = next((e for e in arrival + if sum(e.get("desired_by_lod", [0] * 9)[:3]) > 0 + and sum(e.get("settled_by_lod", [0] * 9)[:3]) + >= sum(e.get("desired_by_lod", [0] * 9)[:3])), None) + first_admission = next((e for e in events if e.get("type") == "scheduler_admission" + and e.get("desired_rebuilt") == 1), None) + request_events = [e for e in events if e.get("type") == "request"] + initial_request_events = [e for e in request_events if e.get("epoch") == 0] + tile_by_ordinal = {e.get("request_ordinal"): e for e in events + if e.get("type") == "tile"} + collision_count = sum(1 for e in events if e.get("type") == "collision_ready" + and e.get("level", 9) <= 2 + and full and e.get("t_s", 1e30) <= full["t_s"]) + initial_tiles = [tile_by_ordinal[r.get("request_ordinal")] for r in initial_request_events + if full and r.get("t_s", 1e30) <= full["t_s"] + and r.get("request_ordinal") in tile_by_ordinal + and tile_by_ordinal[r["request_ordinal"]].get("level", 9) <= 2] + burst_start_s = float(first_admission["t_s"]) if first_admission else -1.0 + burst_end_s = float(full["t_s"]) if full else -1.0 + work_by_frame = {int(e.get("frame", -1)): e for e in events + if e.get("type") == "game_thread_work_frame"} + work_values = [e for e in work_by_frame.values() + if burst_start_s <= float(e.get("t_s", -1.0)) <= burst_end_s] + arrival_frame_ids = {int(e.get("frame", -1)) for e in work_values} + scheduler_by_frame = {int(e.get("frame", -1)): e for e in events + if e.get("type") == "scheduler_admission"} + scheduler_values = [e for e in events if e.get("type") == "scheduler_admission" + and burst_start_s <= float(e.get("t_s", -1.0)) <= burst_end_s] + apply_by_frame = {int(e.get("frame", -1)): e for e in events + if e.get("type") == "apply_frame"} + commandlet_tick_by_frame = {int(e.get("frame", -1)): e for e in events + if e.get("type") == "commandlet_world_tick_frame"} + garbage_collect_by_frame = {int(e.get("frame", -1)): e for e in events + if e.get("type") == "garbage_collect"} + # apply_frame N+1 records the interval containing AVoxelWorld::Tick N. Its apply_ms + # belongs to Tick N+1, so use apply_by_frame[N] for the same-tick apply breakdown. + near_intervals = [apply_by_frame[frame + 1] for frame in arrival_frame_ids + if frame + 1 in apply_by_frame] + rmc_by_frame: dict[int, dict[str, float]] = {} + for event in events: + frame = int(event.get("frame", -1)) + if event.get("type") != "rmc_submit" or frame not in arrival_frame_ids: + continue + values = rmc_by_frame.setdefault(frame, { + "component_acquire_ms": 0.0, + "create_section_group_ms": 0.0, + "create_sections_ms": 0.0, + "collision_handoff_ms": 0.0, + }) + for key in values: + values[key] += float(event.get(key, 0.0)) + collision_completion_by_frame: dict[int, float] = {} + for event in events: + frame = int(event.get("frame", -1)) + if event.get("type") == "collision_completion" and frame in arrival_frame_ids: + collision_completion_by_frame[frame] = collision_completion_by_frame.get(frame, 0.0) \ + + float(event.get("handler_ms", 0.0)) + near_requests = [r for r in request_events if full and r.get("t_s", 1e30) <= full["t_s"] + and r.get("level", 9) <= 2] + initial_lod0_counts = Counter( + tuple(r.get("tile", ())) for r in near_requests if r.get("level") == 0) + repeated_lod0_keys = [ + {"tile": list(tile), "requests": count} + for tile, count in sorted(initial_lod0_counts.items()) if count > 1] + initial_scheduler_frames = [e for e in events + if e.get("type") == "scheduler_admission" and full + and e.get("t_s", 1e30) <= full["t_s"]] + worst_interval = max(near_intervals, key=lambda e: float(e.get("frame_ms", 0.0)), default=None) + worst_interval_frame_id = int(worst_interval.get("frame", -1)) if worst_interval else -1 + worst_work_frame_id = worst_interval_frame_id - 1 + worst_work = work_by_frame.get(worst_work_frame_id, {}) + worst_apply = apply_by_frame.get(worst_work_frame_id, {}) + worst_scheduler = scheduler_by_frame.get(worst_work_frame_id, {}) + worst_rmc = rmc_by_frame.get(worst_work_frame_id, {}) + worst_collision_completion_ms = collision_completion_by_frame.get(worst_work_frame_id, 0.0) + rmc_values = [rmc_by_frame.get(frame, {}) for frame in arrival_frame_ids] + apply_values = [apply_by_frame[frame] for frame in arrival_frame_ids + if frame in apply_by_frame] + commandlet_tick_values = [commandlet_tick_by_frame[frame] for frame in arrival_frame_ids + if frame in commandlet_tick_by_frame] + garbage_collect_values = [garbage_collect_by_frame[frame] for frame in arrival_frame_ids + if frame in garbage_collect_by_frame] + + def work_stat(name: str, fraction: float | None = None) -> float | None: + values = [float(e.get(name, 0.0)) for e in work_values] + return percentile(values, fraction) if fraction is not None else max(values, default=0.0) + + def scheduler_stat(name: str, fraction: float | None = None) -> float | None: + values = [float(e.get(name, 0.0)) for e in scheduler_values] + return percentile(values, fraction) if fraction is not None else max(values, default=0.0) + + def rmc_stat(name: str, fraction: float | None = None) -> float | None: + values = [float(e.get(name, 0.0)) for e in rmc_values] + return percentile(values, fraction) if fraction is not None else max(values, default=0.0) + + def commandlet_stat(name: str, fraction: float | None = None) -> float | None: + values = [float(e.get(name, 0.0)) for e in commandlet_tick_values] + return percentile(values, fraction) if fraction is not None else max(values, default=0.0) + + row = { + "label": label, "stratum": stratum, "repeat": repeat, "phase": phase, + "ready_queue_depth": ready_depth, + "requested_background_worker_cap": background_cap, + "background_worker_cap": worker_cap_readback.get( + "streaming_background_worker_cap", background_cap), + "requested_background_worker_reserve": worker_reserve, + "background_worker_reserve": worker_backend_config.get( + "streaming_background_worker_reserve", worker_cap_readback.get( + "background_worker_reserve", worker_reserve)), + "requested_core_parallel_for_background_priority": helper_background, + "core_parallel_for_background_priority": worker_backend_config.get( + "core_parallel_for_background_priority", helper_background), + "requested_streaming_tile_background_low": tile_background_low, + "streaming_tile_background_low": worker_backend_config.get( + "streaming_tile_background_low", tile_background_low), + "requested_streaming_tile_background_normal": tile_background_normal, + "streaming_tile_background_normal": worker_backend_config.get( + "streaming_tile_background_normal", tile_background_normal), + "effective_tile_slots": worker_backend_config.get("effective_tile_slots"), + "background_worker_threads": worker_backend_config.get("taskgraph_background_threads"), + "startup_apply_boost": startup_boost, "insights": insights, + "engine_tick_logs": tick_logs, + "exit_code": exit_code, + "launch_wrapper": "taskset -c 0-11 timeout 1740s (no address-space limit)", + "peak_rss_kib": peak_rss[0] if peak_rss else None, + "peak_rss_mib": round(peak_rss[0] / 1024.0, 1) if peak_rss else None, + "peak_rss_pid": peak_rss[1] if peak_rss else None, + "endphysics_to_postphysics_gap_ms_max": None, + "endphysics_gap_frame": None, + "wall_s": round(time.monotonic() - started, 3), + "desired_t_s": next((e.get("t_s") for e in events if e.get("type") == "desired_set"), None), + "first_admission_t_s": first_admission.get("t_s") if first_admission else None, + "lod02_full_settled_t_s": full.get("t_s") if full else None, + "near_settle_from_first_admission_s": round( + float(full["t_s"]) - float(first_admission["t_s"]), 4) + if full and first_admission else None, + "desired_by_lod": full.get("desired_by_lod", [])[:3] if full else None, + "settled_by_lod": full.get("settled_by_lod", [])[:3] if full else None, + "near_admitted_tiles": len(near_requests), + "initial_lod0_admissions": sum(initial_lod0_counts.values()), + "repeated_lod0_request_keys_before_settle": repeated_lod0_keys, + "peak_result_backlog_before_settle": max( + (int(e.get("result_backlog", 0)) for e in initial_scheduler_frames), default=0), + "last_admission_t_s": max((e.get("t_s", 0.0) for e in near_requests), default=None), + "near_tile_events": len(initial_tiles), + "near_worker_seconds": round(sum(e.get("worker_task_s", 0.0) for e in initial_tiles), 4), + "near_core_seconds": round(sum(e.get("core_generate_s", 0.0) for e in initial_tiles), 4), + "collision_ready_by_settle": collision_count, + "burst_frame_count": len(near_intervals), + "burst_frame_ms_p95": round(sorted(e.get("frame_ms", 0.0) for e in near_intervals)[ + min(len(near_intervals) - 1, int(.95 * (len(near_intervals) - 1)))], 3) + if near_intervals else None, + "burst_frame_ms_max": round(max((e.get("frame_ms", 0.0) for e in near_intervals), default=0.0), 3), + "burst_full_world_tick_ms_p99": round(commandlet_stat("world_tick_ms", .99) or 0.0, 3), + "burst_full_world_tick_ms_max": round(commandlet_stat("world_tick_ms") or 0.0, 3), + "burst_world_pre_actor_ms_p99": round(commandlet_stat("world_pre_actor_ms", .99) or 0.0, 3), + "burst_world_pre_actor_ms_max": round(commandlet_stat("world_pre_actor_ms") or 0.0, 3), + "burst_world_actor_phase_ms_p99": round(commandlet_stat("world_actor_phase_ms", .99) or 0.0, 3), + "burst_world_actor_phase_ms_max": round(commandlet_stat("world_actor_phase_ms") or 0.0, 3), + "burst_world_post_actor_ms_p99": round(commandlet_stat("world_post_actor_ms", .99) or 0.0, 3), + "burst_world_post_actor_ms_max": round(commandlet_stat("world_post_actor_ms") or 0.0, 3), + "burst_commandlet_readiness_check_ms_max": round( + commandlet_stat("readiness_check_ms") or 0.0, 3), + "burst_commandlet_sleep_ms_p99": round(commandlet_stat("sleep_ms", .99) or 0.0, 3), + "burst_commandlet_sleep_ms_max": round(commandlet_stat("sleep_ms") or 0.0, 3), + "burst_commandlet_loop_ms_max": round(commandlet_stat("loop_ms") or 0.0, 3), + "burst_gc_count": len(garbage_collect_values), + "burst_gc_duration_ms_max": round(max( + (float(e.get("duration_ms", 0.0)) for e in garbage_collect_values), default=0.0), 3), + "burst_max_meshes_per_frame": max((e.get("meshes_applied", 0) for e in apply_values), default=0), + "burst_max_apply_ms": round(max((e.get("apply_ms", 0.0) for e in apply_values), default=0.0), 3), + "burst_max_admit_per_frame": max((sum(e.get("submitted_by_lod", [0] * 9)[:3]) + for e in scheduler_values), default=0), + "burst_frame_timing_count": len(work_values), + "burst_active_generation_workers_p95": round(work_stat("active_generation_workers", .95) or 0.0, 3), + "burst_active_generation_workers_max": round(work_stat("active_generation_workers") or 0.0, 3), + "burst_active_tile_tasks_max": round(work_stat("active_tile_tasks") or 0.0, 3), + "burst_world_tick_ms_p99": round(work_stat("tick_ms", .99) or 0.0, 3), + "burst_world_tick_ms_max": round(work_stat("tick_ms") or 0.0, 3), + "burst_update_chunks_ms_p99": round(work_stat("update_chunks_ms", .99) or 0.0, 3), + "burst_update_chunks_ms_max": round(work_stat("update_chunks_ms") or 0.0, 3), + "burst_pending_drain_ms_p99": round(work_stat("pending_drain_ms", .99) or 0.0, 3), + "burst_pending_drain_ms_max": round(work_stat("pending_drain_ms") or 0.0, 3), + "burst_post_apply_callbacks_ms_p99": round(work_stat("post_apply_callbacks_ms", .99) or 0.0, 3), + "burst_post_apply_callbacks_ms_max": round(work_stat("post_apply_callbacks_ms") or 0.0, 3), + "burst_visibility_reconcile_ms_p99": round(work_stat("visibility_reconcile_ms", .99) or 0.0, 3), + "burst_visibility_reconcile_ms_max": round(work_stat("visibility_reconcile_ms") or 0.0, 3), + "burst_collision_probe_ms_max": round(work_stat("collision_probe_ms") or 0.0, 3), + "burst_visible_apply_probe_ms_max": round(work_stat("visible_apply_probe_ms") or 0.0, 3), + "burst_lod0_ready_ms_max": round(work_stat("lod0_ready_ms") or 0.0, 3), + "burst_steady_trace_ms_max": round(work_stat("steady_trace_ms") or 0.0, 3), + "burst_modification_ms_max": round(work_stat("modification_ms") or 0.0, 3), + "burst_lifecycle_audit_ms_p99": round(work_stat("lifecycle_audit_ms", .99) or 0.0, 3), + "burst_lifecycle_audit_ms_max": round(work_stat("lifecycle_audit_ms") or 0.0, 3), + "burst_collision_gate_ms_p99": round(work_stat("collision_gate_ms", .99) or 0.0, 3), + "burst_collision_gate_ms_max": round(work_stat("collision_gate_ms") or 0.0, 3), + "burst_unload_ms_p99": round(work_stat("unload_ms", .99) or 0.0, 3), + "burst_unload_ms_max": round(work_stat("unload_ms") or 0.0, 3), + "burst_trace_json_ms_p99": round(work_stat("trace_json_ms", .99) or 0.0, 3), + "burst_trace_json_ms_max": round(work_stat("trace_json_ms") or 0.0, 3), + "burst_desired_rebuild_ms_max": round(scheduler_stat("desired_rebuild_ms") or 0.0, 3), + "burst_rmc_create_group_ms_p99": round(rmc_stat("create_section_group_ms", .99) or 0.0, 3), + "burst_rmc_create_group_ms_max": round(rmc_stat("create_section_group_ms") or 0.0, 3), + "burst_rmc_collision_handoff_ms_max": round(rmc_stat("collision_handoff_ms") or 0.0, 3), + "burst_collision_completion_ms_max": round(max( + collision_completion_by_frame.values(), default=0.0), 3), + "worst_frame_breakdown": { + "frame": worst_work_frame_id, + "world_tick_frame": worst_work_frame_id, + "frame_interval_end_frame": worst_interval_frame_id, + "frame_interval_ms": round(float(worst_interval.get("frame_ms", 0.0)), 3) + if worst_interval else None, + "apply_ms": round(float(worst_apply.get("apply_ms", 0.0)), 3) + if worst_apply else None, + "result_drain_ms": round(float(worst_apply.get("drain_ms", 0.0)), 3) + if worst_apply else None, + "outside_world_tick_ms": round(max(0.0, float(worst_interval.get("frame_ms", 0.0)) + - float(worst_work.get("tick_ms", 0.0))), 3) + if worst_interval else None, + "outside_full_world_tick_ms": round(max(0.0, float(worst_interval.get("frame_ms", 0.0)) + - float(commandlet_tick_by_frame.get(worst_work_frame_id, {}).get("world_tick_ms", 0.0))), 3) + if worst_interval else None, + "full_world_tick_ms": round(float(commandlet_tick_by_frame.get( + worst_work_frame_id, {}).get("world_tick_ms", 0.0)), 3), + "world_pre_actor_ms": round(float(commandlet_tick_by_frame.get( + worst_work_frame_id, {}).get("world_pre_actor_ms", 0.0)), 3), + "world_actor_phase_ms": round(float(commandlet_tick_by_frame.get( + worst_work_frame_id, {}).get("world_actor_phase_ms", 0.0)), 3), + "world_post_actor_ms": round(float(commandlet_tick_by_frame.get( + worst_work_frame_id, {}).get("world_post_actor_ms", 0.0)), 3), + "commandlet_readiness_check_ms": round(float(commandlet_tick_by_frame.get( + worst_work_frame_id, {}).get("readiness_check_ms", 0.0)), 3), + "commandlet_sleep_ms": round(float(commandlet_tick_by_frame.get( + worst_work_frame_id, {}).get("sleep_ms", 0.0)), 3), + "commandlet_loop_ms": round(float(commandlet_tick_by_frame.get( + worst_work_frame_id, {}).get("loop_ms", 0.0)), 3), + "gc_duration_ms": round(float(garbage_collect_by_frame.get( + worst_work_frame_id, {}).get("duration_ms", 0.0)), 3), + "world_tick_ms": round(float(worst_work.get("tick_ms", 0.0)), 3), + "active_generation_workers": int(worst_work.get("active_generation_workers", 0)), + "active_tile_tasks": int(worst_work.get("active_tile_tasks", 0)), + "collision_gate_ms": round(float(worst_work.get("collision_gate_ms", 0.0)), 3), + "update_chunks_ms": round(float(worst_work.get("update_chunks_ms", 0.0)), 3), + "desired_rebuild_ms": round(float(worst_scheduler.get("desired_rebuild_ms", 0.0)), 3), + "pending_drain_ms": round(float(worst_work.get("pending_drain_ms", 0.0)), 3), + "post_apply_callbacks_ms": round(float(worst_work.get("post_apply_callbacks_ms", 0.0)), 3), + "collision_probe_ms": round(float(worst_work.get("collision_probe_ms", 0.0)), 3), + "visibility_reconcile_ms": round(float(worst_work.get("visibility_reconcile_ms", 0.0)), 3), + "visible_apply_probe_ms": round(float(worst_work.get("visible_apply_probe_ms", 0.0)), 3), + "lod0_ready_ms": round(float(worst_work.get("lod0_ready_ms", 0.0)), 3), + "unload_ms": round(float(worst_work.get("unload_ms", 0.0)), 3), + "steady_trace_ms": round(float(worst_work.get("steady_trace_ms", 0.0)), 3), + "modification_ms": round(float(worst_work.get("modification_ms", 0.0)), 3), + "lifecycle_audit_ms": round(float(worst_work.get("lifecycle_audit_ms", 0.0)), 3), + "trace_json_ms": round(float(worst_work.get("trace_json_ms", 0.0)), 3), + "trace_archive_serialize_ms": round(float( + worst_work.get("trace_archive_serialize_ms", 0.0)), 3), + "collision_completion_ms": round(worst_collision_completion_ms, 3), + **{key: round(float(worst_rmc.get(key, 0.0)), 3) + for key in ("component_acquire_ms", "create_section_group_ms", + "create_sections_ms", "collision_handoff_ms")}, + }, + "trace": str(trace.relative_to(ROOT)), "utrace": str(utrace.relative_to(ROOT)), + "abslog": str(abslog.relative_to(ROOT)), "stdout": str(stdout.relative_to(ROOT)), + } + stdout_text = stdout.read_text(encoding="utf-8", errors="replace") + gap_ms, gap_frame = endphysics_gap(stdout) + row["endphysics_to_postphysics_gap_ms_max"] = gap_ms + row["endphysics_gap_frame"] = gap_frame + failure = re.search(r"\[VoxelForgeCoreWorldTest\] failed: ([^\r\n]+)", stdout_text) + if failure: + row["world_test_failure"] = failure.group(1) + with (OUT / "runs.jsonl").open("a", encoding="utf-8") as stream: + stream.write(json.dumps(row, sort_keys=True) + "\n") + (OUT / f"{label}.summary.json").write_text(json.dumps(row, indent=2) + "\n", + encoding="utf-8") + print("[L109UnrealArrival] " + json.dumps(row, sort_keys=True), flush=True) + if exit_code: + raise SystemExit(f"Unreal commandlet failed: {stdout}; exit={exit_code}") + if not full or len(arrival) < 8: + raise SystemExit(f"Unreal arrival trace incomplete: {stdout}; exit={exit_code}") + if insights and (not utrace.is_file() or utrace.stat().st_size < 1024): + raise SystemExit(f"Unreal Insights trace missing or empty: {utrace}") + return row + + +def main() -> int: + parser = argparse.ArgumentParser() + parser.add_argument("--stratum", choices=("FI", "SW"), required=True) + parser.add_argument("--repeat", type=int, default=1) + parser.add_argument("--phase", choices=("probe", "before", "after", "snapshot"), default="probe") + parser.add_argument("--ready-depth", type=int, default=64) + parser.add_argument("--background-cap", type=int, choices=(0, 1), default=1) + parser.add_argument("--worker-reserve", type=int, choices=(0, 1, 2, 3), default=0) + parser.add_argument("--helper-background", type=int, choices=(0, 1), default=1) + parser.add_argument("--tile-background-low", type=int, choices=(0, 1), default=1) + parser.add_argument("--tile-background-normal", type=int, choices=(0, 1), default=0) + parser.add_argument("--startup-boost", type=int, choices=(0, 1), default=1) + parser.add_argument("--tick-logs", action="store_true") + parser.add_argument("--insights", action="store_true") + args = parser.parse_args() + if not EDITOR.is_file(): + raise SystemExit(f"missing Unreal commandlet executable: {EDITOR}") + run(args.stratum, args.repeat, args.phase, args.ready_depth, + args.background_cap, args.worker_reserve, args.helper_background, + args.tile_background_low, args.tile_background_normal, args.startup_boost, + args.tick_logs, args.insights) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/INDEX.md b/Standalone/Research/WorldAssemblerM3/Linux109/captures/INDEX.md new file mode 100644 index 0000000..9a4d07d --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux109/captures/INDEX.md @@ -0,0 +1,93 @@ +# L109 passage captures + +Each PNG was rendered from its own exported mesh. The renderer reported visible triangles, and each decoded image met the pixel coverage floor. `low_contrast_geometry_visible` marks images that met this floor below the preferred contrast target. + +## Before + +- [upper-mouth](before/passage-0-1-0-upper-mouth.png) — passage/0-1/0; 188440 visible triangles +- [lower-mouth](before/passage-0-1-0-lower-mouth.png) — passage/0-1/0; 564520 visible triangles +- [25%](before/passage-0-1-0-station-25.png) — passage/0-1/0; 234197 visible triangles +- [50%](before/passage-0-1-0-station-50.png) — passage/0-1/0; 315900 visible triangles +- [75%](before/passage-0-1-0-station-75.png) — passage/0-1/0; 256359 visible triangles +- [section-1/view-1](before/passage-0-1-0-openair-1-view-1.png) — passage/0-1/0 **OPEN AIR**; 211462 visible triangles +- [section-1/view-2](before/passage-0-1-0-openair-1-view-2.png) — passage/0-1/0 **OPEN AIR**; 208255 visible triangles +- [section-1/view-3](before/passage-0-1-0-openair-1-view-3.png) — passage/0-1/0 **OPEN AIR**; 221239 visible triangles +- [section-2/view-1](before/passage-0-1-0-openair-2-view-1.png) — passage/0-1/0 **OPEN AIR**; 218664 visible triangles +- [section-2/view-2](before/passage-0-1-0-openair-2-view-2.png) — passage/0-1/0 **OPEN AIR**; 223817 visible triangles +- [section-2/view-3](before/passage-0-1-0-openair-2-view-3.png) — passage/0-1/0 **OPEN AIR**; 221239 visible triangles +- [section-3/view-1](before/passage-0-1-0-openair-3-view-1.png) — passage/0-1/0 **OPEN AIR**; 224005 visible triangles +- [section-3/view-2](before/passage-0-1-0-openair-3-view-2.png) — passage/0-1/0 **OPEN AIR**; 230599 visible triangles; low_contrast_geometry_visible +- [section-3/view-3](before/passage-0-1-0-openair-3-view-3.png) — passage/0-1/0 **OPEN AIR**; 229291 visible triangles +- [section-4/view-1](before/passage-0-1-0-openair-4-view-1.png) — passage/0-1/0 **OPEN AIR**; 407353 visible triangles +- [section-4/view-2](before/passage-0-1-0-openair-4-view-2.png) — passage/0-1/0 **OPEN AIR**; 406732 visible triangles +- [section-4/view-3](before/passage-0-1-0-openair-4-view-3.png) — passage/0-1/0 **OPEN AIR**; 363878 visible triangles +- [upper-mouth](before/passage-1-2-0-upper-mouth.png) — passage/1-2/0; 576595 visible triangles +- [lower-mouth](before/passage-1-2-0-lower-mouth.png) — passage/1-2/0; 555286 visible triangles +- [25%](before/passage-1-2-0-station-25.png) — passage/1-2/0; 667602 visible triangles +- [50%](before/passage-1-2-0-station-50.png) — passage/1-2/0; 602756 visible triangles +- [75%](before/passage-1-2-0-station-75.png) — passage/1-2/0; 620502 visible triangles +- [section-1/view-1](before/passage-1-2-0-openair-1-view-1.png) — passage/1-2/0 **OPEN AIR**; 636438 visible triangles +- [section-1/view-2](before/passage-1-2-0-openair-1-view-2.png) — passage/1-2/0 **OPEN AIR**; 593960 visible triangles +- [section-1/view-3](before/passage-1-2-0-openair-1-view-3.png) — passage/1-2/0 **OPEN AIR**; 622040 visible triangles +- [upper-mouth](before/passage-2-3-0-upper-mouth.png) — passage/2-3/0; 59568 visible triangles +- [lower-mouth](before/passage-2-3-0-lower-mouth.png) — passage/2-3/0; 294430 visible triangles; low_contrast_geometry_visible +- [25%](before/passage-2-3-0-station-25.png) — passage/2-3/0; 55420 visible triangles; low_contrast_geometry_visible +- [50%](before/passage-2-3-0-station-50.png) — passage/2-3/0; 458134 visible triangles +- [75%](before/passage-2-3-0-station-75.png) — passage/2-3/0; 475978 visible triangles +- [section-1/view-1](before/passage-2-3-0-openair-1-view-1.png) — passage/2-3/0 **OPEN AIR**; 104612 visible triangles +- [section-1/view-2](before/passage-2-3-0-openair-1-view-2.png) — passage/2-3/0 **OPEN AIR**; 81078 visible triangles +- [section-1/view-3](before/passage-2-3-0-openair-1-view-3.png) — passage/2-3/0 **OPEN AIR**; 94962 visible triangles; low_contrast_geometry_visible +- [section-2/view-1](before/passage-2-3-0-openair-2-view-1.png) — passage/2-3/0 **OPEN AIR**; 476052 visible triangles +- [section-2/view-2](before/passage-2-3-0-openair-2-view-2.png) — passage/2-3/0 **OPEN AIR**; 479198 visible triangles +- [section-2/view-3](before/passage-2-3-0-openair-2-view-3.png) — passage/2-3/0 **OPEN AIR**; 479198 visible triangles +- [section-3/view-1](before/passage-2-3-0-openair-3-view-1.png) — passage/2-3/0 **OPEN AIR**; 485580 visible triangles +- [section-3/view-2](before/passage-2-3-0-openair-3-view-2.png) — passage/2-3/0 **OPEN AIR**; 478866 visible triangles +- [section-3/view-3](before/passage-2-3-0-openair-3-view-3.png) — passage/2-3/0 **OPEN AIR**; 490304 visible triangles; low_contrast_geometry_visible +- [section-4/view-1](before/passage-2-3-0-openair-4-view-1.png) — passage/2-3/0 **OPEN AIR**; 475662 visible triangles +- [section-4/view-2](before/passage-2-3-0-openair-4-view-2.png) — passage/2-3/0 **OPEN AIR**; 496128 visible triangles +- [section-4/view-3](before/passage-2-3-0-openair-4-view-3.png) — passage/2-3/0 **OPEN AIR**; 496508 visible triangles; low_contrast_geometry_visible + +## After + +- [upper-mouth](after/passage-0-1-0-upper-mouth.png) — passage/0-1/0; 253282 visible triangles +- [lower-mouth](after/passage-0-1-0-lower-mouth.png) — passage/0-1/0; 559326 visible triangles +- [25%](after/passage-0-1-0-station-25.png) — passage/0-1/0; 145630 visible triangles +- [50%](after/passage-0-1-0-station-50.png) — passage/0-1/0; 430386 visible triangles +- [75%](after/passage-0-1-0-station-75.png) — passage/0-1/0; 294374 visible triangles +- [section-1/view-1](after/passage-0-1-0-openair-1-view-1.png) — passage/0-1/0 **OPEN AIR**; 289074 visible triangles +- [section-1/view-2](after/passage-0-1-0-openair-1-view-2.png) — passage/0-1/0 **OPEN AIR**; 298057 visible triangles +- [section-1/view-3](after/passage-0-1-0-openair-1-view-3.png) — passage/0-1/0 **OPEN AIR**; 322309 visible triangles +- [section-2/view-1](after/passage-0-1-0-openair-2-view-1.png) — passage/0-1/0 **OPEN AIR**; 283642 visible triangles +- [section-2/view-2](after/passage-0-1-0-openair-2-view-2.png) — passage/0-1/0 **OPEN AIR**; 316771 visible triangles +- [section-2/view-3](after/passage-0-1-0-openair-2-view-3.png) — passage/0-1/0 **OPEN AIR**; 322309 visible triangles +- [section-3/view-1](after/passage-0-1-0-openair-3-view-1.png) — passage/0-1/0 **OPEN AIR**; 262299 visible triangles +- [section-3/view-2](after/passage-0-1-0-openair-3-view-2.png) — passage/0-1/0 **OPEN AIR**; 310919 visible triangles; low_contrast_geometry_visible +- [section-3/view-3](after/passage-0-1-0-openair-3-view-3.png) — passage/0-1/0 **OPEN AIR**; 363071 visible triangles +- [section-4/view-1](after/passage-0-1-0-openair-4-view-1.png) — passage/0-1/0 **OPEN AIR**; 378007 visible triangles +- [section-4/view-2](after/passage-0-1-0-openair-4-view-2.png) — passage/0-1/0 **OPEN AIR**; 471132 visible triangles +- [section-4/view-3](after/passage-0-1-0-openair-4-view-3.png) — passage/0-1/0 **OPEN AIR**; 382187 visible triangles +- [upper-mouth](after/passage-1-2-0-upper-mouth.png) — passage/1-2/0; 570417 visible triangles; low_contrast_geometry_visible +- [lower-mouth](after/passage-1-2-0-lower-mouth.png) — passage/1-2/0; 511318 visible triangles +- [25%](after/passage-1-2-0-station-25.png) — passage/1-2/0; 661032 visible triangles +- [50%](after/passage-1-2-0-station-50.png) — passage/1-2/0; 602996 visible triangles +- [75%](after/passage-1-2-0-station-75.png) — passage/1-2/0; 615520 visible triangles +- [section-1/view-1](after/passage-1-2-0-openair-1-view-1.png) — passage/1-2/0 **OPEN AIR**; 629052 visible triangles +- [section-1/view-2](after/passage-1-2-0-openair-1-view-2.png) — passage/1-2/0 **OPEN AIR**; 588414 visible triangles +- [section-1/view-3](after/passage-1-2-0-openair-1-view-3.png) — passage/1-2/0 **OPEN AIR**; 616234 visible triangles +- [upper-mouth](after/passage-2-3-0-upper-mouth.png) — passage/2-3/0; 59562 visible triangles +- [lower-mouth](after/passage-2-3-0-lower-mouth.png) — passage/2-3/0; 294522 visible triangles; low_contrast_geometry_visible +- [25%](after/passage-2-3-0-station-25.png) — passage/2-3/0; 55484 visible triangles; low_contrast_geometry_visible +- [50%](after/passage-2-3-0-station-50.png) — passage/2-3/0; 457754 visible triangles +- [75%](after/passage-2-3-0-station-75.png) — passage/2-3/0; 475706 visible triangles +- [section-1/view-1](after/passage-2-3-0-openair-1-view-1.png) — passage/2-3/0 **OPEN AIR**; 104612 visible triangles +- [section-1/view-2](after/passage-2-3-0-openair-1-view-2.png) — passage/2-3/0 **OPEN AIR**; 81078 visible triangles +- [section-1/view-3](after/passage-2-3-0-openair-1-view-3.png) — passage/2-3/0 **OPEN AIR**; 94962 visible triangles; low_contrast_geometry_visible +- [section-2/view-1](after/passage-2-3-0-openair-2-view-1.png) — passage/2-3/0 **OPEN AIR**; 475688 visible triangles +- [section-2/view-2](after/passage-2-3-0-openair-2-view-2.png) — passage/2-3/0 **OPEN AIR**; 479134 visible triangles +- [section-2/view-3](after/passage-2-3-0-openair-2-view-3.png) — passage/2-3/0 **OPEN AIR**; 479134 visible triangles +- [section-3/view-1](after/passage-2-3-0-openair-3-view-1.png) — passage/2-3/0 **OPEN AIR**; 485216 visible triangles +- [section-3/view-2](after/passage-2-3-0-openair-3-view-2.png) — passage/2-3/0 **OPEN AIR**; 479198 visible triangles +- [section-3/view-3](after/passage-2-3-0-openair-3-view-3.png) — passage/2-3/0 **OPEN AIR**; 490436 visible triangles; low_contrast_geometry_visible +- [section-4/view-1](after/passage-2-3-0-openair-4-view-1.png) — passage/2-3/0 **OPEN AIR**; 475298 visible triangles +- [section-4/view-2](after/passage-2-3-0-openair-4-view-2.png) — passage/2-3/0 **OPEN AIR**; 495856 visible triangles +- [section-4/view-3](after/passage-2-3-0-openair-4-view-3.png) — passage/2-3/0 **OPEN AIR**; 496236 visible triangles; low_contrast_geometry_visible diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-lower-mouth.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-lower-mouth.png new file mode 100644 index 0000000..e92cfe1 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-lower-mouth.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-openair-1-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-openair-1-view-1.png new file mode 100644 index 0000000..38ff704 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-openair-1-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-openair-1-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-openair-1-view-2.png new file mode 100644 index 0000000..bcc62fb Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-openair-1-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-openair-1-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-openair-1-view-3.png new file mode 100644 index 0000000..0b85bb1 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-openair-1-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-openair-2-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-openair-2-view-1.png new file mode 100644 index 0000000..868c4f4 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-openair-2-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-openair-2-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-openair-2-view-2.png new file mode 100644 index 0000000..1111c70 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-openair-2-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-openair-2-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-openair-2-view-3.png new file mode 100644 index 0000000..42b43fc Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-openair-2-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-openair-3-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-openair-3-view-1.png new file mode 100644 index 0000000..f498353 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-openair-3-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-openair-3-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-openair-3-view-2.png new file mode 100644 index 0000000..a077c37 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-openair-3-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-openair-3-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-openair-3-view-3.png new file mode 100644 index 0000000..bef0390 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-openair-3-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-openair-4-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-openair-4-view-1.png new file mode 100644 index 0000000..43049af Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-openair-4-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-openair-4-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-openair-4-view-2.png new file mode 100644 index 0000000..934a77f Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-openair-4-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-openair-4-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-openair-4-view-3.png new file mode 100644 index 0000000..31322cf Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-openair-4-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-station-25.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-station-25.png new file mode 100644 index 0000000..697ccbd Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-station-25.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-station-50.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-station-50.png new file mode 100644 index 0000000..1a96e59 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-station-50.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-station-75.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-station-75.png new file mode 100644 index 0000000..0a47b71 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-station-75.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-upper-mouth.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-upper-mouth.png new file mode 100644 index 0000000..92eebd9 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-0-1-0-upper-mouth.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-1-2-0-lower-mouth.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-1-2-0-lower-mouth.png new file mode 100644 index 0000000..b42b0db Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-1-2-0-lower-mouth.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-1-2-0-openair-1-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-1-2-0-openair-1-view-1.png new file mode 100644 index 0000000..f81c7cf Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-1-2-0-openair-1-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-1-2-0-openair-1-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-1-2-0-openair-1-view-2.png new file mode 100644 index 0000000..8c0052e Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-1-2-0-openair-1-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-1-2-0-openair-1-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-1-2-0-openair-1-view-3.png new file mode 100644 index 0000000..bd130d0 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-1-2-0-openair-1-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-1-2-0-station-25.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-1-2-0-station-25.png new file mode 100644 index 0000000..745cd66 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-1-2-0-station-25.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-1-2-0-station-50.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-1-2-0-station-50.png new file mode 100644 index 0000000..d32a16b Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-1-2-0-station-50.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-1-2-0-station-75.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-1-2-0-station-75.png new file mode 100644 index 0000000..bb01e66 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-1-2-0-station-75.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-1-2-0-upper-mouth.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-1-2-0-upper-mouth.png new file mode 100644 index 0000000..0b0430c Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-1-2-0-upper-mouth.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-lower-mouth.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-lower-mouth.png new file mode 100644 index 0000000..6a11c52 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-lower-mouth.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-openair-1-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-openair-1-view-1.png new file mode 100644 index 0000000..e958856 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-openair-1-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-openair-1-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-openair-1-view-2.png new file mode 100644 index 0000000..e201769 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-openair-1-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-openair-1-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-openair-1-view-3.png new file mode 100644 index 0000000..006b05a Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-openair-1-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-openair-2-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-openair-2-view-1.png new file mode 100644 index 0000000..5a069a4 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-openair-2-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-openair-2-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-openair-2-view-2.png new file mode 100644 index 0000000..054aba4 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-openair-2-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-openair-2-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-openair-2-view-3.png new file mode 100644 index 0000000..0fc9685 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-openair-2-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-openair-3-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-openair-3-view-1.png new file mode 100644 index 0000000..ba11b0c Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-openair-3-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-openair-3-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-openair-3-view-2.png new file mode 100644 index 0000000..fe7f56c Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-openair-3-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-openair-3-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-openair-3-view-3.png new file mode 100644 index 0000000..0f4416a Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-openair-3-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-openair-4-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-openair-4-view-1.png new file mode 100644 index 0000000..0f6a894 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-openair-4-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-openair-4-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-openair-4-view-2.png new file mode 100644 index 0000000..4288fe7 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-openair-4-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-openair-4-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-openair-4-view-3.png new file mode 100644 index 0000000..2e69508 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-openair-4-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-station-25.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-station-25.png new file mode 100644 index 0000000..794aeb3 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-station-25.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-station-50.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-station-50.png new file mode 100644 index 0000000..333947a Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-station-50.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-station-75.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-station-75.png new file mode 100644 index 0000000..4d97c05 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-station-75.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-upper-mouth.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-upper-mouth.png new file mode 100644 index 0000000..5f8dc22 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/after/passage-2-3-0-upper-mouth.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-lower-mouth.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-lower-mouth.png new file mode 100644 index 0000000..e4f8b26 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-lower-mouth.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-openair-1-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-openair-1-view-1.png new file mode 100644 index 0000000..d96125e Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-openair-1-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-openair-1-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-openair-1-view-2.png new file mode 100644 index 0000000..637a5ef Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-openair-1-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-openair-1-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-openair-1-view-3.png new file mode 100644 index 0000000..6c0a0e1 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-openair-1-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-openair-2-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-openair-2-view-1.png new file mode 100644 index 0000000..3d5543c Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-openair-2-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-openair-2-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-openair-2-view-2.png new file mode 100644 index 0000000..876e107 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-openair-2-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-openair-2-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-openair-2-view-3.png new file mode 100644 index 0000000..689ae56 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-openair-2-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-openair-3-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-openair-3-view-1.png new file mode 100644 index 0000000..b26c2ee Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-openair-3-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-openair-3-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-openair-3-view-2.png new file mode 100644 index 0000000..b0ccaee Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-openair-3-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-openair-3-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-openair-3-view-3.png new file mode 100644 index 0000000..eba3cd7 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-openair-3-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-openair-4-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-openair-4-view-1.png new file mode 100644 index 0000000..2a364ac Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-openair-4-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-openair-4-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-openair-4-view-2.png new file mode 100644 index 0000000..638c5ac Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-openair-4-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-openair-4-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-openair-4-view-3.png new file mode 100644 index 0000000..bf36668 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-openair-4-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-station-25.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-station-25.png new file mode 100644 index 0000000..d3f30cb Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-station-25.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-station-50.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-station-50.png new file mode 100644 index 0000000..3b804dd Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-station-50.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-station-75.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-station-75.png new file mode 100644 index 0000000..75fc4ec Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-station-75.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-upper-mouth.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-upper-mouth.png new file mode 100644 index 0000000..a6fb209 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-0-1-0-upper-mouth.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-1-2-0-lower-mouth.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-1-2-0-lower-mouth.png new file mode 100644 index 0000000..2cbf1e7 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-1-2-0-lower-mouth.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-1-2-0-openair-1-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-1-2-0-openair-1-view-1.png new file mode 100644 index 0000000..5e367f9 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-1-2-0-openair-1-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-1-2-0-openair-1-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-1-2-0-openair-1-view-2.png new file mode 100644 index 0000000..6aecd5a Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-1-2-0-openair-1-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-1-2-0-openair-1-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-1-2-0-openair-1-view-3.png new file mode 100644 index 0000000..69dc031 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-1-2-0-openair-1-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-1-2-0-station-25.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-1-2-0-station-25.png new file mode 100644 index 0000000..adeb4d8 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-1-2-0-station-25.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-1-2-0-station-50.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-1-2-0-station-50.png new file mode 100644 index 0000000..31ab127 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-1-2-0-station-50.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-1-2-0-station-75.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-1-2-0-station-75.png new file mode 100644 index 0000000..0e76e0a Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-1-2-0-station-75.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-1-2-0-upper-mouth.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-1-2-0-upper-mouth.png new file mode 100644 index 0000000..2013c80 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-1-2-0-upper-mouth.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-lower-mouth.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-lower-mouth.png new file mode 100644 index 0000000..852c605 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-lower-mouth.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-openair-1-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-openair-1-view-1.png new file mode 100644 index 0000000..5669c9d Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-openair-1-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-openair-1-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-openair-1-view-2.png new file mode 100644 index 0000000..9cacf9c Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-openair-1-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-openair-1-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-openair-1-view-3.png new file mode 100644 index 0000000..5babbad Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-openair-1-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-openair-2-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-openair-2-view-1.png new file mode 100644 index 0000000..783327b Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-openair-2-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-openair-2-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-openair-2-view-2.png new file mode 100644 index 0000000..945558b Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-openair-2-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-openair-2-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-openair-2-view-3.png new file mode 100644 index 0000000..682f0f9 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-openair-2-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-openair-3-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-openair-3-view-1.png new file mode 100644 index 0000000..59204a5 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-openair-3-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-openair-3-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-openair-3-view-2.png new file mode 100644 index 0000000..07bca9b Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-openair-3-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-openair-3-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-openair-3-view-3.png new file mode 100644 index 0000000..5b5193c Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-openair-3-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-openair-4-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-openair-4-view-1.png new file mode 100644 index 0000000..9c09023 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-openair-4-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-openair-4-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-openair-4-view-2.png new file mode 100644 index 0000000..ccb038b Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-openair-4-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-openair-4-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-openair-4-view-3.png new file mode 100644 index 0000000..8ffcc1e Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-openair-4-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-station-25.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-station-25.png new file mode 100644 index 0000000..794aeb3 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-station-25.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-station-50.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-station-50.png new file mode 100644 index 0000000..3ec7b1a Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-station-50.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-station-75.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-station-75.png new file mode 100644 index 0000000..b11eddf Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-station-75.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-upper-mouth.png b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-upper-mouth.png new file mode 100644 index 0000000..047757c Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux109/captures/before/passage-2-3-0-upper-mouth.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux109/captures/capture-index.json b/Standalone/Research/WorldAssemblerM3/Linux109/captures/capture-index.json new file mode 100644 index 0000000..c519a76 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux109/captures/capture-index.json @@ -0,0 +1,4593 @@ +{ + "open_air_sections": [ + { + "passage": "passage/0-1/0", + "section": 1, + "start_m": 7.226, + "end_m": 10.217, + "samples": 13, + "midpoint": [ + 6.375, + 7.507, + -373.204 + ], + "radius_m": 1.958 + }, + { + "passage": "passage/0-1/0", + "section": 2, + "start_m": 13.456, + "end_m": 17.443, + "samples": 17, + "midpoint": [ + 5.121, + 0.955, + -374.039 + ], + "radius_m": 2.31 + }, + { + "passage": "passage/0-1/0", + "section": 3, + "start_m": 23.174, + "end_m": 24.918, + "samples": 8, + "midpoint": [ + 3.519, + -7.417, + -375.105 + ], + "radius_m": 2.761 + }, + { + "passage": "passage/0-1/0", + "section": 4, + "start_m": 1036.913, + "end_m": 1489.321, + "samples": 1838, + "midpoint": [ + -24.253, + -7.219, + -598.622 + ], + "radius_m": 3.5 + }, + { + "passage": "passage/1-2/0", + "section": 1, + "start_m": 101.82, + "end_m": 104.499, + "samples": 12, + "midpoint": [ + 9.136, + -11.613, + -749.434 + ], + "radius_m": 3.173 + }, + { + "passage": "passage/2-3/0", + "section": 1, + "start_m": 7.677, + "end_m": 34.747, + "samples": 108, + "midpoint": [ + -2.846, + -13.149, + -814.246 + ], + "radius_m": 3.0 + }, + { + "passage": "passage/2-3/0", + "section": 2, + "start_m": 368.909, + "end_m": 376.66, + "samples": 32, + "midpoint": [ + -9.545, + 9.558, + -877.248 + ], + "radius_m": 3.0 + }, + { + "passage": "passage/2-3/0", + "section": 3, + "start_m": 393.828, + "end_m": 396.51, + "samples": 7, + "midpoint": [ + -11.172, + -10.684, + -881.259 + ], + "radius_m": 3.0 + }, + { + "passage": "passage/2-3/0", + "section": 4, + "start_m": 444.932, + "end_m": 447.654, + "samples": 11, + "midpoint": [ + 9.72, + 10.251, + -890.42 + ], + "radius_m": 3.0 + } + ], + "captures": [ + { + "name": "passage-0-1-0-upper-mouth", + "passage": "passage/0-1/0", + "kind": "mouth", + "station": "upper-mouth", + "camera": [ + 8.838556323387953, + 20.38227805620432, + -371.842578125 + ], + "target": [ + 7.627308300716465, + 14.052320863909191, + -371.942578125 + ], + "yaw": -169.1673035961806, + "pitch": -0.8889517040780448, + "focus": [ + 8.0, + 16.0, + -371.892578125 + ], + "center_z": -371.892578125, + "variant": "before", + "capture": "captures/before/passage-0-1-0-upper-mouth.png", + "scene": "Saved/Linux/l109/captures/before/passage-0-1-0-upper-mouth.vfmesh", + "drawn_triangles": 188440, + "source_triangles": 221002, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": null, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 8.838556323387953, + 20.38227805620432, + -371.842578125 + ], + "target_actual_m": [ + 7.627308300716465, + 14.052320863909191, + -371.942578125 + ], + "logs": [ + "Saved/Linux/l109/captures/before/passage-0-1-0-upper-mouth-mesh.log", + "Saved/Linux/l109/captures/before/passage-0-1-0-upper-mouth-render.log", + "Saved/Linux/l109/captures/before/passage-0-1-0-upper-mouth-quality.log" + ] + }, + { + "name": "passage-0-1-0-lower-mouth", + "passage": "passage/0-1/0", + "kind": "mouth", + "station": "lower-mouth", + "camera": [ + 32.33499966877697, + 9.970678584968901, + -735.3555900060408 + ], + "target": [ + 24.468896040125948, + 1.7736482584276514, + -736.6798828125 + ], + "yaw": -136.18021933793872, + "pitch": -6.648805956400917, + "focus": [ + 25.83691406250004, + 3.1992187500000426, + -733.6298828125 + ], + "center_z": -733.6298828125, + "variant": "before", + "capture": "captures/before/passage-0-1-0-lower-mouth.png", + "scene": "Saved/Linux/l109/captures/before/passage-0-1-0-lower-mouth.vfmesh", + "drawn_triangles": 564520, + "source_triangles": 601022, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": null, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 32.33499966877697, + 9.970678584968901, + -735.3555900060408 + ], + "target_actual_m": [ + 24.468896040125948, + 1.7736482584276514, + -736.6798828125 + ], + "logs": [ + "Saved/Linux/l109/captures/before/passage-0-1-0-lower-mouth-mesh.log", + "Saved/Linux/l109/captures/before/passage-0-1-0-lower-mouth-render.log", + "Saved/Linux/l109/captures/before/passage-0-1-0-lower-mouth-quality.log" + ] + }, + { + "name": "passage-0-1-0-station-25", + "passage": "passage/0-1/0", + "kind": "station", + "station": "25%", + "camera": [ + -14.775318131856917, + -18.76625515302035, + -463.0107522799883 + ], + "target": [ + -21.881340520350044, + -8.062250257259727, + -465.34545559158664 + ], + "yaw": -33.57882238782777, + "pitch": -10.29924359775097, + "focus": [ + -14.308415511618097, + -18.17931227401582, + -461.11075227998833 + ], + "center_z": -461.11075227998833, + "route_distance_m": 503.5540172132633, + "route_length_m": 2014.2160688530532, + "requested_route_distance_m": 503.5540172132633, + "variant": "before", + "capture": "captures/before/passage-0-1-0-station-25.png", + "scene": "Saved/Linux/l109/captures/before/passage-0-1-0-station-25.vfmesh", + "drawn_triangles": 234197, + "source_triangles": 242189, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 553.5540172132633, + "route_station_adjustment_m": 49.99999999999994, + "fallback_kind": "route-offset", + "fallback_surface_distance_m": 25.94689170909587, + "camera_actual_m": [ + -2.4057464399509403, + 12.461921069738379, + -501.8795912931714 + ], + "target_actual_m": [ + -3.5, + 22.86543083190918, + -496.0 + ], + "logs": [ + "Saved/Linux/l109/captures/before/passage-0-1-0-station-25-attempt-09-mesh.log", + "Saved/Linux/l109/captures/before/passage-0-1-0-station-25-attempt-09-render.log", + "Saved/Linux/l109/captures/before/passage-0-1-0-station-25-attempt-09-quality.log" + ] + }, + { + "name": "passage-0-1-0-station-50", + "passage": "passage/0-1/0", + "kind": "station", + "station": "50%", + "camera": [ + -5.595578384695182, + 21.497727955754474, + -554.1741259385421 + ], + "target": [ + 7.655591484458359, + 21.467443083835786, + -556.5085919136736 + ], + "yaw": 90.13094634964635, + "pitch": -9.991282024617524, + "focus": [ + -5.507332687723769, + 20.752937584598918, + -552.2741259385422 + ], + "center_z": -552.2741259385422, + "route_distance_m": 1007.1080344265266, + "route_length_m": 2014.2160688530532, + "requested_route_distance_m": 1007.1080344265266, + "variant": "before", + "capture": "captures/before/passage-0-1-0-station-50.png", + "scene": "Saved/Linux/l109/captures/before/passage-0-1-0-station-50.vfmesh", + "drawn_triangles": 315900, + "source_triangles": 382184, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1007.1080344265266, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -5.595578384695182, + 21.497727955754474, + -554.1741259385421 + ], + "target_actual_m": [ + 7.655591484458359, + 21.467443083835786, + -556.5085919136736 + ], + "logs": [ + "Saved/Linux/l109/captures/before/passage-0-1-0-station-50-mesh.log", + "Saved/Linux/l109/captures/before/passage-0-1-0-station-50-render.log", + "Saved/Linux/l109/captures/before/passage-0-1-0-station-50-quality.log" + ] + }, + { + "name": "passage-0-1-0-station-75", + "passage": "passage/0-1/0", + "kind": "station", + "station": "75%", + "camera": [ + 16.5076883016004, + -13.46151881110554, + -645.3370683757493 + ], + "target": [ + 6.450888987015778, + -21.51871009256867, + -647.6715880269714 + ], + "yaw": -128.70060982957688, + "pitch": -10.268474883832386, + "focus": [ + 15.90697879980738, + -13.01246637045347, + -643.4370683757493 + ], + "center_z": -643.4370683757493, + "route_distance_m": 1510.66205163979, + "route_length_m": 2014.2160688530532, + "requested_route_distance_m": 1510.66205163979, + "variant": "before", + "capture": "captures/before/passage-0-1-0-station-75.png", + "scene": "Saved/Linux/l109/captures/before/passage-0-1-0-station-75.vfmesh", + "drawn_triangles": 256359, + "source_triangles": 307351, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1510.66205163979, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 16.5076883016004, + -13.46151881110554, + -645.3370683757493 + ], + "target_actual_m": [ + 6.450888987015778, + -21.51871009256867, + -647.6715880269714 + ], + "logs": [ + "Saved/Linux/l109/captures/before/passage-0-1-0-station-75-mesh.log", + "Saved/Linux/l109/captures/before/passage-0-1-0-station-75-render.log", + "Saved/Linux/l109/captures/before/passage-0-1-0-station-75-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-1-view-1", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-1/view-1", + "camera": [ + 13.20900955181851, + 6.199300705187407, + -372.004 + ], + "target": [ + 6.375, + 7.507, + -373.104 + ], + "yaw": -79.1673035961806, + "pitch": -8.983620476603386, + "focus": [ + 6.375, + 7.507, + -373.204 + ], + "center_z": -373.204, + "open_air_section": 1, + "route_distance_m": 8.7215, + "requested_route_distance_m": 8.7215, + "route_length_m": 2014.2160688530532, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-1-view-1.png", + "scene": "Saved/Linux/l109/captures/before/passage-0-1-0-openair-1-view-1.vfmesh", + "drawn_triangles": 211462, + "source_triangles": 250558, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 8.7215, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 13.20900955181851, + 6.199300705187407, + -372.004 + ], + "target_actual_m": [ + 6.375, + 7.507, + -373.104 + ], + "logs": [ + "Saved/Linux/l109/captures/before/passage-0-1-0-openair-1-view-1-mesh.log", + "Saved/Linux/l109/captures/before/passage-0-1-0-openair-1-view-1-render.log", + "Saved/Linux/l109/captures/before/passage-0-1-0-openair-1-view-1-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-1-view-2", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-1/view-2", + "camera": [ + 1.0142606878664218, + 8.532786540828848, + -369.204 + ], + "target": [ + 6.002308300716465, + 5.559320863909191, + -373.46409013845533 + ], + "yaw": 120.7999366723458, + "pitch": -36.26390111401942, + "focus": [ + 6.375, + 7.507, + -373.204 + ], + "center_z": -373.204, + "open_air_section": 1, + "route_distance_m": 8.7215, + "requested_route_distance_m": 8.7215, + "route_length_m": 2014.2160688530532, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-1-view-2.png", + "scene": "Saved/Linux/l109/captures/before/passage-0-1-0-openair-1-view-2.vfmesh", + "drawn_triangles": 208255, + "source_triangles": 245317, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 8.7215, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 1.0142606878664218, + 8.532786540828848, + -369.204 + ], + "target_actual_m": [ + 6.002308300716465, + 5.559320863909191, + -373.46409013845533 + ], + "logs": [ + "Saved/Linux/l109/captures/before/passage-0-1-0-openair-1-view-2-mesh.log", + "Saved/Linux/l109/captures/before/passage-0-1-0-openair-1-view-2-render.log", + "Saved/Linux/l109/captures/before/passage-0-1-0-openair-1-view-2-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-1-view-3", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-1/view-3", + "camera": [ + 6.375, + 7.507, + -373.91200000000003 + ], + "target": [ + 5.070579052507627, + 0.6901230236821672, + -374.8223154845937 + ], + "yaw": -169.16730359618057, + "pitch": -7.47219670147126, + "focus": [ + 6.375, + 7.507, + -373.204 + ], + "center_z": -373.204, + "open_air_section": 1, + "route_distance_m": 8.7215, + "requested_route_distance_m": 8.7215, + "route_length_m": 2014.2160688530532, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-1-view-3.png", + "scene": "Saved/Linux/l109/captures/before/passage-0-1-0-openair-1-view-3.vfmesh", + "drawn_triangles": 221239, + "source_triangles": 263331, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 8.7215, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 6.375, + 7.507, + -373.91200000000003 + ], + "target_actual_m": [ + 5.070579052507627, + 0.6901230236821672, + -374.8223154845937 + ], + "logs": [ + "Saved/Linux/l109/captures/before/passage-0-1-0-openair-1-view-3-mesh.log", + "Saved/Linux/l109/captures/before/passage-0-1-0-openair-1-view-3-render.log", + "Saved/Linux/l109/captures/before/passage-0-1-0-openair-1-view-3-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-2-view-1", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-2/view-1", + "camera": [ + 12.300736968064577, + -0.418854821080778, + -372.839 + ], + "target": [ + 5.121, + 0.955, + -373.93899999999996 + ], + "yaw": -79.1673035961806, + "pitch": -8.557593063277755, + "focus": [ + 5.121, + 0.955, + -374.039 + ], + "center_z": -374.039, + "open_air_section": 2, + "route_distance_m": 15.4495, + "requested_route_distance_m": 15.4495, + "route_length_m": 2014.2160688530532, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-2-view-1.png", + "scene": "Saved/Linux/l109/captures/before/passage-0-1-0-openair-2-view-1.vfmesh", + "drawn_triangles": 218664, + "source_triangles": 261340, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 15.4495, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 12.300736968064577, + -0.418854821080778, + -372.839 + ], + "target_actual_m": [ + 5.121, + 0.955, + -373.93899999999996 + ], + "logs": [ + "Saved/Linux/l109/captures/before/passage-0-1-0-openair-2-view-1-mesh.log", + "Saved/Linux/l109/captures/before/passage-0-1-0-openair-2-view-1-render.log", + "Saved/Linux/l109/captures/before/passage-0-1-0-openair-2-view-1-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-2-view-2", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-2/view-2", + "camera": [ + -0.5854667283796422, + 2.046942067097034, + -370.039 + ], + "target": [ + 4.748308300716466, + -0.9926791360908093, + -374.2990901384553 + ], + "yaw": 119.6780274158634, + "pitch": -34.75787724260944, + "focus": [ + 5.121, + 0.955, + -374.039 + ], + "center_z": -374.039, + "open_air_section": 2, + "route_distance_m": 15.4495, + "requested_route_distance_m": 15.4495, + "route_length_m": 2014.2160688530532, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-2-view-2.png", + "scene": "Saved/Linux/l109/captures/before/passage-0-1-0-openair-2-view-2.vfmesh", + "drawn_triangles": 223817, + "source_triangles": 266353, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 15.4495, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -0.5854667283796422, + 2.046942067097034, + -370.039 + ], + "target_actual_m": [ + 4.748308300716466, + -0.9926791360908093, + -374.2990901384553 + ], + "logs": [ + "Saved/Linux/l109/captures/before/passage-0-1-0-openair-2-view-2-mesh.log", + "Saved/Linux/l109/captures/before/passage-0-1-0-openair-2-view-2-render.log", + "Saved/Linux/l109/captures/before/passage-0-1-0-openair-2-view-2-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-2-view-3", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-2/view-3", + "camera": [ + 5.121, + 0.955, + -375.099 + ], + "target": [ + 3.8165790525076275, + -5.861876976317832, + -376.0093154845936 + ], + "yaw": -169.16730359618057, + "pitch": -7.47219670147126, + "focus": [ + 5.121, + 0.955, + -374.039 + ], + "center_z": -374.039, + "open_air_section": 2, + "route_distance_m": 15.4495, + "requested_route_distance_m": 15.4495, + "route_length_m": 2014.2160688530532, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-2-view-3.png", + "scene": "Saved/Linux/l109/captures/before/passage-0-1-0-openair-2-view-3.vfmesh", + "drawn_triangles": 221239, + "source_triangles": 263331, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 15.4495, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 5.121, + 0.955, + -375.099 + ], + "target_actual_m": [ + 3.8165790525076275, + -5.861876976317832, + -376.0093154845936 + ], + "logs": [ + "Saved/Linux/l109/captures/before/passage-0-1-0-openair-2-view-3-mesh.log", + "Saved/Linux/l109/captures/before/passage-0-1-0-openair-2-view-3-render.log", + "Saved/Linux/l109/captures/before/passage-0-1-0-openair-2-view-3-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-3-view-1", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-3/view-1", + "camera": [ + 11.141700220129849, + -8.875616589111877, + -373.90500000000003 + ], + "target": [ + 3.519, + -7.417, + -375.005 + ], + "yaw": -79.1673035961807, + "pitch": -8.067045700553148, + "focus": [ + 3.519, + -7.417, + -375.105 + ], + "center_z": -375.105, + "open_air_section": 3, + "route_distance_m": 24.046, + "requested_route_distance_m": 24.046, + "route_length_m": 2014.2160688530532, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-3-view-1.png", + "scene": "Saved/Linux/l109/captures/before/passage-0-1-0-openair-3-view-1.vfmesh", + "drawn_triangles": 224005, + "source_triangles": 268361, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 24.046, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 11.141700220129849, + -8.875616589111877, + -373.90500000000003 + ], + "target_actual_m": [ + 3.519, + -7.417, + -375.005 + ], + "logs": [ + "Saved/Linux/l109/captures/before/passage-0-1-0-openair-3-view-1-mesh.log", + "Saved/Linux/l109/captures/before/passage-0-1-0-openair-3-view-1-render.log", + "Saved/Linux/l109/captures/before/passage-0-1-0-openair-3-view-1-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-3-view-2", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-3/view-2", + "camera": [ + -2.630429980444914, + -6.2402961648718644, + -371.105 + ], + "target": [ + 3.1463083007164685, + -9.36467913609081, + -375.36509013845534 + ], + "yaw": 118.40700061385381, + "pitch": -32.969830683540685, + "focus": [ + 3.519, + -7.417, + -375.105 + ], + "center_z": -375.105, + "open_air_section": 3, + "route_distance_m": 24.046, + "requested_route_distance_m": 24.046, + "route_length_m": 2014.2160688530532, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-3-view-2.png", + "scene": "Saved/Linux/l109/captures/before/passage-0-1-0-openair-3-view-2.vfmesh", + "drawn_triangles": 230599, + "source_triangles": 276619, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 24.046, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -2.630429980444914, + -6.2402961648718644, + -371.105 + ], + "target_actual_m": [ + 3.1463083007164685, + -9.36467913609081, + -375.36509013845534 + ], + "logs": [ + "Saved/Linux/l109/captures/before/passage-0-1-0-openair-3-view-2-mesh.log", + "Saved/Linux/l109/captures/before/passage-0-1-0-openair-3-view-2-render.log", + "Saved/Linux/l109/captures/before/passage-0-1-0-openair-3-view-2-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-3-view-3", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-3/view-3", + "camera": [ + 3.519, + -7.417, + -376.61600000000004 + ], + "target": [ + 2.214579052507639, + -14.233876976317834, + -377.5263154845937 + ], + "yaw": -169.1673035961807, + "pitch": -7.47219670147126, + "focus": [ + 3.519, + -7.417, + -375.105 + ], + "center_z": -375.105, + "open_air_section": 3, + "route_distance_m": 24.046, + "requested_route_distance_m": 24.046, + "route_length_m": 2014.2160688530532, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-3-view-3.png", + "scene": "Saved/Linux/l109/captures/before/passage-0-1-0-openair-3-view-3.vfmesh", + "drawn_triangles": 229291, + "source_triangles": 275171, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 24.046, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 3.519, + -7.417, + -376.61600000000004 + ], + "target_actual_m": [ + 2.214579052507639, + -14.233876976317834, + -377.5263154845937 + ], + "logs": [ + "Saved/Linux/l109/captures/before/passage-0-1-0-openair-3-view-3-mesh.log", + "Saved/Linux/l109/captures/before/passage-0-1-0-openair-3-view-3-render.log", + "Saved/Linux/l109/captures/before/passage-0-1-0-openair-3-view-3-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-4-view-1", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-4/view-1", + "camera": [ + -32.48258146846097, + -9.345967055213542, + -597.4219999999999 + ], + "target": [ + -24.253, + -7.219, + -598.5219999999999 + ], + "yaw": 75.50879325593138, + "pitch": -7.373766361330366, + "focus": [ + -24.253, + -7.219, + -598.622 + ], + "center_z": -598.622, + "open_air_section": 4, + "route_distance_m": 1263.117, + "requested_route_distance_m": 1263.117, + "route_length_m": 2014.2160688530532, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-4-view-1.png", + "scene": "Saved/Linux/l109/captures/before/passage-0-1-0-openair-4-view-1.vfmesh", + "drawn_triangles": 407353, + "source_triangles": 489649, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1263.117, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -32.48258146846097, + -9.345967055213542, + -597.4219999999999 + ], + "target_actual_m": [ + -24.253, + -7.219, + -598.5219999999999 + ], + "logs": [ + "Saved/Linux/l109/captures/before/passage-0-1-0-openair-4-view-1-mesh.log", + "Saved/Linux/l109/captures/before/passage-0-1-0-openair-4-view-1-render.log", + "Saved/Linux/l109/captures/before/passage-0-1-0-openair-4-view-1-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-4-view-2", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-4/view-2", + "camera": [ + -17.475697614208613, + -5.467380072177084, + -594.622 + ], + "target": [ + -24.745196104265954, + -5.314613221376812, + -598.9840138013261 + ], + "yaw": -88.79611947547824, + "pitch": -30.960000123282544, + "focus": [ + -24.253, + -7.219, + -598.622 + ], + "center_z": -598.622, + "open_air_section": 4, + "route_distance_m": 1263.117, + "requested_route_distance_m": 1263.117, + "route_length_m": 2014.2160688530532, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-4-view-2.png", + "scene": "Saved/Linux/l109/captures/before/passage-0-1-0-openair-4-view-2.vfmesh", + "drawn_triangles": 406732, + "source_triangles": 488100, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1263.117, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -17.475697614208613, + -5.467380072177084, + -594.622 + ], + "target_actual_m": [ + -24.745196104265954, + -5.314613221376812, + -598.9840138013261 + ], + "logs": [ + "Saved/Linux/l109/captures/before/passage-0-1-0-openair-4-view-2-mesh.log", + "Saved/Linux/l109/captures/before/passage-0-1-0-openair-4-view-2-render.log", + "Saved/Linux/l109/captures/before/passage-0-1-0-openair-4-view-2-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-4-view-3", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-4/view-3", + "camera": [ + -24.253, + -7.219, + -600.872 + ], + "target": [ + -25.975686364930834, + -0.5536462748188384, + -602.1390483046415 + ], + "yaw": -14.491206744068611, + "pitch": -10.428414406509093, + "focus": [ + -24.253, + -7.219, + -598.622 + ], + "center_z": -598.622, + "open_air_section": 4, + "route_distance_m": 1263.117, + "requested_route_distance_m": 1263.117, + "route_length_m": 2014.2160688530532, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-4-view-3.png", + "scene": "Saved/Linux/l109/captures/before/passage-0-1-0-openair-4-view-3.vfmesh", + "drawn_triangles": 363878, + "source_triangles": 435830, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1263.117, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -24.253, + -7.219, + -600.872 + ], + "target_actual_m": [ + -25.975686364930834, + -0.5536462748188384, + -602.1390483046415 + ], + "logs": [ + "Saved/Linux/l109/captures/before/passage-0-1-0-openair-4-view-3-mesh.log", + "Saved/Linux/l109/captures/before/passage-0-1-0-openair-4-view-3-render.log", + "Saved/Linux/l109/captures/before/passage-0-1-0-openair-4-view-3-quality.log" + ] + }, + { + "name": "passage-1-2-0-upper-mouth", + "passage": "passage/1-2/0", + "kind": "mouth", + "station": "upper-mouth", + "camera": [ + 23.138863996797955, + -16.140874907935142, + -731.7810546875 + ], + "target": [ + 17.40030523753424, + -13.337671047862159, + -731.8810546875 + ], + "yaw": -63.96515262359864, + "pitch": -0.8970477694867451, + "focus": [ + 19.166015625, + -14.2001953125, + -728.8310546875 + ], + "center_z": -728.8310546875, + "variant": "before", + "capture": "captures/before/passage-1-2-0-upper-mouth.png", + "scene": "Saved/Linux/l109/captures/before/passage-1-2-0-upper-mouth.vfmesh", + "drawn_triangles": 576595, + "source_triangles": 617939, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": null, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 23.138863996797955, + -16.140874907935142, + -731.7810546875 + ], + "target_actual_m": [ + 17.40030523753424, + -13.337671047862159, + -731.8810546875 + ], + "logs": [ + "Saved/Linux/l109/captures/before/passage-1-2-0-upper-mouth-mesh.log", + "Saved/Linux/l109/captures/before/passage-1-2-0-upper-mouth-render.log", + "Saved/Linux/l109/captures/before/passage-1-2-0-upper-mouth-quality.log" + ] + }, + { + "name": "passage-1-2-0-lower-mouth", + "passage": "passage/1-2/0", + "kind": "mouth", + "station": "lower-mouth", + "camera": [ + 27.85488613118251, + -18.01309630670297, + -751.1981277420393 + ], + "target": [ + 17.33677972896158, + -13.39747931372043, + -753.05390625 + ], + "yaw": -66.30689197709135, + "pitch": -9.177678909861989, + "focus": [ + 19.166015625000004, + -14.200195312500002, + -750.00390625 + ], + "center_z": -750.00390625, + "variant": "before", + "capture": "captures/before/passage-1-2-0-lower-mouth.png", + "scene": "Saved/Linux/l109/captures/before/passage-1-2-0-lower-mouth.vfmesh", + "drawn_triangles": 555286, + "source_triangles": 590144, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": null, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 27.85488613118251, + -18.01309630670297, + -751.1981277420393 + ], + "target_actual_m": [ + 17.33677972896158, + -13.39747931372043, + -753.05390625 + ], + "logs": [ + "Saved/Linux/l109/captures/before/passage-1-2-0-lower-mouth-mesh.log", + "Saved/Linux/l109/captures/before/passage-1-2-0-lower-mouth-render.log", + "Saved/Linux/l109/captures/before/passage-1-2-0-lower-mouth-quality.log" + ] + }, + { + "name": "passage-1-2-0-station-25", + "passage": "passage/1-2/0", + "kind": "station", + "station": "25%", + "camera": [ + 14.061246659434865, + 6.2298603288341345, + -736.9521300666297 + ], + "target": [ + 2.776807018889787, + 14.105710769877629, + -739.3553453762524 + ], + "yaw": -55.0873095784489, + "pitch": -9.906144056135867, + "focus": [ + 14.699251471287738, + 6.62413163143246, + -735.5521300666297 + ], + "center_z": -735.5521300666297, + "route_distance_m": 28.53257769618698, + "route_length_m": 114.13031078474792, + "requested_route_distance_m": 28.53257769618698, + "variant": "before", + "capture": "captures/before/passage-1-2-0-station-25.png", + "scene": "Saved/Linux/l109/captures/before/passage-1-2-0-station-25.vfmesh", + "drawn_triangles": 667602, + "source_triangles": 739230, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 28.53257769618698, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 14.061246659434865, + 6.2298603288341345, + -736.9521300666297 + ], + "target_actual_m": [ + 2.776807018889787, + 14.105710769877629, + -739.3553453762524 + ], + "logs": [ + "Saved/Linux/l109/captures/before/passage-1-2-0-station-25-mesh.log", + "Saved/Linux/l109/captures/before/passage-1-2-0-station-25-render.log", + "Saved/Linux/l109/captures/before/passage-1-2-0-station-25-quality.log" + ] + }, + { + "name": "passage-1-2-0-station-50", + "passage": "passage/1-2/0", + "kind": "station", + "station": "50%", + "camera": [ + -8.084497527648217, + 11.937833199489809, + -742.2574958482095 + ], + "target": [ + -12.736965906524208, + -1.2900547733159642, + -744.6613063712255 + ], + "yaw": -160.62237799298956, + "pitch": -9.72758819089683, + "focus": [ + -8.532722418197661, + 12.539160437765226, + -740.8574958482095 + ], + "center_z": -740.8574958482095, + "route_distance_m": 57.06515539237396, + "route_length_m": 114.13031078474792, + "requested_route_distance_m": 57.06515539237396, + "variant": "before", + "capture": "captures/before/passage-1-2-0-station-50.png", + "scene": "Saved/Linux/l109/captures/before/passage-1-2-0-station-50.vfmesh", + "drawn_triangles": 602756, + "source_triangles": 665938, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 57.06515539237396, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -8.084497527648217, + 11.937833199489809, + -742.2574958482095 + ], + "target_actual_m": [ + -12.736965906524208, + -1.2900547733159642, + -744.6613063712255 + ], + "logs": [ + "Saved/Linux/l109/captures/before/passage-1-2-0-station-50-mesh.log", + "Saved/Linux/l109/captures/before/passage-1-2-0-station-50-render.log", + "Saved/Linux/l109/captures/before/passage-1-2-0-station-50-quality.log" + ] + }, + { + "name": "passage-1-2-0-station-75", + "passage": "passage/1-2/0", + "kind": "station", + "station": "75%", + "camera": [ + -6.834019755975895, + -10.575202023649924, + -747.5631055224986 + ], + "target": [ + 7.157358334976821, + -10.99897026968858, + -749.9667935370503 + ], + "yaw": 91.73483351267123, + "pitch": -9.743746239902421, + "focus": [ + -7.241181052718079, + -11.205058895038356, + -746.1631055224987 + ], + "center_z": -746.1631055224987, + "route_distance_m": 85.59773308856094, + "route_length_m": 114.13031078474792, + "requested_route_distance_m": 85.59773308856094, + "variant": "before", + "capture": "captures/before/passage-1-2-0-station-75.png", + "scene": "Saved/Linux/l109/captures/before/passage-1-2-0-station-75.vfmesh", + "drawn_triangles": 620502, + "source_triangles": 682164, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 85.59773308856094, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -6.834019755975895, + -10.575202023649924, + -747.5631055224986 + ], + "target_actual_m": [ + 7.157358334976821, + -10.99897026968858, + -749.9667935370503 + ], + "logs": [ + "Saved/Linux/l109/captures/before/passage-1-2-0-station-75-mesh.log", + "Saved/Linux/l109/captures/before/passage-1-2-0-station-75-render.log", + "Saved/Linux/l109/captures/before/passage-1-2-0-station-75-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-1-view-1", + "passage": "passage/1-2/0", + "kind": "open-air", + "station": "section-1/view-1", + "camera": [ + 5.970328502711862, + -4.077984872526302, + -748.2339999999999 + ], + "target": [ + 9.136, + -11.613, + -749.334 + ], + "yaw": 157.2113561221713, + "pitch": -7.665347688204901, + "focus": [ + 9.136, + -11.613, + -749.434 + ], + "center_z": -749.434, + "open_air_section": 1, + "route_distance_m": 103.1595, + "requested_route_distance_m": 103.1595, + "route_length_m": 114.13031078474792, + "variant": "before", + "capture": "captures/before/passage-1-2-0-openair-1-view-1.png", + "scene": "Saved/Linux/l109/captures/before/passage-1-2-0-openair-1-view-1.vfmesh", + "drawn_triangles": 636438, + "source_triangles": 703078, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 103.1595, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 5.970328502711862, + -4.077984872526302, + -748.2339999999999 + ], + "target_actual_m": [ + 9.136, + -11.613, + -749.334 + ], + "logs": [ + "Saved/Linux/l109/captures/before/passage-1-2-0-openair-1-view-1-mesh.log", + "Saved/Linux/l109/captures/before/passage-1-2-0-openair-1-view-1-render.log", + "Saved/Linux/l109/captures/before/passage-1-2-0-openair-1-view-1-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-1-view-2", + "passage": "passage/1-2/0", + "kind": "open-air", + "station": "section-1/view-2", + "camera": [ + 11.720672201321882, + -17.76510521786761, + -745.434 + ], + "target": [ + 10.962150679516013, + -10.845782806922454, + -749.7106793710225 + ], + "yaw": -6.255993323541881, + "pitch": -31.566444426346976, + "focus": [ + 9.136, + -11.613, + -749.434 + ], + "center_z": -749.434, + "open_air_section": 1, + "route_distance_m": 103.1595, + "requested_route_distance_m": 103.1595, + "route_length_m": 114.13031078474792, + "variant": "before", + "capture": "captures/before/passage-1-2-0-openair-1-view-2.png", + "scene": "Saved/Linux/l109/captures/before/passage-1-2-0-openair-1-view-2.vfmesh", + "drawn_triangles": 593960, + "source_triangles": 642760, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 103.1595, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 11.720672201321882, + -17.76510521786761, + -745.434 + ], + "target_actual_m": [ + 10.962150679516013, + -10.845782806922454, + -749.7106793710225 + ], + "logs": [ + "Saved/Linux/l109/captures/before/passage-1-2-0-openair-1-view-2-mesh.log", + "Saved/Linux/l109/captures/before/passage-1-2-0-openair-1-view-2-render.log", + "Saved/Linux/l109/captures/before/passage-1-2-0-openair-1-view-2-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-1-view-3", + "passage": "passage/1-2/0", + "kind": "open-air", + "station": "section-1/view-3", + "camera": [ + 9.136, + -11.613, + -751.357 + ], + "target": [ + 15.527527378306049, + -8.927739824228592, + -752.3253777985788 + ], + "yaw": 67.2113561221713, + "pitch": -7.951782379671316, + "focus": [ + 9.136, + -11.613, + -749.434 + ], + "center_z": -749.434, + "open_air_section": 1, + "route_distance_m": 103.1595, + "requested_route_distance_m": 103.1595, + "route_length_m": 114.13031078474792, + "variant": "before", + "capture": "captures/before/passage-1-2-0-openair-1-view-3.png", + "scene": "Saved/Linux/l109/captures/before/passage-1-2-0-openair-1-view-3.vfmesh", + "drawn_triangles": 622040, + "source_triangles": 681980, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 103.1595, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 9.136, + -11.613, + -751.357 + ], + "target_actual_m": [ + 15.527527378306049, + -8.927739824228592, + -752.3253777985788 + ], + "logs": [ + "Saved/Linux/l109/captures/before/passage-1-2-0-openair-1-view-3-mesh.log", + "Saved/Linux/l109/captures/before/passage-1-2-0-openair-1-view-3-render.log", + "Saved/Linux/l109/captures/before/passage-1-2-0-openair-1-view-3-quality.log" + ] + }, + { + "name": "passage-2-3-0-upper-mouth", + "passage": "passage/2-3/0", + "kind": "mouth", + "station": "upper-mouth", + "camera": [ + -24.488242402685422, + -4.955714893216976, + -811.975390625 + ], + "target": [ + -18.095503376584258, + -5.118423589125788, + -812.075390625 + ], + "yaw": 91.45798369615616, + "pitch": -0.8959002046922002, + "focus": [ + -20.0625, + -5.068359375, + -809.025390625 + ], + "center_z": -809.025390625, + "variant": "before", + "capture": "captures/before/passage-2-3-0-upper-mouth.png", + "scene": "Saved/Linux/l109/captures/before/passage-2-3-0-upper-mouth.vfmesh", + "drawn_triangles": 59568, + "source_triangles": 71352, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": null, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -24.488242402685422, + -4.955714893216976, + -811.975390625 + ], + "target_actual_m": [ + -18.095503376584258, + -5.118423589125788, + -812.075390625 + ], + "logs": [ + "Saved/Linux/l109/captures/before/passage-2-3-0-upper-mouth-mesh.log", + "Saved/Linux/l109/captures/before/passage-2-3-0-upper-mouth-render.log", + "Saved/Linux/l109/captures/before/passage-2-3-0-upper-mouth-quality.log" + ] + }, + { + "name": "passage-2-3-0-lower-mouth", + "passage": "passage/2-3/0", + "kind": "mouth", + "station": "lower-mouth", + "camera": [ + -29.252182317846856, + -2.7275305690543954, + -898.2312482566488 + ], + "target": [ + -18.127830038348062, + -5.561165439409593, + -900.0333984375 + ], + "yaw": 104.29068028993369, + "pitch": -8.921903113685321, + "focus": [ + -20.062500000000025, + -5.068359374999994, + -896.9833984375 + ], + "center_z": -896.9833984375, + "variant": "before", + "capture": "captures/before/passage-2-3-0-lower-mouth.png", + "scene": "Saved/Linux/l109/captures/before/passage-2-3-0-lower-mouth.vfmesh", + "drawn_triangles": 294430, + "source_triangles": 315310, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": null, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -29.252182317846856, + -2.7275305690543954, + -898.2312482566488 + ], + "target_actual_m": [ + -18.127830038348062, + -5.561165439409593, + -900.0333984375 + ], + "logs": [ + "Saved/Linux/l109/captures/before/passage-2-3-0-lower-mouth-mesh.log", + "Saved/Linux/l109/captures/before/passage-2-3-0-lower-mouth-render.log", + "Saved/Linux/l109/captures/before/passage-2-3-0-lower-mouth-quality.log" + ] + }, + { + "name": "passage-2-3-0-station-25", + "passage": "passage/2-3/0", + "kind": "station", + "station": "25%", + "camera": [ + 2.951958640669914, + -13.338225235751096, + -833.8468796615592 + ], + "target": [ + 13.807272802607395, + -4.598886839310115, + -836.1551631961163 + ], + "yaw": 51.16333936402171, + "pitch": -9.404734267799613, + "focus": [ + 3.05246502844549, + -14.081460370830369, + -832.4468796615593 + ], + "center_z": -832.4468796615593, + "route_distance_m": 122.7774446799287, + "route_length_m": 491.1097787197148, + "requested_route_distance_m": 122.7774446799287, + "variant": "before", + "capture": "captures/before/passage-2-3-0-station-25.png", + "scene": "Saved/Linux/l109/captures/before/passage-2-3-0-station-25.vfmesh", + "drawn_triangles": 55420, + "source_triangles": 66380, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 122.7774446799287, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 2.951958640669914, + -13.338225235751096, + -833.8468796615592 + ], + "target_actual_m": [ + 13.807272802607395, + -4.598886839310115, + -836.1551631961163 + ], + "logs": [ + "Saved/Linux/l109/captures/before/passage-2-3-0-station-25-mesh.log", + "Saved/Linux/l109/captures/before/passage-2-3-0-station-25-render.log", + "Saved/Linux/l109/captures/before/passage-2-3-0-station-25-quality.log" + ] + }, + { + "name": "passage-2-3-0-station-50", + "passage": "passage/2-3/0", + "kind": "station", + "station": "50%", + "camera": [ + 14.787916568025471, + 4.0845473469571685, + -855.8482064857711 + ], + "target": [ + 4.181856935464122, + 13.428451425109108, + -858.156850261184 + ], + "yaw": -48.620053366666205, + "pitch": -9.276137356776397, + "focus": [ + 15.521366359832331, + 4.241236219882065, + -854.4482064857712 + ], + "center_z": -854.4482064857712, + "route_distance_m": 245.5548893598574, + "route_length_m": 491.1097787197148, + "requested_route_distance_m": 245.5548893598574, + "variant": "before", + "capture": "captures/before/passage-2-3-0-station-50.png", + "scene": "Saved/Linux/l109/captures/before/passage-2-3-0-station-50.vfmesh", + "drawn_triangles": 458134, + "source_triangles": 476210, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 245.5548893598574, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 14.787916568025471, + 4.0845473469571685, + -855.8482064857711 + ], + "target_actual_m": [ + 4.181856935464122, + 13.428451425109108, + -858.156850261184 + ], + "logs": [ + "Saved/Linux/l109/captures/before/passage-2-3-0-station-50-mesh.log", + "Saved/Linux/l109/captures/before/passage-2-3-0-station-50-render.log", + "Saved/Linux/l109/captures/before/passage-2-3-0-station-50-quality.log" + ] + }, + { + "name": "passage-2-3-0-station-75", + "passage": "passage/2-3/0", + "kind": "station", + "station": "75%", + "camera": [ + -5.5279222093760625, + 11.458278186756923, + -877.8500416755847 + ], + "target": [ + -12.142822760321879, + -0.7204200146909749, + -880.1591147812899 + ], + "yaw": -151.49125520686113, + "pitch": -9.4591259387564, + "focus": [ + -5.958484343888987, + 12.072376101037435, + -876.4500416755848 + ], + "center_z": -876.4500416755848, + "route_distance_m": 368.33233403978613, + "route_length_m": 491.1097787197148, + "requested_route_distance_m": 368.33233403978613, + "variant": "before", + "capture": "captures/before/passage-2-3-0-station-75.png", + "scene": "Saved/Linux/l109/captures/before/passage-2-3-0-station-75.vfmesh", + "drawn_triangles": 475978, + "source_triangles": 503510, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 368.33233403978613, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -5.5279222093760625, + 11.458278186756923, + -877.8500416755847 + ], + "target_actual_m": [ + -12.142822760321879, + -0.7204200146909749, + -880.1591147812899 + ], + "logs": [ + "Saved/Linux/l109/captures/before/passage-2-3-0-station-75-mesh.log", + "Saved/Linux/l109/captures/before/passage-2-3-0-station-75-render.log", + "Saved/Linux/l109/captures/before/passage-2-3-0-station-75-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-1-view-1", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-1/view-1", + "camera": [ + -1.189937432971333, + -5.322285697427915, + -813.0459999999999 + ], + "target": [ + -2.846, + -13.149, + -814.146 + ], + "yaw": -168.05293971491665, + "pitch": -7.829076510059767, + "focus": [ + -2.846, + -13.149, + -814.246 + ], + "center_z": -814.246, + "open_air_section": 1, + "route_distance_m": 21.212, + "requested_route_distance_m": 21.212, + "route_length_m": 491.1097787197148, + "variant": "before", + "capture": "captures/before/passage-2-3-0-openair-1-view-1.png", + "scene": "Saved/Linux/l109/captures/before/passage-2-3-0-openair-1-view-1.vfmesh", + "drawn_triangles": 104612, + "source_triangles": 129244, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 21.212, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -1.189937432971333, + -5.322285697427915, + -813.0459999999999 + ], + "target_actual_m": [ + -2.846, + -13.149, + -814.146 + ], + "logs": [ + "Saved/Linux/l109/captures/before/passage-2-3-0-openair-1-view-1-mesh.log", + "Saved/Linux/l109/captures/before/passage-2-3-0-openair-1-view-1-render.log", + "Saved/Linux/l109/captures/before/passage-2-3-0-openair-1-view-1-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-1-view-2", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-1/view-2", + "camera": [ + -4.1915508357107925, + -19.508205370839818, + -810.246 + ], + "target": [ + -0.9210204431637441, + -13.556308413611612, + -814.6045436681405 + ], + "yaw": 28.788521091259426, + "pitch": -32.69176164676129, + "focus": [ + -2.846, + -13.149, + -814.246 + ], + "center_z": -814.246, + "open_air_section": 1, + "route_distance_m": 21.212, + "requested_route_distance_m": 21.212, + "route_length_m": 491.1097787197148, + "variant": "before", + "capture": "captures/before/passage-2-3-0-openair-1-view-2.png", + "scene": "Saved/Linux/l109/captures/before/passage-2-3-0-openair-1-view-2.vfmesh", + "drawn_triangles": 81078, + "source_triangles": 99310, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 21.212, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -4.1915508357107925, + -19.508205370839818, + -810.246 + ], + "target_actual_m": [ + -0.9210204431637441, + -13.556308413611612, + -814.6045436681405 + ], + "logs": [ + "Saved/Linux/l109/captures/before/passage-2-3-0-openair-1-view-2-mesh.log", + "Saved/Linux/l109/captures/before/passage-2-3-0-openair-1-view-2-render.log", + "Saved/Linux/l109/captures/before/passage-2-3-0-openair-1-view-2-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-1-view-3", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-1/view-3", + "camera": [ + -2.846, + -13.149, + -815.996 + ], + "target": [ + 3.891428448926896, + -14.574579447640645, + -817.2509028384919 + ], + "yaw": 101.94706028508335, + "pitch": -10.327349081567025, + "focus": [ + -2.846, + -13.149, + -814.246 + ], + "center_z": -814.246, + "open_air_section": 1, + "route_distance_m": 21.212, + "requested_route_distance_m": 21.212, + "route_length_m": 491.1097787197148, + "variant": "before", + "capture": "captures/before/passage-2-3-0-openair-1-view-3.png", + "scene": "Saved/Linux/l109/captures/before/passage-2-3-0-openair-1-view-3.vfmesh", + "drawn_triangles": 94962, + "source_triangles": 117946, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 21.212, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -2.846, + -13.149, + -815.996 + ], + "target_actual_m": [ + 3.891428448926896, + -14.574579447640645, + -817.2509028384919 + ], + "logs": [ + "Saved/Linux/l109/captures/before/passage-2-3-0-openair-1-view-3-mesh.log", + "Saved/Linux/l109/captures/before/passage-2-3-0-openair-1-view-3-render.log", + "Saved/Linux/l109/captures/before/passage-2-3-0-openair-1-view-3-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-2-view-1", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-2/view-1", + "camera": [ + -3.8677882827668535, + 3.921576744272068, + -876.048 + ], + "target": [ + -9.545, + 9.558, + -877.148 + ], + "yaw": -45.206564607875244, + "pitch": -7.8290765100597675, + "focus": [ + -9.545, + 9.558, + -877.248 + ], + "center_z": -877.248, + "open_air_section": 2, + "route_distance_m": 372.7845, + "requested_route_distance_m": 372.7845, + "route_length_m": 491.1097787197148, + "variant": "before", + "capture": "captures/before/passage-2-3-0-openair-2-view-1.png", + "scene": "Saved/Linux/l109/captures/before/passage-2-3-0-openair-2-view-1.vfmesh", + "drawn_triangles": 476052, + "source_triangles": 504614, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 372.7845, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -3.8677882827668535, + 3.921576744272068, + -876.048 + ], + "target_actual_m": [ + -9.545, + 9.558, + -877.148 + ], + "logs": [ + "Saved/Linux/l109/captures/before/passage-2-3-0-openair-2-view-1-mesh.log", + "Saved/Linux/l109/captures/before/passage-2-3-0-openair-2-view-1-render.log", + "Saved/Linux/l109/captures/before/passage-2-3-0-openair-2-view-1-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-2-view-2", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-2/view-2", + "camera": [ + -14.157734520251932, + 14.137593895278943, + -873.248 + ], + "target": [ + -10.930527244244528, + 8.162446268725978, + -877.6123405530316 + ], + "yaw": 151.6262948374245, + "pitch": -32.72757108790463, + "focus": [ + -9.545, + 9.558, + -877.248 + ], + "center_z": -877.248, + "open_air_section": 2, + "route_distance_m": 372.7845, + "requested_route_distance_m": 372.7845, + "route_length_m": 491.1097787197148, + "variant": "before", + "capture": "captures/before/passage-2-3-0-openair-2-view-2.png", + "scene": "Saved/Linux/l109/captures/before/passage-2-3-0-openair-2-view-2.vfmesh", + "drawn_triangles": 479198, + "source_triangles": 504002, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 372.7845, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -14.157734520251932, + 14.137593895278943, + -873.248 + ], + "target_actual_m": [ + -10.930527244244528, + 8.162446268725978, + -877.6123405530316 + ], + "logs": [ + "Saved/Linux/l109/captures/before/passage-2-3-0-openair-2-view-2-mesh.log", + "Saved/Linux/l109/captures/before/passage-2-3-0-openair-2-view-2-render.log", + "Saved/Linux/l109/captures/before/passage-2-3-0-openair-2-view-2-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-2-view-3", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-2/view-3", + "camera": [ + -9.545, + 9.558, + -878.998 + ], + "target": [ + -14.394345354855847, + 4.673561940540924, + -880.2731919356104 + ], + "yaw": -135.20656460787526, + "pitch": -10.496197864919285, + "focus": [ + -9.545, + 9.558, + -877.248 + ], + "center_z": -877.248, + "open_air_section": 2, + "route_distance_m": 372.7845, + "requested_route_distance_m": 372.7845, + "route_length_m": 491.1097787197148, + "variant": "before", + "capture": "captures/before/passage-2-3-0-openair-2-view-3.png", + "scene": "Saved/Linux/l109/captures/before/passage-2-3-0-openair-2-view-3.vfmesh", + "drawn_triangles": 479198, + "source_triangles": 504002, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 372.7845, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -9.545, + 9.558, + -878.998 + ], + "target_actual_m": [ + -14.394345354855847, + 4.673561940540924, + -880.2731919356104 + ], + "logs": [ + "Saved/Linux/l109/captures/before/passage-2-3-0-openair-2-view-3-mesh.log", + "Saved/Linux/l109/captures/before/passage-2-3-0-openair-2-view-3-render.log", + "Saved/Linux/l109/captures/before/passage-2-3-0-openair-2-view-3-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-3-view-1", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-3/view-1", + "camera": [ + -4.259540253679534, + -6.656854577309233, + -880.059 + ], + "target": [ + -11.172, + -10.684, + -881.159 + ], + "yaw": -120.22474590439407, + "pitch": -7.829076510059767, + "focus": [ + -11.172, + -10.684, + -881.259 + ], + "center_z": -881.259, + "open_air_section": 3, + "route_distance_m": 395.169, + "requested_route_distance_m": 395.169, + "route_length_m": 491.1097787197148, + "variant": "before", + "capture": "captures/before/passage-2-3-0-openair-3-view-1.png", + "scene": "Saved/Linux/l109/captures/before/passage-2-3-0-openair-3-view-1.vfmesh", + "drawn_triangles": 485580, + "source_triangles": 515422, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 395.169, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -4.259540253679534, + -6.656854577309233, + -880.059 + ], + "target_actual_m": [ + -11.172, + -10.684, + -881.159 + ], + "logs": [ + "Saved/Linux/l109/captures/before/passage-2-3-0-openair-3-view-1-mesh.log", + "Saved/Linux/l109/captures/before/passage-2-3-0-openair-3-view-1-render.log", + "Saved/Linux/l109/captures/before/passage-2-3-0-openair-3-view-1-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-3-view-2", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-3/view-2", + "camera": [ + -16.78837354388538, + -13.956055655936247, + -877.259 + ], + "target": [ + -10.181507700208021, + -12.384146737382467, + -881.6173658401976 + ], + "yaw": 76.61697649508203, + "pitch": -32.69066303746625, + "focus": [ + -11.172, + -10.684, + -881.259 + ], + "center_z": -881.259, + "open_air_section": 3, + "route_distance_m": 395.169, + "requested_route_distance_m": 395.169, + "route_length_m": 491.1097787197148, + "variant": "before", + "capture": "captures/before/passage-2-3-0-openair-3-view-2.png", + "scene": "Saved/Linux/l109/captures/before/passage-2-3-0-openair-3-view-2.vfmesh", + "drawn_triangles": 478866, + "source_triangles": 496372, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 395.169, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -16.78837354388538, + -13.956055655936247, + -877.259 + ], + "target_actual_m": [ + -10.181507700208021, + -12.384146737382467, + -881.6173658401976 + ], + "logs": [ + "Saved/Linux/l109/captures/before/passage-2-3-0-openair-3-view-2-mesh.log", + "Saved/Linux/l109/captures/before/passage-2-3-0-openair-3-view-2-render.log", + "Saved/Linux/l109/captures/before/passage-2-3-0-openair-3-view-2-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-3-view-3", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-3/view-3", + "camera": [ + -11.172, + -10.684, + -883.009 + ], + "target": [ + -7.705276950728071, + -16.634513580838636, + -884.2632804406917 + ], + "yaw": 149.77525409560596, + "pitch": -10.322170838480885, + "focus": [ + -11.172, + -10.684, + -881.259 + ], + "center_z": -881.259, + "open_air_section": 3, + "route_distance_m": 395.169, + "requested_route_distance_m": 395.169, + "route_length_m": 491.1097787197148, + "variant": "before", + "capture": "captures/before/passage-2-3-0-openair-3-view-3.png", + "scene": "Saved/Linux/l109/captures/before/passage-2-3-0-openair-3-view-3.vfmesh", + "drawn_triangles": 490304, + "source_triangles": 517768, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 395.169, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -11.172, + -10.684, + -883.009 + ], + "target_actual_m": [ + -7.705276950728071, + -16.634513580838636, + -884.2632804406917 + ], + "logs": [ + "Saved/Linux/l109/captures/before/passage-2-3-0-openair-3-view-3-mesh.log", + "Saved/Linux/l109/captures/before/passage-2-3-0-openair-3-view-3-render.log", + "Saved/Linux/l109/captures/before/passage-2-3-0-openair-3-view-3-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-4-view-1", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-4/view-1", + "camera": [ + 5.633312802598928, + 3.3735740461566452, + -889.2199999999999 + ], + "target": [ + 9.72, + 10.251, + -890.3199999999999 + ], + "yaw": 30.719524653046307, + "pitch": -7.829076510059767, + "focus": [ + 9.72, + 10.251, + -890.42 + ], + "center_z": -890.42, + "open_air_section": 4, + "route_distance_m": 446.293, + "requested_route_distance_m": 446.293, + "route_length_m": 491.1097787197148, + "variant": "before", + "capture": "captures/before/passage-2-3-0-openair-4-view-1.png", + "scene": "Saved/Linux/l109/captures/before/passage-2-3-0-openair-4-view-1.vfmesh", + "drawn_triangles": 475662, + "source_triangles": 504224, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 446.293, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 5.633312802598928, + 3.3735740461566452, + -889.2199999999999 + ], + "target_actual_m": [ + 9.72, + 10.251, + -890.3199999999999 + ], + "logs": [ + "Saved/Linux/l109/captures/before/passage-2-3-0-openair-4-view-1-mesh.log", + "Saved/Linux/l109/captures/before/passage-2-3-0-openair-4-view-1-render.log", + "Saved/Linux/l109/captures/before/passage-2-3-0-openair-4-view-1-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-4-view-2", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-4/view-2", + "camera": [ + 13.040433347888372, + 15.838908587497725, + -886.42 + ], + "target": [ + 8.02847750106997, + 11.256132354297488, + -890.7784139868335 + ], + "yaw": -132.43882376014403, + "pitch": -32.69096048480686, + "focus": [ + 9.72, + 10.251, + -890.42 + ], + "center_z": -890.42, + "open_air_section": 4, + "route_distance_m": 446.293, + "requested_route_distance_m": 446.293, + "route_length_m": 491.1097787197148, + "variant": "before", + "capture": "captures/before/passage-2-3-0-openair-4-view-2.png", + "scene": "Saved/Linux/l109/captures/before/passage-2-3-0-openair-4-view-2.vfmesh", + "drawn_triangles": 496128, + "source_triangles": 527332, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 446.293, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 13.040433347888372, + 15.838908587497725, + -886.42 + ], + "target_actual_m": [ + 8.02847750106997, + 11.256132354297488, + -890.7784139868335 + ], + "logs": [ + "Saved/Linux/l109/captures/before/passage-2-3-0-openair-4-view-2-mesh.log", + "Saved/Linux/l109/captures/before/passage-2-3-0-openair-4-view-2-render.log", + "Saved/Linux/l109/captures/before/passage-2-3-0-openair-4-view-2-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-4-view-3", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-4/view-3", + "camera": [ + 9.72, + 10.251, + -892.17 + ], + "target": [ + 3.7996712537448953, + 13.768963240041211, + -893.4244489539172 + ], + "yaw": -59.28047534695369, + "pitch": -10.32357283123646, + "focus": [ + 9.72, + 10.251, + -890.42 + ], + "center_z": -890.42, + "open_air_section": 4, + "route_distance_m": 446.293, + "requested_route_distance_m": 446.293, + "route_length_m": 491.1097787197148, + "variant": "before", + "capture": "captures/before/passage-2-3-0-openair-4-view-3.png", + "scene": "Saved/Linux/l109/captures/before/passage-2-3-0-openair-4-view-3.vfmesh", + "drawn_triangles": 496508, + "source_triangles": 528248, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 446.293, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 9.72, + 10.251, + -892.17 + ], + "target_actual_m": [ + 3.7996712537448953, + 13.768963240041211, + -893.4244489539172 + ], + "logs": [ + "Saved/Linux/l109/captures/before/passage-2-3-0-openair-4-view-3-mesh.log", + "Saved/Linux/l109/captures/before/passage-2-3-0-openair-4-view-3-render.log", + "Saved/Linux/l109/captures/before/passage-2-3-0-openair-4-view-3-quality.log" + ] + }, + { + "name": "passage-0-1-0-upper-mouth", + "passage": "passage/0-1/0", + "kind": "mouth", + "station": "upper-mouth", + "camera": [ + 8.839199674686244, + 20.385640196824248, + -371.842578125 + ], + "target": [ + 7.627022366806115, + 14.050826579189224, + -371.942578125 + ], + "yaw": -169.1673035961807, + "pitch": -0.8882703208739064, + "focus": [ + 8.0, + 16.0, + -372.122578125 + ], + "center_z": -372.122578125, + "variant": "after", + "capture": "captures/after/passage-0-1-0-upper-mouth.png", + "scene": "Saved/Linux/l109/captures/after/passage-0-1-0-upper-mouth.vfmesh", + "drawn_triangles": 253282, + "source_triangles": 310752, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": null, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 8.839199674686244, + 20.385640196824248, + -371.842578125 + ], + "target_actual_m": [ + 7.627022366806115, + 14.050826579189224, + -371.942578125 + ], + "logs": [ + "Saved/Linux/l109/captures/after/passage-0-1-0-upper-mouth-mesh.log", + "Saved/Linux/l109/captures/after/passage-0-1-0-upper-mouth-render.log", + "Saved/Linux/l109/captures/after/passage-0-1-0-upper-mouth-quality.log" + ] + }, + { + "name": "passage-0-1-0-lower-mouth", + "passage": "passage/0-1/0", + "kind": "mouth", + "station": "lower-mouth", + "camera": [ + 32.29870756948553, + 9.932859678359986, + -735.514490514727 + ], + "target": [ + 24.47653648208193, + 1.781610133503092, + -736.6798828125 + ], + "yaw": -136.18021933793756, + "pitch": -5.889606445716861, + "focus": [ + 25.836914062499947, + 3.199218749999943, + -734.8598828125 + ], + "center_z": -734.8598828125, + "variant": "after", + "capture": "captures/after/passage-0-1-0-lower-mouth.png", + "scene": "Saved/Linux/l109/captures/after/passage-0-1-0-lower-mouth.vfmesh", + "drawn_triangles": 559326, + "source_triangles": 611506, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": null, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 32.29870756948553, + 9.932859678359986, + -735.514490514727 + ], + "target_actual_m": [ + 24.47653648208193, + 1.781610133503092, + -736.6798828125 + ], + "logs": [ + "Saved/Linux/l109/captures/after/passage-0-1-0-lower-mouth-mesh.log", + "Saved/Linux/l109/captures/after/passage-0-1-0-lower-mouth-render.log", + "Saved/Linux/l109/captures/after/passage-0-1-0-lower-mouth-quality.log" + ] + }, + { + "name": "passage-0-1-0-station-25", + "passage": "passage/0-1/0", + "kind": "station", + "station": "25%", + "camera": [ + -14.832678263995309, + -18.72062618817443, + -462.7942446741164 + ], + "target": [ + -21.89083852694916, + -7.989572734179358, + -465.1289462328135 + ], + "yaw": -33.33421057217368, + "pitch": -10.302233434343137, + "focus": [ + -14.365775643756486, + -18.133683309169903, + -461.1242446741164 + ], + "center_z": -461.1242446741164, + "route_distance_m": 503.59931612822896, + "route_length_m": 2014.3972645129159, + "requested_route_distance_m": 503.59931612822896, + "variant": "after", + "capture": "captures/after/passage-0-1-0-station-25.png", + "scene": "Saved/Linux/l109/captures/after/passage-0-1-0-station-25.vfmesh", + "drawn_triangles": 145630, + "source_triangles": 194558, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 503.59931612822896, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -14.832678263995309, + -18.72062618817443, + -462.7942446741164 + ], + "target_actual_m": [ + -21.89083852694916, + -7.989572734179358, + -465.1289462328135 + ], + "logs": [ + "Saved/Linux/l109/captures/after/passage-0-1-0-station-25-mesh.log", + "Saved/Linux/l109/captures/after/passage-0-1-0-station-25-render.log", + "Saved/Linux/l109/captures/after/passage-0-1-0-station-25-quality.log" + ] + }, + { + "name": "passage-0-1-0-station-50", + "passage": "passage/0-1/0", + "kind": "station", + "station": "50%", + "camera": [ + -5.478551888892594, + 21.511593715955158, + -553.9658220811451 + ], + "target": [ + 7.751504608756267, + 21.398972718233775, + -556.3002867114685 + ], + "yaw": 90.48771915686082, + "pitch": -10.006569463318558, + "focus": [ + -5.390306191921176, + 20.7668033447996, + -552.2958220811452 + ], + "center_z": -552.2958220811452, + "route_distance_m": 1007.1986322564579, + "route_length_m": 2014.3972645129159, + "requested_route_distance_m": 1007.1986322564579, + "variant": "after", + "capture": "captures/after/passage-0-1-0-station-50.png", + "scene": "Saved/Linux/l109/captures/after/passage-0-1-0-station-50.vfmesh", + "drawn_triangles": 430386, + "source_triangles": 541436, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1007.1986322564579, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -5.478551888892594, + 21.511593715955158, + -553.9658220811451 + ], + "target_actual_m": [ + 7.751504608756267, + 21.398972718233775, + -556.3002867114685 + ], + "logs": [ + "Saved/Linux/l109/captures/after/passage-0-1-0-station-50-mesh.log", + "Saved/Linux/l109/captures/after/passage-0-1-0-station-50-render.log", + "Saved/Linux/l109/captures/after/passage-0-1-0-station-50-quality.log" + ] + }, + { + "name": "passage-0-1-0-station-75", + "passage": "passage/0-1/0", + "kind": "station", + "station": "75%", + "camera": [ + 16.41045488666863, + -13.591590559867178, + -645.1369534883806 + ], + "target": [ + 6.2905981482465405, + -21.544778689774127, + -647.4714776908803 + ], + "yaw": -128.16377958476315, + "pitch": -10.28040282125882, + "focus": [ + 15.809745384875612, + -13.142538119215107, + -643.4669534883807 + ], + "center_z": -643.4669534883807, + "route_distance_m": 1510.7979483846868, + "route_length_m": 2014.3972645129159, + "requested_route_distance_m": 1510.7979483846868, + "variant": "after", + "capture": "captures/after/passage-0-1-0-station-75.png", + "scene": "Saved/Linux/l109/captures/after/passage-0-1-0-station-75.vfmesh", + "drawn_triangles": 294374, + "source_triangles": 369990, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1510.7979483846868, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 16.41045488666863, + -13.591590559867178, + -645.1369534883806 + ], + "target_actual_m": [ + 6.2905981482465405, + -21.544778689774127, + -647.4714776908803 + ], + "logs": [ + "Saved/Linux/l109/captures/after/passage-0-1-0-station-75-mesh.log", + "Saved/Linux/l109/captures/after/passage-0-1-0-station-75-render.log", + "Saved/Linux/l109/captures/after/passage-0-1-0-station-75-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-1-view-1", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-1/view-1", + "camera": [ + 13.209009551818514, + 6.199300705187415, + -372.004 + ], + "target": [ + 6.375, + 7.507, + -373.104 + ], + "yaw": -79.16730359618066, + "pitch": -8.983620476603383, + "focus": [ + 6.375, + 7.507, + -373.204 + ], + "center_z": -373.204, + "open_air_section": 1, + "route_distance_m": 8.7215, + "requested_route_distance_m": 8.7215, + "route_length_m": 2014.3972645129159, + "variant": "after", + "capture": "captures/after/passage-0-1-0-openair-1-view-1.png", + "scene": "Saved/Linux/l109/captures/after/passage-0-1-0-openair-1-view-1.vfmesh", + "drawn_triangles": 289074, + "source_triangles": 360606, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 8.7215, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 13.209009551818514, + 6.199300705187415, + -372.004 + ], + "target_actual_m": [ + 6.375, + 7.507, + -373.104 + ], + "logs": [ + "Saved/Linux/l109/captures/after/passage-0-1-0-openair-1-view-1-mesh.log", + "Saved/Linux/l109/captures/after/passage-0-1-0-openair-1-view-1-render.log", + "Saved/Linux/l109/captures/after/passage-0-1-0-openair-1-view-1-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-1-view-2", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-1/view-2", + "camera": [ + 1.0142606878664209, + 8.532786540828843, + -369.204 + ], + "target": [ + 6.002022366806118, + 5.557826579189251, + -373.4522149486675 + ], + "yaw": 120.81404399724752, + "pitch": -36.18521056311671, + "focus": [ + 6.375, + 7.507, + -373.204 + ], + "center_z": -373.204, + "open_air_section": 1, + "route_distance_m": 8.7215, + "requested_route_distance_m": 8.7215, + "route_length_m": 2014.3972645129159, + "variant": "after", + "capture": "captures/after/passage-0-1-0-openair-1-view-2.png", + "scene": "Saved/Linux/l109/captures/after/passage-0-1-0-openair-1-view-2.vfmesh", + "drawn_triangles": 298057, + "source_triangles": 371201, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 8.7215, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 1.0142606878664209, + 8.532786540828843, + -369.204 + ], + "target_actual_m": [ + 6.002022366806118, + 5.557826579189251, + -373.4522149486675 + ], + "logs": [ + "Saved/Linux/l109/captures/after/passage-0-1-0-openair-1-view-2-mesh.log", + "Saved/Linux/l109/captures/after/passage-0-1-0-openair-1-view-2-render.log", + "Saved/Linux/l109/captures/after/passage-0-1-0-openair-1-view-2-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-1-view-3", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-1/view-3", + "camera": [ + 6.375, + 7.507, + -373.682 + ], + "target": [ + 5.069578283821414, + 0.6848930271623788, + -374.5507523203363 + ], + "yaw": -169.16730359618066, + "pitch": -7.1292164823138044, + "focus": [ + 6.375, + 7.507, + -373.204 + ], + "center_z": -373.204, + "open_air_section": 1, + "route_distance_m": 8.7215, + "requested_route_distance_m": 8.7215, + "route_length_m": 2014.3972645129159, + "variant": "after", + "capture": "captures/after/passage-0-1-0-openair-1-view-3.png", + "scene": "Saved/Linux/l109/captures/after/passage-0-1-0-openair-1-view-3.vfmesh", + "drawn_triangles": 322309, + "source_triangles": 406051, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 8.7215, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 6.375, + 7.507, + -373.682 + ], + "target_actual_m": [ + 5.069578283821414, + 0.6848930271623788, + -374.5507523203363 + ], + "logs": [ + "Saved/Linux/l109/captures/after/passage-0-1-0-openair-1-view-3-mesh.log", + "Saved/Linux/l109/captures/after/passage-0-1-0-openair-1-view-3-render.log", + "Saved/Linux/l109/captures/after/passage-0-1-0-openair-1-view-3-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-2-view-1", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-2/view-1", + "camera": [ + 12.300736968064577, + -0.41885482108077465, + -372.839 + ], + "target": [ + 5.121, + 0.955, + -373.93899999999996 + ], + "yaw": -79.16730359618062, + "pitch": -8.557593063277757, + "focus": [ + 5.121, + 0.955, + -374.039 + ], + "center_z": -374.039, + "open_air_section": 2, + "route_distance_m": 15.4495, + "requested_route_distance_m": 15.4495, + "route_length_m": 2014.3972645129159, + "variant": "after", + "capture": "captures/after/passage-0-1-0-openair-2-view-1.png", + "scene": "Saved/Linux/l109/captures/after/passage-0-1-0-openair-2-view-1.vfmesh", + "drawn_triangles": 283642, + "source_triangles": 349878, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 15.4495, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 12.300736968064577, + -0.41885482108077465, + -372.839 + ], + "target_actual_m": [ + 5.121, + 0.955, + -373.93899999999996 + ], + "logs": [ + "Saved/Linux/l109/captures/after/passage-0-1-0-openair-2-view-1-mesh.log", + "Saved/Linux/l109/captures/after/passage-0-1-0-openair-2-view-1-render.log", + "Saved/Linux/l109/captures/after/passage-0-1-0-openair-2-view-1-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-2-view-2", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-2/view-2", + "camera": [ + -0.5854667283796422, + 2.0469420670970315, + -370.039 + ], + "target": [ + 4.748022366806118, + -0.9941734208107486, + -374.2872149486675 + ], + "yaw": 119.69146427854264, + "pitch": -34.6808549169467, + "focus": [ + 5.121, + 0.955, + -374.039 + ], + "center_z": -374.039, + "open_air_section": 2, + "route_distance_m": 15.4495, + "requested_route_distance_m": 15.4495, + "route_length_m": 2014.3972645129159, + "variant": "after", + "capture": "captures/after/passage-0-1-0-openair-2-view-2.png", + "scene": "Saved/Linux/l109/captures/after/passage-0-1-0-openair-2-view-2.vfmesh", + "drawn_triangles": 316771, + "source_triangles": 399589, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 15.4495, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -0.5854667283796422, + 2.0469420670970315, + -370.039 + ], + "target_actual_m": [ + 4.748022366806118, + -0.9941734208107486, + -374.2872149486675 + ], + "logs": [ + "Saved/Linux/l109/captures/after/passage-0-1-0-openair-2-view-2-mesh.log", + "Saved/Linux/l109/captures/after/passage-0-1-0-openair-2-view-2-render.log", + "Saved/Linux/l109/captures/after/passage-0-1-0-openair-2-view-2-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-2-view-3", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-2/view-3", + "camera": [ + 5.121, + 0.955, + -374.86899999999997 + ], + "target": [ + 3.8155782838214094, + -5.86710697283762, + -375.73775232033626 + ], + "yaw": -169.1673035961806, + "pitch": -7.1292164823138044, + "focus": [ + 5.121, + 0.955, + -374.039 + ], + "center_z": -374.039, + "open_air_section": 2, + "route_distance_m": 15.4495, + "requested_route_distance_m": 15.4495, + "route_length_m": 2014.3972645129159, + "variant": "after", + "capture": "captures/after/passage-0-1-0-openair-2-view-3.png", + "scene": "Saved/Linux/l109/captures/after/passage-0-1-0-openair-2-view-3.vfmesh", + "drawn_triangles": 322309, + "source_triangles": 406051, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 15.4495, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 5.121, + 0.955, + -374.86899999999997 + ], + "target_actual_m": [ + 3.8155782838214094, + -5.86710697283762, + -375.73775232033626 + ], + "logs": [ + "Saved/Linux/l109/captures/after/passage-0-1-0-openair-2-view-3-mesh.log", + "Saved/Linux/l109/captures/after/passage-0-1-0-openair-2-view-3-render.log", + "Saved/Linux/l109/captures/after/passage-0-1-0-openair-2-view-3-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-3-view-1", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-3/view-1", + "camera": [ + 11.141700220129849, + -8.875616589111877, + -373.90500000000003 + ], + "target": [ + 3.519, + -7.417, + -375.005 + ], + "yaw": -79.1673035961807, + "pitch": -8.067045700553148, + "focus": [ + 3.519, + -7.417, + -375.105 + ], + "center_z": -375.105, + "open_air_section": 3, + "route_distance_m": 24.046, + "requested_route_distance_m": 24.046, + "route_length_m": 2014.3972645129159, + "variant": "after", + "capture": "captures/after/passage-0-1-0-openair-3-view-1.png", + "scene": "Saved/Linux/l109/captures/after/passage-0-1-0-openair-3-view-1.vfmesh", + "drawn_triangles": 262299, + "source_triangles": 321447, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 24.046, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 11.141700220129849, + -8.875616589111877, + -373.90500000000003 + ], + "target_actual_m": [ + 3.519, + -7.417, + -375.005 + ], + "logs": [ + "Saved/Linux/l109/captures/after/passage-0-1-0-openair-3-view-1-mesh.log", + "Saved/Linux/l109/captures/after/passage-0-1-0-openair-3-view-1-render.log", + "Saved/Linux/l109/captures/after/passage-0-1-0-openair-3-view-1-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-3-view-2", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-3/view-2", + "camera": [ + -2.630429980444914, + -6.2402961648718644, + -371.105 + ], + "target": [ + 3.1460223668061196, + -9.36617342081075, + -375.3532149486675 + ], + "yaw": 118.41965303912751, + "pitch": -32.89502331212217, + "focus": [ + 3.519, + -7.417, + -375.105 + ], + "center_z": -375.105, + "open_air_section": 3, + "route_distance_m": 24.046, + "requested_route_distance_m": 24.046, + "route_length_m": 2014.3972645129159, + "variant": "after", + "capture": "captures/after/passage-0-1-0-openair-3-view-2.png", + "scene": "Saved/Linux/l109/captures/after/passage-0-1-0-openair-3-view-2.vfmesh", + "drawn_triangles": 310919, + "source_triangles": 388345, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 24.046, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -2.630429980444914, + -6.2402961648718644, + -371.105 + ], + "target_actual_m": [ + 3.1460223668061196, + -9.36617342081075, + -375.3532149486675 + ], + "logs": [ + "Saved/Linux/l109/captures/after/passage-0-1-0-openair-3-view-2-mesh.log", + "Saved/Linux/l109/captures/after/passage-0-1-0-openair-3-view-2-render.log", + "Saved/Linux/l109/captures/after/passage-0-1-0-openair-3-view-2-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-3-view-3", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-3/view-3", + "camera": [ + 3.519, + -7.417, + -376.386 + ], + "target": [ + 2.2135782838214184, + -14.239106972837622, + -377.2547523203363 + ], + "yaw": -169.16730359618072, + "pitch": -7.1292164823138044, + "focus": [ + 3.519, + -7.417, + -375.105 + ], + "center_z": -375.105, + "open_air_section": 3, + "route_distance_m": 24.046, + "requested_route_distance_m": 24.046, + "route_length_m": 2014.3972645129159, + "variant": "after", + "capture": "captures/after/passage-0-1-0-openair-3-view-3.png", + "scene": "Saved/Linux/l109/captures/after/passage-0-1-0-openair-3-view-3.vfmesh", + "drawn_triangles": 363071, + "source_triangles": 461781, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 24.046, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 3.519, + -7.417, + -376.386 + ], + "target_actual_m": [ + 2.2135782838214184, + -14.239106972837622, + -377.2547523203363 + ], + "logs": [ + "Saved/Linux/l109/captures/after/passage-0-1-0-openair-3-view-3-mesh.log", + "Saved/Linux/l109/captures/after/passage-0-1-0-openair-3-view-3-render.log", + "Saved/Linux/l109/captures/after/passage-0-1-0-openair-3-view-3-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-4-view-1", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-4/view-1", + "camera": [ + -32.482581468460985, + -9.34596705521348, + -597.4219999999999 + ], + "target": [ + -24.253, + -7.219, + -598.5219999999999 + ], + "yaw": 75.50879325593182, + "pitch": -7.373766361330367, + "focus": [ + -24.253, + -7.219, + -598.622 + ], + "center_z": -598.622, + "open_air_section": 4, + "route_distance_m": 1263.117, + "requested_route_distance_m": 1263.117, + "route_length_m": 2014.3972645129159, + "variant": "after", + "capture": "captures/after/passage-0-1-0-openair-4-view-1.png", + "scene": "Saved/Linux/l109/captures/after/passage-0-1-0-openair-4-view-1.vfmesh", + "drawn_triangles": 378007, + "source_triangles": 458499, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1263.117, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -32.482581468460985, + -9.34596705521348, + -597.4219999999999 + ], + "target_actual_m": [ + -24.253, + -7.219, + -598.5219999999999 + ], + "logs": [ + "Saved/Linux/l109/captures/after/passage-0-1-0-openair-4-view-1-mesh.log", + "Saved/Linux/l109/captures/after/passage-0-1-0-openair-4-view-1-render.log", + "Saved/Linux/l109/captures/after/passage-0-1-0-openair-4-view-1-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-4-view-2", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-4/view-2", + "camera": [ + -17.4756976142086, + -5.467380072177135, + -594.622 + ], + "target": [ + -24.74519610426594, + -5.314613221376807, + -598.9840138013261 + ], + "yaw": -88.79611947547781, + "pitch": -30.960000123282537, + "focus": [ + -24.253, + -7.219, + -598.622 + ], + "center_z": -598.622, + "open_air_section": 4, + "route_distance_m": 1263.117, + "requested_route_distance_m": 1263.117, + "route_length_m": 2014.3972645129159, + "variant": "after", + "capture": "captures/after/passage-0-1-0-openair-4-view-2.png", + "scene": "Saved/Linux/l109/captures/after/passage-0-1-0-openair-4-view-2.vfmesh", + "drawn_triangles": 471132, + "source_triangles": 576768, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1263.117, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -17.4756976142086, + -5.467380072177135, + -594.622 + ], + "target_actual_m": [ + -24.74519610426594, + -5.314613221376807, + -598.9840138013261 + ], + "logs": [ + "Saved/Linux/l109/captures/after/passage-0-1-0-openair-4-view-2-mesh.log", + "Saved/Linux/l109/captures/after/passage-0-1-0-openair-4-view-2-render.log", + "Saved/Linux/l109/captures/after/passage-0-1-0-openair-4-view-2-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-4-view-3", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-4/view-3", + "camera": [ + -24.253, + -7.219, + -600.6419999999999 + ], + "target": [ + -25.975686364930784, + -0.5536462748188242, + -601.9090483046415 + ], + "yaw": -14.491206744068183, + "pitch": -10.428414406509091, + "focus": [ + -24.253, + -7.219, + -598.622 + ], + "center_z": -598.622, + "open_air_section": 4, + "route_distance_m": 1263.117, + "requested_route_distance_m": 1263.117, + "route_length_m": 2014.3972645129159, + "variant": "after", + "capture": "captures/after/passage-0-1-0-openair-4-view-3.png", + "scene": "Saved/Linux/l109/captures/after/passage-0-1-0-openair-4-view-3.vfmesh", + "drawn_triangles": 382187, + "source_triangles": 466847, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1263.117, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -24.253, + -7.219, + -600.6419999999999 + ], + "target_actual_m": [ + -25.975686364930784, + -0.5536462748188242, + -601.9090483046415 + ], + "logs": [ + "Saved/Linux/l109/captures/after/passage-0-1-0-openair-4-view-3-mesh.log", + "Saved/Linux/l109/captures/after/passage-0-1-0-openair-4-view-3-render.log", + "Saved/Linux/l109/captures/after/passage-0-1-0-openair-4-view-3-quality.log" + ] + }, + { + "name": "passage-1-2-0-upper-mouth", + "passage": "passage/1-2/0", + "kind": "mouth", + "station": "upper-mouth", + "camera": [ + 23.155674552687962, + -16.14908662400146, + -731.7810546875 + ], + "target": [ + 17.392833879360907, + -13.33402139627713, + -731.8810546875 + ], + "yaw": -63.965152623598414, + "pitch": -0.8932686436727578, + "focus": [ + 19.166015625, + -14.2001953125, + -730.5610546875 + ], + "center_z": -730.5610546875, + "variant": "after", + "capture": "captures/after/passage-1-2-0-upper-mouth.png", + "scene": "Saved/Linux/l109/captures/after/passage-1-2-0-upper-mouth.vfmesh", + "drawn_triangles": 570417, + "source_triangles": 630011, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": null, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 23.155674552687962, + -16.14908662400146, + -731.7810546875 + ], + "target_actual_m": [ + 17.392833879360907, + -13.33402139627713, + -731.8810546875 + ], + "logs": [ + "Saved/Linux/l109/captures/after/passage-1-2-0-upper-mouth-mesh.log", + "Saved/Linux/l109/captures/after/passage-1-2-0-upper-mouth-render.log", + "Saved/Linux/l109/captures/after/passage-1-2-0-upper-mouth-quality.log" + ] + }, + { + "name": "passage-1-2-0-lower-mouth", + "passage": "passage/1-2/0", + "kind": "mouth", + "station": "lower-mouth", + "camera": [ + 27.669370041560203, + -17.931687050798093, + -752.0090260818968 + ], + "target": [ + 17.37583574782943, + -13.414618104437244, + -753.05390625 + ], + "yaw": -66.30689197709175, + "pitch": -5.3105178623917535, + "focus": [ + 19.166015625, + -14.2001953125, + -751.73390625 + ], + "center_z": -751.73390625, + "variant": "after", + "capture": "captures/after/passage-1-2-0-lower-mouth.png", + "scene": "Saved/Linux/l109/captures/after/passage-1-2-0-lower-mouth.vfmesh", + "drawn_triangles": 511318, + "source_triangles": 542780, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": null, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 27.669370041560203, + -17.931687050798093, + -752.0090260818968 + ], + "target_actual_m": [ + 17.37583574782943, + -13.414618104437244, + -753.05390625 + ], + "logs": [ + "Saved/Linux/l109/captures/after/passage-1-2-0-lower-mouth-mesh.log", + "Saved/Linux/l109/captures/after/passage-1-2-0-lower-mouth-render.log", + "Saved/Linux/l109/captures/after/passage-1-2-0-lower-mouth-quality.log" + ] + }, + { + "name": "passage-1-2-0-station-25", + "passage": "passage/1-2/0", + "kind": "station", + "station": "25%", + "camera": [ + 13.839984288397812, + 6.587904286061814, + -736.8018138353019 + ], + "target": [ + 2.363156319326185, + 14.183439358820996, + -739.2050534708565 + ], + "yaw": -56.5028177078219, + "pitch": -9.905162260563504, + "focus": [ + 14.477989100250685, + 6.982175588660137, + -735.631813835302 + ], + "center_z": -735.631813835302, + "route_distance_m": 28.46821190286393, + "route_length_m": 113.87284761145573, + "requested_route_distance_m": 28.46821190286393, + "variant": "after", + "capture": "captures/after/passage-1-2-0-station-25.png", + "scene": "Saved/Linux/l109/captures/after/passage-1-2-0-station-25.vfmesh", + "drawn_triangles": 661032, + "source_triangles": 762668, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 28.46821190286393, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 13.839984288397812, + 6.587904286061814, + -736.8018138353019 + ], + "target_actual_m": [ + 2.363156319326185, + 14.183439358820996, + -739.2050534708565 + ], + "logs": [ + "Saved/Linux/l109/captures/after/passage-1-2-0-station-25-mesh.log", + "Saved/Linux/l109/captures/after/passage-1-2-0-station-25-render.log", + "Saved/Linux/l109/captures/after/passage-1-2-0-station-25-quality.log" + ] + }, + { + "name": "passage-1-2-0-station-50", + "passage": "passage/1-2/0", + "kind": "station", + "station": "50%", + "camera": [ + -8.371258739883528, + 11.724083505834441, + -742.0951650605518 + ], + "target": [ + -12.783765342228843, + -1.6446342816727475, + -744.4990059410221 + ], + "yaw": -161.73390326754287, + "pitch": -9.689827619924415, + "focus": [ + -8.819483630432973, + 12.325410744109856, + -740.9251650605519 + ], + "center_z": -740.9251650605519, + "route_distance_m": 56.93642380572786, + "route_length_m": 113.87284761145573, + "requested_route_distance_m": 56.93642380572786, + "variant": "after", + "capture": "captures/after/passage-1-2-0-station-50.png", + "scene": "Saved/Linux/l109/captures/after/passage-1-2-0-station-50.vfmesh", + "drawn_triangles": 602996, + "source_triangles": 681672, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 56.93642380572786, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -8.371258739883528, + 11.724083505834441, + -742.0951650605518 + ], + "target_actual_m": [ + -12.783765342228843, + -1.6446342816727475, + -744.4990059410221 + ], + "logs": [ + "Saved/Linux/l109/captures/after/passage-1-2-0-station-50-mesh.log", + "Saved/Linux/l109/captures/after/passage-1-2-0-station-50-render.log", + "Saved/Linux/l109/captures/after/passage-1-2-0-station-50-quality.log" + ] + }, + { + "name": "passage-1-2-0-station-75", + "passage": "passage/1-2/0", + "kind": "station", + "station": "75%", + "camera": [ + -6.586769568915752, + -10.735033108069532, + -747.3888312649981 + ], + "target": [ + 7.430752597530391, + -10.891774630023567, + -749.7924798389191 + ], + "yaw": 90.6406448523091, + "pitch": -9.729542154499603, + "focus": [ + -6.9939308656579335, + -11.364889979457965, + -746.2188312649981 + ], + "center_z": -746.2188312649981, + "route_distance_m": 85.4046357085918, + "route_length_m": 113.87284761145573, + "requested_route_distance_m": 85.4046357085918, + "variant": "after", + "capture": "captures/after/passage-1-2-0-station-75.png", + "scene": "Saved/Linux/l109/captures/after/passage-1-2-0-station-75.vfmesh", + "drawn_triangles": 615520, + "source_triangles": 696694, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 85.4046357085918, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -6.586769568915752, + -10.735033108069532, + -747.3888312649981 + ], + "target_actual_m": [ + 7.430752597530391, + -10.891774630023567, + -749.7924798389191 + ], + "logs": [ + "Saved/Linux/l109/captures/after/passage-1-2-0-station-75-mesh.log", + "Saved/Linux/l109/captures/after/passage-1-2-0-station-75-render.log", + "Saved/Linux/l109/captures/after/passage-1-2-0-station-75-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-1-view-1", + "passage": "passage/1-2/0", + "kind": "open-air", + "station": "section-1/view-1", + "camera": [ + 5.970328502711869, + -4.077984872526297, + -748.2339999999999 + ], + "target": [ + 9.136, + -11.613, + -749.334 + ], + "yaw": 157.21135612217134, + "pitch": -7.6653476882049, + "focus": [ + 9.136, + -11.613, + -749.434 + ], + "center_z": -749.434, + "open_air_section": 1, + "route_distance_m": 103.1595, + "requested_route_distance_m": 103.1595, + "route_length_m": 113.87284761145573, + "variant": "after", + "capture": "captures/after/passage-1-2-0-openair-1-view-1.png", + "scene": "Saved/Linux/l109/captures/after/passage-1-2-0-openair-1-view-1.vfmesh", + "drawn_triangles": 629052, + "source_triangles": 721352, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 103.1595, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 5.970328502711869, + -4.077984872526297, + -748.2339999999999 + ], + "target_actual_m": [ + 9.136, + -11.613, + -749.334 + ], + "logs": [ + "Saved/Linux/l109/captures/after/passage-1-2-0-openair-1-view-1-mesh.log", + "Saved/Linux/l109/captures/after/passage-1-2-0-openair-1-view-1-render.log", + "Saved/Linux/l109/captures/after/passage-1-2-0-openair-1-view-1-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-1-view-2", + "passage": "passage/1-2/0", + "kind": "open-air", + "station": "section-1/view-2", + "camera": [ + 11.720672201321875, + -17.765105217867614, + -745.434 + ], + "target": [ + 10.94776719052517, + -10.851825714648527, + -749.8056360513408 + ], + "yaw": -6.379180837289254, + "pitch": -32.14682033821005, + "focus": [ + 9.136, + -11.613, + -749.434 + ], + "center_z": -749.434, + "open_air_section": 1, + "route_distance_m": 103.1595, + "requested_route_distance_m": 103.1595, + "route_length_m": 113.87284761145573, + "variant": "after", + "capture": "captures/after/passage-1-2-0-openair-1-view-2.png", + "scene": "Saved/Linux/l109/captures/after/passage-1-2-0-openair-1-view-2.vfmesh", + "drawn_triangles": 588414, + "source_triangles": 654974, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 103.1595, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 11.720672201321875, + -17.765105217867614, + -745.434 + ], + "target_actual_m": [ + 10.94776719052517, + -10.851825714648527, + -749.8056360513408 + ], + "logs": [ + "Saved/Linux/l109/captures/after/passage-1-2-0-openair-1-view-2-mesh.log", + "Saved/Linux/l109/captures/after/passage-1-2-0-openair-1-view-2-render.log", + "Saved/Linux/l109/captures/after/passage-1-2-0-openair-1-view-2-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-1-view-3", + "passage": "passage/1-2/0", + "kind": "open-air", + "station": "section-1/view-3", + "camera": [ + 9.136, + -11.613, + -750.954 + ], + "target": [ + 15.477185166838094, + -8.948890001269849, + -752.2547261796929 + ], + "yaw": 67.21135612217135, + "pitch": -10.708828804851287, + "focus": [ + 9.136, + -11.613, + -749.434 + ], + "center_z": -749.434, + "open_air_section": 1, + "route_distance_m": 103.1595, + "requested_route_distance_m": 103.1595, + "route_length_m": 113.87284761145573, + "variant": "after", + "capture": "captures/after/passage-1-2-0-openair-1-view-3.png", + "scene": "Saved/Linux/l109/captures/after/passage-1-2-0-openair-1-view-3.vfmesh", + "drawn_triangles": 616234, + "source_triangles": 698168, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 103.1595, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 9.136, + -11.613, + -750.954 + ], + "target_actual_m": [ + 15.477185166838094, + -8.948890001269849, + -752.2547261796929 + ], + "logs": [ + "Saved/Linux/l109/captures/after/passage-1-2-0-openair-1-view-3-mesh.log", + "Saved/Linux/l109/captures/after/passage-1-2-0-openair-1-view-3-render.log", + "Saved/Linux/l109/captures/after/passage-1-2-0-openair-1-view-3-quality.log" + ] + }, + { + "name": "passage-2-3-0-upper-mouth", + "passage": "passage/2-3/0", + "kind": "mouth", + "station": "upper-mouth", + "camera": [ + -24.510890451086325, + -4.955138452601283, + -811.975390625 + ], + "target": [ + -18.085437577294964, + -5.118679784954985, + -812.075390625 + ], + "yaw": 91.4579836961561, + "pitch": -0.8913396541976134, + "focus": [ + -20.0625, + -5.068359375, + -810.755390625 + ], + "center_z": -810.755390625, + "variant": "after", + "capture": "captures/after/passage-2-3-0-upper-mouth.png", + "scene": "Saved/Linux/l109/captures/after/passage-2-3-0-upper-mouth.vfmesh", + "drawn_triangles": 59562, + "source_triangles": 71470, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": null, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -24.510890451086325, + -4.955138452601283, + -811.975390625 + ], + "target_actual_m": [ + -18.085437577294964, + -5.118679784954985, + -812.075390625 + ], + "logs": [ + "Saved/Linux/l109/captures/after/passage-2-3-0-upper-mouth-mesh.log", + "Saved/Linux/l109/captures/after/passage-2-3-0-upper-mouth-render.log", + "Saved/Linux/l109/captures/after/passage-2-3-0-upper-mouth-quality.log" + ] + }, + { + "name": "passage-2-3-0-lower-mouth", + "passage": "passage/2-3/0", + "kind": "mouth", + "station": "lower-mouth", + "camera": [ + -29.049715742915396, + -2.779103580443535, + -899.0170545422176 + ], + "target": [ + -18.170454580438843, + -5.550307963327683, + -900.0333984375 + ], + "yaw": 104.29068028993358, + "pitch": -5.172857326977102, + "focus": [ + -20.062499999999982, + -5.068359375000004, + -898.7133984375 + ], + "center_z": -898.7133984375, + "variant": "after", + "capture": "captures/after/passage-2-3-0-lower-mouth.png", + "scene": "Saved/Linux/l109/captures/after/passage-2-3-0-lower-mouth.vfmesh", + "drawn_triangles": 294522, + "source_triangles": 315506, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": null, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -29.049715742915396, + -2.779103580443535, + -899.0170545422176 + ], + "target_actual_m": [ + -18.170454580438843, + -5.550307963327683, + -900.0333984375 + ], + "logs": [ + "Saved/Linux/l109/captures/after/passage-2-3-0-lower-mouth-mesh.log", + "Saved/Linux/l109/captures/after/passage-2-3-0-lower-mouth-render.log", + "Saved/Linux/l109/captures/after/passage-2-3-0-lower-mouth-quality.log" + ] + }, + { + "name": "passage-2-3-0-station-25", + "passage": "passage/2-3/0", + "kind": "station", + "station": "25%", + "camera": [ + 3.3629477943069905, + -13.28264789111628, + -833.6924223707634 + ], + "target": [ + 14.057544579024707, + -4.268177781320185, + -836.0006826204402 + ], + "yaw": 49.87247810025953, + "pitch": -9.371026953528995, + "focus": [ + 3.463454182082567, + -14.025883026195553, + -832.5224223707635 + ], + "center_z": -832.5224223707635, + "route_distance_m": 122.71082287166668, + "route_length_m": 490.8432914866667, + "requested_route_distance_m": 122.71082287166668, + "variant": "after", + "capture": "captures/after/passage-2-3-0-station-25.png", + "scene": "Saved/Linux/l109/captures/after/passage-2-3-0-station-25.vfmesh", + "drawn_triangles": 55484, + "source_triangles": 66458, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 122.71082287166668, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 3.3629477943069905, + -13.28264789111628, + -833.6924223707634 + ], + "target_actual_m": [ + 14.057544579024707, + -4.268177781320185, + -836.0006826204402 + ], + "logs": [ + "Saved/Linux/l109/captures/after/passage-2-3-0-station-25-mesh.log", + "Saved/Linux/l109/captures/after/passage-2-3-0-station-25-render.log", + "Saved/Linux/l109/captures/after/passage-2-3-0-station-25-quality.log" + ] + }, + { + "name": "passage-2-3-0-station-50", + "passage": "passage/2-3/0", + "kind": "station", + "station": "50%", + "camera": [ + 14.714964374766744, + 4.426031524861205, + -855.6817931947601 + ], + "target": [ + 3.8569544509891096, + 13.535757747237458, + -857.9904777239444 + ], + "yaw": -50.003796291172236, + "pitch": -9.251614459440251, + "focus": [ + 15.448414166573603, + 4.582720397786105, + -854.5117931947601 + ], + "center_z": -854.5117931947601, + "route_distance_m": 245.42164574333336, + "route_length_m": 490.8432914866667, + "requested_route_distance_m": 245.42164574333336, + "variant": "after", + "capture": "captures/after/passage-2-3-0-station-50.png", + "scene": "Saved/Linux/l109/captures/after/passage-2-3-0-station-50.vfmesh", + "drawn_triangles": 457754, + "source_triangles": 479058, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 245.42164574333336, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 14.714964374766744, + 4.426031524861205, + -855.6817931947601 + ], + "target_actual_m": [ + 3.8569544509891096, + 13.535757747237458, + -857.9904777239444 + ], + "logs": [ + "Saved/Linux/l109/captures/after/passage-2-3-0-station-50-mesh.log", + "Saved/Linux/l109/captures/after/passage-2-3-0-station-50-render.log", + "Saved/Linux/l109/captures/after/passage-2-3-0-station-50-quality.log" + ] + }, + { + "name": "passage-2-3-0-station-75", + "passage": "passage/2-3/0", + "kind": "station", + "station": "75%", + "camera": [ + -5.760169952738466, + 11.295442453574074, + -877.6716971250207 + ], + "target": [ + -12.206687475534688, + -0.996781882252304, + -879.9807693267177 + ], + "yaw": -152.32574657735572, + "pitch": -9.445159710566168, + "focus": [ + -6.190732087251391, + 11.909540367854586, + -876.5016971250208 + ], + "center_z": -876.5016971250208, + "route_distance_m": 368.13246861500005, + "route_length_m": 490.8432914866667, + "requested_route_distance_m": 368.13246861500005, + "variant": "after", + "capture": "captures/after/passage-2-3-0-station-75.png", + "scene": "Saved/Linux/l109/captures/after/passage-2-3-0-station-75.vfmesh", + "drawn_triangles": 475706, + "source_triangles": 506686, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 368.13246861500005, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -5.760169952738466, + 11.295442453574074, + -877.6716971250207 + ], + "target_actual_m": [ + -12.206687475534688, + -0.996781882252304, + -879.9807693267177 + ], + "logs": [ + "Saved/Linux/l109/captures/after/passage-2-3-0-station-75-mesh.log", + "Saved/Linux/l109/captures/after/passage-2-3-0-station-75-render.log", + "Saved/Linux/l109/captures/after/passage-2-3-0-station-75-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-1-view-1", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-1/view-1", + "camera": [ + -1.189937432971333, + -5.322285697427915, + -813.0459999999999 + ], + "target": [ + -2.846, + -13.149, + -814.146 + ], + "yaw": -168.05293971491665, + "pitch": -7.829076510059767, + "focus": [ + -2.846, + -13.149, + -814.246 + ], + "center_z": -814.246, + "open_air_section": 1, + "route_distance_m": 21.212, + "requested_route_distance_m": 21.212, + "route_length_m": 490.8432914866667, + "variant": "after", + "capture": "captures/after/passage-2-3-0-openair-1-view-1.png", + "scene": "Saved/Linux/l109/captures/after/passage-2-3-0-openair-1-view-1.vfmesh", + "drawn_triangles": 104612, + "source_triangles": 129366, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 21.212, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -1.189937432971333, + -5.322285697427915, + -813.0459999999999 + ], + "target_actual_m": [ + -2.846, + -13.149, + -814.146 + ], + "logs": [ + "Saved/Linux/l109/captures/after/passage-2-3-0-openair-1-view-1-mesh.log", + "Saved/Linux/l109/captures/after/passage-2-3-0-openair-1-view-1-render.log", + "Saved/Linux/l109/captures/after/passage-2-3-0-openair-1-view-1-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-1-view-2", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-1/view-2", + "camera": [ + -4.1915508357107925, + -19.508205370839818, + -810.246 + ], + "target": [ + -0.9210204431637441, + -13.556308413611612, + -814.6045436681405 + ], + "yaw": 28.788521091259426, + "pitch": -32.69176164676129, + "focus": [ + -2.846, + -13.149, + -814.246 + ], + "center_z": -814.246, + "open_air_section": 1, + "route_distance_m": 21.212, + "requested_route_distance_m": 21.212, + "route_length_m": 490.8432914866667, + "variant": "after", + "capture": "captures/after/passage-2-3-0-openair-1-view-2.png", + "scene": "Saved/Linux/l109/captures/after/passage-2-3-0-openair-1-view-2.vfmesh", + "drawn_triangles": 81078, + "source_triangles": 99432, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 21.212, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -4.1915508357107925, + -19.508205370839818, + -810.246 + ], + "target_actual_m": [ + -0.9210204431637441, + -13.556308413611612, + -814.6045436681405 + ], + "logs": [ + "Saved/Linux/l109/captures/after/passage-2-3-0-openair-1-view-2-mesh.log", + "Saved/Linux/l109/captures/after/passage-2-3-0-openair-1-view-2-render.log", + "Saved/Linux/l109/captures/after/passage-2-3-0-openair-1-view-2-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-1-view-3", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-1/view-3", + "camera": [ + -2.846, + -13.149, + -815.766 + ], + "target": [ + 3.891428448926896, + -14.574579447640645, + -817.0209028384919 + ], + "yaw": 101.94706028508335, + "pitch": -10.327349081567025, + "focus": [ + -2.846, + -13.149, + -814.246 + ], + "center_z": -814.246, + "open_air_section": 1, + "route_distance_m": 21.212, + "requested_route_distance_m": 21.212, + "route_length_m": 490.8432914866667, + "variant": "after", + "capture": "captures/after/passage-2-3-0-openair-1-view-3.png", + "scene": "Saved/Linux/l109/captures/after/passage-2-3-0-openair-1-view-3.vfmesh", + "drawn_triangles": 94962, + "source_triangles": 118068, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 21.212, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -2.846, + -13.149, + -815.766 + ], + "target_actual_m": [ + 3.891428448926896, + -14.574579447640645, + -817.0209028384919 + ], + "logs": [ + "Saved/Linux/l109/captures/after/passage-2-3-0-openair-1-view-3-mesh.log", + "Saved/Linux/l109/captures/after/passage-2-3-0-openair-1-view-3-render.log", + "Saved/Linux/l109/captures/after/passage-2-3-0-openair-1-view-3-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-2-view-1", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-2/view-1", + "camera": [ + -2.9130850464832285, + 5.083885109955194, + -876.048 + ], + "target": [ + -9.545, + 9.558, + -877.148 + ], + "yaw": -55.995061323335754, + "pitch": -7.829076510059767, + "focus": [ + -9.545, + 9.558, + -877.248 + ], + "center_z": -877.248, + "open_air_section": 2, + "route_distance_m": 372.7845, + "requested_route_distance_m": 372.7845, + "route_length_m": 490.8432914866667, + "variant": "after", + "capture": "captures/after/passage-2-3-0-openair-2-view-1.png", + "scene": "Saved/Linux/l109/captures/after/passage-2-3-0-openair-2-view-1.vfmesh", + "drawn_triangles": 475688, + "source_triangles": 507502, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 372.7845, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -2.9130850464832285, + 5.083885109955194, + -876.048 + ], + "target_actual_m": [ + -9.545, + 9.558, + -877.148 + ], + "logs": [ + "Saved/Linux/l109/captures/after/passage-2-3-0-openair-2-view-1-mesh.log", + "Saved/Linux/l109/captures/after/passage-2-3-0-openair-2-view-1-render.log", + "Saved/Linux/l109/captures/after/passage-2-3-0-openair-2-view-1-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-2-view-2", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-2/view-2", + "camera": [ + -14.933430899732377, + 13.193218348161405, + -873.248 + ], + "target": [ + -10.645401808697681, + 7.926890520398333, + -877.6066052494994 + ], + "yaw": 140.84630886232915, + "pitch": -32.69214209091069, + "focus": [ + -9.545, + 9.558, + -877.248 + ], + "center_z": -877.248, + "open_air_section": 2, + "route_distance_m": 372.7845, + "requested_route_distance_m": 372.7845, + "route_length_m": 490.8432914866667, + "variant": "after", + "capture": "captures/after/passage-2-3-0-openair-2-view-2.png", + "scene": "Saved/Linux/l109/captures/after/passage-2-3-0-openair-2-view-2.vfmesh", + "drawn_triangles": 479134, + "source_triangles": 506272, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 372.7845, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -14.933430899732377, + 13.193218348161405, + -873.248 + ], + "target_actual_m": [ + -10.645401808697681, + 7.926890520398333, + -877.6066052494994 + ], + "logs": [ + "Saved/Linux/l109/captures/after/passage-2-3-0-openair-2-view-2-mesh.log", + "Saved/Linux/l109/captures/after/passage-2-3-0-openair-2-view-2-render.log", + "Saved/Linux/l109/captures/after/passage-2-3-0-openair-2-view-2-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-2-view-3", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-2/view-3", + "camera": [ + -9.545, + 9.558, + -878.768 + ], + "target": [ + -13.396406330441884, + 3.8491168213941664, + -880.0231183732476 + ], + "yaw": -145.99506132333573, + "pitch": -10.329142313691902, + "focus": [ + -9.545, + 9.558, + -877.248 + ], + "center_z": -877.248, + "open_air_section": 2, + "route_distance_m": 372.7845, + "requested_route_distance_m": 372.7845, + "route_length_m": 490.8432914866667, + "variant": "after", + "capture": "captures/after/passage-2-3-0-openair-2-view-3.png", + "scene": "Saved/Linux/l109/captures/after/passage-2-3-0-openair-2-view-3.vfmesh", + "drawn_triangles": 479134, + "source_triangles": 506272, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 372.7845, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -9.545, + 9.558, + -878.768 + ], + "target_actual_m": [ + -13.396406330441884, + 3.8491168213941664, + -880.0231183732476 + ], + "logs": [ + "Saved/Linux/l109/captures/after/passage-2-3-0-openair-2-view-3-mesh.log", + "Saved/Linux/l109/captures/after/passage-2-3-0-openair-2-view-3-render.log", + "Saved/Linux/l109/captures/after/passage-2-3-0-openair-2-view-3-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-3-view-1", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-3/view-1", + "camera": [ + -4.259540253679528, + -6.656854577309242, + -880.059 + ], + "target": [ + -11.172, + -10.684, + -881.159 + ], + "yaw": -120.224745904394, + "pitch": -7.829076510059767, + "focus": [ + -11.172, + -10.684, + -881.259 + ], + "center_z": -881.259, + "open_air_section": 3, + "route_distance_m": 395.169, + "requested_route_distance_m": 395.169, + "route_length_m": 490.8432914866667, + "variant": "after", + "capture": "captures/after/passage-2-3-0-openair-3-view-1.png", + "scene": "Saved/Linux/l109/captures/after/passage-2-3-0-openair-3-view-1.vfmesh", + "drawn_triangles": 485216, + "source_triangles": 518310, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 395.169, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -4.259540253679528, + -6.656854577309242, + -880.059 + ], + "target_actual_m": [ + -11.172, + -10.684, + -881.159 + ], + "logs": [ + "Saved/Linux/l109/captures/after/passage-2-3-0-openair-3-view-1-mesh.log", + "Saved/Linux/l109/captures/after/passage-2-3-0-openair-3-view-1-render.log", + "Saved/Linux/l109/captures/after/passage-2-3-0-openair-3-view-1-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-3-view-2", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-3/view-2", + "camera": [ + -16.788373543885385, + -13.95605565593624, + -877.259 + ], + "target": [ + -10.181507700208023, + -12.384146737382467, + -881.6173658401976 + ], + "yaw": 76.6169764950821, + "pitch": -32.69066303746625, + "focus": [ + -11.172, + -10.684, + -881.259 + ], + "center_z": -881.259, + "open_air_section": 3, + "route_distance_m": 395.169, + "requested_route_distance_m": 395.169, + "route_length_m": 490.8432914866667, + "variant": "after", + "capture": "captures/after/passage-2-3-0-openair-3-view-2.png", + "scene": "Saved/Linux/l109/captures/after/passage-2-3-0-openair-3-view-2.vfmesh", + "drawn_triangles": 479198, + "source_triangles": 497212, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 395.169, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -16.788373543885385, + -13.95605565593624, + -877.259 + ], + "target_actual_m": [ + -10.181507700208023, + -12.384146737382467, + -881.6173658401976 + ], + "logs": [ + "Saved/Linux/l109/captures/after/passage-2-3-0-openair-3-view-2-mesh.log", + "Saved/Linux/l109/captures/after/passage-2-3-0-openair-3-view-2-render.log", + "Saved/Linux/l109/captures/after/passage-2-3-0-openair-3-view-2-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-3-view-3", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-3/view-3", + "camera": [ + -11.172, + -10.684, + -882.779 + ], + "target": [ + -7.70527695072808, + -16.63451358083864, + -884.0332804406917 + ], + "yaw": 149.77525409560604, + "pitch": -10.322170838480888, + "focus": [ + -11.172, + -10.684, + -881.259 + ], + "center_z": -881.259, + "open_air_section": 3, + "route_distance_m": 395.169, + "requested_route_distance_m": 395.169, + "route_length_m": 490.8432914866667, + "variant": "after", + "capture": "captures/after/passage-2-3-0-openair-3-view-3.png", + "scene": "Saved/Linux/l109/captures/after/passage-2-3-0-openair-3-view-3.vfmesh", + "drawn_triangles": 490436, + "source_triangles": 519892, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 395.169, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -11.172, + -10.684, + -882.779 + ], + "target_actual_m": [ + -7.70527695072808, + -16.63451358083864, + -884.0332804406917 + ], + "logs": [ + "Saved/Linux/l109/captures/after/passage-2-3-0-openair-3-view-3-mesh.log", + "Saved/Linux/l109/captures/after/passage-2-3-0-openair-3-view-3-render.log", + "Saved/Linux/l109/captures/after/passage-2-3-0-openair-3-view-3-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-4-view-1", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-4/view-1", + "camera": [ + 5.6333128025989625, + 3.3735740461566257, + -889.2199999999999 + ], + "target": [ + 9.72, + 10.251, + -890.3199999999999 + ], + "yaw": 30.71952465304602, + "pitch": -7.8290765100597675, + "focus": [ + 9.72, + 10.251, + -890.42 + ], + "center_z": -890.42, + "open_air_section": 4, + "route_distance_m": 446.293, + "requested_route_distance_m": 446.293, + "route_length_m": 490.8432914866667, + "variant": "after", + "capture": "captures/after/passage-2-3-0-openair-4-view-1.png", + "scene": "Saved/Linux/l109/captures/after/passage-2-3-0-openair-4-view-1.vfmesh", + "drawn_triangles": 475298, + "source_triangles": 507112, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 446.293, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 5.6333128025989625, + 3.3735740461566257, + -889.2199999999999 + ], + "target_actual_m": [ + 9.72, + 10.251, + -890.3199999999999 + ], + "logs": [ + "Saved/Linux/l109/captures/after/passage-2-3-0-openair-4-view-1-mesh.log", + "Saved/Linux/l109/captures/after/passage-2-3-0-openair-4-view-1-render.log", + "Saved/Linux/l109/captures/after/passage-2-3-0-openair-4-view-1-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-4-view-2", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-4/view-2", + "camera": [ + 13.040433347888344, + 15.838908587497741, + -886.42 + ], + "target": [ + 8.028477501069965, + 11.25613235429748, + -890.7784139868335 + ], + "yaw": -132.43882376014432, + "pitch": -32.69096048480686, + "focus": [ + 9.72, + 10.251, + -890.42 + ], + "center_z": -890.42, + "open_air_section": 4, + "route_distance_m": 446.293, + "requested_route_distance_m": 446.293, + "route_length_m": 490.8432914866667, + "variant": "after", + "capture": "captures/after/passage-2-3-0-openair-4-view-2.png", + "scene": "Saved/Linux/l109/captures/after/passage-2-3-0-openair-4-view-2.vfmesh", + "drawn_triangles": 495856, + "source_triangles": 530508, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 446.293, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 13.040433347888344, + 15.838908587497741, + -886.42 + ], + "target_actual_m": [ + 8.028477501069965, + 11.25613235429748, + -890.7784139868335 + ], + "logs": [ + "Saved/Linux/l109/captures/after/passage-2-3-0-openair-4-view-2-mesh.log", + "Saved/Linux/l109/captures/after/passage-2-3-0-openair-4-view-2-render.log", + "Saved/Linux/l109/captures/after/passage-2-3-0-openair-4-view-2-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-4-view-3", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-4/view-3", + "camera": [ + 9.72, + 10.251, + -891.9399999999999 + ], + "target": [ + 3.7996712537448776, + 13.768963240041181, + -893.1944489539172 + ], + "yaw": -59.280475346953985, + "pitch": -10.32357283123646, + "focus": [ + 9.72, + 10.251, + -890.42 + ], + "center_z": -890.42, + "open_air_section": 4, + "route_distance_m": 446.293, + "requested_route_distance_m": 446.293, + "route_length_m": 490.8432914866667, + "variant": "after", + "capture": "captures/after/passage-2-3-0-openair-4-view-3.png", + "scene": "Saved/Linux/l109/captures/after/passage-2-3-0-openair-4-view-3.vfmesh", + "drawn_triangles": 496236, + "source_triangles": 531424, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 446.293, + "route_station_adjustment_m": 0.0, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 9.72, + 10.251, + -891.9399999999999 + ], + "target_actual_m": [ + 3.7996712537448776, + 13.768963240041181, + -893.1944489539172 + ], + "logs": [ + "Saved/Linux/l109/captures/after/passage-2-3-0-openair-4-view-3-mesh.log", + "Saved/Linux/l109/captures/after/passage-2-3-0-openair-4-view-3-render.log", + "Saved/Linux/l109/captures/after/passage-2-3-0-openair-4-view-3-quality.log" + ] + } + ] +} diff --git a/Standalone/Research/WorldAssemblerM3/Linux111/REPORT.md b/Standalone/Research/WorldAssemblerM3/Linux111/REPORT.md new file mode 100644 index 0000000..7099861 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux111/REPORT.md @@ -0,0 +1,42 @@ +# Linux111 report + +## Design + +Version 218 resamples passage controls with a centripetal Catmull–Rom curve at about 1 m spacing (310 control spans became 2,790 prepared segments). Open-air shells use a 0.75 m floor slab and side walls up to 1.0 m above the floor; there is no roof. Passage interior remains higher priority than shell. The second design constrained the floor route to a 14.5° grade ceiling. + +The per-tile candidate lists were not measured. The 310→2,790 figures are prepared route segment counts, not tile candidate list sizes. + +## Speed + +L109 medians below are the candidate column from the saved five-pair timing matrix. L111 timing was not run after the audits failed. + +| Stratum | L109 W8 near-ready (s) | L109 W12 near-ready (s) | L111 W8/W12 | +|---|---:|---:|---| +| SurfaceWorld | 0.737 | 0.761 | Not run | +| FloatingIslands | 0.911 | 0.863 | Not run | +| TunnelNetwork | 0.956 | 0.895 | Not run | +| VerticalShafts | 0.789 | 0.738 | Not run | + +## Audits + +- Clang standalone build completed. The second design removed all grade failures. Passage 0–1 still had 2 unsupported walk samples; passages 1–2 and 2–3 passed. The combined resolved-passage audit failed. +- Mouth-profile audits passed 3/3. Naturalness and ripple audits passed 2/3. +- The half-pipe shell audit passed 2/3; passage 0–1 reported 11,544 floor and 6,945 wall violations. A targeted trace showed at least one reported floor sample was 0.101 m inside the passage after relief, where interior correctly overrides the shell. The audit's smooth-route overlap model still disagreed at that point, so the remaining shell counts are not conclusive. +- Fast tier, Clang/GCC W1/W8/W12 hash matrix, readiness timing, and Unreal Linux build were not run. Canonical v218 hashes were not generated. + +## Captures + +No Linux111 capture images were generated. Mouths, 25/50/75% stations, open-air sections, and programmatically verified 4 m outside/interior close-ups remain outstanding. + +The candidate audit found these open-air sections: + +- passage 0–1: 6.408–16.782 m; 19.500–24.439 m; 1,044.046–1,498.708 m +- passage 1–2: 81.654–85.646 m; 104.092–104.829 m +- passage 2–3: 7.701–26.008 m; 372.697–377.363 m + +## Failed attempts + +1. Dense spline plus half-pipe: walk grades exceeded 15° and passage 0–1 failed shell, naturalness, and ripple checks. +2. Dense spline plus a grade-limited floor: grade failures cleared, but passage 0–1 retained 2 unsupported walk samples and its shell/naturalness/ripple audits still failed. Work stopped after this second design as requested. + +Logs: `Saved/Linux/l111/build-clang.log` and `Saved/Linux/l111/audit-owner.log`. diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/REPORT.md b/Standalone/Research/WorldAssemblerM3/Linux112/REPORT.md new file mode 100644 index 0000000..629df8a --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux112/REPORT.md @@ -0,0 +1,44 @@ +# Linux 112 — horizontal spline, planned floor profile + +## Shape and audits + +The passage now follows a dense centripetal spline in XY. Height stays piecewise linear on the planner's horizontal arc-length profile; radius and floor depth blend smoothly. Open-air sections have a floor slab and 1 m side walls, with no roof, and passage interiors take priority over shells. Version is v219; source stamp is `c31c8baca8f8308dca62edc6d286c8e84a8214ede7ca444fdaf337ae743ccee1`. + +The audit samples the same generated centreline. No walkability thresholds were loosened: the grade limit remains 15°, headroom remains 0.30 m for Caves and 2.20 m for Lattice, and the shell, mouth, naturalness, and ripple gates remain in place. The owner route has zero blocked, unsupported, or grade-failure samples. The native Caves route passes at 15.000° maximum grade and 0.300 m minimum headroom; native Lattice passes with zero support failures at 10.028° maximum grade and 2.200 m headroom. All three passage interfaces pass shell, mouth, naturalness, and ripple audits. The FI blocked control at passage/1-2 remains detected (16,380 blocked capsule samples); all three blocked controls were detected. + +The native Caves field owns its corridor so the transition shell cannot clip it; the passage interior still opens within its own stratum. Lattice's authored support below the floor remains solid. These preserve the same walkability and support requirements. + +## Captures + +[Capture index](captures/INDEX.md): 110 images verified (60 L109 before, 50 L112 after), covering mouths, 25/50/75% stations, and every open-air section. This includes 32 verified 4 m close-ups (18 before, 14 after) of the outside and interior walls. For the close-ups, the nominal route target snaps to a nearby mesh triangle; the camera remains 4.00 m from the mesh within 0.02 m, with wall-normal alignment at least 0.25. + +## Readiness + +Five interleaved L80 pairs per cell, all four strata, W8 and W12. Values are median seconds, L109 binary → L112 binary; near is LOD0–2 ready and whole is whole-view ready. + +| Stratum | W8 near | W8 whole | W12 near | W12 whole | +|---|---:|---:|---:|---:| +| SW | 0.779 → 0.822 | 1.837 → 1.826 | 0.802 → 0.845 | 1.768 → 1.835 | +| FI | 0.972 → 1.063 | 1.935 → 2.022 | 0.924 → 0.992 | 1.792 → 1.884 | +| TN | 1.021 → 1.092 | 1.869 → 1.970 | 0.931 → 1.023 | 1.758 → 1.866 | +| VS | 0.832 → 0.921 | 1.764 → 1.827 | 0.783 → 0.861 | 1.666 → 1.741 | + +L109's prior report recorded W12 near-ready at 0.863 s for FI and 0.895 s for TN. In this matrix the L109 binary remeasured at 0.924 s and 0.931 s; L112 measured 0.992 s and 1.023 s. That is +7.4% and +9.9% against the matched rerun, or +15.0% and +14.3% against the prior report values. + +## Candidate lists + +Feature and route-segment lists have the same counts. Each cell shows L109 → L112; totals are candidates across profiled tiles. + +| Stratum | Profiled tiles | Total candidates | p95 per tile | Maximum per tile | +|---|---:|---:|---:|---:| +| SW | 1,763 → 1,742 | 583 → 4,216 | 3 → 18 | 21 → 185 | +| FI | 1,590 → 1,573 | 1,036 → 7,068 | 4 → 22 | 47 → 420 | +| TN | 1,492 → 1,480 | 869 → 4,784 | 4 → 22 | 23 → 116 | +| VS | 1,660 → 1,660 | 644 → 3,133 | 4 → 18 | 16 → 82 | + +## Verification + +- Fast tier: PASS, 264 checks. +- Clang/GCC W1/W8/W12 determinism: all 18 runs passed; hashes match within each configuration. +- Linux VFHostEditor build: succeeded with `-NoUBA -MaxParallelActions=4` after timing. +- No commit was created. diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/RunL112CandidateLists.py b/Standalone/Research/WorldAssemblerM3/Linux112/RunL112CandidateLists.py new file mode 100644 index 0000000..a4329a3 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux112/RunL112CandidateLists.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python3 +"""Compare per-tile passage candidate-list sizes for L109 and L112.""" +from __future__ import annotations + +import json +import math +import re +import statistics +import subprocess +import time +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / "Saved/Linux/l112/candidate-lists" +DATA = ROOT / "Standalone/data/owner_world.json" +BINARIES = { + "L109": ROOT / "Saved/Linux/l109/bin-final/VoxelForgeCoreHeadless-l109-clang", + "L112": ROOT / "Saved/Linux/l112/bin-clang/VoxelForgeCoreHeadless-l112-clang", +} +CAMERAS = { + 0: (8.0, 16.0, -372.2626953125), + 1: (25.8369140625, 3.19921875, -737.0), + 2: (19.166015625, -14.2001953125, -753.3740234375), + 3: (-20.0625, -5.068359375, -900.353515625), +} +LIST = re.compile(r"^\[PassageComposerTile\].*?features=(\d+) route_candidates=(\d+)", re.M) + + +def percentile(values: list[int], fraction: float) -> int: + ordered = sorted(values) + if not ordered: + return 0 + return ordered[min(len(ordered) - 1, + max(0, math.ceil(fraction * len(ordered)) - 1))] + + +def run(strate: int, version: str) -> dict: + OUT.mkdir(parents=True, exist_ok=True) + log = OUT / f"{version}-s{strate}.log" + camera = ",".join(f"{v:.12f}" for v in CAMERAS[strate]) + ",0,0" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1740s", str(BINARIES[version]), str(DATA), + "--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline", + "--workers=12", "--clip-radius=3", "--max-clip-level=8", "--max-level=8", + f"--camera={camera}", "--profile-passage-composer", "--stream-scheduler-policy=3", + ] + started = time.monotonic() + with log.open("w", encoding="utf-8") as stream: + result = subprocess.run(command, cwd=ROOT, stdout=stream, + stderr=subprocess.STDOUT, check=False, timeout=1740) + output = log.read_text(encoding="utf-8", errors="replace") + features = [int(row[0]) for row in LIST.findall(output)] + routes = [int(row[1]) for row in LIST.findall(output)] + if result.returncode or not features: + raise SystemExit(f"candidate-list profile missing: {log}; exit={result.returncode}") + row = { + "strate": strate, "version": version, "profiled_tiles": len(features), + "feature_candidates": {"sum": sum(features), "min": min(features), + "median": statistics.median(features), "p95": percentile(features, .95), + "max": max(features)}, + "route_segment_candidates": {"sum": sum(routes), "min": min(routes), + "median": statistics.median(routes), "p95": percentile(routes, .95), + "max": max(routes)}, + "elapsed_s": round(time.monotonic() - started, 3), + "log": str(log.relative_to(ROOT)), + } + print("[L112CandidateLists] " + json.dumps(row, sort_keys=True), flush=True) + return row + + +def main() -> int: + if any(not path.is_file() for path in (*BINARIES.values(), DATA)): + raise SystemExit("missing L109/L112 candidate-list input") + rows = [run(strate, version) for strate in range(4) + for version in ("L109", "L112")] + (OUT / "summary.json").write_text(json.dumps(rows, indent=2) + "\n", + encoding="utf-8") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/RunL112Captures.py b/Standalone/Research/WorldAssemblerM3/Linux112/RunL112Captures.py new file mode 100644 index 0000000..b57a7c9 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux112/RunL112Captures.py @@ -0,0 +1,839 @@ +#!/usr/bin/env python3 +"""Capture L109 and L112 routes, every open-air section, and verified 4 m wall views.""" +from __future__ import annotations + +import json +import math +import re +from array import array +import struct +import subprocess +import sys +import time +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +RESEARCH = Path(__file__).resolve().parent +CAPTURES = RESEARCH / "captures" +SAVED = ROOT / "Saved/Linux/l112/captures" +DATA = ROOT / "Standalone/data/owner_world.json" +BINARIES = { + "before": ROOT / "Saved/Linux/l109/bin-final/VoxelForgeCoreHeadless-l109-clang", + "after": ROOT / "Saved/Linux/l112/bin-clang/VoxelForgeCoreHeadless-l112-clang", +} +LAYOUTS = { + "before": ROOT / "Saved/Linux/l109/audit-layout-final-stamp.json", + "after": ROOT / "Saved/Linux/l112/audit-layout-candidate.json", +} +AUDIT_LOGS = { + "before": ROOT / "Saved/Linux/l109/audit-owner4-final-stamp.log", + "after": ROOT / "Saved/Linux/l112/audit-owner-clang.log", +} +RENDERERS = { + "before": ROOT / "Saved/Linux/l109/bin-final/VoxelForgeOffscreenCapture-l109-clang", + "after": ROOT / "Saved/Linux/l112/bin-clang/VoxelForgeOffscreenCapture-l112-clang", +} +SECTION = re.compile( + r"^\[PassageOpenAirSection\] id=(\S+) section=(\d+) start_m=([\d.]+) " + r"end_m=([\d.]+) samples=(\d+) midpoint_xyz_m=\(([^)]*)\) " + r"midpoint_radius_m=([\d.]+)", re.M) +DRAWN = re.compile(r"drawn_triangles=(\d+)") +QUALITY_METRICS = re.compile(r"stddev_luma=([\d.]+).*coverage_luma_gt12=([\d.]+)") + + +def vector(text: str) -> tuple[float, float, float]: + return tuple(float(value) for value in text.split(",")) + + +def add(a, b): + return tuple(x + y for x, y in zip(a, b)) + + +def sub(a, b): + return tuple(x - y for x, y in zip(a, b)) + + +def mul(a, scale): + return tuple(x * scale for x in a) + + +def norm(a): + length = math.sqrt(sum(x * x for x in a)) + if length <= 1.0e-9: + return (0.0, 1.0, 0.0) + return tuple(value / length for value in a) + + +def angles(camera, target): + delta = sub(target, camera) + horizontal = math.hypot(delta[0], delta[1]) + return (math.degrees(math.atan2(delta[0], delta[1])), + math.degrees(math.atan2(delta[2], horizontal))) + + +def fmt(values) -> str: + return ",".join(f"{value:.6f}" for value in values) + + +def mesh_triangle_count(mesh: Path) -> int: + """Read only the VFMSH headers and count indexed triangles.""" + with mesh.open("rb") as stream: + magic = stream.read(8) + materials = magic == b"VFMSH002" + if magic not in (b"VFMSH001", b"VFMSH002"): + raise RuntimeError(f"unsupported mesh scene header: {mesh}") + version, _voxel_um, tile_count = struct.unpack("<3I", stream.read(12)) + if version != (2 if materials else 1): + raise RuntimeError(f"mesh scene version mismatch: {mesh}") + stream.seek(40, 1) + triangles = 0 + for _ in range(tile_count): + stream.seek(16, 1) + surface_count, _skirts, vertex_count, index_count, mask_count = struct.unpack( + "<5I", stream.read(20)) + triangles += index_count // 3 + stream.seek(vertex_count * 24 + (10 * vertex_count if materials else 0) + + index_count * 4 + mask_count, 1) + if stream.read(1): + raise RuntimeError(f"trailing data in mesh scene: {mesh}") + return triangles + + +def dot(a, b): + return sum(x * y for x, y in zip(a, b)) + + +def closest_point_triangle(point, a, b, c): + def closest_segment(start, end, first_weight, second_weight): + edge = sub(end, start) + length_squared = dot(edge, edge) + t = (min(1.0, max(0.0, dot(sub(point, start), edge) / length_squared)) + if length_squared > 1.0e-16 else 0.0) + position = add(start, mul(edge, t)) + weights = [0.0, 0.0, 0.0] + weights[first_weight], weights[second_weight] = 1.0 - t, t + return position, tuple(weights) + + ab, ac = sub(b, a), sub(c, a) + cross = ((ab[1] * ac[2] - ab[2] * ac[1]), + (ab[2] * ac[0] - ab[0] * ac[2]), + (ab[0] * ac[1] - ab[1] * ac[0])) + if dot(cross, cross) <= 1.0e-16: + candidates = [closest_segment(a, b, 0, 1), + closest_segment(b, c, 1, 2), + closest_segment(c, a, 2, 0)] + return min(candidates, key=lambda candidate: + dot(sub(candidate[0], point), sub(candidate[0], point))) + ap = sub(point, a) + d1, d2 = dot(ab, ap), dot(ac, ap) + if d1 <= 0.0 and d2 <= 0.0: + return a, (1.0, 0.0, 0.0) + bp = sub(point, b) + d3, d4 = dot(ab, bp), dot(ac, bp) + if d3 >= 0.0 and d4 <= d3: + return b, (0.0, 1.0, 0.0) + vc = d1 * d4 - d3 * d2 + if vc <= 0.0 and d1 >= 0.0 and d3 <= 0.0: + denominator = d1 - d3 + if denominator <= 1.0e-16: + return a, (1.0, 0.0, 0.0) + v = d1 / denominator + return add(a, mul(ab, v)), (1.0 - v, v, 0.0) + cp = sub(point, c) + d5, d6 = dot(ab, cp), dot(ac, cp) + if d6 >= 0.0 and d5 <= d6: + return c, (0.0, 0.0, 1.0) + vb = d5 * d2 - d1 * d6 + if vb <= 0.0 and d2 >= 0.0 and d6 <= 0.0: + denominator = d2 - d6 + if denominator <= 1.0e-16: + return a, (1.0, 0.0, 0.0) + w = d2 / denominator + return add(a, mul(ac, w)), (1.0 - w, 0.0, w) + va = d3 * d6 - d5 * d4 + if va <= 0.0 and d4 - d3 >= 0.0 and d5 - d6 >= 0.0: + denominator = (d4 - d3) + (d5 - d6) + if denominator <= 1.0e-16: + return b, (0.0, 1.0, 0.0) + w = (d4 - d3) / denominator + edge = sub(c, b) + return add(b, mul(edge, w)), (0.0, 1.0 - w, w) + face_denominator = va + vb + vc + if face_denominator <= 1.0e-16: + candidates = [closest_segment(a, b, 0, 1), + closest_segment(b, c, 1, 2), + closest_segment(c, a, 2, 0)] + return min(candidates, key=lambda candidate: + dot(sub(candidate[0], point), sub(candidate[0], point))) + denominator = 1.0 / face_denominator + v, w = vb * denominator, vc * denominator + weights = (1.0 - v - w, v, w) + closest = tuple(weights[0] * a[axis] + weights[1] * b[axis] + + weights[2] * c[axis] for axis in range(3)) + return closest, weights + + +def nearest_surface_anchor(mesh: Path, point, margin_m=200.0, *, + preferred_normal=None, minimum_alignment=-1.0) -> dict: + """Return the nearest point on a VFMSH surface triangle and its normal.""" + best_distance_sq = float("inf") + best_position = best_normal = None + with mesh.open("rb") as stream: + magic = stream.read(8) + materials = magic == b"VFMSH002" + if magic not in (b"VFMSH001", b"VFMSH002"): + raise RuntimeError(f"unsupported mesh scene header: {mesh}") + version, voxel_um, tile_count = struct.unpack("<3I", stream.read(12)) + if version != (2 if materials else 1): + raise RuntimeError(f"mesh scene version mismatch: {mesh}") + stream.seek(40, 1) + for _ in range(tile_count): + key = struct.unpack("<4i", stream.read(16)) + surface_count, _skirts, vertex_count, index_count, mask_count = struct.unpack( + "<5I", stream.read(20)) + extent = (32 << key[3]) * voxel_um / 1_000_000.0 + origin = (key[0] * extent, key[1] * extent, key[2] * extent) + if any(point[axis] < origin[axis] - margin_m or + point[axis] > origin[axis] + extent + margin_m for axis in range(3)): + stream.seek(vertex_count * 24 + (10 * vertex_count if materials else 0) + + index_count * 4 + mask_count, 1) + continue + positions = array("f") + positions.frombytes(stream.read(vertex_count * 12)) + normals = array("f") + normals.frombytes(stream.read(vertex_count * 12)) + if materials: + stream.seek(vertex_count * 10, 1) + indices = array("I") + indices.frombytes(stream.read(index_count * 4)) + stream.seek(mask_count, 1) + if struct.pack("=I", 1) != struct.pack("= surface_count or vertex_index >= vertex_count + for vertex_index in triangle): + continue + a, b, c = (vertex(vertex_index) for vertex_index in triangle) + position, weights = closest_point_triangle(point, a, b, c) + delta = sub(position, point) + distance_sq = dot(delta, delta) + if distance_sq >= best_distance_sq: + continue + raw_normals = [vertex_normal(vertex_index) for vertex_index in triangle] + raw_normal = tuple(sum(weights[corner] * raw_normals[corner][axis] + for corner in range(3)) for axis in range(3)) + if dot(raw_normal, raw_normal) < 1.0e-10: + raw_normal = ( + (b[1] - a[1]) * (c[2] - a[2]) - (b[2] - a[2]) * (c[1] - a[1]), + (b[2] - a[2]) * (c[0] - a[0]) - (b[0] - a[0]) * (c[2] - a[2]), + (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0])) + if dot(raw_normal, raw_normal) < 1.0e-10: + continue + candidate_normal = norm(raw_normal) + if preferred_normal is not None: + alignment = dot(candidate_normal, preferred_normal) + if abs(alignment) < minimum_alignment: + continue + if alignment < 0.0: + candidate_normal = mul(candidate_normal, -1.0) + best_distance_sq = distance_sq + best_position = position + best_normal = candidate_normal + if best_position is None: + raise RuntimeError(f"no nearby surface vertices in mesh scene: {mesh}") + return {"position_m": best_position, "normal": best_normal, + "distance_m": math.sqrt(best_distance_sq)} + + +def sanitize(value: str) -> str: + return re.sub(r"[^A-Za-z0-9_-]+", "-", value).strip("-").replace("/", "-") + + +def route_height_at_xy(route, x, y): + if not route: + return None + if len(route) == 1: + point = route[0] + return point[2], (x - point[0]) ** 2 + (y - point[1]) ** 2 + best = (float("inf"), None) + for a, b in zip(route, route[1:]): + dx, dy = b[0] - a[0], b[1] - a[1] + length_sq = dx * dx + dy * dy + t = min(1.0, max(0.0, ((x - a[0]) * dx + (y - a[1]) * dy) / length_sq)) \ + if length_sq > 1.0e-12 else 0.0 + px, py = a[0] + t * dx, a[1] + t * dy + distance_sq = (x - px) ** 2 + (y - py) ** 2 + if distance_sq < best[0]: + best = (distance_sq, a[2] + (b[2] - a[2]) * t) + return best[1], best[0] + + +def upper_mouth_floor_depth(layout: dict, passage: dict, controls) -> float: + scale = layout["core_voxel_size_um"] / 256.0 / 1_000_000.0 + authored = max(0.0, controls[0][0][2] - passage["upper_mouth_q"][2] * scale + 1.13) + stratum = next((row for row in layout["strates"] + if row["strate_index"] == passage["upper_strate_index"]), None) + if stratum is None or stratum["generator_kind"] != "FloatingIslands": + return authored + route = [tuple(value * scale for value in anchor["values"][:3]) + for anchor in stratum.get("anchors", []) + if anchor.get("kind") == "route_point" and len(anchor.get("values", [])) >= 3] + projected = route_height_at_xy(route, controls[0][0][0], controls[0][0][1]) + if projected is None or projected[1] > (controls[0][1] + 2.0) ** 2: + return authored + route_depth = max(0.0, controls[0][0][2] - projected[0] + 1.13) + return max(authored, route_depth) + + +def route_controls(layout: dict, passage: dict, *, adjust_upper_mouth=False): + scale = layout["core_voxel_size_um"] / 256.0 / 1_000_000.0 + controls = [(tuple(value * scale for value in row["position_q"]), + row["radius_q"] * scale) for row in passage["control_points"]] + lower_q = passage["lower_mouth_q"] + player_center_above_floor_q = round( + 1.13 * 256.0 * 1_000_000.0 / layout["core_voxel_size_um"]) + lower_index = next((index for index, row in enumerate(passage["control_points"]) + if row["position_q"][0] == lower_q[0] + and row["position_q"][1] == lower_q[1] + and row["position_q"][2] - row["radius_q"] + + player_center_above_floor_q == lower_q[2]), None) + if lower_index is None: + raise RuntimeError(f"{passage['stable_id']}: lower mouth control is unbound") + if lower_index < 1: + raise RuntimeError(f"{passage['stable_id']}: incomplete route controls") + if adjust_upper_mouth: + controls[0] = (controls[0][0], max(controls[0][1], + upper_mouth_floor_depth(layout, passage, controls))) + return controls, lower_index + + +def route_for(layout: dict, passage: dict) -> list[tuple[tuple[float, float, float], float]]: + controls, lower_index = route_controls(layout, passage) + return controls[:lower_index + 1] + + +def spline_knot_span(a, b): + return max(1.0e-6, math.sqrt(math.sqrt((b[0] - a[0]) ** 2 + + (b[1] - a[1]) ** 2))) + + +def spline_point(controls, span, t): + as_point = lambda index: (*controls[index][0], controls[index][1]) + p0, p1, p2, p3 = (as_point(max(0, span - 1)), as_point(span), + as_point(span + 1), as_point(min(span + 2, len(controls) - 1))) + dt0, dt1, dt2 = (spline_knot_span(p0, p1), spline_knot_span(p1, p2), + spline_knot_span(p2, p3)) + t2, t3 = t * t, t * t * t + result = [0.0] * 4 + for axis in (0, 1, 3): + m1 = dt1 * ((p1[axis] - p0[axis]) / dt0 + - (p2[axis] - p0[axis]) / (dt0 + dt1) + + (p2[axis] - p1[axis]) / dt1) + m2 = dt1 * ((p2[axis] - p1[axis]) / dt1 + - (p3[axis] - p1[axis]) / (dt1 + dt2) + + (p3[axis] - p2[axis]) / dt2) + result[axis] = ((2 * t3 - 3 * t2 + 1) * p1[axis] + + (-2 * t3 + 3 * t2) * p2[axis] + + (t3 - 2 * t2 + t) * m1 + (t3 - t2) * m2) + result[2] = p1[2] + (p2[2] - p1[2]) * t + result[3] = min(max(result[3], min(p1[3], p2[3])), max(p1[3], p2[3])) + return result + + +def smooth_route(layout: dict, passage: dict): + """Mirror PassageSpline::BuildSegments from the runtime shared sampler.""" + scale = layout["core_voxel_size_um"] / 256.0 / 1_000_000.0 + planned_floor_profile = [ + (row["position_q"][2] - row["radius_q"]) * scale + for row in passage["control_points"]] + controls, route_end = route_controls(layout, passage, adjust_upper_mouth=True) + result = [] + along = 0.0 + arc_steps = 32 + for span in range(route_end): + arc = [0.0] + previous = spline_point(controls, span, 0.0) + for step in range(1, arc_steps + 1): + current = spline_point(controls, span, step / arc_steps) + arc.append(arc[-1] + math.hypot(current[0] - previous[0], + current[1] - previous[1])) + previous = current + segment_count = max(1, math.ceil(arc[-1])) + points = [spline_point(controls, span, 0.0)] + parameters = [0.0] + for segment in range(1, segment_count + 1): + target = min(arc[-1], arc[-1] * segment / segment_count) + upper = next(index for index in range(1, len(arc)) + if arc[index] >= target) + lower = upper - 1 + width = arc[upper] - arc[lower] + fraction = min(1.0, max(0.0, (target - arc[lower]) / width)) if width > 1e-12 else 0.0 + t = (lower + fraction) / arc_steps + points.append(spline_point(controls, span, t)) + parameters.append(t) + sampled_arc = [0.0] + for a, b in zip(points, points[1:]): + sampled_arc.append(sampled_arc[-1] + math.hypot(b[0] - a[0], b[1] - a[1])) + horizontal_length = sampled_arc[-1] + for index, point in enumerate(points): + progress = sampled_arc[index] / horizontal_length if horizontal_length > 1e-12 else parameters[index] + point[2] = controls[span][0][2] + (controls[span + 1][0][2] + - controls[span][0][2]) * progress + point.append(planned_floor_profile[span] + + (planned_floor_profile[span + 1] + - planned_floor_profile[span]) * progress) + if not result: + result.append((tuple(points[0][:3]), points[0][3], 0.0, points[0][4])) + for a, b in zip(points, points[1:]): + length = math.dist(a[:3], b[:3]) + along += length + result.append((tuple(b[:3]), b[3], along, b[4])) + return result + + +def derived_smooth_route(route, passage, layout): + total = route[-1][2] + interior_radii = [radius for _, radius, distance, _ in route + if distance >= 10.0 and total - distance >= 10.0] + body_depth = max(0.5, min(interior_radii or [radius for _, radius, _, _ in route]) - 0.23) + result = [] + for point, radius, distance, planned_floor in route: + local_radius_depth = max(0.0, radius - 0.23) + tube_depth = min(body_depth, local_radius_depth) + center = (point[0], point[1], planned_floor + tube_depth) + result.append((center, radius, distance, planned_floor)) + return result, body_depth + + +def route_lengths(route): + lengths = [((b[2] - a[2]) if len(a) > 2 and len(b) > 2 + else math.dist(a[0], b[0])) for a, b in zip(route, route[1:])] + prefix = [0.0] + for length in lengths: + prefix.append(prefix[-1] + length) + return lengths, prefix + + +def at_distance(route, lengths, prefix, distance): + distance = max(0.0, min(distance, prefix[-1])) + for index, length in enumerate(lengths): + if distance <= prefix[index + 1] or index + 1 == len(lengths): + t = 0.0 if length <= 1.0e-9 else (distance - prefix[index]) / length + a, b = route[index], route[index + 1] + return (tuple(a[0][axis] + (b[0][axis] - a[0][axis]) * t + for axis in range(3)), + a[1] + (b[1] - a[1]) * t) + return route[-1] + + +def tangent_at(route, lengths, prefix, distance): + before = at_distance(route, lengths, prefix, max(0.0, distance - 0.25))[0] + after = at_distance(route, lengths, prefix, min(prefix[-1], distance + 0.25))[0] + return norm(sub(after, before)) + + +def derived_route(route, passage, layout): + """Apply L109's fixed-depth floor offset to raw layout controls.""" + lengths, prefix = route_lengths(route) + total = prefix[-1] + body_radii = [radius for index, (_, radius) in enumerate(route) + if prefix[index] >= 10.0 and total - prefix[index] >= 10.0] + body_depth = max(0.5, min(body_radii or [radius for _, radius in route]) - 0.23) + scale = layout["core_voxel_size_um"] / 256.0 / 1_000_000.0 + upper_z = passage["upper_mouth_q"][2] * scale + lower_z = passage["lower_mouth_q"][2] * scale + upper_target = max(0.0, route[0][0][2] - upper_z + 1.13) + lower_target = max(0.0, route[-1][0][2] - lower_z + 1.13) + transformed = [] + for index, (point, radius) in enumerate(route): + local_radius_depth = max(0.0, radius - 0.23) + mouth_distance = max(0.0, min(prefix[index], total - prefix[index])) + u = max(0.0, min(1.0, mouth_distance / 5.0)) + ramp = u * u * (3.0 - 2.0 * u) + target = upper_target if prefix[index] <= total * 0.5 else lower_target + mouth_depth = max(0.0, min(radius, target)) + route_depth = mouth_depth + (local_radius_depth - mouth_depth) * ramp + tube_depth = min(body_depth, local_radius_depth) + transformed.append(((point[0], point[1], point[2] - route_depth + tube_depth), + radius)) + return transformed, body_depth + + +def make_views(layout: dict, audit_sections: list[dict], *, use_derived_shape: bool, + use_spline: bool, + include_open_air: bool = True) -> list[dict]: + views = [] + passages = sorted(layout["passages"], key=lambda item: item["stable_id"]) + for passage in passages: + raw_route = smooth_route(layout, passage) if use_spline else route_for(layout, passage) + if use_derived_shape: + route, body_depth = (derived_smooth_route(raw_route, passage, layout) + if use_spline else derived_route(raw_route, passage, layout)) + else: + route = raw_route + body_depth = max(point[1] for point in route) + def floor_depth(radius: float) -> float: + if not use_derived_shape: + return radius + return min(body_depth, max(0.0, radius - 0.23)) + lengths, prefix = route_lengths(route) + total = prefix[-1] + passage_id = passage["stable_id"] + safe_id = sanitize(passage_id) + + for end_name, distance, outward_sign in ( + ("upper-mouth", 0.0, -1.0), ("lower-mouth", total, 1.0)): + center, radius = at_distance(route, lengths, prefix, distance) + tangent = tangent_at(route, lengths, prefix, distance) + outward = mul(tangent, outward_sign) + floor_z = center[2] - floor_depth(radius) + eye = (center[0] + outward[0] * 4.5, + center[1] + outward[1] * 4.5, + floor_z + 1.55) + if end_name == "lower-mouth": + eye = add(eye, add(mul(outward, 5.0), (0.0, 0.0, 2.0))) + target = (center[0] - outward[0] * 2.0, + center[1] - outward[1] * 2.0, + floor_z + 1.45) + yaw, pitch = angles(eye, target) + views.append({"name": f"{safe_id}-{end_name}", "passage": passage_id, + "kind": "mouth", "station": end_name, + "camera": eye, "target": target, "yaw": yaw, "pitch": pitch, + "focus": center, "center_z": center[2]}) + + for fraction in (0.25, 0.50, 0.75): + distance = total * fraction + center, radius = at_distance(route, lengths, prefix, distance) + tangent = tangent_at(route, lengths, prefix, distance) + depth = floor_depth(radius) + floor_z = center[2] - depth + horizontal = norm((-tangent[1], tangent[0], 0.0)) + eye = (center[0] + horizontal[0] * 0.75, + center[1] + horizontal[1] * 0.75, floor_z + 1.60) + target_center, target_radius = at_distance(route, lengths, prefix, + min(total, distance + 14.0)) + target_depth = floor_depth(target_radius) + target = (target_center[0] + horizontal[0] * 2.35, + target_center[1] + horizontal[1] * 2.35, + target_center[2] - target_depth + 1.80) + yaw, pitch = angles(eye, target) + views.append({"name": f"{safe_id}-station-{int(fraction * 100)}", + "passage": passage_id, "kind": "station", + "station": f"{int(fraction * 100)}%", "camera": eye, + "target": target, "yaw": yaw, "pitch": pitch, + "focus": center, "center_z": center[2], + "route_distance_m": distance, + "route_length_m": total, + "requested_route_distance_m": distance}) + + if not include_open_air: + continue + for section in (item for item in audit_sections if item["passage"] == passage_id): + distance = 0.5 * (section["start_m"] + section["end_m"]) + center, radius = (section["midpoint"], section["radius_m"]) + tangent = tangent_at(route, lengths, prefix, distance) + side = norm((-tangent[1], tangent[0], 0.0)) + depth = floor_depth(radius) + section_id = section["section"] + interior_eye = (center[0], center[1], center[2] - depth + 1.25) + interior_target = add(interior_eye, mul(tangent, 7.0)) + side_eye = add(center, add(mul(side, radius + 5.0), (0.0, 0.0, 1.2))) + oblique_eye = add(center, add(mul(side, -(radius + 3.5)), (0.0, 0.0, 4.0))) + targets = (add(center, (0.0, 0.0, 0.1)), + add(center, mul(tangent, 2.0)), interior_target) + for view_index, (eye, target) in enumerate(zip( + (side_eye, oblique_eye, interior_eye), targets), start=1): + yaw, pitch = angles(eye, target) + views.append({"name": f"{safe_id}-openair-{section_id}-view-{view_index}", + "passage": passage_id, "kind": "open-air", + "station": f"section-{section_id}/view-{view_index}", + "camera": eye, "target": target, "yaw": yaw, + "pitch": pitch, "focus": center, + "center_z": center[2], "open_air_section": section_id, + "route_distance_m": distance, + "requested_route_distance_m": distance, + "route_length_m": total}) + floor_z = center[2] - depth + outside_target = add(center, add(mul(side, radius), (0.0, 0.0, -depth + 0.5))) + outside_eye = add(outside_target, mul(side, 4.0)) + interior_radius = math.sqrt(max(0.0, radius * radius + - max(0.0, depth - 0.5) ** 2)) + inside_target = add(center, add(mul(side, interior_radius), + (0.0, 0.0, -depth + 0.5))) + inside_eye = add(inside_target, + add(mul(side, -1.0), mul(tangent, math.sqrt(15.0)))) + for closeup, eye, target in (("outside", outside_eye, outside_target), + ("interior-wall", inside_eye, inside_target)): + yaw, pitch = angles(eye, target) + views.append({"name": f"{safe_id}-openair-{section_id}-4m-{closeup}", + "passage": passage_id, "kind": "open-air-close", + "station": f"section-{section_id}/4m-{closeup}", + "camera": eye, "target": target, "yaw": yaw, + "pitch": pitch, "focus": center, "center_z": center[2], + "open_air_section": section_id, "closeup_side": closeup, + "closeup_preferred_normal": side if closeup == "outside" + else mul(side, -1.0), + "camera_target_distance_m": math.dist(eye, target), + "route_distance_m": distance, + "requested_route_distance_m": distance, + "route_length_m": total}) + return views + + +def run_process(name: str, command: list[str], log: Path, *, allow_failure=False) -> str: + wrapped = ["taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1740s", *map(str, command)] + started = time.monotonic() + with log.open("w", encoding="utf-8") as stream: + result = subprocess.run(wrapped, cwd=ROOT, stdout=stream, + stderr=subprocess.STDOUT, check=False, timeout=1740) + if result.returncode and not allow_failure: + raise RuntimeError(f"{name}: exit={result.returncode} log={log}") + print(f"[L112CaptureProcess] name={name} elapsed_s={time.monotonic()-started:.2f} " + f"exit={result.returncode} log={log.relative_to(ROOT)}", flush=True) + return log.read_text(encoding="utf-8", errors="replace") + + +def capture(variant: str, view: dict, layout: dict) -> dict: + variant_saved = SAVED / variant + variant_saved.mkdir(parents=True, exist_ok=True) + variant_capture = CAPTURES / variant + variant_capture.mkdir(parents=True, exist_ok=True) + scene = variant_saved / f"{view['name']}.vfmesh" + image = variant_capture / f"{view['name']}.png" + candidates = [(view["camera"], view["target"], view["focus"], + view.get("route_distance_m"), 0.0, "requested")] + if variant == "before" and view["kind"] not in ("mouth", "open-air-close"): + passage = next(item for item in layout["passages"] + if item["stable_id"] == view["passage"]) + route = route_for(layout, passage) + lengths, prefix = route_lengths(route) + total = prefix[-1] + eye_offset = sub(view["camera"], view["focus"]) + target_offset = sub(view["target"], view["focus"]) + requested = view["route_distance_m"] + for delta in (5, -5, 10, -10, 20, -20, 35, -35, 50, -50, 75, -75, + 100, -100, 150, -150, 200, -200): + distance = max(0.0, min(total, requested + delta)) + if abs(distance - requested) < 0.01: + continue + center, _radius = at_distance(route, lengths, prefix, distance) + candidates.append((add(center, eye_offset), add(center, target_offset), center, + distance, distance - requested, "route-offset")) + + attempt_errors = [] + for attempt_index, (probe_camera, probe_target, probe_focus, route_distance, + route_adjustment, attempt_kind) in enumerate(candidates): + suffix = "" if attempt_index == 0 else f"-attempt-{attempt_index:02d}" + headless_log = variant_saved / f"{view['name']}{suffix}-mesh.log" + render_log = variant_saved / f"{view['name']}{suffix}-render.log" + quality_log = variant_saved / f"{view['name']}{suffix}-quality.log" + yaw, pitch = angles(probe_camera, probe_target) + camera = (*probe_camera, yaw, pitch) + export_command = [ + str(BINARIES[variant]), str(DATA), "--world-assembler-prototype", + "--stream-benchmark", "--stream-pipeline", "--workers=12", + "--clip-radius=3", "--max-clip-level=0", "--max-level=0", "--force-generate", + "--recipe=surface-world", f"--camera={fmt(camera)}", + "--render-distance-chunks=1", f"--mesh-export={scene}", + ] + export_output = run_process(f"{variant}-{view['name']}{suffix}-mesh", export_command, + headless_log) + if "status=PASS" not in export_output or not scene.is_file(): + raise RuntimeError(f"{variant}-{view['name']}: missing successful scene export") + source_triangles = mesh_triangle_count(scene) + if source_triangles <= 0: + attempt_errors.append(f"{attempt_kind}@{route_distance}: empty mesh") + if variant == "after" or view["kind"] == "mouth": + break + continue + + actual_camera, actual_target = probe_camera, probe_target + actual_focus = probe_focus + surface_distance = None + closeup_surface_distance = None + closeup_anchor_offset = None + closeup_normal_alignment = None + closeup_distance = None + if view["kind"] == "open-air-close": + try: + wall_anchor = nearest_surface_anchor(scene, probe_target, margin_m=5.0, + preferred_normal=view["closeup_preferred_normal"], + minimum_alignment=0.25) + closeup_surface_distance = wall_anchor["distance_m"] + closeup_anchor_offset = closeup_surface_distance + closeup_normal_alignment = dot(wall_anchor["normal"], + view["closeup_preferred_normal"]) + if closeup_surface_distance > 5.0: + raise RuntimeError(f"{variant}-{view['name']}: nearest wall surface is " + f"{closeup_surface_distance:.3f} m from the route-local target") + actual_target = wall_anchor["position_m"] + actual_camera = add(actual_target, mul(wall_anchor["normal"], 4.0)) + closeup_distance = math.dist(actual_camera, actual_target) + if abs(closeup_distance - 4.0) > 0.02: + raise RuntimeError(f"{variant}-{view['name']}: camera-to-wall distance is " + f"{closeup_distance:.3f} m, expected 4 m") + except RuntimeError as error: + raise RuntimeError(f"{variant}-{view['name']}: could not verify the 4 m wall " + f"view: {error}") from error + if attempt_kind == "route-offset": + anchor = nearest_surface_anchor(scene, probe_focus) + surface_distance = anchor["distance_m"] + actual_camera = add(anchor["position_m"], mul(anchor["normal"], 12.0)) + actual_target = anchor["position_m"] + actual_focus = anchor["position_m"] + actual_yaw, actual_pitch = angles(actual_camera, actual_target) + render_command = [ + str(RENDERERS[variant]), str(scene), str(image), "--size=1920x1080", + f"--camera-m={fmt(actual_camera)}", f"--yaw-deg={actual_yaw:.6f}", + f"--pitch-deg={actual_pitch:.6f}", "--shade=readable", "--headlamp=on", + "--height-tint=on", f"--height-center-m={actual_focus[2]:.6f}", + "--height-range-m=32", + ] + render_output = run_process(f"{variant}-{view['name']}{suffix}-render", render_command, + render_log) + drawn = DRAWN.search(render_output) + if drawn is None or int(drawn.group(1)) <= 0 or not image.is_file(): + attempt_errors.append(f"{attempt_kind}@{route_distance}: no drawn geometry") + if variant == "after" or view["kind"] == "mouth": + break + continue + quality = run_process(f"{variant}-{view['name']}{suffix}-quality", [ + "python3", "-B", str(ROOT / "Standalone/Tools/verify/capture_quality.py"), + str(image)], quality_log, allow_failure=True) + quality_status = "pass" + if "status=PASS" not in quality: + metrics = QUALITY_METRICS.search(quality) + coverage = float(metrics.group(2)) if metrics else 0.0 + if coverage >= 0.001: + quality_status = "low_contrast_geometry_visible" + else: + attempt_errors.append(f"{attempt_kind}@{route_distance}: no visible pixel coverage") + if variant == "after" or view["kind"] == "mouth": + break + continue + + row = {**view, "variant": variant, "capture": str(image.relative_to(RESEARCH)), + "scene": str(scene.relative_to(ROOT)), "drawn_triangles": int(drawn.group(1)), + "source_triangles": source_triangles, "verified": True, + "pixel_quality_status": quality_status, + "route_distance_actual_m": route_distance, + "route_station_adjustment_m": route_adjustment, + "closeup_camera_target_distance_m": closeup_distance, + "closeup_target_surface_distance_m": closeup_surface_distance, + "closeup_predicted_target_offset_m": closeup_anchor_offset, + "closeup_wall_normal_alignment": closeup_normal_alignment, + "fallback_kind": attempt_kind if attempt_kind != "requested" else None, + "fallback_surface_distance_m": surface_distance, + "camera_actual_m": actual_camera, "target_actual_m": actual_target, + "logs": [str(headless_log.relative_to(ROOT)), + str(render_log.relative_to(ROOT)), + str(quality_log.relative_to(ROOT))]} + print("[L112Capture] " + json.dumps(row, sort_keys=True), flush=True) + return row + raise RuntimeError(f"{variant}-{view['name']}: no verified image; " + + "; ".join(attempt_errors)) + + +def main() -> int: + if any(not path.is_file() for path in (*BINARIES.values(), *RENDERERS.values(), + *LAYOUTS.values(), *AUDIT_LOGS.values())): + raise SystemExit("missing L109 capture binary, layout, or audit log") + all_rows = [] + variants = ("before", "after") + if "--after-only" in sys.argv[1:]: + prior_log = SAVED.parent / "captures-before-first.log" + if not prior_log.is_file(): + raise SystemExit(f"missing reusable L109 capture rows: {prior_log}") + for line in prior_log.read_text(encoding="utf-8", errors="replace").splitlines(): + if line.startswith("[L112Capture] ") or line.startswith("[L109Capture] "): + all_rows.append(json.loads(line.split(" ", 1)[1])) + if not all_rows or any(row["variant"] != "before" for row in all_rows): + raise SystemExit("saved L109 capture rows are incomplete") + variants = ("after",) + sections_by_variant = {} + for variant in ("before", "after"): + sections = [] + for passage, section, start, end, samples, midpoint, radius in SECTION.findall( + AUDIT_LOGS[variant].read_text(encoding="utf-8", errors="replace")): + sections.append({"passage": passage, "section": int(section), + "start_m": float(start), "end_m": float(end), + "samples": int(samples), "midpoint": vector(midpoint), + "radius_m": float(radius)}) + if not sections: + raise SystemExit(f"no open-air sections found in the {variant} passage audit") + sections_by_variant[variant] = sections + if variant not in variants: + continue + if variant == "after" and variants == ("after",): + expected_before = 15 + 5 * len(sections_by_variant["before"]) + if len(all_rows) != expected_before or any( + row.get("variant") != "before" or not row.get("verified") + for row in all_rows): + raise RuntimeError("saved L109 capture rows do not cover every required view") + layout = json.loads(LAYOUTS[variant].read_text(encoding="utf-8")) + include_open_air = True + views = make_views(layout, sections, use_derived_shape=True, + use_spline=variant == "after", + include_open_air=include_open_air) + expected = 5 * len(layout["passages"]) + if include_open_air: + expected += 5 * len(sections) + if len(views) != expected: + raise RuntimeError(f"unexpected camera count: {len(views)} != {expected}") + print(f"[L112CapturePlan] variant={variant} passage_views={5*len(layout['passages'])} " + f"open_air_sections={len(sections) if include_open_air else 0} " + f"open_air_views={5*len(sections) if include_open_air else 0} " + f"total={len(views)}", flush=True) + for view in views: + all_rows.append(capture(variant, view, layout)) + CAPTURES.mkdir(parents=True, exist_ok=True) + (CAPTURES / "capture-index.json").write_text( + json.dumps({"open_air_sections_by_variant": sections_by_variant, + "captures": all_rows}, indent=2) + "\n", + encoding="utf-8") + lines = ["# L112 passage captures", "", + "Each PNG was rendered from its own exported mesh. The renderer reported visible " + "triangles, and each decoded image met the pixel coverage floor. " + "`low_contrast_geometry_visible` marks images that met this floor below the " + "preferred contrast target.", ""] + for variant in ("before", "after"): + lines.extend([f"## {variant.title()}", ""]) + for row in all_rows: + if row["variant"] != variant: + continue + flag = " **OPEN AIR**" if row["kind"] == "open-air" else "" + quality_note = (f"; {row['pixel_quality_status']}" + if row["pixel_quality_status"] != "pass" else "") + lines.append(f"- [{row['station']}]({variant}/{Path(row['capture']).name}) — " + f"{row['passage']}{flag}; {row['drawn_triangles']} visible triangles" + f"{quality_note}") + lines.append("") + (CAPTURES / "INDEX.md").write_text("\n".join(lines), encoding="utf-8") + failures = [row for row in all_rows if not row["verified"]] + closeups = [row for row in all_rows if row["kind"] == "open-air-close"] + closeups_ok = (len(closeups) == 2 * sum(1 for row in all_rows + if row["kind"] == "open-air" and row["station"].endswith("view-1")) + and all(row["verified"] and abs(row["closeup_camera_target_distance_m"] - 4.0) <= 0.02 + and row["closeup_target_surface_distance_m"] <= 5.0 + and row["closeup_wall_normal_alignment"] >= 0.25 + and row["drawn_triangles"] > 0 + and row["pixel_quality_status"] in + ("pass", "low_contrast_geometry_visible") for row in closeups)) + print(f"[L112CaptureSummary] captures={len(all_rows)} verified={len(all_rows)-len(failures)} " + f"failed={len(failures)} 4m_closeups={len(closeups)} closeups_verified=" + f"{str(closeups_ok).lower()}", flush=True) + return 1 if failures or not closeups_ok else 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/RunL112HashMatrix.py b/Standalone/Research/WorldAssemblerM3/Linux112/RunL112HashMatrix.py new file mode 100644 index 0000000..9f037e1 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux112/RunL112HashMatrix.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python3 +"""Check Clang/GCC hash identity at W1/W8/W12 and pin v219 owner hashes.""" +from __future__ import annotations + +import json +import re +import subprocess +import time +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / "Saved/Linux/l112/hashes" +DATASETS = { + "owner4": ROOT / "Standalone/data/owner_world.json", + "owner2": ROOT / "Standalone/data/regression/owner_world_2strate_l61.json", +} +BINARIES = { + "clang": ROOT / "Saved/Linux/l112/bin-clang/VoxelForgeCoreHeadless-l112-clang", + "gcc": ROOT / "Saved/Linux/l112/bin-gcc/VoxelForgeCoreHeadless-l112-gcc", +} +HASH = re.compile(r"^\[Pipeline(?:FullDetailHash|WholeViewHash|LODHash|ExactQueryHash)\].*$", re.M) +STAMP = re.compile(r"^\[VoxelForgeSourceStamp\] sha256=(\S+)$", re.M) + + +def run(dataset: str, recipe: str, workers: int, compiler: str) -> dict: + OUT.mkdir(parents=True, exist_ok=True) + label = f"{dataset}-{recipe}-w{workers}-{compiler}" + log = OUT / f"{label}.log" + layout = OUT / f"{label}.layout.json" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1740s", str(BINARIES[compiler]), str(DATASETS[dataset]), + f"--workers={workers}", "--world-assembler-prototype", "--stream-benchmark", + "--stream-pipeline", "--force-generate", "--clip-radius=3", + "--max-clip-level=8", "--max-level=8", f"--recipe={recipe}", + "--stream-hash", f"--resolved-layout-output={layout}", + ] + started = time.monotonic() + with log.open("w", encoding="utf-8") as stream: + result = subprocess.run(command, cwd=ROOT, stdout=stream, + stderr=subprocess.STDOUT, check=False, timeout=1740) + output = log.read_text(encoding="utf-8", errors="replace") + hashes = HASH.findall(output) + if result.returncode or len(hashes) != 12: + raise SystemExit(f"hash run failed or incomplete: {label}; exit={result.returncode} " + f"hashes={len(hashes)} log={log}") + row = {"dataset": dataset, "recipe": recipe, "workers": workers, + "compiler": compiler, "exit_code": result.returncode, + "hashes": hashes, "source_stamp": (STAMP.search(output).group(1) + if STAMP.search(output) else None), + "elapsed_s": round(time.monotonic() - started, 3), + "log": str(log.relative_to(ROOT))} + print("[L112HashRun] " + json.dumps(row, sort_keys=True), flush=True) + return row + + +def main() -> int: + if any(not path.is_file() for path in (*DATASETS.values(), *BINARIES.values())): + raise SystemExit("missing L112 hash input") + rows = [] + recipes = {"owner4": ("surface-world",), + "owner2": ("surface-world", "floating-islands")} + for dataset, dataset_recipes in recipes.items(): + for recipe in dataset_recipes: + for workers in (1, 8, 12): + for compiler in ("clang", "gcc"): + rows.append(run(dataset, recipe, workers, compiler)) + (OUT / "runs-partial.json").write_text( + json.dumps(rows, indent=2) + "\n", encoding="utf-8") + groups = {} + for dataset, dataset_recipes in recipes.items(): + for recipe in dataset_recipes: + key = f"{dataset}/{recipe}" + group = [row for row in rows if row["dataset"] == dataset + and row["recipe"] == recipe] + reference = group[0]["hashes"] + groups[key] = {"all_worker_compiler_hashes_match": all( + row["hashes"] == reference for row in group), + "source_stamps": sorted({row["source_stamp"] for row in group}), + "runs": [{"workers": row["workers"], "compiler": row["compiler"], + "log": row["log"]} for row in group]} + if not groups[key]["all_worker_compiler_hashes_match"]: + raise SystemExit(f"determinism mismatch: {key}") + if dataset == "owner2": + canonical = next(row for row in group if row["workers"] == 12 + and row["compiler"] == "clang") + recipe_name = "floating-islands" if recipe == "floating-islands" else "surface-world" + style = 1 if recipe_name == "surface-world" else 2 + baseline = (ROOT / "Standalone/Tools/verify/baselines/owner-hash/canonical" + / f"owner-hash-{recipe_name}-style{style}-v219.baseline") + baseline.write_text("\n".join(canonical["hashes"]) + "\n", + encoding="utf-8") + summary = {"runs": rows, "groups": groups, + "owner4_all_four_strata": "owner4/surface-world", + "owner2_canonical_pins": ["owner2/surface-world", + "owner2/floating-islands"]} + (OUT / "summary.json").write_text(json.dumps(summary, indent=2) + "\n", + encoding="utf-8") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/RunL112Timing.py b/Standalone/Research/WorldAssemblerM3/Linux112/RunL112Timing.py new file mode 100644 index 0000000..ff6bb0d --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux112/RunL112Timing.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python3 +"""Five interleaved L80 readiness pairs comparing L109 and L112 at W8 and W12.""" +from __future__ import annotations + +import json +import re +import statistics +import subprocess +import time +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / "Saved/Linux/l112/timing" +DATA = ROOT / "Standalone/data/owner_world.json" +BINARIES = { + "base": ROOT / "Saved/Linux/l109/bin-final/VoxelForgeCoreHeadless-l109-clang", + "candidate": ROOT / "Saved/Linux/l112/bin-clang/VoxelForgeCoreHeadless-l112-clang", +} +CAMERAS = { + 0: (8.0, 16.0, -372.2626953125), + 1: (25.8369140625, 3.19921875, -737.0), + 2: (19.166015625, -14.2001953125, -753.3740234375), + 3: (-20.0625, -5.068359375, -900.353515625), +} +PIPELINE = re.compile(r"^\[StreamPipeline\] (.*)$", re.M) +FIELDS = re.compile(r"([a-zA-Z0-9_]+)=([^ ]+)") +NEAR = re.compile( + r"^\[WorldAssemblerNearLODReady\] lods=0-2 tiles=(\d+)/(\d+) cold_ready_s=([0-9.]+)$", + re.M, +) + + +def run(strate: int, workers: int, variant: str, phase: str, replicate: int) -> dict: + OUT.mkdir(parents=True, exist_ok=True) + label = f"s{strate}-w{workers}-{variant}-{phase}{replicate}" + log = OUT / f"{label}.log" + camera = ",".join(f"{v:.12f}" for v in CAMERAS[strate]) + ",0,0" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1740s", str(BINARIES[variant]), str(DATA), + "--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline", + f"--workers={workers}", "--clip-radius=3", "--max-clip-level=8", "--max-level=8", + f"--camera={camera}", "--profile-lod-work", "--stream-scheduler-policy=3", + ] + start = time.monotonic() + with log.open("w", encoding="utf-8") as output: + result = subprocess.run(command, cwd=ROOT, stdout=output, + stderr=subprocess.STDOUT, check=False, timeout=1740) + content = log.read_text(encoding="utf-8", errors="replace") + pipeline_match = PIPELINE.search(content) + near_match = NEAR.search(content) + if result.returncode or pipeline_match is None or near_match is None: + raise SystemExit(f"readiness run failed or trace missing: {log}; exit={result.returncode}") + pipeline = dict(FIELDS.findall(pipeline_match.group(1))) + row = { + "strate": strate, "workers": workers, "variant": variant, + "phase": phase, "replicate": replicate, "exit_code": result.returncode, + "wall_s": round(time.monotonic() - start, 3), + "lod02_ready_s": float(near_match.group(3)), + "whole_view_ready_s": float(pipeline["whole_view_ready"].removesuffix("s")), + "whole_tiles": int(pipeline["whole_tiles"].split("/")[0]), + "log": str(log.relative_to(ROOT)), + } + print("[L112TimingRun] " + json.dumps(row, sort_keys=True), flush=True) + return row + + +def main() -> int: + if not DATA.is_file() or any(not binary.is_file() for binary in BINARIES.values()): + raise SystemExit("missing L109/L112 data or timing binary") + rows = [] + for strate in range(4): + for workers in (8, 12): + run(strate, workers, "base", "warmup", 0) + run(strate, workers, "candidate", "warmup", 0) + for replicate in range(1, 6): + order = ("base", "candidate") if replicate % 2 else ("candidate", "base") + for variant in order: + rows.append(run(strate, workers, variant, "measured", replicate)) + (OUT / "runs-partial.json").write_text( + json.dumps(rows, indent=2) + "\n", encoding="utf-8") + summary = [] + for strate in range(4): + for workers in (8, 12): + item = {"strate": strate, "workers": workers, "pairs": 5} + for variant in ("base", "candidate"): + group = [row for row in rows if row["strate"] == strate + and row["workers"] == workers and row["variant"] == variant] + for key in ("lod02_ready_s", "whole_view_ready_s"): + values = [row[key] for row in group] + item[f"{variant}_{key}"] = values + item[f"{variant}_{key}_median"] = statistics.median(values) + for key in ("lod02_ready_s", "whole_view_ready_s"): + base = item[f"base_{key}_median"] + candidate = item[f"candidate_{key}_median"] + item[f"{key}_delta_pct"] = round(100 * (candidate / base - 1), 2) + summary.append(item) + (OUT / "summary.json").write_text( + json.dumps({"runs": rows, "summary": summary}, indent=2) + "\n", + encoding="utf-8") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/__pycache__/RunL112Captures.cpython-313.pyc b/Standalone/Research/WorldAssemblerM3/Linux112/__pycache__/RunL112Captures.cpython-313.pyc new file mode 100644 index 0000000..dfcf2a5 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/__pycache__/RunL112Captures.cpython-313.pyc differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/INDEX.md b/Standalone/Research/WorldAssemblerM3/Linux112/captures/INDEX.md new file mode 100644 index 0000000..bf5de51 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux112/captures/INDEX.md @@ -0,0 +1,119 @@ +# L112 passage captures + +Each PNG was rendered from its own exported mesh. The renderer reported visible triangles, and each decoded image met the pixel coverage floor. `low_contrast_geometry_visible` marks images that met this floor below the preferred contrast target. + +## Before + +- [upper-mouth](before/passage-0-1-0-upper-mouth.png) — passage/0-1/0; 253282 visible triangles +- [lower-mouth](before/passage-0-1-0-lower-mouth.png) — passage/0-1/0; 559326 visible triangles +- [25%](before/passage-0-1-0-station-25.png) — passage/0-1/0; 145630 visible triangles +- [50%](before/passage-0-1-0-station-50.png) — passage/0-1/0; 430386 visible triangles +- [75%](before/passage-0-1-0-station-75.png) — passage/0-1/0; 294374 visible triangles +- [section-1/view-1](before/passage-0-1-0-openair-1-view-1.png) — passage/0-1/0 **OPEN AIR**; 289074 visible triangles +- [section-1/view-2](before/passage-0-1-0-openair-1-view-2.png) — passage/0-1/0 **OPEN AIR**; 298057 visible triangles +- [section-1/view-3](before/passage-0-1-0-openair-1-view-3.png) — passage/0-1/0 **OPEN AIR**; 322309 visible triangles +- [section-1/4m-outside](before/passage-0-1-0-openair-1-4m-outside.png) — passage/0-1/0; 289074 visible triangles +- [section-1/4m-interior-wall](before/passage-0-1-0-openair-1-4m-interior-wall.png) — passage/0-1/0; 322309 visible triangles +- [section-2/view-1](before/passage-0-1-0-openair-2-view-1.png) — passage/0-1/0 **OPEN AIR**; 283642 visible triangles +- [section-2/view-2](before/passage-0-1-0-openair-2-view-2.png) — passage/0-1/0 **OPEN AIR**; 316771 visible triangles +- [section-2/view-3](before/passage-0-1-0-openair-2-view-3.png) — passage/0-1/0 **OPEN AIR**; 322309 visible triangles +- [section-2/4m-outside](before/passage-0-1-0-openair-2-4m-outside.png) — passage/0-1/0; 283642 visible triangles +- [section-2/4m-interior-wall](before/passage-0-1-0-openair-2-4m-interior-wall.png) — passage/0-1/0; 363071 visible triangles +- [section-3/view-1](before/passage-0-1-0-openair-3-view-1.png) — passage/0-1/0 **OPEN AIR**; 262299 visible triangles +- [section-3/view-2](before/passage-0-1-0-openair-3-view-2.png) — passage/0-1/0 **OPEN AIR**; 310919 visible triangles; low_contrast_geometry_visible +- [section-3/view-3](before/passage-0-1-0-openair-3-view-3.png) — passage/0-1/0 **OPEN AIR**; 363071 visible triangles +- [section-3/4m-outside](before/passage-0-1-0-openair-3-4m-outside.png) — passage/0-1/0; 298863 visible triangles +- [section-3/4m-interior-wall](before/passage-0-1-0-openair-3-4m-interior-wall.png) — passage/0-1/0; 340799 visible triangles +- [section-4/view-1](before/passage-0-1-0-openair-4-view-1.png) — passage/0-1/0 **OPEN AIR**; 378007 visible triangles +- [section-4/view-2](before/passage-0-1-0-openair-4-view-2.png) — passage/0-1/0 **OPEN AIR**; 471132 visible triangles +- [section-4/view-3](before/passage-0-1-0-openair-4-view-3.png) — passage/0-1/0 **OPEN AIR**; 382187 visible triangles +- [section-4/4m-outside](before/passage-0-1-0-openair-4-4m-outside.png) — passage/0-1/0; 309174 visible triangles +- [section-4/4m-interior-wall](before/passage-0-1-0-openair-4-4m-interior-wall.png) — passage/0-1/0; 382187 visible triangles +- [upper-mouth](before/passage-1-2-0-upper-mouth.png) — passage/1-2/0; 570417 visible triangles; low_contrast_geometry_visible +- [lower-mouth](before/passage-1-2-0-lower-mouth.png) — passage/1-2/0; 511318 visible triangles +- [25%](before/passage-1-2-0-station-25.png) — passage/1-2/0; 661032 visible triangles +- [50%](before/passage-1-2-0-station-50.png) — passage/1-2/0; 602996 visible triangles +- [75%](before/passage-1-2-0-station-75.png) — passage/1-2/0; 615520 visible triangles +- [section-1/view-1](before/passage-1-2-0-openair-1-view-1.png) — passage/1-2/0 **OPEN AIR**; 629052 visible triangles +- [section-1/view-2](before/passage-1-2-0-openair-1-view-2.png) — passage/1-2/0 **OPEN AIR**; 588414 visible triangles +- [section-1/view-3](before/passage-1-2-0-openair-1-view-3.png) — passage/1-2/0 **OPEN AIR**; 616234 visible triangles +- [section-1/4m-outside](before/passage-1-2-0-openair-1-4m-outside.png) — passage/1-2/0; 629052 visible triangles +- [section-1/4m-interior-wall](before/passage-1-2-0-openair-1-4m-interior-wall.png) — passage/1-2/0; 573086 visible triangles +- [upper-mouth](before/passage-2-3-0-upper-mouth.png) — passage/2-3/0; 59562 visible triangles +- [lower-mouth](before/passage-2-3-0-lower-mouth.png) — passage/2-3/0; 294522 visible triangles; low_contrast_geometry_visible +- [25%](before/passage-2-3-0-station-25.png) — passage/2-3/0; 55484 visible triangles; low_contrast_geometry_visible +- [50%](before/passage-2-3-0-station-50.png) — passage/2-3/0; 457754 visible triangles +- [75%](before/passage-2-3-0-station-75.png) — passage/2-3/0; 475706 visible triangles +- [section-1/view-1](before/passage-2-3-0-openair-1-view-1.png) — passage/2-3/0 **OPEN AIR**; 104612 visible triangles +- [section-1/view-2](before/passage-2-3-0-openair-1-view-2.png) — passage/2-3/0 **OPEN AIR**; 81078 visible triangles +- [section-1/view-3](before/passage-2-3-0-openair-1-view-3.png) — passage/2-3/0 **OPEN AIR**; 94962 visible triangles; low_contrast_geometry_visible +- [section-1/4m-outside](before/passage-2-3-0-openair-1-4m-outside.png) — passage/2-3/0; 104612 visible triangles; low_contrast_geometry_visible +- [section-1/4m-interior-wall](before/passage-2-3-0-openair-1-4m-interior-wall.png) — passage/2-3/0; 99334 visible triangles +- [section-2/view-1](before/passage-2-3-0-openair-2-view-1.png) — passage/2-3/0 **OPEN AIR**; 475688 visible triangles +- [section-2/view-2](before/passage-2-3-0-openair-2-view-2.png) — passage/2-3/0 **OPEN AIR**; 479134 visible triangles +- [section-2/view-3](before/passage-2-3-0-openair-2-view-3.png) — passage/2-3/0 **OPEN AIR**; 479134 visible triangles +- [section-2/4m-outside](before/passage-2-3-0-openair-2-4m-outside.png) — passage/2-3/0; 475688 visible triangles +- [section-2/4m-interior-wall](before/passage-2-3-0-openair-2-4m-interior-wall.png) — passage/2-3/0; 486364 visible triangles +- [section-3/view-1](before/passage-2-3-0-openair-3-view-1.png) — passage/2-3/0 **OPEN AIR**; 485216 visible triangles +- [section-3/view-2](before/passage-2-3-0-openair-3-view-2.png) — passage/2-3/0 **OPEN AIR**; 479198 visible triangles +- [section-3/view-3](before/passage-2-3-0-openair-3-view-3.png) — passage/2-3/0 **OPEN AIR**; 490436 visible triangles; low_contrast_geometry_visible +- [section-3/4m-outside](before/passage-2-3-0-openair-3-4m-outside.png) — passage/2-3/0; 485216 visible triangles +- [section-3/4m-interior-wall](before/passage-2-3-0-openair-3-4m-interior-wall.png) — passage/2-3/0; 490436 visible triangles +- [section-4/view-1](before/passage-2-3-0-openair-4-view-1.png) — passage/2-3/0 **OPEN AIR**; 475298 visible triangles +- [section-4/view-2](before/passage-2-3-0-openair-4-view-2.png) — passage/2-3/0 **OPEN AIR**; 495856 visible triangles +- [section-4/view-3](before/passage-2-3-0-openair-4-view-3.png) — passage/2-3/0 **OPEN AIR**; 496236 visible triangles; low_contrast_geometry_visible +- [section-4/4m-outside](before/passage-2-3-0-openair-4-4m-outside.png) — passage/2-3/0; 475298 visible triangles +- [section-4/4m-interior-wall](before/passage-2-3-0-openair-4-4m-interior-wall.png) — passage/2-3/0; 475316 visible triangles + +## After + +- [upper-mouth](after/passage-0-1-0-upper-mouth.png) — passage/0-1/0; 244874 visible triangles +- [lower-mouth](after/passage-0-1-0-lower-mouth.png) — passage/0-1/0; 551596 visible triangles +- [25%](after/passage-0-1-0-station-25.png) — passage/0-1/0; 135136 visible triangles +- [50%](after/passage-0-1-0-station-50.png) — passage/0-1/0; 316508 visible triangles +- [75%](after/passage-0-1-0-station-75.png) — passage/0-1/0; 257040 visible triangles +- [section-1/view-1](after/passage-0-1-0-openair-1-view-1.png) — passage/0-1/0 **OPEN AIR**; 278629 visible triangles +- [section-1/view-2](after/passage-0-1-0-openair-1-view-2.png) — passage/0-1/0 **OPEN AIR**; 287396 visible triangles +- [section-1/view-3](after/passage-0-1-0-openair-1-view-3.png) — passage/0-1/0 **OPEN AIR**; 311780 visible triangles +- [section-1/4m-outside](after/passage-0-1-0-openair-1-4m-outside.png) — passage/0-1/0; 278629 visible triangles +- [section-1/4m-interior-wall](after/passage-0-1-0-openair-1-4m-interior-wall.png) — passage/0-1/0; 311780 visible triangles +- [section-2/view-1](after/passage-0-1-0-openair-2-view-1.png) — passage/0-1/0 **OPEN AIR**; 278629 visible triangles +- [section-2/view-2](after/passage-0-1-0-openair-2-view-2.png) — passage/0-1/0 **OPEN AIR**; 311780 visible triangles +- [section-2/view-3](after/passage-0-1-0-openair-2-view-3.png) — passage/0-1/0 **OPEN AIR**; 311780 visible triangles +- [section-2/4m-outside](after/passage-0-1-0-openair-2-4m-outside.png) — passage/0-1/0; 278629 visible triangles +- [section-2/4m-interior-wall](after/passage-0-1-0-openair-2-4m-interior-wall.png) — passage/0-1/0; 350192 visible triangles +- [section-3/view-1](after/passage-0-1-0-openair-3-view-1.png) — passage/0-1/0 **OPEN AIR**; 210501 visible triangles +- [section-3/view-2](after/passage-0-1-0-openair-3-view-2.png) — passage/0-1/0 **OPEN AIR**; 189354 visible triangles +- [section-3/view-3](after/passage-0-1-0-openair-3-view-3.png) — passage/0-1/0 **OPEN AIR**; 189354 visible triangles +- [section-3/4m-outside](after/passage-0-1-0-openair-3-4m-outside.png) — passage/0-1/0; 156696 visible triangles +- [section-3/4m-interior-wall](after/passage-0-1-0-openair-3-4m-interior-wall.png) — passage/0-1/0; 156658 visible triangles +- [upper-mouth](after/passage-1-2-0-upper-mouth.png) — passage/1-2/0; 595932 visible triangles +- [lower-mouth](after/passage-1-2-0-lower-mouth.png) — passage/1-2/0; 546268 visible triangles +- [25%](after/passage-1-2-0-station-25.png) — passage/1-2/0; 655074 visible triangles +- [50%](after/passage-1-2-0-station-50.png) — passage/1-2/0; 604662 visible triangles +- [75%](after/passage-1-2-0-station-75.png) — passage/1-2/0; 612135 visible triangles +- [section-1/view-1](after/passage-1-2-0-openair-1-view-1.png) — passage/1-2/0 **OPEN AIR**; 623352 visible triangles +- [section-1/view-2](after/passage-1-2-0-openair-1-view-2.png) — passage/1-2/0 **OPEN AIR**; 576164 visible triangles; low_contrast_geometry_visible +- [section-1/view-3](after/passage-1-2-0-openair-1-view-3.png) — passage/1-2/0 **OPEN AIR**; 570605 visible triangles +- [section-1/4m-outside](after/passage-1-2-0-openair-1-4m-outside.png) — passage/1-2/0; 623352 visible triangles +- [section-1/4m-interior-wall](after/passage-1-2-0-openair-1-4m-interior-wall.png) — passage/1-2/0; 612135 visible triangles +- [section-2/view-1](after/passage-1-2-0-openair-2-view-1.png) — passage/1-2/0 **OPEN AIR**; 628316 visible triangles +- [section-2/view-2](after/passage-1-2-0-openair-2-view-2.png) — passage/1-2/0 **OPEN AIR**; 585440 visible triangles +- [section-2/view-3](after/passage-1-2-0-openair-2-view-3.png) — passage/1-2/0 **OPEN AIR**; 613722 visible triangles +- [section-2/4m-outside](after/passage-1-2-0-openair-2-4m-outside.png) — passage/1-2/0; 585802 visible triangles +- [section-2/4m-interior-wall](after/passage-1-2-0-openair-2-4m-interior-wall.png) — passage/1-2/0; 574472 visible triangles +- [upper-mouth](after/passage-2-3-0-upper-mouth.png) — passage/2-3/0; 59568 visible triangles +- [lower-mouth](after/passage-2-3-0-lower-mouth.png) — passage/2-3/0; 294004 visible triangles; low_contrast_geometry_visible +- [25%](after/passage-2-3-0-station-25.png) — passage/2-3/0; 55514 visible triangles; low_contrast_geometry_visible +- [50%](after/passage-2-3-0-station-50.png) — passage/2-3/0; 458230 visible triangles +- [75%](after/passage-2-3-0-station-75.png) — passage/2-3/0; 475838 visible triangles +- [section-1/view-1](after/passage-2-3-0-openair-1-view-1.png) — passage/2-3/0 **OPEN AIR**; 104612 visible triangles +- [section-1/view-2](after/passage-2-3-0-openair-1-view-2.png) — passage/2-3/0 **OPEN AIR**; 76426 visible triangles +- [section-1/view-3](after/passage-2-3-0-openair-1-view-3.png) — passage/2-3/0 **OPEN AIR**; 94962 visible triangles +- [section-1/4m-outside](after/passage-2-3-0-openair-1-4m-outside.png) — passage/2-3/0; 104612 visible triangles; low_contrast_geometry_visible +- [section-1/4m-interior-wall](after/passage-2-3-0-openair-1-4m-interior-wall.png) — passage/2-3/0; 94962 visible triangles; low_contrast_geometry_visible +- [section-2/view-1](after/passage-2-3-0-openair-2-view-1.png) — passage/2-3/0 **OPEN AIR**; 476214 visible triangles +- [section-2/view-2](after/passage-2-3-0-openair-2-view-2.png) — passage/2-3/0 **OPEN AIR**; 479366 visible triangles +- [section-2/view-3](after/passage-2-3-0-openair-2-view-3.png) — passage/2-3/0 **OPEN AIR**; 479366 visible triangles +- [section-2/4m-outside](after/passage-2-3-0-openair-2-4m-outside.png) — passage/2-3/0; 476214 visible triangles +- [section-2/4m-interior-wall](after/passage-2-3-0-openair-2-4m-interior-wall.png) — passage/2-3/0; 486990 visible triangles diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-lower-mouth.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-lower-mouth.png new file mode 100644 index 0000000..eccd3c0 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-lower-mouth.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-1-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-1-4m-interior-wall.png new file mode 100644 index 0000000..e10071a Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-1-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-1-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-1-4m-outside.png new file mode 100644 index 0000000..a25faeb Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-1-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-1-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-1-view-1.png new file mode 100644 index 0000000..b2f9837 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-1-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-1-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-1-view-2.png new file mode 100644 index 0000000..3b394f1 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-1-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-1-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-1-view-3.png new file mode 100644 index 0000000..7bc7c9f Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-1-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-2-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-2-4m-interior-wall.png new file mode 100644 index 0000000..e7ac719 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-2-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-2-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-2-4m-outside.png new file mode 100644 index 0000000..58e65cb Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-2-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-2-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-2-view-1.png new file mode 100644 index 0000000..87476c9 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-2-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-2-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-2-view-2.png new file mode 100644 index 0000000..c904473 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-2-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-2-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-2-view-3.png new file mode 100644 index 0000000..8e8a59f Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-2-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-3-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-3-4m-interior-wall.png new file mode 100644 index 0000000..b370fe5 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-3-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-3-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-3-4m-outside.png new file mode 100644 index 0000000..eea6716 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-3-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-3-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-3-view-1.png new file mode 100644 index 0000000..20f5ecd Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-3-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-3-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-3-view-2.png new file mode 100644 index 0000000..2dc7280 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-3-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-3-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-3-view-3.png new file mode 100644 index 0000000..6d222d2 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-3-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-4-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-4-4m-interior-wall.png new file mode 100644 index 0000000..0073250 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-4-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-4-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-4-4m-outside.png new file mode 100644 index 0000000..50f97d3 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-4-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-4-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-4-view-1.png new file mode 100644 index 0000000..f7c85d9 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-4-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-4-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-4-view-2.png new file mode 100644 index 0000000..1bf0938 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-4-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-4-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-4-view-3.png new file mode 100644 index 0000000..6a5f9d1 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-4-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-station-25.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-station-25.png new file mode 100644 index 0000000..6d5b759 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-station-25.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-station-50.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-station-50.png new file mode 100644 index 0000000..44c7050 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-station-50.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-station-75.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-station-75.png new file mode 100644 index 0000000..72f1e02 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-station-75.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-upper-mouth.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-upper-mouth.png new file mode 100644 index 0000000..4a21f52 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-upper-mouth.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-lower-mouth.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-lower-mouth.png new file mode 100644 index 0000000..2ab98a0 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-lower-mouth.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-openair-1-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-openair-1-4m-interior-wall.png new file mode 100644 index 0000000..2e156af Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-openair-1-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-openair-1-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-openair-1-4m-outside.png new file mode 100644 index 0000000..b4da33f Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-openair-1-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-openair-1-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-openair-1-view-1.png new file mode 100644 index 0000000..8d8bbd7 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-openair-1-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-openair-1-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-openair-1-view-2.png new file mode 100644 index 0000000..9dafe3d Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-openair-1-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-openair-1-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-openair-1-view-3.png new file mode 100644 index 0000000..43909f5 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-openair-1-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-openair-2-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-openair-2-4m-interior-wall.png new file mode 100644 index 0000000..9d1043a Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-openair-2-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-openair-2-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-openair-2-4m-outside.png new file mode 100644 index 0000000..e89577e Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-openair-2-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-openair-2-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-openair-2-view-1.png new file mode 100644 index 0000000..8fc4c66 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-openair-2-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-openair-2-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-openair-2-view-2.png new file mode 100644 index 0000000..226da7d Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-openair-2-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-openair-2-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-openair-2-view-3.png new file mode 100644 index 0000000..f171a9b Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-openair-2-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-station-25.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-station-25.png new file mode 100644 index 0000000..aeeed93 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-station-25.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-station-50.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-station-50.png new file mode 100644 index 0000000..6422188 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-station-50.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-station-75.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-station-75.png new file mode 100644 index 0000000..5b2f35c Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-station-75.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-upper-mouth.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-upper-mouth.png new file mode 100644 index 0000000..a0c4f1a Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-upper-mouth.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-lower-mouth.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-lower-mouth.png new file mode 100644 index 0000000..70a3431 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-lower-mouth.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-openair-1-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-openair-1-4m-interior-wall.png new file mode 100644 index 0000000..0829ac3 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-openair-1-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-openair-1-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-openair-1-4m-outside.png new file mode 100644 index 0000000..23440bc Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-openair-1-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-openair-1-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-openair-1-view-1.png new file mode 100644 index 0000000..96e6e48 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-openair-1-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-openair-1-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-openair-1-view-2.png new file mode 100644 index 0000000..5b6337f Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-openair-1-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-openair-1-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-openair-1-view-3.png new file mode 100644 index 0000000..1f19638 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-openair-1-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-openair-2-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-openair-2-4m-interior-wall.png new file mode 100644 index 0000000..e54a164 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-openair-2-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-openair-2-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-openair-2-4m-outside.png new file mode 100644 index 0000000..69e235d Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-openair-2-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-openair-2-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-openair-2-view-1.png new file mode 100644 index 0000000..b06dba2 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-openair-2-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-openair-2-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-openair-2-view-2.png new file mode 100644 index 0000000..6ddebea Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-openair-2-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-openair-2-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-openair-2-view-3.png new file mode 100644 index 0000000..c76a392 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-openair-2-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-station-25.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-station-25.png new file mode 100644 index 0000000..794aeb3 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-station-25.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-station-50.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-station-50.png new file mode 100644 index 0000000..897b55b Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-station-50.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-station-75.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-station-75.png new file mode 100644 index 0000000..bbf4e47 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-station-75.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-upper-mouth.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-upper-mouth.png new file mode 100644 index 0000000..50b6f6e Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-upper-mouth.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-lower-mouth.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-lower-mouth.png new file mode 100644 index 0000000..e92cfe1 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-lower-mouth.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-1-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-1-4m-interior-wall.png new file mode 100644 index 0000000..aac4121 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-1-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-1-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-1-4m-outside.png new file mode 100644 index 0000000..286c351 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-1-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-1-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-1-view-1.png new file mode 100644 index 0000000..38ff704 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-1-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-1-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-1-view-2.png new file mode 100644 index 0000000..bcc62fb Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-1-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-1-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-1-view-3.png new file mode 100644 index 0000000..0b85bb1 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-1-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-2-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-2-4m-interior-wall.png new file mode 100644 index 0000000..efe106d Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-2-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-2-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-2-4m-outside.png new file mode 100644 index 0000000..82d39f5 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-2-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-2-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-2-view-1.png new file mode 100644 index 0000000..868c4f4 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-2-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-2-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-2-view-2.png new file mode 100644 index 0000000..1111c70 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-2-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-2-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-2-view-3.png new file mode 100644 index 0000000..42b43fc Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-2-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-3-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-3-4m-interior-wall.png new file mode 100644 index 0000000..0e3b675 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-3-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-3-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-3-4m-outside.png new file mode 100644 index 0000000..cd380a8 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-3-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-3-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-3-view-1.png new file mode 100644 index 0000000..f498353 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-3-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-3-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-3-view-2.png new file mode 100644 index 0000000..a077c37 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-3-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-3-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-3-view-3.png new file mode 100644 index 0000000..bef0390 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-3-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-4-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-4-4m-interior-wall.png new file mode 100644 index 0000000..eea76a0 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-4-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-4-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-4-4m-outside.png new file mode 100644 index 0000000..d556c2c Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-4-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-4-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-4-view-1.png new file mode 100644 index 0000000..43049af Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-4-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-4-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-4-view-2.png new file mode 100644 index 0000000..934a77f Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-4-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-4-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-4-view-3.png new file mode 100644 index 0000000..31322cf Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-openair-4-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-station-25.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-station-25.png new file mode 100644 index 0000000..697ccbd Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-station-25.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-station-50.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-station-50.png new file mode 100644 index 0000000..1a96e59 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-station-50.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-station-75.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-station-75.png new file mode 100644 index 0000000..0a47b71 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-station-75.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-upper-mouth.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-upper-mouth.png new file mode 100644 index 0000000..92eebd9 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-0-1-0-upper-mouth.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-1-2-0-lower-mouth.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-1-2-0-lower-mouth.png new file mode 100644 index 0000000..b42b0db Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-1-2-0-lower-mouth.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-1-2-0-openair-1-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-1-2-0-openair-1-4m-interior-wall.png new file mode 100644 index 0000000..44f94a1 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-1-2-0-openair-1-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-1-2-0-openair-1-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-1-2-0-openair-1-4m-outside.png new file mode 100644 index 0000000..b3077cd Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-1-2-0-openair-1-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-1-2-0-openair-1-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-1-2-0-openair-1-view-1.png new file mode 100644 index 0000000..f81c7cf Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-1-2-0-openair-1-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-1-2-0-openair-1-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-1-2-0-openair-1-view-2.png new file mode 100644 index 0000000..8c0052e Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-1-2-0-openair-1-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-1-2-0-openair-1-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-1-2-0-openair-1-view-3.png new file mode 100644 index 0000000..bd130d0 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-1-2-0-openair-1-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-1-2-0-station-25.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-1-2-0-station-25.png new file mode 100644 index 0000000..745cd66 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-1-2-0-station-25.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-1-2-0-station-50.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-1-2-0-station-50.png new file mode 100644 index 0000000..d32a16b Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-1-2-0-station-50.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-1-2-0-station-75.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-1-2-0-station-75.png new file mode 100644 index 0000000..bb01e66 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-1-2-0-station-75.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-1-2-0-upper-mouth.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-1-2-0-upper-mouth.png new file mode 100644 index 0000000..0b0430c Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-1-2-0-upper-mouth.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-lower-mouth.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-lower-mouth.png new file mode 100644 index 0000000..6a11c52 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-lower-mouth.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-1-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-1-4m-interior-wall.png new file mode 100644 index 0000000..650adc1 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-1-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-1-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-1-4m-outside.png new file mode 100644 index 0000000..78008c6 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-1-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-1-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-1-view-1.png new file mode 100644 index 0000000..e958856 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-1-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-1-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-1-view-2.png new file mode 100644 index 0000000..e201769 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-1-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-1-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-1-view-3.png new file mode 100644 index 0000000..006b05a Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-1-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-2-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-2-4m-interior-wall.png new file mode 100644 index 0000000..e018324 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-2-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-2-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-2-4m-outside.png new file mode 100644 index 0000000..805438d Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-2-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-2-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-2-view-1.png new file mode 100644 index 0000000..5a069a4 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-2-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-2-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-2-view-2.png new file mode 100644 index 0000000..054aba4 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-2-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-2-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-2-view-3.png new file mode 100644 index 0000000..0fc9685 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-2-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-3-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-3-4m-interior-wall.png new file mode 100644 index 0000000..947f4f1 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-3-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-3-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-3-4m-outside.png new file mode 100644 index 0000000..0911f75 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-3-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-3-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-3-view-1.png new file mode 100644 index 0000000..ba11b0c Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-3-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-3-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-3-view-2.png new file mode 100644 index 0000000..fe7f56c Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-3-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-3-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-3-view-3.png new file mode 100644 index 0000000..0f4416a Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-3-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-4-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-4-4m-interior-wall.png new file mode 100644 index 0000000..4da66c6 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-4-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-4-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-4-4m-outside.png new file mode 100644 index 0000000..25cae09 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-4-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-4-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-4-view-1.png new file mode 100644 index 0000000..0f6a894 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-4-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-4-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-4-view-2.png new file mode 100644 index 0000000..4288fe7 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-4-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-4-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-4-view-3.png new file mode 100644 index 0000000..2e69508 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-openair-4-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-station-25.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-station-25.png new file mode 100644 index 0000000..794aeb3 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-station-25.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-station-50.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-station-50.png new file mode 100644 index 0000000..333947a Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-station-50.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-station-75.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-station-75.png new file mode 100644 index 0000000..4d97c05 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-station-75.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-upper-mouth.png b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-upper-mouth.png new file mode 100644 index 0000000..5f8dc22 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux112/captures/before/passage-2-3-0-upper-mouth.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux112/captures/capture-index.json b/Standalone/Research/WorldAssemblerM3/Linux112/captures/capture-index.json new file mode 100644 index 0000000..00c6ed0 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux112/captures/capture-index.json @@ -0,0 +1,6756 @@ +{ + "open_air_sections_by_variant": { + "before": [ + { + "passage": "passage/0-1/0", + "section": 1, + "start_m": 7.226, + "end_m": 10.217, + "samples": 13, + "midpoint": [ + 6.375, + 7.507, + -373.204 + ], + "radius_m": 1.958 + }, + { + "passage": "passage/0-1/0", + "section": 2, + "start_m": 13.456, + "end_m": 17.443, + "samples": 17, + "midpoint": [ + 5.121, + 0.955, + -374.039 + ], + "radius_m": 2.31 + }, + { + "passage": "passage/0-1/0", + "section": 3, + "start_m": 23.174, + "end_m": 24.918, + "samples": 8, + "midpoint": [ + 3.519, + -7.417, + -375.105 + ], + "radius_m": 2.761 + }, + { + "passage": "passage/0-1/0", + "section": 4, + "start_m": 1036.913, + "end_m": 1489.321, + "samples": 1838, + "midpoint": [ + -24.253, + -7.219, + -598.622 + ], + "radius_m": 3.5 + }, + { + "passage": "passage/1-2/0", + "section": 1, + "start_m": 101.82, + "end_m": 104.499, + "samples": 12, + "midpoint": [ + 9.136, + -11.613, + -749.434 + ], + "radius_m": 3.173 + }, + { + "passage": "passage/2-3/0", + "section": 1, + "start_m": 7.677, + "end_m": 34.747, + "samples": 108, + "midpoint": [ + -2.846, + -13.149, + -814.246 + ], + "radius_m": 3.0 + }, + { + "passage": "passage/2-3/0", + "section": 2, + "start_m": 368.909, + "end_m": 376.66, + "samples": 32, + "midpoint": [ + -9.545, + 9.558, + -877.248 + ], + "radius_m": 3.0 + }, + { + "passage": "passage/2-3/0", + "section": 3, + "start_m": 393.828, + "end_m": 396.51, + "samples": 7, + "midpoint": [ + -11.172, + -10.684, + -881.259 + ], + "radius_m": 3.0 + }, + { + "passage": "passage/2-3/0", + "section": 4, + "start_m": 444.932, + "end_m": 447.654, + "samples": 11, + "midpoint": [ + 9.72, + 10.251, + -890.42 + ], + "radius_m": 3.0 + } + ], + "after": [ + { + "passage": "passage/0-1/0", + "section": 1, + "start_m": 6.905, + "end_m": 9.618, + "samples": 12, + "midpoint": [ + 7.282, + 7.839, + -373.185 + ], + "radius_m": 1.93 + }, + { + "passage": "passage/0-1/0", + "section": 2, + "start_m": 13.078, + "end_m": 15.794, + "samples": 12, + "midpoint": [ + 6.611, + 1.753, + -374.166 + ], + "radius_m": 2.253 + }, + { + "passage": "passage/0-1/0", + "section": 3, + "start_m": 1041.174, + "end_m": 1489.448, + "samples": 1979, + "midpoint": [ + -22.039, + -12.355, + -599.25 + ], + "radius_m": 3.5 + }, + { + "passage": "passage/1-2/0", + "section": 1, + "start_m": 81.367, + "end_m": 85.596, + "samples": 19, + "midpoint": [ + -9.52, + -9.729, + -745.879 + ], + "radius_m": 3.0 + }, + { + "passage": "passage/1-2/0", + "section": 2, + "start_m": 104.041, + "end_m": 104.778, + "samples": 4, + "midpoint": [ + 9.488, + -11.155, + -749.755 + ], + "radius_m": 3.139 + }, + { + "passage": "passage/2-3/0", + "section": 1, + "start_m": 7.733, + "end_m": 25.281, + "samples": 74, + "midpoint": [ + -7.267, + -11.478, + -813.609 + ], + "radius_m": 3.0 + }, + { + "passage": "passage/2-3/0", + "section": 2, + "start_m": 372.675, + "end_m": 377.341, + "samples": 21, + "midpoint": [ + -9.548, + 9.557, + -877.478 + ], + "radius_m": 3.0 + } + ] + }, + "captures": [ + { + "name": "passage-0-1-0-upper-mouth", + "passage": "passage/0-1/0", + "kind": "mouth", + "station": "upper-mouth", + "camera": [ + 8.839199674686244, + 20.385640196824248, + -371.842578125 + ], + "target": [ + 7.627022366806115, + 14.050826579189224, + -371.942578125 + ], + "yaw": -169.1673035961807, + "pitch": -0.8882703208739064, + "focus": [ + 8.0, + 16.0, + -372.122578125 + ], + "center_z": -372.122578125, + "variant": "before", + "capture": "captures/before/passage-0-1-0-upper-mouth.png", + "scene": "Saved/Linux/l112/captures/before/passage-0-1-0-upper-mouth.vfmesh", + "drawn_triangles": 253282, + "source_triangles": 310752, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": null, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 8.839199674686244, + 20.385640196824248, + -371.842578125 + ], + "target_actual_m": [ + 7.627022366806115, + 14.050826579189224, + -371.942578125 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-0-1-0-upper-mouth-mesh.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-upper-mouth-render.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-upper-mouth-quality.log" + ] + }, + { + "name": "passage-0-1-0-lower-mouth", + "passage": "passage/0-1/0", + "kind": "mouth", + "station": "lower-mouth", + "camera": [ + 32.29870756948553, + 9.932859678359986, + -735.514490514727 + ], + "target": [ + 24.47653648208193, + 1.781610133503092, + -736.6798828125 + ], + "yaw": -136.18021933793756, + "pitch": -5.889606445716861, + "focus": [ + 25.836914062499947, + 3.199218749999943, + -734.8598828125 + ], + "center_z": -734.8598828125, + "variant": "before", + "capture": "captures/before/passage-0-1-0-lower-mouth.png", + "scene": "Saved/Linux/l112/captures/before/passage-0-1-0-lower-mouth.vfmesh", + "drawn_triangles": 559326, + "source_triangles": 611506, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": null, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 32.29870756948553, + 9.932859678359986, + -735.514490514727 + ], + "target_actual_m": [ + 24.47653648208193, + 1.781610133503092, + -736.6798828125 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-0-1-0-lower-mouth-mesh.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-lower-mouth-render.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-lower-mouth-quality.log" + ] + }, + { + "name": "passage-0-1-0-station-25", + "passage": "passage/0-1/0", + "kind": "station", + "station": "25%", + "camera": [ + -14.832678263995309, + -18.72062618817443, + -462.7942446741164 + ], + "target": [ + -21.89083852694916, + -7.989572734179358, + -465.1289462328135 + ], + "yaw": -33.33421057217368, + "pitch": -10.302233434343137, + "focus": [ + -14.365775643756486, + -18.133683309169903, + -461.1242446741164 + ], + "center_z": -461.1242446741164, + "route_distance_m": 503.59931612822896, + "route_length_m": 2014.3972645129159, + "requested_route_distance_m": 503.59931612822896, + "variant": "before", + "capture": "captures/before/passage-0-1-0-station-25.png", + "scene": "Saved/Linux/l112/captures/before/passage-0-1-0-station-25.vfmesh", + "drawn_triangles": 145630, + "source_triangles": 194558, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 503.59931612822896, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -14.832678263995309, + -18.72062618817443, + -462.7942446741164 + ], + "target_actual_m": [ + -21.89083852694916, + -7.989572734179358, + -465.1289462328135 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-0-1-0-station-25-mesh.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-station-25-render.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-station-25-quality.log" + ] + }, + { + "name": "passage-0-1-0-station-50", + "passage": "passage/0-1/0", + "kind": "station", + "station": "50%", + "camera": [ + -5.478551888892594, + 21.511593715955158, + -553.9658220811451 + ], + "target": [ + 7.751504608756267, + 21.398972718233775, + -556.3002867114685 + ], + "yaw": 90.48771915686082, + "pitch": -10.006569463318558, + "focus": [ + -5.390306191921176, + 20.7668033447996, + -552.2958220811452 + ], + "center_z": -552.2958220811452, + "route_distance_m": 1007.1986322564579, + "route_length_m": 2014.3972645129159, + "requested_route_distance_m": 1007.1986322564579, + "variant": "before", + "capture": "captures/before/passage-0-1-0-station-50.png", + "scene": "Saved/Linux/l112/captures/before/passage-0-1-0-station-50.vfmesh", + "drawn_triangles": 430386, + "source_triangles": 541436, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1007.1986322564579, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -5.478551888892594, + 21.511593715955158, + -553.9658220811451 + ], + "target_actual_m": [ + 7.751504608756267, + 21.398972718233775, + -556.3002867114685 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-0-1-0-station-50-mesh.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-station-50-render.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-station-50-quality.log" + ] + }, + { + "name": "passage-0-1-0-station-75", + "passage": "passage/0-1/0", + "kind": "station", + "station": "75%", + "camera": [ + 16.41045488666863, + -13.591590559867178, + -645.1369534883806 + ], + "target": [ + 6.2905981482465405, + -21.544778689774127, + -647.4714776908803 + ], + "yaw": -128.16377958476315, + "pitch": -10.28040282125882, + "focus": [ + 15.809745384875612, + -13.142538119215107, + -643.4669534883807 + ], + "center_z": -643.4669534883807, + "route_distance_m": 1510.7979483846868, + "route_length_m": 2014.3972645129159, + "requested_route_distance_m": 1510.7979483846868, + "variant": "before", + "capture": "captures/before/passage-0-1-0-station-75.png", + "scene": "Saved/Linux/l112/captures/before/passage-0-1-0-station-75.vfmesh", + "drawn_triangles": 294374, + "source_triangles": 369990, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1510.7979483846868, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 16.41045488666863, + -13.591590559867178, + -645.1369534883806 + ], + "target_actual_m": [ + 6.2905981482465405, + -21.544778689774127, + -647.4714776908803 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-0-1-0-station-75-mesh.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-station-75-render.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-station-75-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-1-view-1", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-1/view-1", + "camera": [ + 13.209009551818514, + 6.199300705187415, + -372.004 + ], + "target": [ + 6.375, + 7.507, + -373.104 + ], + "yaw": -79.16730359618066, + "pitch": -8.983620476603383, + "focus": [ + 6.375, + 7.507, + -373.204 + ], + "center_z": -373.204, + "open_air_section": 1, + "route_distance_m": 8.7215, + "requested_route_distance_m": 8.7215, + "route_length_m": 2014.3972645129159, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-1-view-1.png", + "scene": "Saved/Linux/l112/captures/before/passage-0-1-0-openair-1-view-1.vfmesh", + "drawn_triangles": 289074, + "source_triangles": 360606, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 8.7215, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 13.209009551818514, + 6.199300705187415, + -372.004 + ], + "target_actual_m": [ + 6.375, + 7.507, + -373.104 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-1-view-1-mesh.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-1-view-1-render.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-1-view-1-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-1-view-2", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-1/view-2", + "camera": [ + 1.0142606878664209, + 8.532786540828843, + -369.204 + ], + "target": [ + 6.002022366806118, + 5.557826579189251, + -373.4522149486675 + ], + "yaw": 120.81404399724752, + "pitch": -36.18521056311671, + "focus": [ + 6.375, + 7.507, + -373.204 + ], + "center_z": -373.204, + "open_air_section": 1, + "route_distance_m": 8.7215, + "requested_route_distance_m": 8.7215, + "route_length_m": 2014.3972645129159, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-1-view-2.png", + "scene": "Saved/Linux/l112/captures/before/passage-0-1-0-openair-1-view-2.vfmesh", + "drawn_triangles": 298057, + "source_triangles": 371201, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 8.7215, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 1.0142606878664209, + 8.532786540828843, + -369.204 + ], + "target_actual_m": [ + 6.002022366806118, + 5.557826579189251, + -373.4522149486675 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-1-view-2-mesh.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-1-view-2-render.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-1-view-2-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-1-view-3", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-1/view-3", + "camera": [ + 6.375, + 7.507, + -373.682 + ], + "target": [ + 5.069578283821414, + 0.6848930271623788, + -374.5507523203363 + ], + "yaw": -169.16730359618066, + "pitch": -7.1292164823138044, + "focus": [ + 6.375, + 7.507, + -373.204 + ], + "center_z": -373.204, + "open_air_section": 1, + "route_distance_m": 8.7215, + "requested_route_distance_m": 8.7215, + "route_length_m": 2014.3972645129159, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-1-view-3.png", + "scene": "Saved/Linux/l112/captures/before/passage-0-1-0-openair-1-view-3.vfmesh", + "drawn_triangles": 322309, + "source_triangles": 406051, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 8.7215, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 6.375, + 7.507, + -373.682 + ], + "target_actual_m": [ + 5.069578283821414, + 0.6848930271623788, + -374.5507523203363 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-1-view-3-mesh.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-1-view-3-render.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-1-view-3-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-1-4m-outside", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-1/4m-outside", + "camera": [ + 12.226829392028558, + 6.387242541176576, + -374.432 + ], + "target": [ + 8.298108752868734, + 7.1390098851332215, + -374.432 + ], + "yaw": -79.16730359618066, + "pitch": 0.0, + "focus": [ + 6.375, + 7.507, + -373.204 + ], + "center_z": -373.204, + "open_air_section": 1, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.9821801597899559, + -0.18794183598916137, + 0.0 + ], + "camera_target_distance_m": 4.000000000000001, + "route_distance_m": 8.7215, + "requested_route_distance_m": 8.7215, + "route_length_m": 2014.3972645129159, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-1-4m-outside.png", + "scene": "Saved/Linux/l112/captures/before/passage-0-1-0-openair-1-4m-outside.vfmesh", + "drawn_triangles": 289074, + "source_triangles": 360606, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 8.7215, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.999999999999993, + "closeup_target_surface_distance_m": 1.099219737390483, + "closeup_predicted_target_offset_m": 1.099219737390483, + "closeup_wall_normal_alignment": 0.6786316477708347, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 11.011816777527464, + 7.963487706581901, + -376.64806417591785 + ], + "target_actual_m": [ + 8.255026817321777, + 8.0, + -373.75 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-1-4m-outside-mesh.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-1-4m-outside-render.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-1-4m-outside-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-1-4m-interior-wall", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-1/4m-interior-wall", + "camera": [ + 6.16842641619789, + 3.6337628862872573, + -374.9126661812345 + ], + "target": [ + 7.872874656921727, + 7.220379149133182, + -374.432 + ], + "yaw": 25.418216346738422, + "pitch": 6.901714476028475, + "focus": [ + 6.375, + 7.507, + -373.204 + ], + "center_z": -373.204, + "open_air_section": 1, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.9821801597899559, + 0.18794183598916137, + -0.0 + ], + "camera_target_distance_m": 3.9999999999999987, + "route_distance_m": 8.7215, + "requested_route_distance_m": 8.7215, + "route_length_m": 2014.3972645129159, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-1-4m-interior-wall.png", + "scene": "Saved/Linux/l112/captures/before/passage-0-1-0-openair-1-4m-interior-wall.vfmesh", + "drawn_triangles": 322309, + "source_triangles": 406051, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 8.7215, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.9999999999999925, + "closeup_target_surface_distance_m": 1.104071077786548, + "closeup_predicted_target_offset_m": 1.104071077786548, + "closeup_wall_normal_alignment": 0.6786316477708347, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 5.498236857116091, + 8.036512293418099, + -370.85193582408215 + ], + "target_actual_m": [ + 8.255026817321777, + 8.0, + -373.75 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-1-4m-interior-wall-mesh.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-1-4m-interior-wall-render.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-1-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-2-view-1", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-2/view-1", + "camera": [ + 12.300736968064577, + -0.41885482108077465, + -372.839 + ], + "target": [ + 5.121, + 0.955, + -373.93899999999996 + ], + "yaw": -79.16730359618062, + "pitch": -8.557593063277757, + "focus": [ + 5.121, + 0.955, + -374.039 + ], + "center_z": -374.039, + "open_air_section": 2, + "route_distance_m": 15.4495, + "requested_route_distance_m": 15.4495, + "route_length_m": 2014.3972645129159, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-2-view-1.png", + "scene": "Saved/Linux/l112/captures/before/passage-0-1-0-openair-2-view-1.vfmesh", + "drawn_triangles": 283642, + "source_triangles": 349878, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 15.4495, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 12.300736968064577, + -0.41885482108077465, + -372.839 + ], + "target_actual_m": [ + 5.121, + 0.955, + -373.93899999999996 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-2-view-1-mesh.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-2-view-1-render.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-2-view-1-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-2-view-2", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-2/view-2", + "camera": [ + -0.5854667283796422, + 2.0469420670970315, + -370.039 + ], + "target": [ + 4.748022366806118, + -0.9941734208107486, + -374.2872149486675 + ], + "yaw": 119.69146427854264, + "pitch": -34.6808549169467, + "focus": [ + 5.121, + 0.955, + -374.039 + ], + "center_z": -374.039, + "open_air_section": 2, + "route_distance_m": 15.4495, + "requested_route_distance_m": 15.4495, + "route_length_m": 2014.3972645129159, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-2-view-2.png", + "scene": "Saved/Linux/l112/captures/before/passage-0-1-0-openair-2-view-2.vfmesh", + "drawn_triangles": 316771, + "source_triangles": 399589, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 15.4495, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -0.5854667283796422, + 2.0469420670970315, + -370.039 + ], + "target_actual_m": [ + 4.748022366806118, + -0.9941734208107486, + -374.2872149486675 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-2-view-2-mesh.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-2-view-2-render.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-2-view-2-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-2-view-3", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-2/view-3", + "camera": [ + 5.121, + 0.955, + -374.86899999999997 + ], + "target": [ + 3.8155782838214094, + -5.86710697283762, + -375.73775232033626 + ], + "yaw": -169.1673035961806, + "pitch": -7.1292164823138044, + "focus": [ + 5.121, + 0.955, + -374.039 + ], + "center_z": -374.039, + "open_air_section": 2, + "route_distance_m": 15.4495, + "requested_route_distance_m": 15.4495, + "route_length_m": 2014.3972645129159, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-2-view-3.png", + "scene": "Saved/Linux/l112/captures/before/passage-0-1-0-openair-2-view-3.vfmesh", + "drawn_triangles": 322309, + "source_triangles": 406051, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 15.4495, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 5.121, + 0.955, + -374.86899999999997 + ], + "target_actual_m": [ + 3.8155782838214094, + -5.86710697283762, + -375.73775232033626 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-2-view-3-mesh.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-2-view-3-render.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-2-view-3-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-2-4m-outside", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-2/4m-outside", + "camera": [ + 11.31855680827462, + -0.2309129850916125, + -375.61899999999997 + ], + "target": [ + 7.389836169114798, + 0.5208543588650356, + -375.61899999999997 + ], + "yaw": -79.16730359618062, + "pitch": 0.0, + "focus": [ + 5.121, + 0.955, + -374.039 + ], + "center_z": -374.039, + "open_air_section": 2, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.9821801597899557, + -0.18794183598916203, + 0.0 + ], + "camera_target_distance_m": 3.9999999999999996, + "route_distance_m": 15.4495, + "requested_route_distance_m": 15.4495, + "route_length_m": 2014.3972645129159, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-2-4m-outside.png", + "scene": "Saved/Linux/l112/captures/before/passage-0-1-0-openair-2-4m-outside.vfmesh", + "drawn_triangles": 283642, + "source_triangles": 349878, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 15.4495, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.9999999999999885, + "closeup_target_surface_distance_m": 1.3085037734738154, + "closeup_predicted_target_offset_m": 1.3085037734738154, + "closeup_wall_normal_alignment": 0.4725205931402216, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 8.58190299568095, + 2.121719373896101, + -378.46326758049844 + ], + "target_actual_m": [ + 6.2515339851379395, + 0.0, + -376.0 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-2-4m-outside-mesh.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-2-4m-outside-render.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-2-4m-outside-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-2-4m-interior-wall", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-2/4m-interior-wall", + "camera": [ + 5.071663760588935, + -2.9483247456979305, + -376.09966618123445 + ], + "target": [ + 6.776112001312775, + 0.6382915171479924, + -375.61899999999997 + ], + "yaw": 25.418216346738465, + "pitch": 6.901714476028475, + "focus": [ + 5.121, + 0.955, + -374.039 + ], + "center_z": -374.039, + "open_air_section": 2, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.9821801597899557, + 0.18794183598916203, + -0.0 + ], + "camera_target_distance_m": 3.9999999999999987, + "route_distance_m": 15.4495, + "requested_route_distance_m": 15.4495, + "route_length_m": 2014.3972645129159, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-2-4m-interior-wall.png", + "scene": "Saved/Linux/l112/captures/before/passage-0-1-0-openair-2-4m-interior-wall.vfmesh", + "drawn_triangles": 363071, + "source_triangles": 461781, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 15.4495, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.99999999999999, + "closeup_target_surface_distance_m": 0.8749770375822671, + "closeup_predicted_target_offset_m": 0.8749770375822671, + "closeup_wall_normal_alignment": 0.44992927562510365, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 3.749137959759578, + -1.6905712289969719, + -373.5237186849657 + ], + "target_actual_m": [ + 6.000677108764648, + 0.5, + -376.0 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-2-4m-interior-wall-mesh.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-2-4m-interior-wall-render.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-2-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-3-view-1", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-3/view-1", + "camera": [ + 11.141700220129849, + -8.875616589111877, + -373.90500000000003 + ], + "target": [ + 3.519, + -7.417, + -375.005 + ], + "yaw": -79.1673035961807, + "pitch": -8.067045700553148, + "focus": [ + 3.519, + -7.417, + -375.105 + ], + "center_z": -375.105, + "open_air_section": 3, + "route_distance_m": 24.046, + "requested_route_distance_m": 24.046, + "route_length_m": 2014.3972645129159, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-3-view-1.png", + "scene": "Saved/Linux/l112/captures/before/passage-0-1-0-openair-3-view-1.vfmesh", + "drawn_triangles": 262299, + "source_triangles": 321447, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 24.046, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 11.141700220129849, + -8.875616589111877, + -373.90500000000003 + ], + "target_actual_m": [ + 3.519, + -7.417, + -375.005 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-3-view-1-mesh.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-3-view-1-render.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-3-view-1-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-3-view-2", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-3/view-2", + "camera": [ + -2.630429980444914, + -6.2402961648718644, + -371.105 + ], + "target": [ + 3.1460223668061196, + -9.36617342081075, + -375.3532149486675 + ], + "yaw": 118.41965303912751, + "pitch": -32.89502331212217, + "focus": [ + 3.519, + -7.417, + -375.105 + ], + "center_z": -375.105, + "open_air_section": 3, + "route_distance_m": 24.046, + "requested_route_distance_m": 24.046, + "route_length_m": 2014.3972645129159, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-3-view-2.png", + "scene": "Saved/Linux/l112/captures/before/passage-0-1-0-openair-3-view-2.vfmesh", + "drawn_triangles": 310919, + "source_triangles": 388345, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 24.046, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -2.630429980444914, + -6.2402961648718644, + -371.105 + ], + "target_actual_m": [ + 3.1460223668061196, + -9.36617342081075, + -375.3532149486675 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-3-view-2-mesh.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-3-view-2-render.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-3-view-2-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-3-view-3", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-3/view-3", + "camera": [ + 3.519, + -7.417, + -376.386 + ], + "target": [ + 2.2135782838214184, + -14.239106972837622, + -377.2547523203363 + ], + "yaw": -169.16730359618072, + "pitch": -7.1292164823138044, + "focus": [ + 3.519, + -7.417, + -375.105 + ], + "center_z": -375.105, + "open_air_section": 3, + "route_distance_m": 24.046, + "requested_route_distance_m": 24.046, + "route_length_m": 2014.3972645129159, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-3-view-3.png", + "scene": "Saved/Linux/l112/captures/before/passage-0-1-0-openair-3-view-3.vfmesh", + "drawn_triangles": 363071, + "source_triangles": 461781, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 24.046, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 3.519, + -7.417, + -376.386 + ], + "target_actual_m": [ + 2.2135782838214184, + -14.239106972837622, + -377.2547523203363 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-3-view-3-mesh.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-3-view-3-render.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-3-view-3-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-3-4m-outside", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-3/4m-outside", + "camera": [ + 10.159520060339894, + -8.687674753122714, + -377.136 + ], + "target": [ + 6.230799421180069, + -7.935907409166072, + -377.136 + ], + "yaw": -79.16730359618072, + "pitch": 0.0, + "focus": [ + 3.519, + -7.417, + -375.105 + ], + "center_z": -375.105, + "open_air_section": 3, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.982180159789956, + -0.18794183598916067, + 0.0 + ], + "camera_target_distance_m": 4.000000000000001, + "route_distance_m": 24.046, + "requested_route_distance_m": 24.046, + "route_length_m": 2014.3972645129159, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-3-4m-outside.png", + "scene": "Saved/Linux/l112/captures/before/passage-0-1-0-openair-3-4m-outside.vfmesh", + "drawn_triangles": 298863, + "source_triangles": 375623, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 24.046, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.999999999999986, + "closeup_target_surface_distance_m": 0.7431252768660993, + "closeup_predicted_target_offset_m": 0.7431252768660993, + "closeup_wall_normal_alignment": 0.6879553779351849, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 8.301559926890484, + -7.937797889531149, + -379.85526137236525 + ], + "target_actual_m": [ + 5.500224917936388, + -7.935638471332045, + -377.0 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-3-4m-outside-mesh.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-3-4m-outside-render.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-3-4m-outside-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-3-4m-interior-wall", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-3/4m-interior-wall", + "camera": [ + 3.6515595232019518, + -11.355130807746109, + -377.6166661812345 + ], + "target": [ + 5.356007763925787, + -7.7685145449001825, + -377.136 + ], + "yaw": 25.418216346738376, + "pitch": 6.901714476028474, + "focus": [ + 3.519, + -7.417, + -375.105 + ], + "center_z": -375.105, + "open_air_section": 3, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.982180159789956, + 0.18794183598916067, + -0.0 + ], + "camera_target_distance_m": 3.9999999999999996, + "route_distance_m": 24.046, + "requested_route_distance_m": 24.046, + "route_length_m": 2014.3972645129159, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-3-4m-interior-wall.png", + "scene": "Saved/Linux/l112/captures/before/passage-0-1-0-openair-3-4m-interior-wall.vfmesh", + "drawn_triangles": 340799, + "source_triangles": 430763, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 24.046, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.9999999999999742, + "closeup_target_surface_distance_m": 0.12589120059539705, + "closeup_predicted_target_offset_m": 0.12589120059539705, + "closeup_wall_normal_alignment": 0.27053428417287734, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 4.062119454567632, + -8.45955209298347, + -373.30404532102955 + ], + "target_actual_m": [ + 5.282520932591845, + -7.839589106089317, + -377.06253785492095 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-3-4m-interior-wall-mesh.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-3-4m-interior-wall-render.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-3-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-4-view-1", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-4/view-1", + "camera": [ + -32.482581468460985, + -9.34596705521348, + -597.4219999999999 + ], + "target": [ + -24.253, + -7.219, + -598.5219999999999 + ], + "yaw": 75.50879325593182, + "pitch": -7.373766361330367, + "focus": [ + -24.253, + -7.219, + -598.622 + ], + "center_z": -598.622, + "open_air_section": 4, + "route_distance_m": 1263.117, + "requested_route_distance_m": 1263.117, + "route_length_m": 2014.3972645129159, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-4-view-1.png", + "scene": "Saved/Linux/l112/captures/before/passage-0-1-0-openair-4-view-1.vfmesh", + "drawn_triangles": 378007, + "source_triangles": 458499, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1263.117, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -32.482581468460985, + -9.34596705521348, + -597.4219999999999 + ], + "target_actual_m": [ + -24.253, + -7.219, + -598.5219999999999 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-4-view-1-mesh.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-4-view-1-render.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-4-view-1-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-4-view-2", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-4/view-2", + "camera": [ + -17.4756976142086, + -5.467380072177135, + -594.622 + ], + "target": [ + -24.74519610426594, + -5.314613221376807, + -598.9840138013261 + ], + "yaw": -88.79611947547781, + "pitch": -30.960000123282537, + "focus": [ + -24.253, + -7.219, + -598.622 + ], + "center_z": -598.622, + "open_air_section": 4, + "route_distance_m": 1263.117, + "requested_route_distance_m": 1263.117, + "route_length_m": 2014.3972645129159, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-4-view-2.png", + "scene": "Saved/Linux/l112/captures/before/passage-0-1-0-openair-4-view-2.vfmesh", + "drawn_triangles": 471132, + "source_triangles": 576768, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1263.117, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -17.4756976142086, + -5.467380072177135, + -594.622 + ], + "target_actual_m": [ + -24.74519610426594, + -5.314613221376807, + -598.9840138013261 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-4-view-2-mesh.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-4-view-2-render.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-4-view-2-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-4-view-3", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-4/view-3", + "camera": [ + -24.253, + -7.219, + -600.6419999999999 + ], + "target": [ + -25.975686364930784, + -0.5536462748188242, + -601.9090483046415 + ], + "yaw": -14.491206744068183, + "pitch": -10.428414406509091, + "focus": [ + -24.253, + -7.219, + -598.622 + ], + "center_z": -598.622, + "open_air_section": 4, + "route_distance_m": 1263.117, + "requested_route_distance_m": 1263.117, + "route_length_m": 2014.3972645129159, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-4-view-3.png", + "scene": "Saved/Linux/l112/captures/before/passage-0-1-0-openair-4-view-3.vfmesh", + "drawn_triangles": 382187, + "source_triangles": 466847, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1263.117, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -24.253, + -7.219, + -600.6419999999999 + ], + "target_actual_m": [ + -25.975686364930784, + -0.5536462748188242, + -601.9090483046415 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-4-view-3-mesh.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-4-view-3-render.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-4-view-3-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-4-4m-outside", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-4/4m-outside", + "camera": [ + -31.51439541334793, + -9.095735636953071, + -601.3919999999999 + ], + "target": [ + -27.6416511928957, + -8.094809963911434, + -601.3919999999999 + ], + "yaw": 75.50879325593182, + "pitch": 0.0, + "focus": [ + -24.253, + -7.219, + -598.622 + ], + "center_z": -598.622, + "open_air_section": 4, + "closeup_side": "outside", + "closeup_preferred_normal": [ + -0.9681860551130573, + -0.25023141826040934, + 0.0 + ], + "camera_target_distance_m": 4.0, + "route_distance_m": 1263.117, + "requested_route_distance_m": 1263.117, + "route_length_m": 2014.3972645129159, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-4-4m-outside.png", + "scene": "Saved/Linux/l112/captures/before/passage-0-1-0-openair-4-4m-outside.vfmesh", + "drawn_triangles": 309174, + "source_triangles": 380146, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1263.117, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.000000000000027, + "closeup_target_surface_distance_m": 0.2167936962313581, + "closeup_predicted_target_offset_m": 0.2167936962313581, + "closeup_wall_normal_alignment": 0.7087101938626713, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -29.84592210087621, + -10.26659976537498, + -603.5729649494914 + ], + "target_actual_m": [ + -27.50374180447916, + -8.0, + -601.2541900654693 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-4-4m-outside-mesh.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-4-4m-outside-render.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-4-4m-outside-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-4-4m-interior-wall", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-4/4m-interior-wall", + "camera": [ + -26.309300153834595, + -3.816288494479615, + -602.0930367118167 + ], + "target": [ + -26.324352551502578, + -7.754349051912634, + -601.3919999999999 + ], + "yaw": -179.7810001534144, + "pitch": 10.09374101112515, + "focus": [ + -24.253, + -7.219, + -598.622 + ], + "center_z": -598.622, + "open_air_section": 4, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + 0.9681860551130573, + 0.25023141826040934, + -0.0 + ], + "camera_target_distance_m": 4.000000000000007, + "route_distance_m": 1263.117, + "requested_route_distance_m": 1263.117, + "route_length_m": 2014.3972645129159, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-4-4m-interior-wall.png", + "scene": "Saved/Linux/l112/captures/before/passage-0-1-0-openair-4-4m-interior-wall.vfmesh", + "drawn_triangles": 382187, + "source_triangles": 466847, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1263.117, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.000000000000032, + "closeup_target_surface_distance_m": 0.051112078454061474, + "closeup_predicted_target_offset_m": 0.051112078454061474, + "closeup_wall_normal_alignment": 0.6123283223290849, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -24.141782780412917, + -6.539714983582917, + -598.3334145921336 + ], + "target_actual_m": [ + -26.353346402157452, + -7.771008131701157, + -601.4306558695245 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-4-4m-interior-wall-mesh.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-4-4m-interior-wall-render.log", + "Saved/Linux/l112/captures/before/passage-0-1-0-openair-4-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-1-2-0-upper-mouth", + "passage": "passage/1-2/0", + "kind": "mouth", + "station": "upper-mouth", + "camera": [ + 23.155674552687962, + -16.14908662400146, + -731.7810546875 + ], + "target": [ + 17.392833879360907, + -13.33402139627713, + -731.8810546875 + ], + "yaw": -63.965152623598414, + "pitch": -0.8932686436727578, + "focus": [ + 19.166015625, + -14.2001953125, + -730.5610546875 + ], + "center_z": -730.5610546875, + "variant": "before", + "capture": "captures/before/passage-1-2-0-upper-mouth.png", + "scene": "Saved/Linux/l112/captures/before/passage-1-2-0-upper-mouth.vfmesh", + "drawn_triangles": 570417, + "source_triangles": 630011, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": null, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 23.155674552687962, + -16.14908662400146, + -731.7810546875 + ], + "target_actual_m": [ + 17.392833879360907, + -13.33402139627713, + -731.8810546875 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-1-2-0-upper-mouth-mesh.log", + "Saved/Linux/l112/captures/before/passage-1-2-0-upper-mouth-render.log", + "Saved/Linux/l112/captures/before/passage-1-2-0-upper-mouth-quality.log" + ] + }, + { + "name": "passage-1-2-0-lower-mouth", + "passage": "passage/1-2/0", + "kind": "mouth", + "station": "lower-mouth", + "camera": [ + 27.669370041560203, + -17.931687050798093, + -752.0090260818968 + ], + "target": [ + 17.37583574782943, + -13.414618104437244, + -753.05390625 + ], + "yaw": -66.30689197709175, + "pitch": -5.3105178623917535, + "focus": [ + 19.166015625, + -14.2001953125, + -751.73390625 + ], + "center_z": -751.73390625, + "variant": "before", + "capture": "captures/before/passage-1-2-0-lower-mouth.png", + "scene": "Saved/Linux/l112/captures/before/passage-1-2-0-lower-mouth.vfmesh", + "drawn_triangles": 511318, + "source_triangles": 542780, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": null, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 27.669370041560203, + -17.931687050798093, + -752.0090260818968 + ], + "target_actual_m": [ + 17.37583574782943, + -13.414618104437244, + -753.05390625 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-1-2-0-lower-mouth-mesh.log", + "Saved/Linux/l112/captures/before/passage-1-2-0-lower-mouth-render.log", + "Saved/Linux/l112/captures/before/passage-1-2-0-lower-mouth-quality.log" + ] + }, + { + "name": "passage-1-2-0-station-25", + "passage": "passage/1-2/0", + "kind": "station", + "station": "25%", + "camera": [ + 13.839984288397812, + 6.587904286061814, + -736.8018138353019 + ], + "target": [ + 2.363156319326185, + 14.183439358820996, + -739.2050534708565 + ], + "yaw": -56.5028177078219, + "pitch": -9.905162260563504, + "focus": [ + 14.477989100250685, + 6.982175588660137, + -735.631813835302 + ], + "center_z": -735.631813835302, + "route_distance_m": 28.46821190286393, + "route_length_m": 113.87284761145573, + "requested_route_distance_m": 28.46821190286393, + "variant": "before", + "capture": "captures/before/passage-1-2-0-station-25.png", + "scene": "Saved/Linux/l112/captures/before/passage-1-2-0-station-25.vfmesh", + "drawn_triangles": 661032, + "source_triangles": 762668, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 28.46821190286393, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 13.839984288397812, + 6.587904286061814, + -736.8018138353019 + ], + "target_actual_m": [ + 2.363156319326185, + 14.183439358820996, + -739.2050534708565 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-1-2-0-station-25-mesh.log", + "Saved/Linux/l112/captures/before/passage-1-2-0-station-25-render.log", + "Saved/Linux/l112/captures/before/passage-1-2-0-station-25-quality.log" + ] + }, + { + "name": "passage-1-2-0-station-50", + "passage": "passage/1-2/0", + "kind": "station", + "station": "50%", + "camera": [ + -8.371258739883528, + 11.724083505834441, + -742.0951650605518 + ], + "target": [ + -12.783765342228843, + -1.6446342816727475, + -744.4990059410221 + ], + "yaw": -161.73390326754287, + "pitch": -9.689827619924415, + "focus": [ + -8.819483630432973, + 12.325410744109856, + -740.9251650605519 + ], + "center_z": -740.9251650605519, + "route_distance_m": 56.93642380572786, + "route_length_m": 113.87284761145573, + "requested_route_distance_m": 56.93642380572786, + "variant": "before", + "capture": "captures/before/passage-1-2-0-station-50.png", + "scene": "Saved/Linux/l112/captures/before/passage-1-2-0-station-50.vfmesh", + "drawn_triangles": 602996, + "source_triangles": 681672, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 56.93642380572786, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -8.371258739883528, + 11.724083505834441, + -742.0951650605518 + ], + "target_actual_m": [ + -12.783765342228843, + -1.6446342816727475, + -744.4990059410221 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-1-2-0-station-50-mesh.log", + "Saved/Linux/l112/captures/before/passage-1-2-0-station-50-render.log", + "Saved/Linux/l112/captures/before/passage-1-2-0-station-50-quality.log" + ] + }, + { + "name": "passage-1-2-0-station-75", + "passage": "passage/1-2/0", + "kind": "station", + "station": "75%", + "camera": [ + -6.586769568915752, + -10.735033108069532, + -747.3888312649981 + ], + "target": [ + 7.430752597530391, + -10.891774630023567, + -749.7924798389191 + ], + "yaw": 90.6406448523091, + "pitch": -9.729542154499603, + "focus": [ + -6.9939308656579335, + -11.364889979457965, + -746.2188312649981 + ], + "center_z": -746.2188312649981, + "route_distance_m": 85.4046357085918, + "route_length_m": 113.87284761145573, + "requested_route_distance_m": 85.4046357085918, + "variant": "before", + "capture": "captures/before/passage-1-2-0-station-75.png", + "scene": "Saved/Linux/l112/captures/before/passage-1-2-0-station-75.vfmesh", + "drawn_triangles": 615520, + "source_triangles": 696694, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 85.4046357085918, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -6.586769568915752, + -10.735033108069532, + -747.3888312649981 + ], + "target_actual_m": [ + 7.430752597530391, + -10.891774630023567, + -749.7924798389191 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-1-2-0-station-75-mesh.log", + "Saved/Linux/l112/captures/before/passage-1-2-0-station-75-render.log", + "Saved/Linux/l112/captures/before/passage-1-2-0-station-75-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-1-view-1", + "passage": "passage/1-2/0", + "kind": "open-air", + "station": "section-1/view-1", + "camera": [ + 5.970328502711869, + -4.077984872526297, + -748.2339999999999 + ], + "target": [ + 9.136, + -11.613, + -749.334 + ], + "yaw": 157.21135612217134, + "pitch": -7.6653476882049, + "focus": [ + 9.136, + -11.613, + -749.434 + ], + "center_z": -749.434, + "open_air_section": 1, + "route_distance_m": 103.1595, + "requested_route_distance_m": 103.1595, + "route_length_m": 113.87284761145573, + "variant": "before", + "capture": "captures/before/passage-1-2-0-openair-1-view-1.png", + "scene": "Saved/Linux/l112/captures/before/passage-1-2-0-openair-1-view-1.vfmesh", + "drawn_triangles": 629052, + "source_triangles": 721352, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 103.1595, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 5.970328502711869, + -4.077984872526297, + -748.2339999999999 + ], + "target_actual_m": [ + 9.136, + -11.613, + -749.334 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-1-2-0-openair-1-view-1-mesh.log", + "Saved/Linux/l112/captures/before/passage-1-2-0-openair-1-view-1-render.log", + "Saved/Linux/l112/captures/before/passage-1-2-0-openair-1-view-1-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-1-view-2", + "passage": "passage/1-2/0", + "kind": "open-air", + "station": "section-1/view-2", + "camera": [ + 11.720672201321875, + -17.765105217867614, + -745.434 + ], + "target": [ + 10.94776719052517, + -10.851825714648527, + -749.8056360513408 + ], + "yaw": -6.379180837289254, + "pitch": -32.14682033821005, + "focus": [ + 9.136, + -11.613, + -749.434 + ], + "center_z": -749.434, + "open_air_section": 1, + "route_distance_m": 103.1595, + "requested_route_distance_m": 103.1595, + "route_length_m": 113.87284761145573, + "variant": "before", + "capture": "captures/before/passage-1-2-0-openair-1-view-2.png", + "scene": "Saved/Linux/l112/captures/before/passage-1-2-0-openair-1-view-2.vfmesh", + "drawn_triangles": 588414, + "source_triangles": 654974, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 103.1595, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 11.720672201321875, + -17.765105217867614, + -745.434 + ], + "target_actual_m": [ + 10.94776719052517, + -10.851825714648527, + -749.8056360513408 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-1-2-0-openair-1-view-2-mesh.log", + "Saved/Linux/l112/captures/before/passage-1-2-0-openair-1-view-2-render.log", + "Saved/Linux/l112/captures/before/passage-1-2-0-openair-1-view-2-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-1-view-3", + "passage": "passage/1-2/0", + "kind": "open-air", + "station": "section-1/view-3", + "camera": [ + 9.136, + -11.613, + -750.954 + ], + "target": [ + 15.477185166838094, + -8.948890001269849, + -752.2547261796929 + ], + "yaw": 67.21135612217135, + "pitch": -10.708828804851287, + "focus": [ + 9.136, + -11.613, + -749.434 + ], + "center_z": -749.434, + "open_air_section": 1, + "route_distance_m": 103.1595, + "requested_route_distance_m": 103.1595, + "route_length_m": 113.87284761145573, + "variant": "before", + "capture": "captures/before/passage-1-2-0-openair-1-view-3.png", + "scene": "Saved/Linux/l112/captures/before/passage-1-2-0-openair-1-view-3.vfmesh", + "drawn_triangles": 616234, + "source_triangles": 698168, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 103.1595, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 9.136, + -11.613, + -750.954 + ], + "target_actual_m": [ + 15.477185166838094, + -8.948890001269849, + -752.2547261796929 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-1-2-0-openair-1-view-3-mesh.log", + "Saved/Linux/l112/captures/before/passage-1-2-0-openair-1-view-3-render.log", + "Saved/Linux/l112/captures/before/passage-1-2-0-openair-1-view-3-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-1-4m-outside", + "passage": "passage/1-2/0", + "kind": "open-air-close", + "station": "section-1/4m-outside", + "camera": [ + 6.357661366689372, + -4.999924812263689, + -751.704 + ], + "target": [ + 7.906992822599383, + -8.687684571213255, + -751.704 + ], + "yaw": 157.21135612217134, + "pitch": 0.0, + "focus": [ + 9.136, + -11.613, + -749.434 + ], + "center_z": -749.434, + "open_air_section": 1, + "closeup_side": "outside", + "closeup_preferred_normal": [ + -0.3873328639775028, + 0.9219399397373916, + 0.0 + ], + "camera_target_distance_m": 3.9999999999999996, + "route_distance_m": 103.1595, + "requested_route_distance_m": 103.1595, + "route_length_m": 113.87284761145573, + "variant": "before", + "capture": "captures/before/passage-1-2-0-openair-1-4m-outside.png", + "scene": "Saved/Linux/l112/captures/before/passage-1-2-0-openair-1-4m-outside.vfmesh", + "drawn_triangles": 629052, + "source_triangles": 721352, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 103.1595, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.0, + "closeup_target_surface_distance_m": 0.3297392655628349, + "closeup_predicted_target_offset_m": 0.3297392655628349, + "closeup_wall_normal_alignment": 0.9257124649048741, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 7.8586145006242, + -5.017894162140777, + -751.6522969837506 + ], + "target_actual_m": [ + 7.898985787247995, + -9.017300820452297, + -751.708122969365 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-1-2-0-openair-1-4m-outside-mesh.log", + "Saved/Linux/l112/captures/before/passage-1-2-0-openair-1-4m-outside-render.log", + "Saved/Linux/l112/captures/before/passage-1-2-0-openair-1-4m-outside-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-1-4m-interior-wall", + "passage": "passage/1-2/0", + "kind": "open-air-close", + "station": "section-1/4m-interior-wall", + "camera": [ + 12.173093223920612, + -9.017003903520504, + -752.4236701188466 + ], + "target": [ + 8.277288281888616, + -9.569071629146903, + -751.704 + ], + "yaw": -98.06558218574223, + "pitch": 10.36495618281995, + "focus": [ + 9.136, + -11.613, + -749.434 + ], + "center_z": -749.434, + "open_air_section": 1, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + 0.3873328639775028, + -0.9219399397373916, + -0.0 + ], + "camera_target_distance_m": 4.000000000000004, + "route_distance_m": 103.1595, + "requested_route_distance_m": 103.1595, + "route_length_m": 113.87284761145573, + "variant": "before", + "capture": "captures/before/passage-1-2-0-openair-1-4m-interior-wall.png", + "scene": "Saved/Linux/l112/captures/before/passage-1-2-0-openair-1-4m-interior-wall.vfmesh", + "drawn_triangles": 573086, + "source_triangles": 634798, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 103.1595, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.9999999999999987, + "closeup_target_surface_distance_m": 0.5763280269776941, + "closeup_predicted_target_offset_m": 0.5763280269776941, + "closeup_wall_normal_alignment": 0.9856460223931174, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 9.119253550190452, + -12.892454942281582, + -751.7213326583923 + ], + "target_actual_m": [ + 8.214412385318102, + -8.996203988275933, + -751.6991748208959 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-1-2-0-openair-1-4m-interior-wall-mesh.log", + "Saved/Linux/l112/captures/before/passage-1-2-0-openair-1-4m-interior-wall-render.log", + "Saved/Linux/l112/captures/before/passage-1-2-0-openair-1-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-2-3-0-upper-mouth", + "passage": "passage/2-3/0", + "kind": "mouth", + "station": "upper-mouth", + "camera": [ + -24.510890451086325, + -4.955138452601283, + -811.975390625 + ], + "target": [ + -18.085437577294964, + -5.118679784954985, + -812.075390625 + ], + "yaw": 91.4579836961561, + "pitch": -0.8913396541976134, + "focus": [ + -20.0625, + -5.068359375, + -810.755390625 + ], + "center_z": -810.755390625, + "variant": "before", + "capture": "captures/before/passage-2-3-0-upper-mouth.png", + "scene": "Saved/Linux/l112/captures/before/passage-2-3-0-upper-mouth.vfmesh", + "drawn_triangles": 59562, + "source_triangles": 71470, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": null, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -24.510890451086325, + -4.955138452601283, + -811.975390625 + ], + "target_actual_m": [ + -18.085437577294964, + -5.118679784954985, + -812.075390625 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-2-3-0-upper-mouth-mesh.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-upper-mouth-render.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-upper-mouth-quality.log" + ] + }, + { + "name": "passage-2-3-0-lower-mouth", + "passage": "passage/2-3/0", + "kind": "mouth", + "station": "lower-mouth", + "camera": [ + -29.049715742915396, + -2.779103580443535, + -899.0170545422176 + ], + "target": [ + -18.170454580438843, + -5.550307963327683, + -900.0333984375 + ], + "yaw": 104.29068028993358, + "pitch": -5.172857326977102, + "focus": [ + -20.062499999999982, + -5.068359375000004, + -898.7133984375 + ], + "center_z": -898.7133984375, + "variant": "before", + "capture": "captures/before/passage-2-3-0-lower-mouth.png", + "scene": "Saved/Linux/l112/captures/before/passage-2-3-0-lower-mouth.vfmesh", + "drawn_triangles": 294522, + "source_triangles": 315506, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": null, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -29.049715742915396, + -2.779103580443535, + -899.0170545422176 + ], + "target_actual_m": [ + -18.170454580438843, + -5.550307963327683, + -900.0333984375 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-2-3-0-lower-mouth-mesh.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-lower-mouth-render.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-lower-mouth-quality.log" + ] + }, + { + "name": "passage-2-3-0-station-25", + "passage": "passage/2-3/0", + "kind": "station", + "station": "25%", + "camera": [ + 3.3629477943069905, + -13.28264789111628, + -833.6924223707634 + ], + "target": [ + 14.057544579024707, + -4.268177781320185, + -836.0006826204402 + ], + "yaw": 49.87247810025953, + "pitch": -9.371026953528995, + "focus": [ + 3.463454182082567, + -14.025883026195553, + -832.5224223707635 + ], + "center_z": -832.5224223707635, + "route_distance_m": 122.71082287166668, + "route_length_m": 490.8432914866667, + "requested_route_distance_m": 122.71082287166668, + "variant": "before", + "capture": "captures/before/passage-2-3-0-station-25.png", + "scene": "Saved/Linux/l112/captures/before/passage-2-3-0-station-25.vfmesh", + "drawn_triangles": 55484, + "source_triangles": 66458, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 122.71082287166668, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 3.3629477943069905, + -13.28264789111628, + -833.6924223707634 + ], + "target_actual_m": [ + 14.057544579024707, + -4.268177781320185, + -836.0006826204402 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-2-3-0-station-25-mesh.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-station-25-render.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-station-25-quality.log" + ] + }, + { + "name": "passage-2-3-0-station-50", + "passage": "passage/2-3/0", + "kind": "station", + "station": "50%", + "camera": [ + 14.714964374766744, + 4.426031524861205, + -855.6817931947601 + ], + "target": [ + 3.8569544509891096, + 13.535757747237458, + -857.9904777239444 + ], + "yaw": -50.003796291172236, + "pitch": -9.251614459440251, + "focus": [ + 15.448414166573603, + 4.582720397786105, + -854.5117931947601 + ], + "center_z": -854.5117931947601, + "route_distance_m": 245.42164574333336, + "route_length_m": 490.8432914866667, + "requested_route_distance_m": 245.42164574333336, + "variant": "before", + "capture": "captures/before/passage-2-3-0-station-50.png", + "scene": "Saved/Linux/l112/captures/before/passage-2-3-0-station-50.vfmesh", + "drawn_triangles": 457754, + "source_triangles": 479058, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 245.42164574333336, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 14.714964374766744, + 4.426031524861205, + -855.6817931947601 + ], + "target_actual_m": [ + 3.8569544509891096, + 13.535757747237458, + -857.9904777239444 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-2-3-0-station-50-mesh.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-station-50-render.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-station-50-quality.log" + ] + }, + { + "name": "passage-2-3-0-station-75", + "passage": "passage/2-3/0", + "kind": "station", + "station": "75%", + "camera": [ + -5.760169952738466, + 11.295442453574074, + -877.6716971250207 + ], + "target": [ + -12.206687475534688, + -0.996781882252304, + -879.9807693267177 + ], + "yaw": -152.32574657735572, + "pitch": -9.445159710566168, + "focus": [ + -6.190732087251391, + 11.909540367854586, + -876.5016971250208 + ], + "center_z": -876.5016971250208, + "route_distance_m": 368.13246861500005, + "route_length_m": 490.8432914866667, + "requested_route_distance_m": 368.13246861500005, + "variant": "before", + "capture": "captures/before/passage-2-3-0-station-75.png", + "scene": "Saved/Linux/l112/captures/before/passage-2-3-0-station-75.vfmesh", + "drawn_triangles": 475706, + "source_triangles": 506686, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 368.13246861500005, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -5.760169952738466, + 11.295442453574074, + -877.6716971250207 + ], + "target_actual_m": [ + -12.206687475534688, + -0.996781882252304, + -879.9807693267177 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-2-3-0-station-75-mesh.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-station-75-render.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-station-75-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-1-view-1", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-1/view-1", + "camera": [ + -1.189937432971333, + -5.322285697427915, + -813.0459999999999 + ], + "target": [ + -2.846, + -13.149, + -814.146 + ], + "yaw": -168.05293971491665, + "pitch": -7.829076510059767, + "focus": [ + -2.846, + -13.149, + -814.246 + ], + "center_z": -814.246, + "open_air_section": 1, + "route_distance_m": 21.212, + "requested_route_distance_m": 21.212, + "route_length_m": 490.8432914866667, + "variant": "before", + "capture": "captures/before/passage-2-3-0-openair-1-view-1.png", + "scene": "Saved/Linux/l112/captures/before/passage-2-3-0-openair-1-view-1.vfmesh", + "drawn_triangles": 104612, + "source_triangles": 129366, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 21.212, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -1.189937432971333, + -5.322285697427915, + -813.0459999999999 + ], + "target_actual_m": [ + -2.846, + -13.149, + -814.146 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-1-view-1-mesh.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-1-view-1-render.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-1-view-1-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-1-view-2", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-1/view-2", + "camera": [ + -4.1915508357107925, + -19.508205370839818, + -810.246 + ], + "target": [ + -0.9210204431637441, + -13.556308413611612, + -814.6045436681405 + ], + "yaw": 28.788521091259426, + "pitch": -32.69176164676129, + "focus": [ + -2.846, + -13.149, + -814.246 + ], + "center_z": -814.246, + "open_air_section": 1, + "route_distance_m": 21.212, + "requested_route_distance_m": 21.212, + "route_length_m": 490.8432914866667, + "variant": "before", + "capture": "captures/before/passage-2-3-0-openair-1-view-2.png", + "scene": "Saved/Linux/l112/captures/before/passage-2-3-0-openair-1-view-2.vfmesh", + "drawn_triangles": 81078, + "source_triangles": 99432, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 21.212, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -4.1915508357107925, + -19.508205370839818, + -810.246 + ], + "target_actual_m": [ + -0.9210204431637441, + -13.556308413611612, + -814.6045436681405 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-1-view-2-mesh.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-1-view-2-render.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-1-view-2-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-1-view-3", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-1/view-3", + "camera": [ + -2.846, + -13.149, + -815.766 + ], + "target": [ + 3.891428448926896, + -14.574579447640645, + -817.0209028384919 + ], + "yaw": 101.94706028508335, + "pitch": -10.327349081567025, + "focus": [ + -2.846, + -13.149, + -814.246 + ], + "center_z": -814.246, + "open_air_section": 1, + "route_distance_m": 21.212, + "requested_route_distance_m": 21.212, + "route_length_m": 490.8432914866667, + "variant": "before", + "capture": "captures/before/passage-2-3-0-openair-1-view-3.png", + "scene": "Saved/Linux/l112/captures/before/passage-2-3-0-openair-1-view-3.vfmesh", + "drawn_triangles": 94962, + "source_triangles": 118068, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 21.212, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -2.846, + -13.149, + -815.766 + ], + "target_actual_m": [ + 3.891428448926896, + -14.574579447640645, + -817.0209028384919 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-1-view-3-mesh.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-1-view-3-render.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-1-view-3-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-1-4m-outside", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-1/4m-outside", + "camera": [ + -1.3969452538499163, + -6.300624985249425, + -816.516 + ], + "target": [ + -2.22497653736425, + -10.213982136535467, + -816.516 + ], + "yaw": -168.05293971491665, + "pitch": 0.0, + "focus": [ + -2.846, + -13.149, + -814.246 + ], + "center_z": -814.246, + "open_air_section": 1, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.20700782087858338, + 0.9783392878215105, + 0.0 + ], + "camera_target_distance_m": 4.0, + "route_distance_m": 21.212, + "requested_route_distance_m": 21.212, + "route_length_m": 490.8432914866667, + "variant": "before", + "capture": "captures/before/passage-2-3-0-openair-1-4m-outside.png", + "scene": "Saved/Linux/l112/captures/before/passage-2-3-0-openair-1-4m-outside.vfmesh", + "drawn_triangles": 104612, + "source_triangles": 129366, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 21.212, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.9999999999999805, + "closeup_target_surface_distance_m": 0.21863746532605915, + "closeup_predicted_target_offset_m": 0.21863746532605915, + "closeup_wall_normal_alignment": 0.5616963397392034, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -1.6846709702918434, + -8.159235090682637, + -813.3879076292367 + ], + "target_actual_m": [ + -2.2544507075828024, + -10.33520463791381, + -816.695551440244 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-1-4m-outside-mesh.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-1-4m-outside-render.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-1-4m-outside-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-1-4m-interior-wall", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-1/4m-interior-wall", + "camera": [ + 1.0807247315156623, + -12.997171456076, + -817.2103168277982 + ], + "target": [ + -2.439974330314031, + -11.230082816910521, + -816.516 + ], + "yaw": -63.34727833660725, + "pitch": 9.995987331937334, + "focus": [ + -2.846, + -13.149, + -814.246 + ], + "center_z": -814.246, + "open_air_section": 1, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.20700782087858338, + -0.9783392878215105, + -0.0 + ], + "camera_target_distance_m": 4.000000000000006, + "route_distance_m": 21.212, + "requested_route_distance_m": 21.212, + "route_length_m": 490.8432914866667, + "variant": "before", + "capture": "captures/before/passage-2-3-0-openair-1-4m-interior-wall.png", + "scene": "Saved/Linux/l112/captures/before/passage-2-3-0-openair-1-4m-interior-wall.vfmesh", + "drawn_triangles": 99334, + "source_triangles": 123368, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 21.212, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.000000000000003, + "closeup_target_surface_distance_m": 0.39080816806882795, + "closeup_predicted_target_offset_m": 0.39080816806882795, + "closeup_wall_normal_alignment": 0.684565492215496, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -3.529921390663112, + -13.549857433706853, + -819.0758935568331 + ], + "target_actual_m": [ + -2.4258698745683085, + -10.984576961360762, + -816.2122583936168 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-1-4m-interior-wall-mesh.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-1-4m-interior-wall-render.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-1-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-2-view-1", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-2/view-1", + "camera": [ + -2.9130850464832285, + 5.083885109955194, + -876.048 + ], + "target": [ + -9.545, + 9.558, + -877.148 + ], + "yaw": -55.995061323335754, + "pitch": -7.829076510059767, + "focus": [ + -9.545, + 9.558, + -877.248 + ], + "center_z": -877.248, + "open_air_section": 2, + "route_distance_m": 372.7845, + "requested_route_distance_m": 372.7845, + "route_length_m": 490.8432914866667, + "variant": "before", + "capture": "captures/before/passage-2-3-0-openair-2-view-1.png", + "scene": "Saved/Linux/l112/captures/before/passage-2-3-0-openair-2-view-1.vfmesh", + "drawn_triangles": 475688, + "source_triangles": 507502, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 372.7845, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -2.9130850464832285, + 5.083885109955194, + -876.048 + ], + "target_actual_m": [ + -9.545, + 9.558, + -877.148 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-2-view-1-mesh.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-2-view-1-render.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-2-view-1-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-2-view-2", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-2/view-2", + "camera": [ + -14.933430899732377, + 13.193218348161405, + -873.248 + ], + "target": [ + -10.645401808697681, + 7.926890520398333, + -877.6066052494994 + ], + "yaw": 140.84630886232915, + "pitch": -32.69214209091069, + "focus": [ + -9.545, + 9.558, + -877.248 + ], + "center_z": -877.248, + "open_air_section": 2, + "route_distance_m": 372.7845, + "requested_route_distance_m": 372.7845, + "route_length_m": 490.8432914866667, + "variant": "before", + "capture": "captures/before/passage-2-3-0-openair-2-view-2.png", + "scene": "Saved/Linux/l112/captures/before/passage-2-3-0-openair-2-view-2.vfmesh", + "drawn_triangles": 479134, + "source_triangles": 506272, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 372.7845, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -14.933430899732377, + 13.193218348161405, + -873.248 + ], + "target_actual_m": [ + -10.645401808697681, + 7.926890520398333, + -877.6066052494994 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-2-view-2-mesh.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-2-view-2-render.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-2-view-2-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-2-view-3", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-2/view-3", + "camera": [ + -9.545, + 9.558, + -878.768 + ], + "target": [ + -13.396406330441884, + 3.8491168213941664, + -880.0231183732476 + ], + "yaw": -145.99506132333573, + "pitch": -10.329142313691902, + "focus": [ + -9.545, + 9.558, + -877.248 + ], + "center_z": -877.248, + "open_air_section": 2, + "route_distance_m": 372.7845, + "requested_route_distance_m": 372.7845, + "route_length_m": 490.8432914866667, + "variant": "before", + "capture": "captures/before/passage-2-3-0-openair-2-view-3.png", + "scene": "Saved/Linux/l112/captures/before/passage-2-3-0-openair-2-view-3.vfmesh", + "drawn_triangles": 479134, + "source_triangles": 506272, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 372.7845, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -9.545, + 9.558, + -878.768 + ], + "target_actual_m": [ + -13.396406330441884, + 3.8491168213941664, + -880.0231183732476 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-2-view-3-mesh.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-2-view-3-render.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-2-view-3-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-2-4m-outside", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-2/4m-outside", + "camera": [ + -3.7420744156728247, + 5.643149471210794, + -879.518 + ], + "target": [ + -7.05803189243121, + 7.880206916233197, + -879.518 + ], + "yaw": -55.995061323335754, + "pitch": 0.0, + "focus": [ + -9.545, + 9.558, + -877.248 + ], + "center_z": -877.248, + "open_air_section": 2, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.8289893691895964, + -0.5592643612556008, + 0.0 + ], + "camera_target_distance_m": 4.0, + "route_distance_m": 372.7845, + "requested_route_distance_m": 372.7845, + "route_length_m": 490.8432914866667, + "variant": "before", + "capture": "captures/before/passage-2-3-0-openair-2-4m-outside.png", + "scene": "Saved/Linux/l112/captures/before/passage-2-3-0-openair-2-4m-outside.vfmesh", + "drawn_triangles": 475688, + "source_triangles": 507502, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 372.7845, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.9999999999999987, + "closeup_target_surface_distance_m": 1.2985903598285988, + "closeup_predicted_target_offset_m": 1.2985903598285988, + "closeup_wall_normal_alignment": 0.5540615952253409, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -7.048834538896178, + 5.179718947010304, + -879.432382591364 + ], + "target_actual_m": [ + -7.02557587321013, + 9.176983429370068, + -879.5784500159857 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-2-4m-outside-mesh.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-2-4m-outside-render.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-2-4m-outside-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-2-4m-interior-wall", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-2/4m-interior-wall", + "camera": [ + -10.87892643836146, + 5.861691886541483, + -880.2124360795867 + ], + "target": [ + -7.919018129560545, + 8.461057450455034, + -879.518 + ], + "yaw": 48.71068029668619, + "pitch": 9.997721822254437, + "focus": [ + -9.545, + 9.558, + -877.248 + ], + "center_z": -877.248, + "open_air_section": 2, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.8289893691895964, + 0.5592643612556008, + -0.0 + ], + "camera_target_distance_m": 4.000000000000005, + "route_distance_m": 372.7845, + "requested_route_distance_m": 372.7845, + "route_length_m": 490.8432914866667, + "variant": "before", + "capture": "captures/before/passage-2-3-0-openair-2-4m-interior-wall.png", + "scene": "Saved/Linux/l112/captures/before/passage-2-3-0-openair-2-4m-interior-wall.vfmesh", + "drawn_triangles": 486364, + "source_triangles": 515880, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 372.7845, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.999999999999999, + "closeup_target_surface_distance_m": 0.7484696644179646, + "closeup_predicted_target_offset_m": 0.7484696644179646, + "closeup_wall_normal_alignment": 0.5468393137974433, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -7.844397023781797, + 13.208794016256846, + -879.5542227782431 + ], + "target_actual_m": [ + -7.903971927571609, + 9.20935408756137, + -879.5237090502709 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-2-4m-interior-wall-mesh.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-2-4m-interior-wall-render.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-2-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-3-view-1", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-3/view-1", + "camera": [ + -4.259540253679528, + -6.656854577309242, + -880.059 + ], + "target": [ + -11.172, + -10.684, + -881.159 + ], + "yaw": -120.224745904394, + "pitch": -7.829076510059767, + "focus": [ + -11.172, + -10.684, + -881.259 + ], + "center_z": -881.259, + "open_air_section": 3, + "route_distance_m": 395.169, + "requested_route_distance_m": 395.169, + "route_length_m": 490.8432914866667, + "variant": "before", + "capture": "captures/before/passage-2-3-0-openair-3-view-1.png", + "scene": "Saved/Linux/l112/captures/before/passage-2-3-0-openair-3-view-1.vfmesh", + "drawn_triangles": 485216, + "source_triangles": 518310, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 395.169, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -4.259540253679528, + -6.656854577309242, + -880.059 + ], + "target_actual_m": [ + -11.172, + -10.684, + -881.159 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-3-view-1-mesh.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-3-view-1-render.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-3-view-1-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-3-view-2", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-3/view-2", + "camera": [ + -16.788373543885385, + -13.95605565593624, + -877.259 + ], + "target": [ + -10.181507700208023, + -12.384146737382467, + -881.6173658401976 + ], + "yaw": 76.6169764950821, + "pitch": -32.69066303746625, + "focus": [ + -11.172, + -10.684, + -881.259 + ], + "center_z": -881.259, + "open_air_section": 3, + "route_distance_m": 395.169, + "requested_route_distance_m": 395.169, + "route_length_m": 490.8432914866667, + "variant": "before", + "capture": "captures/before/passage-2-3-0-openair-3-view-2.png", + "scene": "Saved/Linux/l112/captures/before/passage-2-3-0-openair-3-view-2.vfmesh", + "drawn_triangles": 479198, + "source_triangles": 497212, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 395.169, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -16.788373543885385, + -13.95605565593624, + -877.259 + ], + "target_actual_m": [ + -10.181507700208023, + -12.384146737382467, + -881.6173658401976 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-3-view-2-mesh.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-3-view-2-render.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-3-view-2-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-3-view-3", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-3/view-3", + "camera": [ + -11.172, + -10.684, + -882.779 + ], + "target": [ + -7.70527695072808, + -16.63451358083864, + -884.0332804406917 + ], + "yaw": 149.77525409560604, + "pitch": -10.322170838480888, + "focus": [ + -11.172, + -10.684, + -881.259 + ], + "center_z": -881.259, + "open_air_section": 3, + "route_distance_m": 395.169, + "requested_route_distance_m": 395.169, + "route_length_m": 490.8432914866667, + "variant": "before", + "capture": "captures/before/passage-2-3-0-openair-3-view-3.png", + "scene": "Saved/Linux/l112/captures/before/passage-2-3-0-openair-3-view-3.vfmesh", + "drawn_triangles": 490436, + "source_triangles": 519892, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 395.169, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -11.172, + -10.684, + -882.779 + ], + "target_actual_m": [ + -7.70527695072808, + -16.63451358083864, + -884.0332804406917 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-3-view-3-mesh.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-3-view-3-render.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-3-view-3-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-3-4m-outside", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-3/4m-outside", + "camera": [ + -5.123597721969588, + -7.160247755145587, + -883.529 + ], + "target": [ + -8.579827595129824, + -9.173820466490966, + -883.529 + ], + "yaw": -120.224745904394, + "pitch": 0.0, + "focus": [ + -11.172, + -10.684, + -881.259 + ], + "center_z": -881.259, + "open_air_section": 3, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.864057468290059, + 0.5033931778363446, + 0.0 + ], + "camera_target_distance_m": 4.0, + "route_distance_m": 395.169, + "requested_route_distance_m": 395.169, + "route_length_m": 490.8432914866667, + "variant": "before", + "capture": "captures/before/passage-2-3-0-openair-3-4m-outside.png", + "scene": "Saved/Linux/l112/captures/before/passage-2-3-0-openair-3-4m-outside.vfmesh", + "drawn_triangles": 485216, + "source_triangles": 518310, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 395.169, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.000000000000001, + "closeup_target_surface_distance_m": 0.21370595699941178, + "closeup_predicted_target_offset_m": 0.21370595699941178, + "closeup_wall_normal_alignment": 0.6967986735426744, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -7.5347876884777225, + -5.095624431260692, + -883.6515043714523 + ], + "target_actual_m": [ + -8.5, + -8.97568453916576, + -883.5353202385876 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-3-4m-outside-mesh.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-3-4m-outside-render.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-3-4m-outside-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-3-4m-interior-wall", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-3/4m-interior-wall", + "camera": [ + -8.423212847701345, + -13.492356510441905, + -884.2229724654675 + ], + "target": [ + -9.477235470231792, + -9.696643332609971, + -883.529 + ], + "yaw": -15.519316154639963, + "pitch": 9.990978711588388, + "focus": [ + -11.172, + -10.684, + -881.259 + ], + "center_z": -881.259, + "open_air_section": 3, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.864057468290059, + -0.5033931778363446, + -0.0 + ], + "camera_target_distance_m": 3.999999999999996, + "route_distance_m": 395.169, + "requested_route_distance_m": 395.169, + "route_length_m": 490.8432914866667, + "variant": "before", + "capture": "captures/before/passage-2-3-0-openair-3-4m-interior-wall.png", + "scene": "Saved/Linux/l112/captures/before/passage-2-3-0-openair-3-4m-interior-wall.vfmesh", + "drawn_triangles": 490436, + "source_triangles": 519892, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 395.169, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.0, + "closeup_target_surface_distance_m": 1.111400216475651, + "closeup_predicted_target_offset_m": 1.111400216475651, + "closeup_wall_normal_alignment": 0.9285343847245275, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -11.213041949597612, + -12.006856406716684, + -883.4572259543174 + ], + "target_actual_m": [ + -8.75, + -8.856381157025917, + -883.5462768139893 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-3-4m-interior-wall-mesh.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-3-4m-interior-wall-render.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-3-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-4-view-1", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-4/view-1", + "camera": [ + 5.6333128025989625, + 3.3735740461566257, + -889.2199999999999 + ], + "target": [ + 9.72, + 10.251, + -890.3199999999999 + ], + "yaw": 30.71952465304602, + "pitch": -7.8290765100597675, + "focus": [ + 9.72, + 10.251, + -890.42 + ], + "center_z": -890.42, + "open_air_section": 4, + "route_distance_m": 446.293, + "requested_route_distance_m": 446.293, + "route_length_m": 490.8432914866667, + "variant": "before", + "capture": "captures/before/passage-2-3-0-openair-4-view-1.png", + "scene": "Saved/Linux/l112/captures/before/passage-2-3-0-openair-4-view-1.vfmesh", + "drawn_triangles": 475298, + "source_triangles": 507112, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 446.293, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 5.6333128025989625, + 3.3735740461566257, + -889.2199999999999 + ], + "target_actual_m": [ + 9.72, + 10.251, + -890.3199999999999 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-4-view-1-mesh.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-4-view-1-render.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-4-view-1-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-4-view-2", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-4/view-2", + "camera": [ + 13.040433347888344, + 15.838908587497741, + -886.42 + ], + "target": [ + 8.028477501069965, + 11.25613235429748, + -890.7784139868335 + ], + "yaw": -132.43882376014432, + "pitch": -32.69096048480686, + "focus": [ + 9.72, + 10.251, + -890.42 + ], + "center_z": -890.42, + "open_air_section": 4, + "route_distance_m": 446.293, + "requested_route_distance_m": 446.293, + "route_length_m": 490.8432914866667, + "variant": "before", + "capture": "captures/before/passage-2-3-0-openair-4-view-2.png", + "scene": "Saved/Linux/l112/captures/before/passage-2-3-0-openair-4-view-2.vfmesh", + "drawn_triangles": 495856, + "source_triangles": 530508, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 446.293, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 13.040433347888344, + 15.838908587497741, + -886.42 + ], + "target_actual_m": [ + 8.028477501069965, + 11.25613235429748, + -890.7784139868335 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-4-view-2-mesh.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-4-view-2-render.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-4-view-2-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-4-view-3", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-4/view-3", + "camera": [ + 9.72, + 10.251, + -891.9399999999999 + ], + "target": [ + 3.7996712537448776, + 13.768963240041181, + -893.1944489539172 + ], + "yaw": -59.280475346953985, + "pitch": -10.32357283123646, + "focus": [ + 9.72, + 10.251, + -890.42 + ], + "center_z": -890.42, + "open_air_section": 4, + "route_distance_m": 446.293, + "requested_route_distance_m": 446.293, + "route_length_m": 490.8432914866667, + "variant": "before", + "capture": "captures/before/passage-2-3-0-openair-4-view-3.png", + "scene": "Saved/Linux/l112/captures/before/passage-2-3-0-openair-4-view-3.vfmesh", + "drawn_triangles": 496236, + "source_triangles": 531424, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 446.293, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 9.72, + 10.251, + -891.9399999999999 + ], + "target_actual_m": [ + 3.7996712537448776, + 13.768963240041181, + -893.1944489539172 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-4-view-3-mesh.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-4-view-3-render.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-4-view-3-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-4-4m-outside", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-4/4m-outside", + "camera": [ + 6.144148702274093, + 4.233252290387048, + -892.6899999999999 + ], + "target": [ + 8.187492300974611, + 7.671965267308734, + -892.6899999999999 + ], + "yaw": 30.719524653046015, + "pitch": 0.0, + "focus": [ + 9.72, + 10.251, + -890.42 + ], + "center_z": -890.42, + "open_air_section": 4, + "closeup_side": "outside", + "closeup_preferred_normal": [ + -0.5108358996751298, + -0.8596782442304217, + 0.0 + ], + "camera_target_distance_m": 3.999999999999999, + "route_distance_m": 446.293, + "requested_route_distance_m": 446.293, + "route_length_m": 490.8432914866667, + "variant": "before", + "capture": "captures/before/passage-2-3-0-openair-4-4m-outside.png", + "scene": "Saved/Linux/l112/captures/before/passage-2-3-0-openair-4-4m-outside.vfmesh", + "drawn_triangles": 475298, + "source_triangles": 507112, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 446.293, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.999999999999969, + "closeup_target_surface_distance_m": 2.7431385655379885, + "closeup_predicted_target_offset_m": 2.7431385655379885, + "closeup_wall_normal_alignment": 0.27070559761624624, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 6.657064522391594, + 7.603943299491346, + -886.5753044006359 + ], + "target_actual_m": [ + 8.723573849747169, + 7.63555424139971, + -890.0 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-4-4m-outside-mesh.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-4-4m-outside-render.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-4-4m-outside-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-4-4m-interior-wall", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-4/4m-interior-wall", + "camera": [ + 5.953261824576057, + 11.370933570205146, + -893.3840657010269 + ], + "target": [ + 8.718045158946516, + 8.564824891510526, + -892.6899999999999 + ], + "yaw": 135.4250171034422, + "pitch": 9.992334780054298, + "focus": [ + 9.72, + 10.251, + -890.42 + ], + "center_z": -890.42, + "open_air_section": 4, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + 0.5108358996751298, + 0.8596782442304217, + -0.0 + ], + "camera_target_distance_m": 3.999999999999991, + "route_distance_m": 446.293, + "requested_route_distance_m": 446.293, + "route_length_m": 490.8432914866667, + "variant": "before", + "capture": "captures/before/passage-2-3-0-openair-4-4m-interior-wall.png", + "scene": "Saved/Linux/l112/captures/before/passage-2-3-0-openair-4-4m-interior-wall.vfmesh", + "drawn_triangles": 475316, + "source_triangles": 506296, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 446.293, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.000000000000006, + "closeup_target_surface_distance_m": 2.6750073628142315, + "closeup_predicted_target_offset_m": 2.6750073628142315, + "closeup_wall_normal_alignment": 0.3031820710235188, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 8.728378023171791, + 9.651746412116331, + -893.8555657051302 + ], + "target_actual_m": [ + 8.292627617084863, + 8.5, + -890.0498329523252 + ], + "logs": [ + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-4-4m-interior-wall-mesh.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-4-4m-interior-wall-render.log", + "Saved/Linux/l112/captures/before/passage-2-3-0-openair-4-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-0-1-0-upper-mouth", + "passage": "passage/0-1/0", + "kind": "mouth", + "station": "upper-mouth", + "camera": [ + 8.335073547378155, + 20.44994601927027, + -371.842578125 + ], + "target": [ + 7.851078423387487, + 14.022246213657658, + -371.942578125 + ], + "yaw": -175.69384905314672, + "pitch": -0.8888009211775196, + "focus": [ + 8.0, + 16.0, + -372.1224609375 + ], + "center_z": -372.1224609375, + "variant": "after", + "capture": "captures/after/passage-0-1-0-upper-mouth.png", + "scene": "Saved/Linux/l112/captures/after/passage-0-1-0-upper-mouth.vfmesh", + "drawn_triangles": 244874, + "source_triangles": 300692, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": null, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 8.335073547378155, + 20.44994601927027, + -371.842578125 + ], + "target_actual_m": [ + 7.851078423387487, + 14.022246213657658, + -371.942578125 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-0-1-0-upper-mouth-mesh.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-upper-mouth-render.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-upper-mouth-quality.log" + ] + }, + { + "name": "passage-0-1-0-lower-mouth", + "passage": "passage/0-1/0", + "kind": "mouth", + "station": "lower-mouth", + "camera": [ + 32.6815683216108, + 9.56067063407582, + -735.4811957974861 + ], + "target": [ + 24.395934218476675, + 1.8599657217735117, + -736.6798828125 + ], + "yaw": -132.9045214795435, + "pitch": -6.049035133760526, + "focus": [ + 25.8369140625, + 3.19921875, + -736.2942543532574 + ], + "center_z": -736.2942543532574, + "variant": "after", + "capture": "captures/after/passage-0-1-0-lower-mouth.png", + "scene": "Saved/Linux/l112/captures/after/passage-0-1-0-lower-mouth.vfmesh", + "drawn_triangles": 551596, + "source_triangles": 601134, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": null, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 32.6815683216108, + 9.56067063407582, + -735.4811957974861 + ], + "target_actual_m": [ + 24.395934218476675, + 1.8599657217735117, + -736.6798828125 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-0-1-0-lower-mouth-mesh.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-lower-mouth-render.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-lower-mouth-quality.log" + ] + }, + { + "name": "passage-0-1-0-station-25", + "passage": "passage/0-1/0", + "kind": "station", + "station": "25%", + "camera": [ + -14.773420908313007, + -19.15622259434896, + -462.9505434032349 + ], + "target": [ + -22.332571996402073, + -8.365303107352405, + -465.2710323468326 + ], + "yaw": -35.01164133311156, + "pitch": -9.988838244260211, + "focus": [ + -14.252149448584996, + -18.61698603654429, + -462.71491494399237 + ], + "center_z": -462.71491494399237, + "route_distance_m": 506.6753072603284, + "route_length_m": 2026.7012290413136, + "requested_route_distance_m": 506.6753072603284, + "variant": "after", + "capture": "captures/after/passage-0-1-0-station-25.png", + "scene": "Saved/Linux/l112/captures/after/passage-0-1-0-station-25.vfmesh", + "drawn_triangles": 135136, + "source_triangles": 181364, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 506.6753072603284, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -14.773420908313007, + -19.15622259434896, + -462.9505434032349 + ], + "target_actual_m": [ + -22.332571996402073, + -8.365303107352405, + -465.2710323468326 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-0-1-0-station-25-mesh.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-station-25-render.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-station-25-quality.log" + ] + }, + { + "name": "passage-0-1-0-station-50", + "passage": "passage/0-1/0", + "kind": "station", + "station": "50%", + "camera": [ + -5.87968914032497, + 21.857993246713395, + -554.13630134032 + ], + "target": [ + 7.315979337237899, + 21.580426280018035, + -556.4572725224375 + ], + "yaw": 91.20502199933122, + "pitch": -9.973491174456086, + "focus": [ + -5.762536970286937, + 21.11719950412685, + -553.9006728810774 + ], + "center_z": -553.9006728810774, + "route_distance_m": 1013.3506145206568, + "route_length_m": 2026.7012290413136, + "requested_route_distance_m": 1013.3506145206568, + "variant": "after", + "capture": "captures/after/passage-0-1-0-station-50.png", + "scene": "Saved/Linux/l112/captures/after/passage-0-1-0-station-50.vfmesh", + "drawn_triangles": 316508, + "source_triangles": 404356, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1013.3506145206568, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -5.87968914032497, + 21.857993246713395, + -554.13630134032 + ], + "target_actual_m": [ + 7.315979337237899, + 21.580426280018035, + -556.4572725224375 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-0-1-0-station-50-mesh.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-station-50-render.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-station-50-quality.log" + ] + }, + { + "name": "passage-0-1-0-station-75", + "passage": "passage/0-1/0", + "kind": "station", + "station": "75%", + "camera": [ + 16.79632298277704, + -13.630908634595473, + -645.3200745693888 + ], + "target": [ + 6.584565856030696, + -21.9376366230758, + -647.640607952583 + ], + "yaw": -129.12654304255443, + "pitch": -9.997579084277536, + "focus": [ + 16.22588361858051, + -13.143980578538871, + -645.0844461101462 + ], + "center_z": -645.0844461101462, + "route_distance_m": 1520.0259217809853, + "route_length_m": 2026.7012290413136, + "requested_route_distance_m": 1520.0259217809853, + "variant": "after", + "capture": "captures/after/passage-0-1-0-station-75.png", + "scene": "Saved/Linux/l112/captures/after/passage-0-1-0-station-75.vfmesh", + "drawn_triangles": 257040, + "source_triangles": 329218, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1520.0259217809853, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 16.79632298277704, + -13.630908634595473, + -645.3200745693888 + ], + "target_actual_m": [ + 6.584565856030696, + -21.9376366230758, + -647.640607952583 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-0-1-0-station-75-mesh.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-station-75-render.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-station-75-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-1-view-1", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-1/view-1", + "camera": [ + 14.177038985763101, + 7.143775299052934, + -371.985 + ], + "target": [ + 7.282, + 7.839, + -373.085 + ], + "yaw": -84.24234320176159, + "pitch": -9.01932243138141, + "focus": [ + 7.282, + 7.839, + -373.185 + ], + "center_z": -373.185, + "open_air_section": 1, + "route_distance_m": 8.2615, + "requested_route_distance_m": 8.2615, + "route_length_m": 2026.7012290413136, + "variant": "after", + "capture": "captures/after/passage-0-1-0-openair-1-view-1.png", + "scene": "Saved/Linux/l112/captures/after/passage-0-1-0-openair-1-view-1.vfmesh", + "drawn_triangles": 278629, + "source_triangles": 346431, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 8.2615, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 14.177038985763101, + 7.143775299052934, + -371.985 + ], + "target_actual_m": [ + 7.282, + 7.839, + -373.085 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-1-view-1-mesh.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-1-view-1-render.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-1-view-1-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-1-view-2", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-1/view-2", + "camera": [ + 1.8793936951380026, + 8.383743163945537, + -369.185 + ], + "target": [ + 7.083023812394741, + 5.865611297170759, + -373.44218768304876 + ], + "yaw": 115.82318961848594, + "pitch": -36.368805894026266, + "focus": [ + 7.282, + 7.839, + -373.185 + ], + "center_z": -373.185, + "open_air_section": 1, + "route_distance_m": 8.2615, + "requested_route_distance_m": 8.2615, + "route_length_m": 2026.7012290413136, + "variant": "after", + "capture": "captures/after/passage-0-1-0-openair-1-view-2.png", + "scene": "Saved/Linux/l112/captures/after/passage-0-1-0-openair-1-view-2.vfmesh", + "drawn_triangles": 287396, + "source_triangles": 358400, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 8.2615, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 1.8793936951380026, + 8.383743163945537, + -369.185 + ], + "target_actual_m": [ + 7.083023812394741, + 5.865611297170759, + -373.44218768304876 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-1-view-2-mesh.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-1-view-2-render.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-1-view-2-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-1-view-3", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-1/view-3", + "camera": [ + 7.282, + 7.839, + -373.635 + ], + "target": [ + 6.585583343381591, + 0.9321395400976531, + -374.5351568906707 + ], + "yaw": -174.2423432017616, + "pitch": -7.388343353280002, + "focus": [ + 7.282, + 7.839, + -373.185 + ], + "center_z": -373.185, + "open_air_section": 1, + "route_distance_m": 8.2615, + "requested_route_distance_m": 8.2615, + "route_length_m": 2026.7012290413136, + "variant": "after", + "capture": "captures/after/passage-0-1-0-openair-1-view-3.png", + "scene": "Saved/Linux/l112/captures/after/passage-0-1-0-openair-1-view-3.vfmesh", + "drawn_triangles": 311780, + "source_triangles": 392506, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 8.2615, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 7.282, + 7.839, + -373.635 + ], + "target_actual_m": [ + 6.585583343381591, + 0.9321395400976531, + -374.5351568906707 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-1-view-3-mesh.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-1-view-3-render.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-1-view-3-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-1-4m-outside", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-1/4m-outside", + "camera": [ + 13.182083865162365, + 7.244096323720621, + -374.385 + ], + "target": [ + 9.202263382759421, + 7.645380422391366, + -374.385 + ], + "yaw": -84.24234320176159, + "pitch": 0.0, + "focus": [ + 7.282, + 7.839, + -373.185 + ], + "center_z": -373.185, + "open_air_section": 1, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.9949551206007362, + -0.10032102466768629, + 0.0 + ], + "camera_target_distance_m": 3.9999999999999996, + "route_distance_m": 8.2615, + "requested_route_distance_m": 8.2615, + "route_length_m": 2026.7012290413136, + "variant": "after", + "capture": "captures/after/passage-0-1-0-openair-1-4m-outside.png", + "scene": "Saved/Linux/l112/captures/after/passage-0-1-0-openair-1-4m-outside.vfmesh", + "drawn_triangles": 278629, + "source_triangles": 346431, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 8.2615, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.9999999999999996, + "closeup_target_surface_distance_m": 0.7515085626476259, + "closeup_predicted_target_offset_m": 0.7515085626476259, + "closeup_wall_normal_alignment": 0.9914561643267705, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 13.001904038143014, + 8.028532071234862, + -374.0476239046015 + ], + "target_actual_m": [ + 9.013093948364258, + 8.0, + -373.75 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-1-4m-outside-mesh.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-1-4m-outside-render.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-1-4m-outside-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-1-4m-interior-wall", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-1/4m-interior-wall", + "camera": [ + 7.405691935288184, + 3.966226119787983, + -374.8830418066488 + ], + "target": [ + 8.785962786332426, + 7.687355885946053, + -374.385 + ], + "yaw": 20.351222510561445, + "pitch": 7.1524858702584835, + "focus": [ + 7.282, + 7.839, + -373.185 + ], + "center_z": -373.185, + "open_air_section": 1, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.9949551206007362, + 0.10032102466768629, + -0.0 + ], + "camera_target_distance_m": 4.000000000000003, + "route_distance_m": 8.2615, + "requested_route_distance_m": 8.2615, + "route_length_m": 2026.7012290413136, + "variant": "after", + "capture": "captures/after/passage-0-1-0-openair-1-4m-interior-wall.png", + "scene": "Saved/Linux/l112/captures/after/passage-0-1-0-openair-1-4m-interior-wall.vfmesh", + "drawn_triangles": 311780, + "source_triangles": 392506, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 8.2615, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.9999999999999987, + "closeup_target_surface_distance_m": 0.743343733960606, + "closeup_predicted_target_offset_m": 0.743343733960606, + "closeup_wall_normal_alignment": 0.9914561643267705, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 5.024283858585503, + 7.971467928765139, + -373.4523760953985 + ], + "target_actual_m": [ + 9.013093948364258, + 8.0, + -373.75 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-1-4m-interior-wall-mesh.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-1-4m-interior-wall-render.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-1-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-2-view-1", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-2/view-1", + "camera": [ + 13.81216559375693, + 0.8874232608882145, + -372.966 + ], + "target": [ + 6.611, + 1.753, + -374.066 + ], + "yaw": -83.14595676247222, + "pitch": -8.623838343279465, + "focus": [ + 6.611, + 1.753, + -374.166 + ], + "center_z": -374.166, + "open_air_section": 2, + "route_distance_m": 14.436, + "requested_route_distance_m": 14.436, + "route_length_m": 2026.7012290413136, + "variant": "after", + "capture": "captures/after/passage-0-1-0-openair-2-view-1.png", + "scene": "Saved/Linux/l112/captures/after/passage-0-1-0-openair-2-view-1.vfmesh", + "drawn_triangles": 278629, + "source_triangles": 346431, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 14.436, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 13.81216559375693, + 0.8874232608882145, + -372.966 + ], + "target_actual_m": [ + 6.611, + 1.753, + -374.066 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-2-view-1-mesh.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-2-view-1-render.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-2-view-1-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-2-view-2", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-2/view-2", + "camera": [ + 0.8991144821613641, + 2.4395659699586516, + -370.166 + ], + "target": [ + 6.3761872034956015, + -0.2005250368401441, + -374.52461243848546 + ], + "yaw": 115.73527173937683, + "pitch": -35.63513396653433, + "focus": [ + 6.611, + 1.753, + -374.166 + ], + "center_z": -374.166, + "open_air_section": 2, + "route_distance_m": 14.436, + "requested_route_distance_m": 14.436, + "route_length_m": 2026.7012290413136, + "variant": "after", + "capture": "captures/after/passage-0-1-0-openair-2-view-2.png", + "scene": "Saved/Linux/l112/captures/after/passage-0-1-0-openair-2-view-2.vfmesh", + "drawn_triangles": 311780, + "source_triangles": 392506, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 14.436, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 0.8991144821613641, + 2.4395659699586516, + -370.166 + ], + "target_actual_m": [ + 6.3761872034956015, + -0.2005250368401441, + -374.52461243848546 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-2-view-2-mesh.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-2-view-2-render.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-2-view-2-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-2-view-3", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-2/view-3", + "camera": [ + 6.611, + 1.753, + -374.75162845924257 + ], + "target": [ + 5.789155212234605, + -5.084337628940504, + -376.00677199394175 + ], + "yaw": -173.14595676247222, + "pitch": -10.329351655646626, + "focus": [ + 6.611, + 1.753, + -374.166 + ], + "center_z": -374.166, + "open_air_section": 2, + "route_distance_m": 14.436, + "requested_route_distance_m": 14.436, + "route_length_m": 2026.7012290413136, + "variant": "after", + "capture": "captures/after/passage-0-1-0-openair-2-view-3.png", + "scene": "Saved/Linux/l112/captures/after/passage-0-1-0-openair-2-view-3.vfmesh", + "drawn_triangles": 311780, + "source_triangles": 392506, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 14.436, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 6.611, + 1.753, + -374.75162845924257 + ], + "target_actual_m": [ + 5.789155212234605, + -5.084337628940504, + -376.00677199394175 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-2-view-3-mesh.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-2-view-3-render.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-2-view-3-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-2-4m-outside", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-2/4m-outside", + "camera": [ + 12.8193122098114, + 1.0067637736569703, + -375.50162845924257 + ], + "target": [ + 8.84789867402928, + 1.4841258247319933, + -375.50162845924257 + ], + "yaw": -83.14595676247222, + "pitch": 0.0, + "focus": [ + 6.611, + 1.753, + -374.166 + ], + "center_z": -374.166, + "open_air_section": 2, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.9928533839455302, + -0.11934051276875574, + 0.0 + ], + "camera_target_distance_m": 4.0, + "route_distance_m": 14.436, + "requested_route_distance_m": 14.436, + "route_length_m": 2026.7012290413136, + "variant": "after", + "capture": "captures/after/passage-0-1-0-openair-2-4m-outside.png", + "scene": "Saved/Linux/l112/captures/after/passage-0-1-0-openair-2-4m-outside.vfmesh", + "drawn_triangles": 278629, + "source_triangles": 346431, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 14.436, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.000000000000009, + "closeup_target_surface_distance_m": 1.0954207812570795, + "closeup_predicted_target_offset_m": 1.0954207812570795, + "closeup_wall_normal_alignment": 0.5096506905478002, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 10.316430262687657, + 3.180776532410437, + -378.42551295829554 + ], + "target_actual_m": [ + 8.001025199890137, + 1.0, + -376.0 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-2-4m-outside-mesh.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-2-4m-outside-render.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-2-4m-outside-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-2-4m-interior-wall", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-2/4m-interior-wall", + "camera": [ + 6.964882710490212, + -2.1271777965928074, + -376.1960784602411 + ], + "target": [ + 8.412449119604705, + 1.5364666576789914, + -375.50162845924257 + ], + "yaw": 21.55979422592298, + "pitch": 9.997924306647324, + "focus": [ + 6.611, + 1.753, + -374.166 + ], + "center_z": -374.166, + "open_air_section": 2, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.9928533839455302, + 0.11934051276875574, + -0.0 + ], + "camera_target_distance_m": 3.9999999999999987, + "route_distance_m": 14.436, + "requested_route_distance_m": 14.436, + "route_length_m": 2026.7012290413136, + "variant": "after", + "capture": "captures/after/passage-0-1-0-openair-2-4m-interior-wall.png", + "scene": "Saved/Linux/l112/captures/after/passage-0-1-0-openair-2-4m-interior-wall.vfmesh", + "drawn_triangles": 350192, + "source_triangles": 445232, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 14.436, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.999999999999987, + "closeup_target_surface_distance_m": 0.8280897194612481, + "closeup_predicted_target_offset_m": 0.8280897194612481, + "closeup_wall_normal_alignment": 0.6621482949540899, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 5.041511761376583, + 1.1856761795197162, + -373.0783207113634 + ], + "target_actual_m": [ + 7.751120738544031, + 1.534688106544318, + -376.0 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-2-4m-interior-wall-mesh.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-2-4m-interior-wall-render.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-2-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-3-view-1", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-3/view-1", + "camera": [ + -29.016924787180837, + -17.208716685638674, + -598.05 + ], + "target": [ + -22.039, + -12.355, + -599.15 + ], + "yaw": 55.178232541175774, + "pitch": -7.373766361330367, + "focus": [ + -22.039, + -12.355, + -599.25 + ], + "center_z": -599.25, + "open_air_section": 3, + "route_distance_m": 1265.3110000000001, + "requested_route_distance_m": 1265.3110000000001, + "route_length_m": 2026.7012290413136, + "variant": "after", + "capture": "captures/after/passage-0-1-0-openair-3-view-1.png", + "scene": "Saved/Linux/l112/captures/after/passage-0-1-0-openair-3-view-1.vfmesh", + "drawn_triangles": 210501, + "source_triangles": 262807, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1265.3110000000001, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -29.016924787180837, + -17.208716685638674, + -598.05 + ], + "target_actual_m": [ + -22.039, + -12.355, + -599.15 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-3-view-1-mesh.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-3-view-1-render.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-3-view-1-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-3-view-2", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-3/view-2", + "camera": [ + -16.292473704674606, + -8.357821553003445, + -595.25 + ], + "target": [ + -23.162403628923403, + -10.739943634747398, + -599.6099405834007 + ], + "yaw": -109.12379416410603, + "pitch": -30.947627602730336, + "focus": [ + -22.039, + -12.355, + -599.25 + ], + "center_z": -599.25, + "open_air_section": 3, + "route_distance_m": 1265.3110000000001, + "requested_route_distance_m": 1265.3110000000001, + "route_length_m": 2026.7012290413136, + "variant": "after", + "capture": "captures/after/passage-0-1-0-openair-3-view-2.png", + "scene": "Saved/Linux/l112/captures/after/passage-0-1-0-openair-3-view-2.vfmesh", + "drawn_triangles": 189354, + "source_triangles": 238324, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1265.3110000000001, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -16.292473704674606, + -8.357821553003445, + -595.25 + ], + "target_actual_m": [ + -23.162403628923403, + -10.739943634747398, + -599.6099405834007 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-3-view-2-mesh.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-3-view-2-render.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-3-view-2-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-3-view-3", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-3/view-3", + "camera": [ + -22.039, + -12.355, + -599.8356284592426 + ], + "target": [ + -25.970912701231907, + -6.70230272161589, + -601.0954205011448 + ], + "yaw": -34.821767458824226, + "pitch": -10.368029386382458, + "focus": [ + -22.039, + -12.355, + -599.25 + ], + "center_z": -599.25, + "open_air_section": 3, + "route_distance_m": 1265.3110000000001, + "requested_route_distance_m": 1265.3110000000001, + "route_length_m": 2026.7012290413136, + "variant": "after", + "capture": "captures/after/passage-0-1-0-openair-3-view-3.png", + "scene": "Saved/Linux/l112/captures/after/passage-0-1-0-openair-3-view-3.vfmesh", + "drawn_triangles": 189354, + "source_triangles": 238324, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1265.3110000000001, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -22.039, + -12.355, + -599.8356284592426 + ], + "target_actual_m": [ + -25.970912701231907, + -6.70230272161589, + -601.0954205011448 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-3-view-3-mesh.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-3-view-3-render.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-3-view-3-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-3-4m-outside", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-3/4m-outside", + "camera": [ + -28.19599245927721, + -16.637691193210596, + -600.5856284592426 + ], + "target": [ + -24.9122631476627, + -14.353589223498279, + -600.5856284592426 + ], + "yaw": 55.17823254117577, + "pitch": 0.0, + "focus": [ + -22.039, + -12.355, + -599.25 + ], + "center_z": -599.25, + "open_air_section": 3, + "closeup_side": "outside", + "closeup_preferred_normal": [ + -0.8209323279036278, + -0.5710254924280793, + 0.0 + ], + "camera_target_distance_m": 4.0, + "route_distance_m": 1265.3110000000001, + "requested_route_distance_m": 1265.3110000000001, + "route_length_m": 2026.7012290413136, + "variant": "after", + "capture": "captures/after/passage-0-1-0-openair-3-4m-outside.png", + "scene": "Saved/Linux/l112/captures/after/passage-0-1-0-openair-3-4m-outside.vfmesh", + "drawn_triangles": 156696, + "source_triangles": 196328, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1265.3110000000001, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.999999999999989, + "closeup_target_surface_distance_m": 0.19024061574976878, + "closeup_predicted_target_offset_m": 0.19024061574976878, + "closeup_wall_normal_alignment": 0.8867453188356844, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -27.424064445340754, + -16.658813034913997, + -602.2859722225862 + ], + "target_actual_m": [ + -24.785626505535024, + -14.240353099760217, + -600.5 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-3-4m-outside-mesh.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-3-4m-outside-render.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-3-4m-outside-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-3-4m-interior-wall", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-3/4m-interior-wall", + "camera": [ + -26.04935611703069, + -10.503775697900165, + -601.28265040181 + ], + "target": [ + -24.694826671989663, + -14.202344393233052, + -600.5856284592426 + ], + "yaw": 159.88571784104565, + "pitch": 10.035334894495504, + "focus": [ + -22.039, + -12.355, + -599.25 + ], + "center_z": -599.25, + "open_air_section": 3, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + 0.8209323279036278, + 0.5710254924280793, + -0.0 + ], + "camera_target_distance_m": 4.0, + "route_distance_m": 1265.3110000000001, + "requested_route_distance_m": 1265.3110000000001, + "route_length_m": 2026.7012290413136, + "variant": "after", + "capture": "captures/after/passage-0-1-0-openair-3-4m-interior-wall.png", + "scene": "Saved/Linux/l112/captures/after/passage-0-1-0-openair-3-4m-interior-wall.vfmesh", + "drawn_triangles": 156658, + "source_triangles": 198088, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1265.3110000000001, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.999999999999988, + "closeup_target_surface_distance_m": 0.03447160931397061, + "closeup_predicted_target_offset_m": 0.03447160931397061, + "closeup_wall_normal_alignment": 0.8640470577938766, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -22.16608291175724, + -11.835991531939918, + -598.6539123835992 + ], + "target_actual_m": [ + -24.716274302444134, + -14.222318752507483, + -600.6037755242438 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-3-4m-interior-wall-mesh.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-3-4m-interior-wall-render.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-3-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-1-2-0-upper-mouth", + "passage": "passage/1-2/0", + "kind": "mouth", + "station": "upper-mouth", + "camera": [ + 23.382701629372992, + -15.537907964013215, + -731.7810546875 + ], + "target": [ + 17.291932956389783, + -13.605656356271904, + -731.8810546875 + ], + "yaw": -72.39875236992931, + "pitch": -0.8965858034836333, + "focus": [ + 19.166015625, + -14.2001953125, + -730.5610546875 + ], + "center_z": -730.5610546875, + "variant": "after", + "capture": "captures/after/passage-1-2-0-upper-mouth.png", + "scene": "Saved/Linux/l112/captures/after/passage-1-2-0-upper-mouth.vfmesh", + "drawn_triangles": 595932, + "source_triangles": 664560, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": null, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 23.382701629372992, + -15.537907964013215, + -731.7810546875 + ], + "target_actual_m": [ + 17.291932956389783, + -13.605656356271904, + -731.8810546875 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-1-2-0-upper-mouth-mesh.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-upper-mouth-render.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-upper-mouth-quality.log" + ] + }, + { + "name": "passage-1-2-0-lower-mouth", + "passage": "passage/1-2/0", + "kind": "mouth", + "station": "lower-mouth", + "camera": [ + 27.171071433601465, + -19.00546282978966, + -751.8773596007359 + ], + "target": [ + 17.480740717926007, + -13.188560045702177, + -753.05390625 + ], + "yaw": -59.02448758369992, + "pitch": -5.943042074548474, + "focus": [ + 19.166015625, + -14.2001953125, + -751.73390625 + ], + "center_z": -751.73390625, + "variant": "after", + "capture": "captures/after/passage-1-2-0-lower-mouth.png", + "scene": "Saved/Linux/l112/captures/after/passage-1-2-0-lower-mouth.vfmesh", + "drawn_triangles": 546268, + "source_triangles": 592894, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": null, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 27.171071433601465, + -19.00546282978966, + -751.8773596007359 + ], + "target_actual_m": [ + 17.480740717926007, + -13.188560045702177, + -753.05390625 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-1-2-0-lower-mouth-mesh.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-lower-mouth-render.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-lower-mouth-quality.log" + ] + }, + { + "name": "passage-1-2-0-station-25", + "passage": "passage/1-2/0", + "kind": "station", + "station": "25%", + "camera": [ + 14.113736360885516, + 6.28488001817556, + -736.9318566664899 + ], + "target": [ + 2.8375390569633967, + 14.668469005956942, + -739.318388075095 + ], + "yaw": -53.37006031730614, + "pitch": -9.639411679864782, + "focus": [ + 14.810173613706882, + 6.563223605999366, + -735.76185666649 + ], + "center_z": -735.76185666649, + "route_distance_m": 28.742403046133614, + "route_length_m": 114.96961218453445, + "requested_route_distance_m": 28.742403046133614, + "variant": "after", + "capture": "captures/after/passage-1-2-0-station-25.png", + "scene": "Saved/Linux/l112/captures/after/passage-1-2-0-station-25.vfmesh", + "drawn_triangles": 655074, + "source_triangles": 754544, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 28.742403046133614, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 14.113736360885516, + 6.28488001817556, + -736.9318566664899 + ], + "target_actual_m": [ + 2.8375390569633967, + 14.668469005956942, + -739.318388075095 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-1-2-0-station-25-mesh.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-station-25-render.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-station-25-quality.log" + ] + }, + { + "name": "passage-1-2-0-station-50", + "passage": "passage/1-2/0", + "kind": "station", + "station": "50%", + "camera": [ + -8.167639189328659, + 12.234449393806269, + -742.2421769171431 + ], + "target": [ + -12.719097109722199, + -1.058412445588001, + -744.6306758761227 + ], + "yaw": -161.09886549116882, + "pitch": -9.647718818107231, + "focus": [ + -8.641894120979037, + 12.815467689391955, + -741.0721769171431 + ], + "center_z": -741.0721769171431, + "route_distance_m": 57.48480609226723, + "route_length_m": 114.96961218453445, + "requested_route_distance_m": 57.48480609226723, + "variant": "after", + "capture": "captures/after/passage-1-2-0-station-50.png", + "scene": "Saved/Linux/l112/captures/after/passage-1-2-0-station-50.vfmesh", + "drawn_triangles": 604662, + "source_triangles": 685224, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 57.48480609226723, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -8.167639189328659, + 12.234449393806269, + -742.2421769171431 + ], + "target_actual_m": [ + -12.719097109722199, + -1.058412445588001, + -744.6306758761227 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-1-2-0-station-50-mesh.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-station-50-render.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-station-50-quality.log" + ] + }, + { + "name": "passage-1-2-0-station-75", + "passage": "passage/1-2/0", + "kind": "station", + "station": "75%", + "camera": [ + -6.988640302303379, + -10.765776249210223, + -747.5570701728814 + ], + "target": [ + 7.082949158733629, + -11.036833196961979, + -749.9491196202687 + ], + "yaw": 91.10353551175237, + "pitch": -9.645811664959123, + "focus": [ + -7.4007113577862444, + -11.392432012156066, + -746.3870701728814 + ], + "center_z": -746.3870701728814, + "route_distance_m": 86.22720913840084, + "route_length_m": 114.96961218453445, + "requested_route_distance_m": 86.22720913840084, + "variant": "after", + "capture": "captures/after/passage-1-2-0-station-75.png", + "scene": "Saved/Linux/l112/captures/after/passage-1-2-0-station-75.vfmesh", + "drawn_triangles": 612135, + "source_triangles": 691923, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 86.22720913840084, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -6.988640302303379, + -10.765776249210223, + -747.5570701728814 + ], + "target_actual_m": [ + 7.082949158733629, + -11.036833196961979, + -749.9491196202687 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-1-2-0-station-75-mesh.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-station-75-render.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-station-75-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-1-view-1", + "passage": "passage/1-2/0", + "kind": "open-air", + "station": "section-1/view-1", + "camera": [ + -4.012736377201166, + -3.9264102860018895, + -744.679 + ], + "target": [ + -9.52, + -9.729, + -745.779 + ], + "yaw": -136.49578370469135, + "pitch": -7.829076510059767, + "focus": [ + -9.52, + -9.729, + -745.879 + ], + "center_z": -745.879, + "open_air_section": 1, + "route_distance_m": 83.48150000000001, + "requested_route_distance_m": 83.48150000000001, + "route_length_m": 114.96961218453445, + "variant": "after", + "capture": "captures/after/passage-1-2-0-openair-1-view-1.png", + "scene": "Saved/Linux/l112/captures/after/passage-1-2-0-openair-1-view-1.vfmesh", + "drawn_triangles": 623352, + "source_triangles": 711724, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 83.48150000000001, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -4.012736377201166, + -3.9264102860018895, + -744.679 + ], + "target_actual_m": [ + -9.52, + -9.729, + -745.779 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-1-view-1-mesh.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-1-view-1-render.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-1-view-1-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-1-view-2", + "passage": "passage/1-2/0", + "kind": "open-air", + "station": "section-1/view-2", + "camera": [ + -13.994651693524052, + -14.443604142623464, + -741.879 + ], + "target": [ + -8.094413332043812, + -11.082030626763467, + -746.2491496659267 + ], + "yaw": 60.32831225573483, + "pitch": -32.76344960660182, + "focus": [ + -9.52, + -9.729, + -745.879 + ], + "center_z": -745.879, + "open_air_section": 1, + "route_distance_m": 83.48150000000001, + "requested_route_distance_m": 83.48150000000001, + "route_length_m": 114.96961218453445, + "variant": "after", + "capture": "captures/after/passage-1-2-0-openair-1-view-2.png", + "scene": "Saved/Linux/l112/captures/after/passage-1-2-0-openair-1-view-2.vfmesh", + "drawn_triangles": 576164, + "source_triangles": 644692, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 83.48150000000001, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -13.994651693524052, + -14.443604142623464, + -741.879 + ], + "target_actual_m": [ + -8.094413332043812, + -11.082030626763467, + -746.2491496659267 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-1-view-2-mesh.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-1-view-2-render.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-1-view-2-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-1-view-3", + "passage": "passage/1-2/0", + "kind": "open-air", + "station": "section-1/view-3", + "camera": [ + -9.52, + -9.729, + -747.399 + ], + "target": [ + -4.5304466621533415, + -14.464607193672137, + -748.6945238307434 + ], + "yaw": 133.50421629530865, + "pitch": -10.665495352457787, + "focus": [ + -9.52, + -9.729, + -745.879 + ], + "center_z": -745.879, + "open_air_section": 1, + "route_distance_m": 83.48150000000001, + "requested_route_distance_m": 83.48150000000001, + "route_length_m": 114.96961218453445, + "variant": "after", + "capture": "captures/after/passage-1-2-0-openair-1-view-3.png", + "scene": "Saved/Linux/l112/captures/after/passage-1-2-0-openair-1-view-3.vfmesh", + "drawn_triangles": 570605, + "source_triangles": 638189, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 83.48150000000001, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -9.52, + -9.729, + -747.399 + ], + "target_actual_m": [ + -4.5304466621533415, + -14.464607193672137, + -748.6945238307434 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-1-view-3-mesh.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-1-view-3-render.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-1-view-3-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-1-4m-outside", + "passage": "passage/1-2/0", + "kind": "open-air-close", + "station": "section-1/4m-outside", + "camera": [ + -4.7011443300510205, + -4.651734000251653, + -748.149 + ], + "target": [ + -7.454776141450437, + -7.553028857250708, + -748.149 + ], + "yaw": -136.49578370469135, + "pitch": 0.0, + "focus": [ + -9.52, + -9.729, + -745.879 + ], + "center_z": -745.879, + "open_air_section": 1, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.6884079528498542, + 0.7253237142497637, + 0.0 + ], + "camera_target_distance_m": 3.9999999999999996, + "route_distance_m": 83.48150000000001, + "requested_route_distance_m": 83.48150000000001, + "route_length_m": 114.96961218453445, + "variant": "after", + "capture": "captures/after/passage-1-2-0-openair-1-4m-outside.png", + "scene": "Saved/Linux/l112/captures/after/passage-1-2-0-openair-1-4m-outside.vfmesh", + "drawn_triangles": 623352, + "source_triangles": 711724, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 83.48150000000001, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.000000000000037, + "closeup_target_surface_distance_m": 0.5979370452655519, + "closeup_predicted_target_offset_m": 0.5979370452655519, + "closeup_wall_normal_alignment": 0.42190567041017063, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -5.2402003673605835, + -7.419699358529216, + -744.2592769877698 + ], + "target_actual_m": [ + -7.5, + -7.601630046981916, + -747.5547597816745 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-1-4m-outside-mesh.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-1-4m-outside-render.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-1-4m-outside-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-1-4m-interior-wall", + "passage": "passage/1-2/0", + "kind": "open-air-close", + "station": "section-1/4m-interior-wall", + "camera": [ + -6.097526120437678, + -11.651804466912369, + -748.8657917458692 + ], + "target": [ + -8.169754879372643, + -8.306348210480857, + -748.149 + ], + "yaw": -31.774732032092412, + "pitch": 10.323045367792538, + "focus": [ + -9.52, + -9.729, + -745.879 + ], + "center_z": -745.879, + "open_air_section": 1, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.6884079528498542, + -0.7253237142497637, + -0.0 + ], + "camera_target_distance_m": 4.000000000000005, + "route_distance_m": 83.48150000000001, + "requested_route_distance_m": 83.48150000000001, + "route_length_m": 114.96961218453445, + "variant": "after", + "capture": "captures/after/passage-1-2-0-openair-1-4m-interior-wall.png", + "scene": "Saved/Linux/l112/captures/after/passage-1-2-0-openair-1-4m-interior-wall.vfmesh", + "drawn_triangles": 612135, + "source_triangles": 691923, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 83.48150000000001, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.000000000000001, + "closeup_target_surface_distance_m": 0.6529446089467095, + "closeup_predicted_target_offset_m": 0.6529446089467095, + "closeup_wall_normal_alignment": 0.781464055310911, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -8.531084729501915, + -12.940973897704662, + -748.3218199263141 + ], + "target_actual_m": [ + -8.186284222607911, + -8.958624012538072, + -748.1734892060998 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-1-4m-interior-wall-mesh.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-1-4m-interior-wall-render.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-1-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-2-view-1", + "passage": "passage/1-2/0", + "kind": "open-air", + "station": "section-2/view-1", + "camera": [ + 6.37266079290948, + -3.635825668681128, + -748.555 + ], + "target": [ + 9.488, + -11.155, + -749.655 + ], + "yaw": 157.49482804323503, + "pitch": -7.696985964433935, + "focus": [ + 9.488, + -11.155, + -749.755 + ], + "center_z": -749.755, + "open_air_section": 2, + "route_distance_m": 104.40950000000001, + "requested_route_distance_m": 104.40950000000001, + "route_length_m": 114.96961218453445, + "variant": "after", + "capture": "captures/after/passage-1-2-0-openair-2-view-1.png", + "scene": "Saved/Linux/l112/captures/after/passage-1-2-0-openair-2-view-1.vfmesh", + "drawn_triangles": 628316, + "source_triangles": 719702, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 104.40950000000001, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 6.37266079290948, + -3.635825668681128, + -748.555 + ], + "target_actual_m": [ + 9.488, + -11.155, + -749.655 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-2-view-1-mesh.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-2-view-1-render.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-2-view-1-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-2-view-2", + "passage": "passage/1-2/0", + "kind": "open-air", + "station": "section-2/view-2", + "camera": [ + 12.029188966196578, + -17.288406854113035, + -745.755 + ], + "target": [ + 11.303971870631361, + -10.402607766721497, + -750.1239879298538 + ], + "yaw": -6.01226603270804, + "pitch": -32.25202716463738, + "focus": [ + 9.488, + -11.155, + -749.755 + ], + "center_z": -749.755, + "open_air_section": 2, + "route_distance_m": 104.40950000000001, + "requested_route_distance_m": 104.40950000000001, + "route_length_m": 114.96961218453445, + "variant": "after", + "capture": "captures/after/passage-1-2-0-openair-2-view-2.png", + "scene": "Saved/Linux/l112/captures/after/passage-1-2-0-openair-2-view-2.vfmesh", + "drawn_triangles": 585440, + "source_triangles": 649826, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 104.40950000000001, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 12.029188966196578, + -17.288406854113035, + -745.755 + ], + "target_actual_m": [ + 11.303971870631361, + -10.402607766721497, + -750.1239879298538 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-2-view-2-mesh.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-2-view-2-render.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-2-view-2-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-2-view-3", + "passage": "passage/1-2/0", + "kind": "open-air", + "station": "section-2/view-3", + "camera": [ + 9.488, + -11.155, + -751.275 + ], + "target": [ + 15.843901547209768, + -8.52162718352524, + -752.5664577544884 + ], + "yaw": 67.49482804323503, + "pitch": -10.63163088784527, + "focus": [ + 9.488, + -11.155, + -749.755 + ], + "center_z": -749.755, + "open_air_section": 2, + "route_distance_m": 104.40950000000001, + "requested_route_distance_m": 104.40950000000001, + "route_length_m": 114.96961218453445, + "variant": "after", + "capture": "captures/after/passage-1-2-0-openair-2-view-3.png", + "scene": "Saved/Linux/l112/captures/after/passage-1-2-0-openair-2-view-3.vfmesh", + "drawn_triangles": 613722, + "source_triangles": 693804, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 104.40950000000001, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 9.488, + -11.155, + -751.275 + ], + "target_actual_m": [ + 15.843901547209768, + -8.52162718352524, + -752.5664577544884 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-2-view-3-mesh.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-2-view-3-render.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-2-view-3-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-2-4m-outside", + "passage": "passage/1-2/0", + "kind": "open-air-close", + "station": "section-2/4m-outside", + "camera": [ + 6.755427620172105, + -4.559670653485019, + -752.025 + ], + "target": [ + 8.286494929222613, + -8.255050592700584, + -752.025 + ], + "yaw": 157.49482804323503, + "pitch": 0.0, + "focus": [ + 9.488, + -11.155, + -749.755 + ], + "center_z": -749.755, + "open_air_section": 2, + "closeup_side": "outside", + "closeup_preferred_normal": [ + -0.3827668272626269, + 0.9238449848038914, + 0.0 + ], + "camera_target_distance_m": 4.0, + "route_distance_m": 104.40950000000001, + "requested_route_distance_m": 104.40950000000001, + "route_length_m": 114.96961218453445, + "variant": "after", + "capture": "captures/after/passage-1-2-0-openair-2-4m-outside.png", + "scene": "Saved/Linux/l112/captures/after/passage-1-2-0-openair-2-4m-outside.vfmesh", + "drawn_triangles": 585802, + "source_triangles": 657076, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 104.40950000000001, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.0, + "closeup_target_surface_distance_m": 0.5569723033142947, + "closeup_predicted_target_offset_m": 0.5569723033142947, + "closeup_wall_normal_alignment": 0.8300132989203148, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 5.456826350119467, + -6.285898707784279, + -752.1262448423768 + ], + "target_actual_m": [ + 8.786704307765559, + -8.5, + -752.027917557296 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-2-4m-outside-mesh.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-2-4m-outside-render.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-2-4m-outside-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-2-4m-interior-wall", + "passage": "passage/1-2/0", + "kind": "open-air-close", + "station": "section-2/4m-interior-wall", + "camera": [ + 12.557525361540653, + -8.61890578995272, + -752.7395420536377 + ], + "target": [ + 8.658144128209829, + -9.15206209980055, + -752.025 + ], + "yaw": -97.78568510593111, + "pitch": 10.290292405231583, + "focus": [ + 9.488, + -11.155, + -749.755 + ], + "center_z": -749.755, + "open_air_section": 2, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + 0.3827668272626269, + -0.9238449848038914, + -0.0 + ], + "camera_target_distance_m": 4.000000000000001, + "route_distance_m": 104.40950000000001, + "requested_route_distance_m": 104.40950000000001, + "route_length_m": 114.96961218453445, + "variant": "after", + "capture": "captures/after/passage-1-2-0-openair-2-4m-interior-wall.png", + "scene": "Saved/Linux/l112/captures/after/passage-1-2-0-openair-2-4m-interior-wall.vfmesh", + "drawn_triangles": 574472, + "source_triangles": 635712, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 104.40950000000001, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.000000000000001, + "closeup_target_surface_distance_m": 0.3789200867234511, + "closeup_predicted_target_offset_m": 0.3789200867234511, + "closeup_wall_normal_alignment": 0.9970173084578355, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 10.235234629238544, + -12.420762087601563, + -752.017966381381 + ], + "target_actual_m": [ + 8.423532662676926, + -8.854568760433747, + -752.0190329743256 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-2-4m-interior-wall-mesh.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-2-4m-interior-wall-render.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-2-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-2-3-0-upper-mouth", + "passage": "passage/2-3/0", + "kind": "mouth", + "station": "upper-mouth", + "camera": [ + -24.46109203696401, + -5.5818896409784315, + -811.975390625 + ], + "target": [ + -18.107570205793774, + -4.840123701231809, + -812.075390625 + ], + "yaw": 83.34093327385727, + "pitch": -0.8956388887564393, + "focus": [ + -20.0625, + -5.068359375, + -810.755390625 + ], + "center_z": -810.755390625, + "variant": "after", + "capture": "captures/after/passage-2-3-0-upper-mouth.png", + "scene": "Saved/Linux/l112/captures/after/passage-2-3-0-upper-mouth.vfmesh", + "drawn_triangles": 59568, + "source_triangles": 71508, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": null, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -24.46109203696401, + -5.5818896409784315, + -811.975390625 + ], + "target_actual_m": [ + -18.107570205793774, + -4.840123701231809, + -812.075390625 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-2-3-0-upper-mouth-mesh.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-upper-mouth-render.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-upper-mouth-quality.log" + ] + }, + { + "name": "passage-2-3-0-lower-mouth", + "passage": "passage/2-3/0", + "kind": "mouth", + "station": "lower-mouth", + "camera": [ + -28.636475339787903, + -1.3354368899879738, + -898.8144448742513 + ], + "target": [ + -18.25745256004465, + -5.854237792897269, + -900.0333984375 + ], + "yaw": 113.5272620393567, + "pitch": -6.145978083088789, + "focus": [ + -20.0625, + -5.068359375, + -898.7133984375 + ], + "center_z": -898.7133984375, + "variant": "after", + "capture": "captures/after/passage-2-3-0-lower-mouth.png", + "scene": "Saved/Linux/l112/captures/after/passage-2-3-0-lower-mouth.vfmesh", + "drawn_triangles": 294004, + "source_triangles": 314734, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": null, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -28.636475339787903, + -1.3354368899879738, + -898.8144448742513 + ], + "target_actual_m": [ + -18.25745256004465, + -5.854237792897269, + -900.0333984375 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-2-3-0-lower-mouth-mesh.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-lower-mouth-render.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-lower-mouth-quality.log" + ] + }, + { + "name": "passage-2-3-0-station-25", + "passage": "passage/2-3/0", + "kind": "station", + "station": "25%", + "camera": [ + 3.019701774592388, + -13.591453110374651, + -833.8488531811187 + ], + "target": [ + 14.00155446639769, + -4.75985656647419, + -836.142478466213 + ], + "yaw": 51.19378873289192, + "pitch": -9.244130451366324, + "focus": [ + 3.0967290150193443, + -14.33748716069153, + -832.6788531811187 + ], + "center_z": -832.6788531811187, + "route_distance_m": 123.53373286582855, + "route_length_m": 494.1349314633142, + "requested_route_distance_m": 123.53373286582855, + "variant": "after", + "capture": "captures/after/passage-2-3-0-station-25.png", + "scene": "Saved/Linux/l112/captures/after/passage-2-3-0-station-25.vfmesh", + "drawn_triangles": 55514, + "source_triangles": 66412, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 123.53373286582855, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 3.019701774592388, + -13.591453110374651, + -833.8488531811187 + ], + "target_actual_m": [ + 14.00155446639769, + -4.75985656647419, + -836.142478466213 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-2-3-0-station-25-mesh.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-station-25-render.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-station-25-quality.log" + ] + }, + { + "name": "passage-2-3-0-station-50", + "passage": "passage/2-3/0", + "kind": "station", + "station": "50%", + "camera": [ + 15.037366176324477, + 4.106782632885063, + -855.8546237305741 + ], + "target": [ + 4.302090316791295, + 13.21257795312749, + -858.1474627779044 + ], + "yaw": -49.69497333173356, + "pitch": -9.251013429114066, + "focus": [ + 15.752039052912956, + 4.334252805586342, + -854.6846237305741 + ], + "center_z": -854.6846237305741, + "route_distance_m": 247.0674657316571, + "route_length_m": 494.1349314633142, + "requested_route_distance_m": 247.0674657316571, + "variant": "after", + "capture": "captures/after/passage-2-3-0-station-50.png", + "scene": "Saved/Linux/l112/captures/after/passage-2-3-0-station-50.vfmesh", + "drawn_triangles": 458230, + "source_triangles": 479098, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 247.0674657316571, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 15.037366176324477, + 4.106782632885063, + -855.8546237305741 + ], + "target_actual_m": [ + 4.302090316791295, + 13.21257795312749, + -858.1474627779044 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-2-3-0-station-50-mesh.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-station-50-render.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-station-50-quality.log" + ] + }, + { + "name": "passage-2-3-0-station-75", + "passage": "passage/2-3/0", + "kind": "station", + "station": "75%", + "camera": [ + -5.729592517417305, + 11.518390950074156, + -877.8627102922013 + ], + "target": [ + -12.468742929423927, + -0.8048224106496764, + -880.1601105631271 + ], + "yaw": -151.3272360910958, + "pitch": -9.289478775200905, + "focus": [ + -6.104061615549714, + 12.168216230087099, + -876.6927102922014 + ], + "center_z": -876.6927102922014, + "route_distance_m": 370.6011985974857, + "route_length_m": 494.1349314633142, + "requested_route_distance_m": 370.6011985974857, + "variant": "after", + "capture": "captures/after/passage-2-3-0-station-75.png", + "scene": "Saved/Linux/l112/captures/after/passage-2-3-0-station-75.vfmesh", + "drawn_triangles": 475838, + "source_triangles": 506104, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 370.6011985974857, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -5.729592517417305, + 11.518390950074156, + -877.8627102922013 + ], + "target_actual_m": [ + -12.468742929423927, + -0.8048224106496764, + -880.1601105631271 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-2-3-0-station-75-mesh.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-station-75-render.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-station-75-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-1-view-1", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-1/view-1", + "camera": [ + -2.9979042861664693, + -4.712290740348933, + -812.409 + ], + "target": [ + -7.267, + -11.478, + -813.509 + ], + "yaw": -147.74847917454895, + "pitch": -7.829076510059765, + "focus": [ + -7.267, + -11.478, + -813.609 + ], + "center_z": -813.609, + "open_air_section": 1, + "route_distance_m": 16.506999999999998, + "requested_route_distance_m": 16.506999999999998, + "route_length_m": 494.1349314633142, + "variant": "after", + "capture": "captures/after/passage-2-3-0-openair-1-view-1.png", + "scene": "Saved/Linux/l112/captures/after/passage-2-3-0-openair-1-view-1.vfmesh", + "drawn_triangles": 104612, + "source_triangles": 129352, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 16.506999999999998, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -2.9979042861664693, + -4.712290740348933, + -812.409 + ], + "target_actual_m": [ + -7.267, + -11.478, + -813.509 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-1-view-1-mesh.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-1-view-1-render.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-1-view-1-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-1-view-2", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-1/view-2", + "camera": [ + -10.735640267489744, + -16.97513877346649, + -809.609 + ], + "target": [ + -5.6026931633198105, + -12.528161174579008, + -813.9657131351471 + ], + "yaw": 49.09566798491317, + "pitch": -32.68045244303501, + "focus": [ + -7.267, + -11.478, + -813.609 + ], + "center_z": -813.609, + "open_air_section": 1, + "route_distance_m": 16.506999999999998, + "requested_route_distance_m": 16.506999999999998, + "route_length_m": 494.1349314633142, + "variant": "after", + "capture": "captures/after/passage-2-3-0-openair-1-view-2.png", + "scene": "Saved/Linux/l112/captures/after/passage-2-3-0-openair-1-view-2.vfmesh", + "drawn_triangles": 76426, + "source_triangles": 93942, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 16.506999999999998, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -10.735640267489744, + -16.97513877346649, + -809.609 + ], + "target_actual_m": [ + -5.6026931633198105, + -12.528161174579008, + -813.9657131351471 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-1-view-2-mesh.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-1-view-2-render.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-1-view-2-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-1-view-3", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-1/view-3", + "camera": [ + -7.267, + -11.478, + -815.129 + ], + "target": [ + -1.441926071619335, + -15.153564111026531, + -816.3774959730146 + ], + "yaw": 122.25152082545104, + "pitch": -10.27404912928437, + "focus": [ + -7.267, + -11.478, + -813.609 + ], + "center_z": -813.609, + "open_air_section": 1, + "route_distance_m": 16.506999999999998, + "requested_route_distance_m": 16.506999999999998, + "route_length_m": 494.1349314633142, + "variant": "after", + "capture": "captures/after/passage-2-3-0-openair-1-view-3.png", + "scene": "Saved/Linux/l112/captures/after/passage-2-3-0-openair-1-view-3.vfmesh", + "drawn_triangles": 94962, + "source_triangles": 118054, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 16.506999999999998, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -7.267, + -11.478, + -815.129 + ], + "target_actual_m": [ + -1.441926071619335, + -15.153564111026531, + -816.3774959730146 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-1-view-3-mesh.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-1-view-3-render.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-1-view-3-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-1-4m-outside", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-1/4m-outside", + "camera": [ + -3.5315412503956605, + -5.558004397805316, + -815.879 + ], + "target": [ + -5.666089107312426, + -8.94085902763085, + -815.879 + ], + "yaw": -147.74847917454895, + "pitch": 0.0, + "focus": [ + -7.267, + -11.478, + -813.609 + ], + "center_z": -813.609, + "open_air_section": 1, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.5336369642291914, + 0.8457136574563834, + 0.0 + ], + "camera_target_distance_m": 4.000000000000001, + "route_distance_m": 16.506999999999998, + "requested_route_distance_m": 16.506999999999998, + "route_length_m": 494.1349314633142, + "variant": "after", + "capture": "captures/after/passage-2-3-0-openair-1-4m-outside.png", + "scene": "Saved/Linux/l112/captures/after/passage-2-3-0-openair-1-4m-outside.vfmesh", + "drawn_triangles": 104612, + "source_triangles": 129352, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 16.506999999999998, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.999999999999996, + "closeup_target_surface_distance_m": 0.29683911895713316, + "closeup_predicted_target_offset_m": 0.29683911895713316, + "closeup_wall_normal_alignment": 0.67494340532841, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -3.8308683215077686, + -7.14211062127575, + -813.2125534154507 + ], + "target_actual_m": [ + -5.8142006488753735, + -9.08294977482132, + -816.0934449891276 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-1-4m-outside-mesh.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-1-4m-outside-render.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-1-4m-outside-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-1-4m-interior-wall", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-1/4m-interior-wall", + "camera": [ + -3.5310437260816867, + -12.698557095195458, + -816.5697720158989 + ], + "target": [ + -6.220323092573257, + -9.819215067750013, + -815.879 + ], + "yaw": -43.04519612653523, + "pitch": 9.944433062490045, + "focus": [ + -7.267, + -11.478, + -813.609 + ], + "center_z": -813.609, + "open_air_section": 1, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.5336369642291914, + -0.8457136574563834, + -0.0 + ], + "camera_target_distance_m": 3.9999999999999996, + "route_distance_m": 16.506999999999998, + "requested_route_distance_m": 16.506999999999998, + "route_length_m": 494.1349314633142, + "variant": "after", + "capture": "captures/after/passage-2-3-0-openair-1-4m-interior-wall.png", + "scene": "Saved/Linux/l112/captures/after/passage-2-3-0-openair-1-4m-interior-wall.vfmesh", + "drawn_triangles": 94962, + "source_triangles": 118054, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 16.506999999999998, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.9999999999999925, + "closeup_target_surface_distance_m": 0.41884655036552404, + "closeup_predicted_target_offset_m": 0.41884655036552404, + "closeup_wall_normal_alignment": 0.7463542809089274, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -8.06908339833993, + -11.810743463701222, + -818.2117291711875 + ], + "target_actual_m": [ + -6.01271131624994, + -9.578237281759943, + -815.6064940555799 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-1-4m-interior-wall-mesh.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-1-4m-interior-wall-render.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-1-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-2-view-1", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-2/view-1", + "camera": [ + -3.8431494955986567, + 3.9485527351653085, + -876.2779999999999 + ], + "target": [ + -9.548, + 9.557, + -877.3779999999999 + ], + "yaw": -45.48821883657469, + "pitch": -7.829076510059767, + "focus": [ + -9.548, + 9.557, + -877.478 + ], + "center_z": -877.478, + "open_air_section": 2, + "route_distance_m": 375.00800000000004, + "requested_route_distance_m": 375.00800000000004, + "route_length_m": 494.1349314633142, + "variant": "after", + "capture": "captures/after/passage-2-3-0-openair-2-view-1.png", + "scene": "Saved/Linux/l112/captures/after/passage-2-3-0-openair-2-view-1.vfmesh", + "drawn_triangles": 476214, + "source_triangles": 507486, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 375.00800000000004, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -3.8431494955986567, + 3.9485527351653085, + -876.2779999999999 + ], + "target_actual_m": [ + -9.548, + 9.557, + -877.3779999999999 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-2-view-1-mesh.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-2-view-1-render.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-2-view-1-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-2-view-2", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-2/view-2", + "camera": [ + -14.183191034826091, + 14.113863402678188, + -873.478 + ], + "target": [ + -10.927615416535147, + 8.153670462741282, + -877.8348298086144 + ], + "yaw": 151.35575752769614, + "pitch": -32.6811732818988, + "focus": [ + -9.548, + 9.557, + -877.478 + ], + "center_z": -877.478, + "open_air_section": 2, + "route_distance_m": 375.00800000000004, + "requested_route_distance_m": 375.00800000000004, + "route_length_m": 494.1349314633142, + "variant": "after", + "capture": "captures/after/passage-2-3-0-openair-2-view-2.png", + "scene": "Saved/Linux/l112/captures/after/passage-2-3-0-openair-2-view-2.vfmesh", + "drawn_triangles": 479366, + "source_triangles": 505714, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 375.00800000000004, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -14.183191034826091, + 14.113863402678188, + -873.478 + ], + "target_actual_m": [ + -10.927615416535147, + 8.153670462741282, + -877.8348298086144 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-2-view-2-mesh.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-2-view-2-render.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-2-view-2-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-2-view-3", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-2/view-3", + "camera": [ + -9.548, + 9.557, + -878.9979999999999 + ], + "target": [ + -14.376653957873012, + 4.645346619594482, + -880.2469043301503 + ], + "yaw": -135.4882188365747, + "pitch": -10.277446062572244, + "focus": [ + -9.548, + 9.557, + -877.478 + ], + "center_z": -877.478, + "open_air_section": 2, + "route_distance_m": 375.00800000000004, + "requested_route_distance_m": 375.00800000000004, + "route_length_m": 494.1349314633142, + "variant": "after", + "capture": "captures/after/passage-2-3-0-openair-2-view-3.png", + "scene": "Saved/Linux/l112/captures/after/passage-2-3-0-openair-2-view-3.vfmesh", + "drawn_triangles": 479366, + "source_triangles": 505714, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 375.00800000000004, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -9.548, + 9.557, + -878.9979999999999 + ], + "target_actual_m": [ + -14.376653957873012, + 4.645346619594482, + -880.2469043301503 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-2-view-3-mesh.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-2-view-3-render.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-2-view-3-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-2-4m-outside", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-2/4m-outside", + "camera": [ + -4.5562558086488245, + 4.649608643269644, + -879.7479999999999 + ], + "target": [ + -7.408681060849496, + 7.453832275686991, + -879.7479999999999 + ], + "yaw": -45.48821883657468, + "pitch": 0.0, + "focus": [ + -9.548, + 9.557, + -877.478 + ], + "center_z": -877.478, + "open_air_section": 2, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.7131063130501679, + -0.7010559081043365, + 0.0 + ], + "camera_target_distance_m": 4.0, + "route_distance_m": 375.00800000000004, + "requested_route_distance_m": 375.00800000000004, + "route_length_m": 494.1349314633142, + "variant": "after", + "capture": "captures/after/passage-2-3-0-openair-2-4m-outside.png", + "scene": "Saved/Linux/l112/captures/after/passage-2-3-0-openair-2-4m-outside.vfmesh", + "drawn_triangles": 476214, + "source_triangles": 507486, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 375.00800000000004, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.000000000000001, + "closeup_target_surface_distance_m": 1.7270706511220406, + "closeup_predicted_target_offset_m": 1.7270706511220406, + "closeup_wall_normal_alignment": 0.6707823544913467, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -7.471987180266219, + 5.182171434598743, + -879.6783661883575 + ], + "target_actual_m": [ + -7.306491283931798, + 9.177780848974395, + -879.7662098907449 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-2-4m-outside-mesh.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-2-4m-outside-render.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-2-4m-outside-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-2-4m-interior-wall", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-2/4m-interior-wall", + "camera": [ + -11.53403153171888, + 6.16546709214774, + -880.4389979530969 + ], + "target": [ + -8.149311452462896, + 8.181947147565394, + -879.7479999999999 + ], + "yaw": 59.21521540250373, + "pitch": 9.947718755981942, + "focus": [ + -9.548, + 9.557, + -877.478 + ], + "center_z": -877.478, + "open_air_section": 2, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.7131063130501679, + 0.7010559081043365, + -0.0 + ], + "camera_target_distance_m": 3.9999999999999964, + "route_distance_m": 375.00800000000004, + "requested_route_distance_m": 375.00800000000004, + "route_length_m": 494.1349314633142, + "variant": "after", + "capture": "captures/after/passage-2-3-0-openair-2-4m-interior-wall.png", + "scene": "Saved/Linux/l112/captures/after/passage-2-3-0-openair-2-4m-interior-wall.vfmesh", + "drawn_triangles": 486990, + "source_triangles": 515888, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 375.00800000000004, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.9999999999999996, + "closeup_target_surface_distance_m": 1.0276132856323636, + "closeup_predicted_target_offset_m": 1.0276132856323636, + "closeup_wall_normal_alignment": 0.7200130865712391, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -8.257090453232413, + 13.208090455668112, + -879.7612152592583 + ], + "target_actual_m": [ + -8.149311452462896, + 9.209558486938477, + -879.75 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-2-4m-interior-wall-mesh.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-2-4m-interior-wall-render.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-2-4m-interior-wall-quality.log" + ] + } + ] +} diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/REPORT.md b/Standalone/Research/WorldAssemblerM3/Linux113/REPORT.md new file mode 100644 index 0000000..5c6a841 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux113/REPORT.md @@ -0,0 +1,44 @@ +# Linux 113 — half-pipe crest, floor bands, and readiness + +Version v220 is on `wip/l111-halfpipe-spline` at the existing `16554cd` base. No commit was made. + +## Shape and walk audits + +The open-air wall uses a 0.75 m rounded shell, three 0.25 m voxels thick. Wall relief fades across the top 0.25 m instead of ending at the crest. The captures show the needle-like spikes are gone; some low scalloping remains at the voxel scale. + +All three owner passage plans pass the 15° forward-grade check. Their maximum sampled grades are 10.391°, 10.687°, and 10.289°. Passage, mouth, floor, and shell audits pass. + +The floor bands remain visible. On the exported mesh, upward-facing floor samples along the long open-air run show a median 1.25 m interval and 0.21 m vertical drop (most drops are 0.17–0.25 m). The planned grade there is about 10.43°; a 0.25 m voxel row projects to about 1.36 m along that grade. Control points are spaced a median 9.18 m apart, and a temporary 1 m sampler control reproduced the same audit misses. The measured bands align with voxel rows; they do not match the control-point interval or the 0.75 m slab thickness. They were not removed in this round. + +## Captures + +[Capture index](captures/INDEX.md) contains 50 L112 before images and 50 L113 after images. All 100 pass the pixel and geometry checks. The set includes mouths, stations, open-air views, and 14 after 4 m wall close-ups; their measured camera distance is 4.00 m within 0.02 m. + +## Readiness + +Five interleaved runs per cell, all four strates. Each value is median `LOD0–2 / whole-view` seconds in **L109 / L112 / L113** order. + +| Strate | W8 near | W8 whole | W12 near | W12 whole | +|---|---:|---:|---:|---:| +| SW | 1.038 / 1.027 / 1.511 | 2.291 / 2.235 / 2.947 | 1.304 / 1.623 / 1.629 | 2.476 / 2.886 / 2.819 | +| FI | 1.081 / 1.122 / 1.238 | 2.123 / 2.081 / 2.267 | 1.080 / 1.187 / 1.187 | 2.048 / 2.168 / 2.132 | +| TN | 1.497 / 1.379 / 1.312 | 2.538 / 2.403 / 2.352 | 1.152 / 1.415 / 1.279 | 2.126 / 2.385 / 2.286 | +| VS | 1.444 / 1.617 / 1.136 | 2.676 / 3.117 / 2.639 | 0.818 / 0.896 / 0.925 | 1.753 / 1.824 / 1.853 | + +FI/TN W12 near readiness is 1.187 / 1.279 s for L113 versus 1.080 / 1.152 s for the matched L109 rerun. The speed target was not met. + +| Strate | L109 p95/max | L112 p95/max | L113 p95/max candidates per tile | +|---|---:|---:|---:| +| SW | 3 / 21 | 18 / 185 | 14 / 137 | +| FI | 4 / 47 | 22 / 420 | 17 / 297 | +| TN | 4 / 23 | 22 / 116 | 18 / 92 | +| VS | 4 / 16 | 18 / 82 | 12 / 58 | + +The second speed design, an exact segment-to-tile distance filter, barely changed L113 candidate counts and did not recover near readiness. It was removed; there was no third design. + +## Verification + +- Fast tier: PASS, 264 checks. +- Clang/GCC determinism: all 18 W1/W8/W12 hash runs match within each owner configuration. +- Linux `VFHostEditor`: succeeded after timing with `-NoUBA -MaxParallelActions=4`; no `prlimit` was used. +- No commit, push, or stash. diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/RunL113CandidateLists.py b/Standalone/Research/WorldAssemblerM3/Linux113/RunL113CandidateLists.py new file mode 100644 index 0000000..e010d36 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux113/RunL113CandidateLists.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python3 +"""Compare per-tile passage candidate-list sizes for L109, L112, and L113.""" +from __future__ import annotations + +import json +import math +import re +import statistics +import subprocess +import time +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / "Saved/Linux/l113/candidate-lists" +DATA = ROOT / "Standalone/data/owner_world.json" +BINARIES = { + "L109": ROOT / "Saved/Linux/l109/bin-final/VoxelForgeCoreHeadless-l109-clang", + "L112": ROOT / "Saved/Linux/l112/bin-clang/VoxelForgeCoreHeadless-l112-clang", + "L113": ROOT / "Saved/Linux/l113/bin/VoxelForgeCoreHeadless-l113-clang", +} +CAMERAS = { + 0: (8.0, 16.0, -372.2626953125), + 1: (25.8369140625, 3.19921875, -737.0), + 2: (19.166015625, -14.2001953125, -753.3740234375), + 3: (-20.0625, -5.068359375, -900.353515625), +} +LIST = re.compile(r"^\[PassageComposerTile\].*?features=(\d+) route_candidates=(\d+)", re.M) + + +def percentile(values: list[int], fraction: float) -> int: + ordered = sorted(values) + if not ordered: + return 0 + return ordered[min(len(ordered) - 1, + max(0, math.ceil(fraction * len(ordered)) - 1))] + + +def run(strate: int, version: str) -> dict: + OUT.mkdir(parents=True, exist_ok=True) + log = OUT / f"{version}-s{strate}.log" + camera = ",".join(f"{v:.12f}" for v in CAMERAS[strate]) + ",0,0" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1740s", str(BINARIES[version]), str(DATA), + "--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline", + "--workers=12", "--clip-radius=3", "--max-clip-level=8", "--max-level=8", + f"--camera={camera}", "--profile-passage-composer", "--stream-scheduler-policy=3", + ] + started = time.monotonic() + with log.open("w", encoding="utf-8") as stream: + result = subprocess.run(command, cwd=ROOT, stdout=stream, + stderr=subprocess.STDOUT, check=False, timeout=1740) + output = log.read_text(encoding="utf-8", errors="replace") + features = [int(row[0]) for row in LIST.findall(output)] + routes = [int(row[1]) for row in LIST.findall(output)] + if result.returncode or not features: + raise SystemExit(f"candidate-list profile missing: {log}; exit={result.returncode}") + row = { + "strate": strate, "version": version, "profiled_tiles": len(features), + "feature_candidates": {"sum": sum(features), "min": min(features), + "median": statistics.median(features), "p95": percentile(features, .95), + "max": max(features)}, + "route_segment_candidates": {"sum": sum(routes), "min": min(routes), + "median": statistics.median(routes), "p95": percentile(routes, .95), + "max": max(routes)}, + "elapsed_s": round(time.monotonic() - started, 3), + "log": str(log.relative_to(ROOT)), + } + print("[L113CandidateLists] " + json.dumps(row, sort_keys=True), flush=True) + return row + + +def main() -> int: + if any(not path.is_file() for path in (*BINARIES.values(), DATA)): + raise SystemExit("missing L109/L112/L113 candidate-list input") + rows = [run(strate, version) for strate in range(4) + for version in ("L109", "L112", "L113")] + (OUT / "summary.json").write_text(json.dumps(rows, indent=2) + "\n", + encoding="utf-8") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/RunL113Captures.py b/Standalone/Research/WorldAssemblerM3/Linux113/RunL113Captures.py new file mode 100644 index 0000000..3c0abc2 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux113/RunL113Captures.py @@ -0,0 +1,892 @@ +#!/usr/bin/env python3 +"""Compare copied L112 captures against L113 routes and verified 4 m wall views.""" +from __future__ import annotations + +import hashlib +import json +import math +import re +from array import array +import shutil +import struct +import subprocess +import sys +import time +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +RESEARCH = Path(__file__).resolve().parent +CAPTURES = RESEARCH / "captures" +SAVED = ROOT / "Saved/Linux/l113/captures" +DATA = ROOT / "Standalone/data/owner_world.json" +BINARIES = { + "after": ROOT / "Saved/Linux/l113/bin/VoxelForgeCoreHeadless-l113-clang", +} +LAYOUTS = { + "before": ROOT / "Saved/Linux/l112/audit-layout-candidate.json", + "after": ROOT / "Saved/Linux/l113/audit-layout-candidate.json", +} +AUDIT_LOGS = { + "before": ROOT / "Saved/Linux/l112/audit-owner-clang.log", + "after": ROOT / "Saved/Linux/l113/audit-owner-clang.log", +} +RENDERERS = { + "after": ROOT / "Saved/Linux/l113/bin/VoxelForgeOffscreenCapture-l113-clang", +} +SECTION = re.compile( + r"^\[PassageOpenAirSection\] id=(\S+) section=(\d+) start_m=([\d.]+) " + r"end_m=([\d.]+) samples=(\d+) midpoint_xyz_m=\(([^)]*)\) " + r"midpoint_radius_m=([\d.]+)", re.M) +DRAWN = re.compile(r"drawn_triangles=(\d+)") +QUALITY_METRICS = re.compile(r"stddev_luma=([\d.]+).*coverage_luma_gt12=([\d.]+)") + + +def vector(text: str) -> tuple[float, float, float]: + return tuple(float(value) for value in text.split(",")) + + +def add(a, b): + return tuple(x + y for x, y in zip(a, b)) + + +def sub(a, b): + return tuple(x - y for x, y in zip(a, b)) + + +def mul(a, scale): + return tuple(x * scale for x in a) + + +def norm(a): + length = math.sqrt(sum(x * x for x in a)) + if length <= 1.0e-9: + return (0.0, 1.0, 0.0) + return tuple(value / length for value in a) + + +def angles(camera, target): + delta = sub(target, camera) + horizontal = math.hypot(delta[0], delta[1]) + return (math.degrees(math.atan2(delta[0], delta[1])), + math.degrees(math.atan2(delta[2], horizontal))) + + +def fmt(values) -> str: + return ",".join(f"{value:.6f}" for value in values) + + +def mesh_triangle_count(mesh: Path) -> int: + """Read only the VFMSH headers and count indexed triangles.""" + with mesh.open("rb") as stream: + magic = stream.read(8) + materials = magic == b"VFMSH002" + if magic not in (b"VFMSH001", b"VFMSH002"): + raise RuntimeError(f"unsupported mesh scene header: {mesh}") + version, _voxel_um, tile_count = struct.unpack("<3I", stream.read(12)) + if version != (2 if materials else 1): + raise RuntimeError(f"mesh scene version mismatch: {mesh}") + stream.seek(40, 1) + triangles = 0 + for _ in range(tile_count): + stream.seek(16, 1) + surface_count, _skirts, vertex_count, index_count, mask_count = struct.unpack( + "<5I", stream.read(20)) + triangles += index_count // 3 + stream.seek(vertex_count * 24 + (10 * vertex_count if materials else 0) + + index_count * 4 + mask_count, 1) + if stream.read(1): + raise RuntimeError(f"trailing data in mesh scene: {mesh}") + return triangles + + +def dot(a, b): + return sum(x * y for x, y in zip(a, b)) + + +def closest_point_triangle(point, a, b, c): + def closest_segment(start, end, first_weight, second_weight): + edge = sub(end, start) + length_squared = dot(edge, edge) + t = (min(1.0, max(0.0, dot(sub(point, start), edge) / length_squared)) + if length_squared > 1.0e-16 else 0.0) + position = add(start, mul(edge, t)) + weights = [0.0, 0.0, 0.0] + weights[first_weight], weights[second_weight] = 1.0 - t, t + return position, tuple(weights) + + ab, ac = sub(b, a), sub(c, a) + cross = ((ab[1] * ac[2] - ab[2] * ac[1]), + (ab[2] * ac[0] - ab[0] * ac[2]), + (ab[0] * ac[1] - ab[1] * ac[0])) + if dot(cross, cross) <= 1.0e-16: + candidates = [closest_segment(a, b, 0, 1), + closest_segment(b, c, 1, 2), + closest_segment(c, a, 2, 0)] + return min(candidates, key=lambda candidate: + dot(sub(candidate[0], point), sub(candidate[0], point))) + ap = sub(point, a) + d1, d2 = dot(ab, ap), dot(ac, ap) + if d1 <= 0.0 and d2 <= 0.0: + return a, (1.0, 0.0, 0.0) + bp = sub(point, b) + d3, d4 = dot(ab, bp), dot(ac, bp) + if d3 >= 0.0 and d4 <= d3: + return b, (0.0, 1.0, 0.0) + vc = d1 * d4 - d3 * d2 + if vc <= 0.0 and d1 >= 0.0 and d3 <= 0.0: + denominator = d1 - d3 + if denominator <= 1.0e-16: + return a, (1.0, 0.0, 0.0) + v = d1 / denominator + return add(a, mul(ab, v)), (1.0 - v, v, 0.0) + cp = sub(point, c) + d5, d6 = dot(ab, cp), dot(ac, cp) + if d6 >= 0.0 and d5 <= d6: + return c, (0.0, 0.0, 1.0) + vb = d5 * d2 - d1 * d6 + if vb <= 0.0 and d2 >= 0.0 and d6 <= 0.0: + denominator = d2 - d6 + if denominator <= 1.0e-16: + return a, (1.0, 0.0, 0.0) + w = d2 / denominator + return add(a, mul(ac, w)), (1.0 - w, 0.0, w) + va = d3 * d6 - d5 * d4 + if va <= 0.0 and d4 - d3 >= 0.0 and d5 - d6 >= 0.0: + denominator = (d4 - d3) + (d5 - d6) + if denominator <= 1.0e-16: + return b, (0.0, 1.0, 0.0) + w = (d4 - d3) / denominator + edge = sub(c, b) + return add(b, mul(edge, w)), (0.0, 1.0 - w, w) + face_denominator = va + vb + vc + if face_denominator <= 1.0e-16: + candidates = [closest_segment(a, b, 0, 1), + closest_segment(b, c, 1, 2), + closest_segment(c, a, 2, 0)] + return min(candidates, key=lambda candidate: + dot(sub(candidate[0], point), sub(candidate[0], point))) + denominator = 1.0 / face_denominator + v, w = vb * denominator, vc * denominator + weights = (1.0 - v - w, v, w) + closest = tuple(weights[0] * a[axis] + weights[1] * b[axis] + + weights[2] * c[axis] for axis in range(3)) + return closest, weights + + +def nearest_surface_anchor(mesh: Path, point, margin_m=200.0, *, + preferred_normal=None, minimum_alignment=-1.0) -> dict: + """Return the nearest point on a VFMSH surface triangle and its normal.""" + best_distance_sq = float("inf") + best_position = best_normal = None + with mesh.open("rb") as stream: + magic = stream.read(8) + materials = magic == b"VFMSH002" + if magic not in (b"VFMSH001", b"VFMSH002"): + raise RuntimeError(f"unsupported mesh scene header: {mesh}") + version, voxel_um, tile_count = struct.unpack("<3I", stream.read(12)) + if version != (2 if materials else 1): + raise RuntimeError(f"mesh scene version mismatch: {mesh}") + stream.seek(40, 1) + for _ in range(tile_count): + key = struct.unpack("<4i", stream.read(16)) + surface_count, _skirts, vertex_count, index_count, mask_count = struct.unpack( + "<5I", stream.read(20)) + extent = (32 << key[3]) * voxel_um / 1_000_000.0 + origin = (key[0] * extent, key[1] * extent, key[2] * extent) + if any(point[axis] < origin[axis] - margin_m or + point[axis] > origin[axis] + extent + margin_m for axis in range(3)): + stream.seek(vertex_count * 24 + (10 * vertex_count if materials else 0) + + index_count * 4 + mask_count, 1) + continue + positions = array("f") + positions.frombytes(stream.read(vertex_count * 12)) + normals = array("f") + normals.frombytes(stream.read(vertex_count * 12)) + if materials: + stream.seek(vertex_count * 10, 1) + indices = array("I") + indices.frombytes(stream.read(index_count * 4)) + stream.seek(mask_count, 1) + if struct.pack("=I", 1) != struct.pack("= surface_count or vertex_index >= vertex_count + for vertex_index in triangle): + continue + a, b, c = (vertex(vertex_index) for vertex_index in triangle) + position, weights = closest_point_triangle(point, a, b, c) + delta = sub(position, point) + distance_sq = dot(delta, delta) + if distance_sq >= best_distance_sq: + continue + raw_normals = [vertex_normal(vertex_index) for vertex_index in triangle] + raw_normal = tuple(sum(weights[corner] * raw_normals[corner][axis] + for corner in range(3)) for axis in range(3)) + if dot(raw_normal, raw_normal) < 1.0e-10: + raw_normal = ( + (b[1] - a[1]) * (c[2] - a[2]) - (b[2] - a[2]) * (c[1] - a[1]), + (b[2] - a[2]) * (c[0] - a[0]) - (b[0] - a[0]) * (c[2] - a[2]), + (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0])) + if dot(raw_normal, raw_normal) < 1.0e-10: + continue + candidate_normal = norm(raw_normal) + if preferred_normal is not None: + alignment = dot(candidate_normal, preferred_normal) + if abs(alignment) < minimum_alignment: + continue + if alignment < 0.0: + candidate_normal = mul(candidate_normal, -1.0) + best_distance_sq = distance_sq + best_position = position + best_normal = candidate_normal + if best_position is None: + raise RuntimeError(f"no nearby surface vertices in mesh scene: {mesh}") + return {"position_m": best_position, "normal": best_normal, + "distance_m": math.sqrt(best_distance_sq)} + + +def sanitize(value: str) -> str: + return re.sub(r"[^A-Za-z0-9_-]+", "-", value).strip("-").replace("/", "-") + + +def route_height_at_xy(route, x, y): + if not route: + return None + if len(route) == 1: + point = route[0] + return point[2], (x - point[0]) ** 2 + (y - point[1]) ** 2 + best = (float("inf"), None) + for a, b in zip(route, route[1:]): + dx, dy = b[0] - a[0], b[1] - a[1] + length_sq = dx * dx + dy * dy + t = min(1.0, max(0.0, ((x - a[0]) * dx + (y - a[1]) * dy) / length_sq)) \ + if length_sq > 1.0e-12 else 0.0 + px, py = a[0] + t * dx, a[1] + t * dy + distance_sq = (x - px) ** 2 + (y - py) ** 2 + if distance_sq < best[0]: + best = (distance_sq, a[2] + (b[2] - a[2]) * t) + return best[1], best[0] + + +def upper_mouth_floor_depth(layout: dict, passage: dict, controls) -> float: + scale = layout["core_voxel_size_um"] / 256.0 / 1_000_000.0 + authored = max(0.0, controls[0][0][2] - passage["upper_mouth_q"][2] * scale + 1.13) + stratum = next((row for row in layout["strates"] + if row["strate_index"] == passage["upper_strate_index"]), None) + if stratum is None or stratum["generator_kind"] != "FloatingIslands": + return authored + route = [tuple(value * scale for value in anchor["values"][:3]) + for anchor in stratum.get("anchors", []) + if anchor.get("kind") == "route_point" and len(anchor.get("values", [])) >= 3] + projected = route_height_at_xy(route, controls[0][0][0], controls[0][0][1]) + if projected is None or projected[1] > (controls[0][1] + 2.0) ** 2: + return authored + route_depth = max(0.0, controls[0][0][2] - projected[0] + 1.13) + return max(authored, route_depth) + + +def route_controls(layout: dict, passage: dict, *, adjust_upper_mouth=False): + scale = layout["core_voxel_size_um"] / 256.0 / 1_000_000.0 + controls = [(tuple(value * scale for value in row["position_q"]), + row["radius_q"] * scale) for row in passage["control_points"]] + lower_q = passage["lower_mouth_q"] + player_center_above_floor_q = round( + 1.13 * 256.0 * 1_000_000.0 / layout["core_voxel_size_um"]) + lower_index = next((index for index, row in enumerate(passage["control_points"]) + if row["position_q"][0] == lower_q[0] + and row["position_q"][1] == lower_q[1] + and row["position_q"][2] - row["radius_q"] + + player_center_above_floor_q == lower_q[2]), None) + if lower_index is None: + raise RuntimeError(f"{passage['stable_id']}: lower mouth control is unbound") + if lower_index < 1: + raise RuntimeError(f"{passage['stable_id']}: incomplete route controls") + if adjust_upper_mouth: + controls[0] = (controls[0][0], max(controls[0][1], + upper_mouth_floor_depth(layout, passage, controls))) + return controls, lower_index + + +def route_for(layout: dict, passage: dict) -> list[tuple[tuple[float, float, float], float]]: + controls, lower_index = route_controls(layout, passage) + return controls[:lower_index + 1] + + +def spline_knot_span(a, b): + return max(1.0e-6, math.sqrt(math.sqrt((b[0] - a[0]) ** 2 + + (b[1] - a[1]) ** 2))) + + +def spline_point(controls, span, t): + as_point = lambda index: (*controls[index][0], controls[index][1]) + p0, p1, p2, p3 = (as_point(max(0, span - 1)), as_point(span), + as_point(span + 1), as_point(min(span + 2, len(controls) - 1))) + dt0, dt1, dt2 = (spline_knot_span(p0, p1), spline_knot_span(p1, p2), + spline_knot_span(p2, p3)) + t2, t3 = t * t, t * t * t + result = [0.0] * 4 + for axis in (0, 1, 3): + m1 = dt1 * ((p1[axis] - p0[axis]) / dt0 + - (p2[axis] - p0[axis]) / (dt0 + dt1) + + (p2[axis] - p1[axis]) / dt1) + m2 = dt1 * ((p2[axis] - p1[axis]) / dt1 + - (p3[axis] - p1[axis]) / (dt1 + dt2) + + (p3[axis] - p2[axis]) / dt2) + result[axis] = ((2 * t3 - 3 * t2 + 1) * p1[axis] + + (-2 * t3 + 3 * t2) * p2[axis] + + (t3 - 2 * t2 + t) * m1 + (t3 - t2) * m2) + result[2] = p1[2] + (p2[2] - p1[2]) * t + result[3] = min(max(result[3], min(p1[3], p2[3])), max(p1[3], p2[3])) + return result + + +def smooth_route(layout: dict, passage: dict): + """Mirror the runtime adaptive PassageSpline::BuildSegments sampler.""" + scale = layout["core_voxel_size_um"] / 256.0 / 1_000_000.0 + planned_floor_profile = [ + (row["position_q"][2] - row["radius_q"]) * scale + for row in passage["control_points"]] + controls, route_end = route_controls(layout, passage, adjust_upper_mouth=True) + result = [] + along = 0.0 + arc_steps = 32 + maximum_spacing = 8.0 + maximum_chord_error = 0.025 + for span in range(route_end): + arc = [0.0] + previous = spline_point(controls, span, 0.0) + for step in range(1, arc_steps + 1): + current = spline_point(controls, span, step / arc_steps) + arc.append(arc[-1] + math.hypot(current[0] - previous[0], + current[1] - previous[1])) + previous = current + span_length = arc[-1] + segment_count = max(1, math.ceil(span_length / maximum_spacing)) + + def parameter_at_arc(target): + upper = next(index for index in range(1, len(arc)) if arc[index] >= target) + lower = upper - 1 + width = arc[upper] - arc[lower] + fraction = min(1.0, max(0.0, (target - arc[lower]) / width)) if width > 1e-12 else 0.0 + return (lower + fraction) / arc_steps + + parameters = [0.0] + + def append_adaptive(t_a, t_b, a, b, depth): + maximum_error = 0.0 + polyline_length = 0.0 + previous_point = a + for fraction in (0.25, 0.5, 0.75): + current = spline_point(controls, span, t_a + (t_b - t_a) * fraction) + dx = current[0] - (a[0] + (b[0] - a[0]) * fraction) + dy = current[1] - (a[1] + (b[1] - a[1]) * fraction) + dr = current[3] - (a[3] + (b[3] - a[3]) * fraction) + maximum_error = max(maximum_error, math.sqrt(dx * dx + dy * dy + dr * dr)) + polyline_length += math.hypot(current[0] - previous_point[0], + current[1] - previous_point[1]) + previous_point = current + polyline_length += math.hypot(b[0] - previous_point[0], + b[1] - previous_point[1]) + split = (polyline_length > maximum_spacing * (1.0 + 1.0e-9) + or maximum_error > maximum_chord_error) and depth < 12 + if split: + t_mid = (t_a + t_b) * 0.5 + middle = spline_point(controls, span, t_mid) + append_adaptive(t_a, t_mid, a, middle, depth + 1) + append_adaptive(t_mid, t_b, middle, b, depth + 1) + else: + parameters.append(t_b) + + for segment in range(1, segment_count + 1): + target_a = span_length * (segment - 1) / segment_count + target_b = span_length * segment / segment_count + t_a, t_b = parameter_at_arc(target_a), parameter_at_arc(target_b) + append_adaptive(t_a, t_b, + spline_point(controls, span, t_a), + spline_point(controls, span, t_b), 0) + points = [spline_point(controls, span, t) for t in parameters] + sampled_arc = [0.0] + for a, b in zip(points, points[1:]): + sampled_arc.append(sampled_arc[-1] + math.hypot(b[0] - a[0], b[1] - a[1])) + horizontal_length = sampled_arc[-1] + for index, point in enumerate(points): + progress = sampled_arc[index] / horizontal_length if horizontal_length > 1e-12 else parameters[index] + point[2] = controls[span][0][2] + (controls[span + 1][0][2] + - controls[span][0][2]) * progress + point.append(planned_floor_profile[span] + + (planned_floor_profile[span + 1] + - planned_floor_profile[span]) * progress) + if not result: + result.append((tuple(points[0][:3]), points[0][3], 0.0, points[0][4])) + for a, b in zip(points, points[1:]): + length = math.dist(a[:3], b[:3]) + along += length + result.append((tuple(b[:3]), b[3], along, b[4])) + return result + +def derived_smooth_route(route, passage, layout): + total = route[-1][2] + interior_radii = [radius for _, radius, distance, _ in route + if distance >= 10.0 and total - distance >= 10.0] + body_depth = max(0.5, min(interior_radii or [radius for _, radius, _, _ in route]) - 0.23) + result = [] + for point, radius, distance, planned_floor in route: + local_radius_depth = max(0.0, radius - 0.23) + tube_depth = min(body_depth, local_radius_depth) + center = (point[0], point[1], planned_floor + tube_depth) + result.append((center, radius, distance, planned_floor)) + return result, body_depth + + +def route_lengths(route): + lengths = [((b[2] - a[2]) if len(a) > 2 and len(b) > 2 + else math.dist(a[0], b[0])) for a, b in zip(route, route[1:])] + prefix = [0.0] + for length in lengths: + prefix.append(prefix[-1] + length) + return lengths, prefix + + +def at_distance(route, lengths, prefix, distance): + distance = max(0.0, min(distance, prefix[-1])) + for index, length in enumerate(lengths): + if distance <= prefix[index + 1] or index + 1 == len(lengths): + t = 0.0 if length <= 1.0e-9 else (distance - prefix[index]) / length + a, b = route[index], route[index + 1] + return (tuple(a[0][axis] + (b[0][axis] - a[0][axis]) * t + for axis in range(3)), + a[1] + (b[1] - a[1]) * t) + return route[-1] + + +def tangent_at(route, lengths, prefix, distance): + before = at_distance(route, lengths, prefix, max(0.0, distance - 0.25))[0] + after = at_distance(route, lengths, prefix, min(prefix[-1], distance + 0.25))[0] + return norm(sub(after, before)) + + +def derived_route(route, passage, layout): + """Apply L109's fixed-depth floor offset to raw layout controls.""" + lengths, prefix = route_lengths(route) + total = prefix[-1] + body_radii = [radius for index, (_, radius) in enumerate(route) + if prefix[index] >= 10.0 and total - prefix[index] >= 10.0] + body_depth = max(0.5, min(body_radii or [radius for _, radius in route]) - 0.23) + scale = layout["core_voxel_size_um"] / 256.0 / 1_000_000.0 + upper_z = passage["upper_mouth_q"][2] * scale + lower_z = passage["lower_mouth_q"][2] * scale + upper_target = max(0.0, route[0][0][2] - upper_z + 1.13) + lower_target = max(0.0, route[-1][0][2] - lower_z + 1.13) + transformed = [] + for index, (point, radius) in enumerate(route): + local_radius_depth = max(0.0, radius - 0.23) + mouth_distance = max(0.0, min(prefix[index], total - prefix[index])) + u = max(0.0, min(1.0, mouth_distance / 5.0)) + ramp = u * u * (3.0 - 2.0 * u) + target = upper_target if prefix[index] <= total * 0.5 else lower_target + mouth_depth = max(0.0, min(radius, target)) + route_depth = mouth_depth + (local_radius_depth - mouth_depth) * ramp + tube_depth = min(body_depth, local_radius_depth) + transformed.append(((point[0], point[1], point[2] - route_depth + tube_depth), + radius)) + return transformed, body_depth + + +def make_views(layout: dict, audit_sections: list[dict], *, use_derived_shape: bool, + use_spline: bool, + include_open_air: bool = True) -> list[dict]: + views = [] + passages = sorted(layout["passages"], key=lambda item: item["stable_id"]) + for passage in passages: + raw_route = smooth_route(layout, passage) if use_spline else route_for(layout, passage) + if use_derived_shape: + route, body_depth = (derived_smooth_route(raw_route, passage, layout) + if use_spline else derived_route(raw_route, passage, layout)) + else: + route = raw_route + body_depth = max(point[1] for point in route) + def floor_depth(radius: float) -> float: + if not use_derived_shape: + return radius + return min(body_depth, max(0.0, radius - 0.23)) + lengths, prefix = route_lengths(route) + total = prefix[-1] + passage_id = passage["stable_id"] + safe_id = sanitize(passage_id) + + for end_name, distance, outward_sign in ( + ("upper-mouth", 0.0, -1.0), ("lower-mouth", total, 1.0)): + center, radius = at_distance(route, lengths, prefix, distance) + tangent = tangent_at(route, lengths, prefix, distance) + outward = mul(tangent, outward_sign) + floor_z = center[2] - floor_depth(radius) + eye = (center[0] + outward[0] * 4.5, + center[1] + outward[1] * 4.5, + floor_z + 1.55) + if end_name == "lower-mouth": + eye = add(eye, add(mul(outward, 5.0), (0.0, 0.0, 2.0))) + target = (center[0] - outward[0] * 2.0, + center[1] - outward[1] * 2.0, + floor_z + 1.45) + yaw, pitch = angles(eye, target) + views.append({"name": f"{safe_id}-{end_name}", "passage": passage_id, + "kind": "mouth", "station": end_name, + "camera": eye, "target": target, "yaw": yaw, "pitch": pitch, + "focus": center, "center_z": center[2]}) + + for fraction in (0.25, 0.50, 0.75): + distance = total * fraction + center, radius = at_distance(route, lengths, prefix, distance) + tangent = tangent_at(route, lengths, prefix, distance) + depth = floor_depth(radius) + floor_z = center[2] - depth + horizontal = norm((-tangent[1], tangent[0], 0.0)) + eye = (center[0] + horizontal[0] * 0.75, + center[1] + horizontal[1] * 0.75, floor_z + 1.60) + target_center, target_radius = at_distance(route, lengths, prefix, + min(total, distance + 14.0)) + target_depth = floor_depth(target_radius) + target = (target_center[0] + horizontal[0] * 2.35, + target_center[1] + horizontal[1] * 2.35, + target_center[2] - target_depth + 1.80) + yaw, pitch = angles(eye, target) + views.append({"name": f"{safe_id}-station-{int(fraction * 100)}", + "passage": passage_id, "kind": "station", + "station": f"{int(fraction * 100)}%", "camera": eye, + "target": target, "yaw": yaw, "pitch": pitch, + "focus": center, "center_z": center[2], + "route_distance_m": distance, + "route_length_m": total, + "requested_route_distance_m": distance}) + + if not include_open_air: + continue + for section in (item for item in audit_sections if item["passage"] == passage_id): + distance = 0.5 * (section["start_m"] + section["end_m"]) + center, radius = (section["midpoint"], section["radius_m"]) + tangent = tangent_at(route, lengths, prefix, distance) + side = norm((-tangent[1], tangent[0], 0.0)) + depth = floor_depth(radius) + section_id = section["section"] + interior_eye = (center[0], center[1], center[2] - depth + 1.25) + interior_target = add(interior_eye, mul(tangent, 7.0)) + side_eye = add(center, add(mul(side, radius + 5.0), (0.0, 0.0, 1.2))) + oblique_eye = add(center, add(mul(side, -(radius + 3.5)), (0.0, 0.0, 4.0))) + targets = (add(center, (0.0, 0.0, 0.1)), + add(center, mul(tangent, 2.0)), interior_target) + for view_index, (eye, target) in enumerate(zip( + (side_eye, oblique_eye, interior_eye), targets), start=1): + yaw, pitch = angles(eye, target) + views.append({"name": f"{safe_id}-openair-{section_id}-view-{view_index}", + "passage": passage_id, "kind": "open-air", + "station": f"section-{section_id}/view-{view_index}", + "camera": eye, "target": target, "yaw": yaw, + "pitch": pitch, "focus": center, + "center_z": center[2], "open_air_section": section_id, + "route_distance_m": distance, + "requested_route_distance_m": distance, + "route_length_m": total}) + floor_z = center[2] - depth + outside_target = add(center, add(mul(side, radius), (0.0, 0.0, -depth + 0.5))) + outside_eye = add(outside_target, mul(side, 4.0)) + interior_radius = math.sqrt(max(0.0, radius * radius + - max(0.0, depth - 0.5) ** 2)) + inside_target = add(center, add(mul(side, interior_radius), + (0.0, 0.0, -depth + 0.5))) + inside_eye = add(inside_target, + add(mul(side, -1.0), mul(tangent, math.sqrt(15.0)))) + for closeup, eye, target in (("outside", outside_eye, outside_target), + ("interior-wall", inside_eye, inside_target)): + yaw, pitch = angles(eye, target) + views.append({"name": f"{safe_id}-openair-{section_id}-4m-{closeup}", + "passage": passage_id, "kind": "open-air-close", + "station": f"section-{section_id}/4m-{closeup}", + "camera": eye, "target": target, "yaw": yaw, + "pitch": pitch, "focus": center, "center_z": center[2], + "open_air_section": section_id, "closeup_side": closeup, + "closeup_preferred_normal": side if closeup == "outside" + else mul(side, -1.0), + "camera_target_distance_m": math.dist(eye, target), + "route_distance_m": distance, + "requested_route_distance_m": distance, + "route_length_m": total}) + return views + + +def run_process(name: str, command: list[str], log: Path, *, allow_failure=False) -> str: + wrapped = ["taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1740s", *map(str, command)] + started = time.monotonic() + with log.open("w", encoding="utf-8") as stream: + result = subprocess.run(wrapped, cwd=ROOT, stdout=stream, + stderr=subprocess.STDOUT, check=False, timeout=1740) + if result.returncode and not allow_failure: + raise RuntimeError(f"{name}: exit={result.returncode} log={log}") + print(f"[L113CaptureProcess] name={name} elapsed_s={time.monotonic()-started:.2f} " + f"exit={result.returncode} log={log.relative_to(ROOT)}", flush=True) + return log.read_text(encoding="utf-8", errors="replace") + + +def capture(variant: str, view: dict, layout: dict) -> dict: + variant_saved = SAVED / variant + variant_saved.mkdir(parents=True, exist_ok=True) + variant_capture = CAPTURES / variant + variant_capture.mkdir(parents=True, exist_ok=True) + scene = variant_saved / f"{view['name']}.vfmesh" + image = variant_capture / f"{view['name']}.png" + candidates = [(view["camera"], view["target"], view["focus"], + view.get("route_distance_m"), 0.0, "requested")] + if variant == "before" and view["kind"] not in ("mouth", "open-air-close"): + passage = next(item for item in layout["passages"] + if item["stable_id"] == view["passage"]) + route = route_for(layout, passage) + lengths, prefix = route_lengths(route) + total = prefix[-1] + eye_offset = sub(view["camera"], view["focus"]) + target_offset = sub(view["target"], view["focus"]) + requested = view["route_distance_m"] + for delta in (5, -5, 10, -10, 20, -20, 35, -35, 50, -50, 75, -75, + 100, -100, 150, -150, 200, -200): + distance = max(0.0, min(total, requested + delta)) + if abs(distance - requested) < 0.01: + continue + center, _radius = at_distance(route, lengths, prefix, distance) + candidates.append((add(center, eye_offset), add(center, target_offset), center, + distance, distance - requested, "route-offset")) + + attempt_errors = [] + for attempt_index, (probe_camera, probe_target, probe_focus, route_distance, + route_adjustment, attempt_kind) in enumerate(candidates): + suffix = "" if attempt_index == 0 else f"-attempt-{attempt_index:02d}" + headless_log = variant_saved / f"{view['name']}{suffix}-mesh.log" + render_log = variant_saved / f"{view['name']}{suffix}-render.log" + quality_log = variant_saved / f"{view['name']}{suffix}-quality.log" + yaw, pitch = angles(probe_camera, probe_target) + camera = (*probe_camera, yaw, pitch) + export_command = [ + str(BINARIES[variant]), str(DATA), "--world-assembler-prototype", + "--stream-benchmark", "--stream-pipeline", "--workers=12", + "--clip-radius=3", "--max-clip-level=0", "--max-level=0", "--force-generate", + "--recipe=surface-world", f"--camera={fmt(camera)}", + "--render-distance-chunks=1", f"--mesh-export={scene}", + ] + export_output = run_process(f"{variant}-{view['name']}{suffix}-mesh", export_command, + headless_log) + if "status=PASS" not in export_output or not scene.is_file(): + raise RuntimeError(f"{variant}-{view['name']}: missing successful scene export") + source_triangles = mesh_triangle_count(scene) + if source_triangles <= 0: + attempt_errors.append(f"{attempt_kind}@{route_distance}: empty mesh") + if variant == "after" or view["kind"] == "mouth": + break + continue + + actual_camera, actual_target = probe_camera, probe_target + actual_focus = probe_focus + surface_distance = None + closeup_surface_distance = None + closeup_anchor_offset = None + closeup_normal_alignment = None + closeup_distance = None + if view["kind"] == "open-air-close": + try: + wall_anchor = nearest_surface_anchor(scene, probe_target, margin_m=5.0, + preferred_normal=view["closeup_preferred_normal"], + minimum_alignment=0.25) + closeup_surface_distance = wall_anchor["distance_m"] + closeup_anchor_offset = closeup_surface_distance + closeup_normal_alignment = dot(wall_anchor["normal"], + view["closeup_preferred_normal"]) + if closeup_surface_distance > 5.0: + raise RuntimeError(f"{variant}-{view['name']}: nearest wall surface is " + f"{closeup_surface_distance:.3f} m from the route-local target") + actual_target = wall_anchor["position_m"] + actual_camera = add(actual_target, mul(wall_anchor["normal"], 4.0)) + closeup_distance = math.dist(actual_camera, actual_target) + if abs(closeup_distance - 4.0) > 0.02: + raise RuntimeError(f"{variant}-{view['name']}: camera-to-wall distance is " + f"{closeup_distance:.3f} m, expected 4 m") + except RuntimeError as error: + raise RuntimeError(f"{variant}-{view['name']}: could not verify the 4 m wall " + f"view: {error}") from error + if attempt_kind == "route-offset": + anchor = nearest_surface_anchor(scene, probe_focus) + surface_distance = anchor["distance_m"] + actual_camera = add(anchor["position_m"], mul(anchor["normal"], 12.0)) + actual_target = anchor["position_m"] + actual_focus = anchor["position_m"] + actual_yaw, actual_pitch = angles(actual_camera, actual_target) + render_command = [ + str(RENDERERS[variant]), str(scene), str(image), "--size=1920x1080", + f"--camera-m={fmt(actual_camera)}", f"--yaw-deg={actual_yaw:.6f}", + f"--pitch-deg={actual_pitch:.6f}", "--shade=readable", "--headlamp=on", + "--height-tint=on", f"--height-center-m={actual_focus[2]:.6f}", + "--height-range-m=32", + ] + render_output = run_process(f"{variant}-{view['name']}{suffix}-render", render_command, + render_log) + drawn = DRAWN.search(render_output) + if drawn is None or int(drawn.group(1)) <= 0 or not image.is_file(): + attempt_errors.append(f"{attempt_kind}@{route_distance}: no drawn geometry") + if variant == "after" or view["kind"] == "mouth": + break + continue + quality = run_process(f"{variant}-{view['name']}{suffix}-quality", [ + "python3", "-B", str(ROOT / "Standalone/Tools/verify/capture_quality.py"), + str(image)], quality_log, allow_failure=True) + quality_status = "pass" + if "status=PASS" not in quality: + metrics = QUALITY_METRICS.search(quality) + coverage = float(metrics.group(2)) if metrics else 0.0 + if coverage >= 0.001: + quality_status = "low_contrast_geometry_visible" + else: + attempt_errors.append(f"{attempt_kind}@{route_distance}: no visible pixel coverage") + if variant == "after" or view["kind"] == "mouth": + break + continue + + row = {**view, "variant": variant, "capture": str(image.relative_to(RESEARCH)), + "scene": str(scene.relative_to(ROOT)), "drawn_triangles": int(drawn.group(1)), + "source_triangles": source_triangles, "verified": True, + "pixel_quality_status": quality_status, + "route_distance_actual_m": route_distance, + "route_station_adjustment_m": route_adjustment, + "closeup_camera_target_distance_m": closeup_distance, + "closeup_target_surface_distance_m": closeup_surface_distance, + "closeup_predicted_target_offset_m": closeup_anchor_offset, + "closeup_wall_normal_alignment": closeup_normal_alignment, + "fallback_kind": attempt_kind if attempt_kind != "requested" else None, + "fallback_surface_distance_m": surface_distance, + "camera_actual_m": actual_camera, "target_actual_m": actual_target, + "logs": [str(headless_log.relative_to(ROOT)), + str(render_log.relative_to(ROOT)), + str(quality_log.relative_to(ROOT))]} + print("[L113Capture] " + json.dumps(row, sort_keys=True), flush=True) + return row + raise RuntimeError(f"{variant}-{view['name']}: no verified image; " + + "; ".join(attempt_errors)) + + +def main() -> int: + before_index = ROOT / "Standalone/Research/WorldAssemblerM3/Linux112/captures/capture-index.json" + required = (*BINARIES.values(), *RENDERERS.values(), *LAYOUTS.values(), + *AUDIT_LOGS.values(), before_index) + if any(not path.is_file() for path in required): + raise SystemExit("missing L112 before captures or L113 capture inputs") + (SAVED / "before").mkdir(parents=True, exist_ok=True) + + before_document = json.loads(before_index.read_text(encoding="utf-8")) + before_rows = [] + before_source = ROOT / "Standalone/Research/WorldAssemblerM3/Linux112" + for source_row in before_document.get("captures", []): + if source_row.get("variant") != "after": + continue + source_image = before_source / source_row["capture"] + target_image = CAPTURES / "before" / Path(source_row["capture"]).name + target_image.parent.mkdir(parents=True, exist_ok=True) + shutil.copy2(source_image, target_image) + source_hash = hashlib.sha256(source_image.read_bytes()).hexdigest() + target_hash = hashlib.sha256(target_image.read_bytes()).hexdigest() + if source_hash != target_hash: + raise RuntimeError(f"L112 before capture copy changed bytes: {source_image}") + quality_log = SAVED / "before" / f"{target_image.stem}-quality.log" + quality = run_process(f"before-{target_image.stem}-quality", [ + "python3", "-B", str(ROOT / "Standalone/Tools/verify/capture_quality.py"), + str(target_image)], quality_log, allow_failure=True) + quality_status = "pass" + if "status=PASS" not in quality: + metrics = QUALITY_METRICS.search(quality) + coverage = float(metrics.group(2)) if metrics else 0.0 + if coverage < 0.001: + raise RuntimeError(f"L112 before capture failed image quality: {source_image}") + quality_status = "low_contrast_geometry_visible" + row = dict(source_row) + row["variant"] = "before" + row["capture"] = str(target_image.relative_to(RESEARCH)) + row["source_capture"] = str(source_image.relative_to(ROOT)) + row["source_sha256"] = source_hash + row["verified"] = True + row["pixel_quality_status"] = quality_status + row["logs"] = [*row.get("logs", []), str(quality_log.relative_to(ROOT))] + before_rows.append(row) + + sections_by_variant = {} + for variant in ("before", "after"): + sections = [] + for passage, section, start, end, samples, midpoint, radius in SECTION.findall( + AUDIT_LOGS[variant].read_text(encoding="utf-8", errors="replace")): + sections.append({"passage": passage, "section": int(section), + "start_m": float(start), "end_m": float(end), + "samples": int(samples), "midpoint": vector(midpoint), + "radius_m": float(radius)}) + if not sections: + raise SystemExit(f"no open-air sections found in the {variant} passage audit") + sections_by_variant[variant] = sections + + layout = json.loads(LAYOUTS["after"].read_text(encoding="utf-8")) + views = make_views(layout, sections_by_variant["after"], use_derived_shape=True, + use_spline=True, include_open_air=True) + expected = 5 * len(layout["passages"]) + 5 * len(sections_by_variant["after"]) + if len(views) != expected: + raise RuntimeError(f"unexpected L113 camera count: {len(views)} != {expected}") + print(f"[L113CapturePlan] passages={len(layout['passages'])} " + f"open_air_sections={len(sections_by_variant['after'])} " + f"after_views={len(views)} before_copies={len(before_rows)}", flush=True) + + all_rows = before_rows + for view in views: + all_rows.append(capture("after", view, layout)) + if not before_rows: + raise RuntimeError("no L112 captures were copied to the L113 before set") + + CAPTURES.mkdir(parents=True, exist_ok=True) + (CAPTURES / "capture-index.json").write_text( + json.dumps({"open_air_sections_by_variant": sections_by_variant, + "captures": all_rows}, indent=2) + "\n", encoding="utf-8") + lines = ["# L113 passage captures", "", + "Before images are byte-identical copies of the verified L112 captures. " + "After images use L113 meshes. Every image has nonzero visible triangles, " + "a passing pixel coverage check, and the 4 m close-ups are surface-snapped.", ""] + for variant in ("before", "after"): + lines.extend([f"## {variant.title()}", ""]) + for row in all_rows: + if row["variant"] != variant: + continue + flag = " **OPEN AIR**" if row["kind"] == "open-air" else "" + quality_note = (f"; {row['pixel_quality_status']}" + if row["pixel_quality_status"] != "pass" else "") + lines.append(f"- [{row['station']}]({variant}/{Path(row['capture']).name}) — " + f"{row['passage']}{flag}; {row['drawn_triangles']} visible triangles" + f"{quality_note}") + lines.append("") + (CAPTURES / "INDEX.md").write_text("\n".join(lines), encoding="utf-8") + failures = [row for row in all_rows if not row["verified"]] + closeups = [row for row in all_rows if row["kind"] == "open-air-close"] + open_air_views = [row for row in all_rows + if row["kind"] == "open-air" and row["station"].endswith("view-1")] + closeups_ok = (len(closeups) == 2 * len(open_air_views) + and all(row["verified"] and abs(row["closeup_camera_target_distance_m"] - 4.0) <= 0.02 + and row["closeup_target_surface_distance_m"] <= 5.0 + and row["closeup_wall_normal_alignment"] >= 0.25 + and row["drawn_triangles"] > 0 + and row["pixel_quality_status"] in + ("pass", "low_contrast_geometry_visible") for row in closeups)) + print(f"[L113CaptureSummary] captures={len(all_rows)} " + f"verified={len(all_rows)-len(failures)} failed={len(failures)} " + f"4m_closeups={len(closeups)} closeups_verified={str(closeups_ok).lower()}", + flush=True) + return 1 if failures or not closeups_ok else 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/RunL113HashMatrix.py b/Standalone/Research/WorldAssemblerM3/Linux113/RunL113HashMatrix.py new file mode 100644 index 0000000..cd255bc --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux113/RunL113HashMatrix.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python3 +"""Check Clang/GCC hash identity at W1/W8/W12 and pin v220 owner hashes.""" +from __future__ import annotations + +import json +import re +import subprocess +import time +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / "Saved/Linux/l113/hashes" +DATASETS = { + "owner4": ROOT / "Standalone/data/owner_world.json", + "owner2": ROOT / "Standalone/data/regression/owner_world_2strate_l61.json", +} +BINARIES = { + "clang": ROOT / "Saved/Linux/l113/bin/VoxelForgeCoreHeadless-l113-clang", + "gcc": ROOT / "Saved/Linux/l113/bin/VoxelForgeCoreHeadless-l113-gcc", +} +HASH = re.compile(r"^\[Pipeline(?:FullDetailHash|WholeViewHash|LODHash|ExactQueryHash)\].*$", re.M) +STAMP = re.compile(r"^\[VoxelForgeSourceStamp\] sha256=(\S+)$", re.M) + + +def run(dataset: str, recipe: str, workers: int, compiler: str) -> dict: + OUT.mkdir(parents=True, exist_ok=True) + label = f"{dataset}-{recipe}-w{workers}-{compiler}" + log = OUT / f"{label}.log" + layout = OUT / f"{label}.layout.json" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1740s", str(BINARIES[compiler]), str(DATASETS[dataset]), + f"--workers={workers}", "--world-assembler-prototype", "--stream-benchmark", + "--stream-pipeline", "--force-generate", "--clip-radius=3", + "--max-clip-level=8", "--max-level=8", f"--recipe={recipe}", + "--stream-hash", f"--resolved-layout-output={layout}", + ] + started = time.monotonic() + with log.open("w", encoding="utf-8") as stream: + result = subprocess.run(command, cwd=ROOT, stdout=stream, + stderr=subprocess.STDOUT, check=False, timeout=1740) + output = log.read_text(encoding="utf-8", errors="replace") + hashes = HASH.findall(output) + if result.returncode or len(hashes) != 12: + raise SystemExit(f"hash run failed or incomplete: {label}; exit={result.returncode} " + f"hashes={len(hashes)} log={log}") + row = {"dataset": dataset, "recipe": recipe, "workers": workers, + "compiler": compiler, "exit_code": result.returncode, + "hashes": hashes, "source_stamp": (STAMP.search(output).group(1) + if STAMP.search(output) else None), + "elapsed_s": round(time.monotonic() - started, 3), + "log": str(log.relative_to(ROOT))} + print("[L113HashRun] " + json.dumps(row, sort_keys=True), flush=True) + return row + + +def main() -> int: + if any(not path.is_file() for path in (*DATASETS.values(), *BINARIES.values())): + raise SystemExit("missing L113 hash input") + rows = [] + recipes = {"owner4": ("surface-world",), + "owner2": ("surface-world", "floating-islands")} + for dataset, dataset_recipes in recipes.items(): + for recipe in dataset_recipes: + for workers in (1, 8, 12): + for compiler in ("clang", "gcc"): + rows.append(run(dataset, recipe, workers, compiler)) + (OUT / "runs-partial.json").write_text( + json.dumps(rows, indent=2) + "\n", encoding="utf-8") + groups = {} + for dataset, dataset_recipes in recipes.items(): + for recipe in dataset_recipes: + key = f"{dataset}/{recipe}" + group = [row for row in rows if row["dataset"] == dataset + and row["recipe"] == recipe] + reference = group[0]["hashes"] + groups[key] = {"all_worker_compiler_hashes_match": all( + row["hashes"] == reference for row in group), + "source_stamps": sorted({row["source_stamp"] for row in group}), + "runs": [{"workers": row["workers"], "compiler": row["compiler"], + "log": row["log"]} for row in group]} + if not groups[key]["all_worker_compiler_hashes_match"]: + raise SystemExit(f"determinism mismatch: {key}") + if dataset == "owner2": + canonical = next(row for row in group if row["workers"] == 12 + and row["compiler"] == "clang") + recipe_name = "floating-islands" if recipe == "floating-islands" else "surface-world" + style = 1 if recipe_name == "surface-world" else 2 + baseline = (ROOT / "Standalone/Tools/verify/baselines/owner-hash/canonical" + / f"owner-hash-{recipe_name}-style{style}-v220.baseline") + baseline.write_text("\n".join(canonical["hashes"]) + "\n", + encoding="utf-8") + summary = {"runs": rows, "groups": groups, + "owner4_all_four_strata": "owner4/surface-world", + "owner2_canonical_pins": ["owner2/surface-world", + "owner2/floating-islands"]} + (OUT / "summary.json").write_text(json.dumps(summary, indent=2) + "\n", + encoding="utf-8") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/RunL113Timing.py b/Standalone/Research/WorldAssemblerM3/Linux113/RunL113Timing.py new file mode 100644 index 0000000..735b8e1 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux113/RunL113Timing.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python3 +"""Five interleaved L80 readiness runs for L109, L112, and L113.""" +from __future__ import annotations + +import json +import re +import statistics +import subprocess +import time +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / "Saved/Linux/l113/timing" +DATA = ROOT / "Standalone/data/owner_world.json" +BINARIES = { + "L109": ROOT / "Saved/Linux/l109/bin-final/VoxelForgeCoreHeadless-l109-clang", + "L112": ROOT / "Saved/Linux/l112/bin-clang/VoxelForgeCoreHeadless-l112-clang", + "L113": ROOT / "Saved/Linux/l113/bin/VoxelForgeCoreHeadless-l113-clang", +} +CAMERAS = { + 0: (8.0, 16.0, -372.2626953125), + 1: (25.8369140625, 3.19921875, -737.0), + 2: (19.166015625, -14.2001953125, -753.3740234375), + 3: (-20.0625, -5.068359375, -900.353515625), +} +PIPELINE = re.compile(r"^\[StreamPipeline\] (.*)$", re.M) +FIELDS = re.compile(r"([a-zA-Z0-9_]+)=([^ ]+)") +NEAR = re.compile( + r"^\[WorldAssemblerNearLODReady\] lods=0-2 tiles=(\d+)/(\d+) cold_ready_s=([0-9.]+)$", + re.M, +) + + +def run(strate: int, workers: int, version: str, phase: str, replicate: int) -> dict: + OUT.mkdir(parents=True, exist_ok=True) + label = f"s{strate}-w{workers}-{version}-{phase}{replicate}" + log = OUT / f"{label}.log" + camera = ",".join(f"{v:.12f}" for v in CAMERAS[strate]) + ",0,0" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1740s", str(BINARIES[version]), str(DATA), + "--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline", + f"--workers={workers}", "--clip-radius=3", "--max-clip-level=8", "--max-level=8", + f"--camera={camera}", "--profile-lod-work", "--stream-scheduler-policy=3", + ] + start = time.monotonic() + with log.open("w", encoding="utf-8") as output: + result = subprocess.run(command, cwd=ROOT, stdout=output, + stderr=subprocess.STDOUT, check=False, timeout=1740) + content = log.read_text(encoding="utf-8", errors="replace") + pipeline_match = PIPELINE.search(content) + near_match = NEAR.search(content) + if result.returncode or pipeline_match is None or near_match is None: + raise SystemExit(f"readiness run failed or trace missing: {log}; exit={result.returncode}") + pipeline = dict(FIELDS.findall(pipeline_match.group(1))) + row = { + "strate": strate, "workers": workers, "version": version, + "phase": phase, "replicate": replicate, "exit_code": result.returncode, + "wall_s": round(time.monotonic() - start, 3), + "lod02_ready_s": float(near_match.group(3)), + "whole_view_ready_s": float(pipeline["whole_view_ready"].removesuffix("s")), + "whole_tiles": int(pipeline["whole_tiles"].split("/")[0]), + "log": str(log.relative_to(ROOT)), + } + print("[L113TimingRun] " + json.dumps(row, sort_keys=True), flush=True) + return row + + +def main() -> int: + if not DATA.is_file() or any(not binary.is_file() for binary in BINARIES.values()): + raise SystemExit("missing L109/L112/L113 data or timing binary") + rows = [] + versions = ("L109", "L112", "L113") + for strate in range(4): + for workers in (8, 12): + for version in versions: + run(strate, workers, version, "warmup", 0) + for replicate in range(1, 6): + offset = (replicate - 1) % len(versions) + order = versions[offset:] + versions[:offset] + for version in order: + rows.append(run(strate, workers, version, "measured", replicate)) + (OUT / "runs-partial.json").write_text( + json.dumps(rows, indent=2) + "\n", encoding="utf-8") + summary = [] + for strate in range(4): + for workers in (8, 12): + item = {"strate": strate, "workers": workers, "replicates": 5} + medians = {} + for version in versions: + group = [row for row in rows if row["strate"] == strate + and row["workers"] == workers and row["version"] == version] + medians[version] = {} + for key in ("lod02_ready_s", "whole_view_ready_s"): + values = [row[key] for row in group] + medians[version][key] = statistics.median(values) + item[f"{version}_{key}_values"] = values + item[f"{version}_{key}_median"] = medians[version][key] + for comparison in ("L109", "L112"): + for key in ("lod02_ready_s", "whole_view_ready_s"): + item[f"L113_vs_{comparison}_{key}_delta_pct"] = round( + 100.0 * (medians["L113"][key] / medians[comparison][key] - 1.0), 2) + summary.append(item) + (OUT / "summary.json").write_text( + json.dumps({"runs": rows, "summary": summary}, indent=2) + "\n", + encoding="utf-8") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/INDEX.md b/Standalone/Research/WorldAssemblerM3/Linux113/captures/INDEX.md new file mode 100644 index 0000000..586c643 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux113/captures/INDEX.md @@ -0,0 +1,109 @@ +# L113 passage captures + +Before images are byte-identical copies of the verified L112 captures. After images use L113 meshes. Every image has nonzero visible triangles, a passing pixel coverage check, and the 4 m close-ups are surface-snapped. + +## Before + +- [upper-mouth](before/passage-0-1-0-upper-mouth.png) — passage/0-1/0; 244874 visible triangles +- [lower-mouth](before/passage-0-1-0-lower-mouth.png) — passage/0-1/0; 551596 visible triangles +- [25%](before/passage-0-1-0-station-25.png) — passage/0-1/0; 135136 visible triangles +- [50%](before/passage-0-1-0-station-50.png) — passage/0-1/0; 316508 visible triangles +- [75%](before/passage-0-1-0-station-75.png) — passage/0-1/0; 257040 visible triangles +- [section-1/view-1](before/passage-0-1-0-openair-1-view-1.png) — passage/0-1/0 **OPEN AIR**; 278629 visible triangles +- [section-1/view-2](before/passage-0-1-0-openair-1-view-2.png) — passage/0-1/0 **OPEN AIR**; 287396 visible triangles +- [section-1/view-3](before/passage-0-1-0-openair-1-view-3.png) — passage/0-1/0 **OPEN AIR**; 311780 visible triangles +- [section-1/4m-outside](before/passage-0-1-0-openair-1-4m-outside.png) — passage/0-1/0; 278629 visible triangles +- [section-1/4m-interior-wall](before/passage-0-1-0-openair-1-4m-interior-wall.png) — passage/0-1/0; 311780 visible triangles +- [section-2/view-1](before/passage-0-1-0-openair-2-view-1.png) — passage/0-1/0 **OPEN AIR**; 278629 visible triangles +- [section-2/view-2](before/passage-0-1-0-openair-2-view-2.png) — passage/0-1/0 **OPEN AIR**; 311780 visible triangles +- [section-2/view-3](before/passage-0-1-0-openair-2-view-3.png) — passage/0-1/0 **OPEN AIR**; 311780 visible triangles +- [section-2/4m-outside](before/passage-0-1-0-openair-2-4m-outside.png) — passage/0-1/0; 278629 visible triangles +- [section-2/4m-interior-wall](before/passage-0-1-0-openair-2-4m-interior-wall.png) — passage/0-1/0; 350192 visible triangles +- [section-3/view-1](before/passage-0-1-0-openair-3-view-1.png) — passage/0-1/0 **OPEN AIR**; 210501 visible triangles +- [section-3/view-2](before/passage-0-1-0-openair-3-view-2.png) — passage/0-1/0 **OPEN AIR**; 189354 visible triangles +- [section-3/view-3](before/passage-0-1-0-openair-3-view-3.png) — passage/0-1/0 **OPEN AIR**; 189354 visible triangles +- [section-3/4m-outside](before/passage-0-1-0-openair-3-4m-outside.png) — passage/0-1/0; 156696 visible triangles +- [section-3/4m-interior-wall](before/passage-0-1-0-openair-3-4m-interior-wall.png) — passage/0-1/0; 156658 visible triangles +- [upper-mouth](before/passage-1-2-0-upper-mouth.png) — passage/1-2/0; 595932 visible triangles +- [lower-mouth](before/passage-1-2-0-lower-mouth.png) — passage/1-2/0; 546268 visible triangles +- [25%](before/passage-1-2-0-station-25.png) — passage/1-2/0; 655074 visible triangles +- [50%](before/passage-1-2-0-station-50.png) — passage/1-2/0; 604662 visible triangles +- [75%](before/passage-1-2-0-station-75.png) — passage/1-2/0; 612135 visible triangles +- [section-1/view-1](before/passage-1-2-0-openair-1-view-1.png) — passage/1-2/0 **OPEN AIR**; 623352 visible triangles +- [section-1/view-2](before/passage-1-2-0-openair-1-view-2.png) — passage/1-2/0 **OPEN AIR**; 576164 visible triangles; low_contrast_geometry_visible +- [section-1/view-3](before/passage-1-2-0-openair-1-view-3.png) — passage/1-2/0 **OPEN AIR**; 570605 visible triangles +- [section-1/4m-outside](before/passage-1-2-0-openair-1-4m-outside.png) — passage/1-2/0; 623352 visible triangles +- [section-1/4m-interior-wall](before/passage-1-2-0-openair-1-4m-interior-wall.png) — passage/1-2/0; 612135 visible triangles +- [section-2/view-1](before/passage-1-2-0-openair-2-view-1.png) — passage/1-2/0 **OPEN AIR**; 628316 visible triangles +- [section-2/view-2](before/passage-1-2-0-openair-2-view-2.png) — passage/1-2/0 **OPEN AIR**; 585440 visible triangles +- [section-2/view-3](before/passage-1-2-0-openair-2-view-3.png) — passage/1-2/0 **OPEN AIR**; 613722 visible triangles +- [section-2/4m-outside](before/passage-1-2-0-openair-2-4m-outside.png) — passage/1-2/0; 585802 visible triangles +- [section-2/4m-interior-wall](before/passage-1-2-0-openair-2-4m-interior-wall.png) — passage/1-2/0; 574472 visible triangles +- [upper-mouth](before/passage-2-3-0-upper-mouth.png) — passage/2-3/0; 59568 visible triangles +- [lower-mouth](before/passage-2-3-0-lower-mouth.png) — passage/2-3/0; 294004 visible triangles; low_contrast_geometry_visible +- [25%](before/passage-2-3-0-station-25.png) — passage/2-3/0; 55514 visible triangles; low_contrast_geometry_visible +- [50%](before/passage-2-3-0-station-50.png) — passage/2-3/0; 458230 visible triangles +- [75%](before/passage-2-3-0-station-75.png) — passage/2-3/0; 475838 visible triangles +- [section-1/view-1](before/passage-2-3-0-openair-1-view-1.png) — passage/2-3/0 **OPEN AIR**; 104612 visible triangles +- [section-1/view-2](before/passage-2-3-0-openair-1-view-2.png) — passage/2-3/0 **OPEN AIR**; 76426 visible triangles +- [section-1/view-3](before/passage-2-3-0-openair-1-view-3.png) — passage/2-3/0 **OPEN AIR**; 94962 visible triangles +- [section-1/4m-outside](before/passage-2-3-0-openair-1-4m-outside.png) — passage/2-3/0; 104612 visible triangles; low_contrast_geometry_visible +- [section-1/4m-interior-wall](before/passage-2-3-0-openair-1-4m-interior-wall.png) — passage/2-3/0; 94962 visible triangles; low_contrast_geometry_visible +- [section-2/view-1](before/passage-2-3-0-openair-2-view-1.png) — passage/2-3/0 **OPEN AIR**; 476214 visible triangles +- [section-2/view-2](before/passage-2-3-0-openair-2-view-2.png) — passage/2-3/0 **OPEN AIR**; 479366 visible triangles +- [section-2/view-3](before/passage-2-3-0-openair-2-view-3.png) — passage/2-3/0 **OPEN AIR**; 479366 visible triangles +- [section-2/4m-outside](before/passage-2-3-0-openair-2-4m-outside.png) — passage/2-3/0; 476214 visible triangles +- [section-2/4m-interior-wall](before/passage-2-3-0-openair-2-4m-interior-wall.png) — passage/2-3/0; 486990 visible triangles + +## After + +- [upper-mouth](after/passage-0-1-0-upper-mouth.png) — passage/0-1/0; 245708 visible triangles +- [lower-mouth](after/passage-0-1-0-lower-mouth.png) — passage/0-1/0; 551698 visible triangles +- [25%](after/passage-0-1-0-station-25.png) — passage/0-1/0; 134404 visible triangles +- [50%](after/passage-0-1-0-station-50.png) — passage/0-1/0; 314118 visible triangles +- [75%](after/passage-0-1-0-station-75.png) — passage/0-1/0; 255252 visible triangles +- [section-1/view-1](after/passage-0-1-0-openair-1-view-1.png) — passage/0-1/0 **OPEN AIR**; 279171 visible triangles +- [section-1/view-2](after/passage-0-1-0-openair-1-view-2.png) — passage/0-1/0 **OPEN AIR**; 287908 visible triangles +- [section-1/view-3](after/passage-0-1-0-openair-1-view-3.png) — passage/0-1/0 **OPEN AIR**; 312014 visible triangles +- [section-1/4m-outside](after/passage-0-1-0-openair-1-4m-outside.png) — passage/0-1/0; 279171 visible triangles +- [section-1/4m-interior-wall](after/passage-0-1-0-openair-1-4m-interior-wall.png) — passage/0-1/0; 312014 visible triangles +- [section-2/view-1](after/passage-0-1-0-openair-2-view-1.png) — passage/0-1/0 **OPEN AIR**; 279171 visible triangles +- [section-2/view-2](after/passage-0-1-0-openair-2-view-2.png) — passage/0-1/0 **OPEN AIR**; 312014 visible triangles +- [section-2/view-3](after/passage-0-1-0-openair-2-view-3.png) — passage/0-1/0 **OPEN AIR**; 312014 visible triangles +- [section-2/4m-outside](after/passage-0-1-0-openair-2-4m-outside.png) — passage/0-1/0; 279171 visible triangles +- [section-2/4m-interior-wall](after/passage-0-1-0-openair-2-4m-interior-wall.png) — passage/0-1/0; 350214 visible triangles +- [section-3/view-1](after/passage-0-1-0-openair-3-view-1.png) — passage/0-1/0 **OPEN AIR**; 207429 visible triangles +- [section-3/view-2](after/passage-0-1-0-openair-3-view-2.png) — passage/0-1/0 **OPEN AIR**; 185112 visible triangles +- [section-3/view-3](after/passage-0-1-0-openair-3-view-3.png) — passage/0-1/0 **OPEN AIR**; 185112 visible triangles +- [section-3/4m-outside](after/passage-0-1-0-openair-3-4m-outside.png) — passage/0-1/0; 153860 visible triangles +- [section-3/4m-interior-wall](after/passage-0-1-0-openair-3-4m-interior-wall.png) — passage/0-1/0; 152882 visible triangles +- [upper-mouth](after/passage-1-2-0-upper-mouth.png) — passage/1-2/0; 595672 visible triangles; low_contrast_geometry_visible +- [lower-mouth](after/passage-1-2-0-lower-mouth.png) — passage/1-2/0; 546142 visible triangles +- [25%](after/passage-1-2-0-station-25.png) — passage/1-2/0; 654984 visible triangles +- [50%](after/passage-1-2-0-station-50.png) — passage/1-2/0; 604712 visible triangles +- [75%](after/passage-1-2-0-station-75.png) — passage/1-2/0; 612097 visible triangles +- [section-1/view-1](after/passage-1-2-0-openair-1-view-1.png) — passage/1-2/0 **OPEN AIR**; 623418 visible triangles +- [section-1/view-2](after/passage-1-2-0-openair-1-view-2.png) — passage/1-2/0 **OPEN AIR**; 575936 visible triangles; low_contrast_geometry_visible +- [section-1/view-3](after/passage-1-2-0-openair-1-view-3.png) — passage/1-2/0 **OPEN AIR**; 570541 visible triangles +- [section-1/4m-outside](after/passage-1-2-0-openair-1-4m-outside.png) — passage/1-2/0; 623418 visible triangles +- [section-1/4m-interior-wall](after/passage-1-2-0-openair-1-4m-interior-wall.png) — passage/1-2/0; 612097 visible triangles +- [section-2/view-1](after/passage-1-2-0-openair-2-view-1.png) — passage/1-2/0 **OPEN AIR**; 628096 visible triangles +- [section-2/view-2](after/passage-1-2-0-openair-2-view-2.png) — passage/1-2/0 **OPEN AIR**; 585354 visible triangles +- [section-2/view-3](after/passage-1-2-0-openair-2-view-3.png) — passage/1-2/0 **OPEN AIR**; 613434 visible triangles +- [section-2/4m-outside](after/passage-1-2-0-openair-2-4m-outside.png) — passage/1-2/0; 585844 visible triangles +- [section-2/4m-interior-wall](after/passage-1-2-0-openair-2-4m-interior-wall.png) — passage/1-2/0; 574404 visible triangles +- [upper-mouth](after/passage-2-3-0-upper-mouth.png) — passage/2-3/0; 59570 visible triangles +- [lower-mouth](after/passage-2-3-0-lower-mouth.png) — passage/2-3/0; 293916 visible triangles; low_contrast_geometry_visible +- [25%](after/passage-2-3-0-station-25.png) — passage/2-3/0; 55516 visible triangles; low_contrast_geometry_visible +- [50%](after/passage-2-3-0-station-50.png) — passage/2-3/0; 457922 visible triangles +- [75%](after/passage-2-3-0-station-75.png) — passage/2-3/0; 475608 visible triangles +- [section-1/view-1](after/passage-2-3-0-openair-1-view-1.png) — passage/2-3/0 **OPEN AIR**; 104612 visible triangles +- [section-1/view-2](after/passage-2-3-0-openair-1-view-2.png) — passage/2-3/0 **OPEN AIR**; 76426 visible triangles +- [section-1/view-3](after/passage-2-3-0-openair-1-view-3.png) — passage/2-3/0 **OPEN AIR**; 94962 visible triangles +- [section-1/4m-outside](after/passage-2-3-0-openair-1-4m-outside.png) — passage/2-3/0; 104612 visible triangles; low_contrast_geometry_visible +- [section-1/4m-interior-wall](after/passage-2-3-0-openair-1-4m-interior-wall.png) — passage/2-3/0; 94962 visible triangles; low_contrast_geometry_visible +- [section-2/view-1](after/passage-2-3-0-openair-2-view-1.png) — passage/2-3/0 **OPEN AIR**; 475906 visible triangles +- [section-2/view-2](after/passage-2-3-0-openair-2-view-2.png) — passage/2-3/0 **OPEN AIR**; 479214 visible triangles +- [section-2/view-3](after/passage-2-3-0-openair-2-view-3.png) — passage/2-3/0 **OPEN AIR**; 479214 visible triangles +- [section-2/4m-outside](after/passage-2-3-0-openair-2-4m-outside.png) — passage/2-3/0; 475906 visible triangles +- [section-2/4m-interior-wall](after/passage-2-3-0-openair-2-4m-interior-wall.png) — passage/2-3/0; 486760 visible triangles diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-lower-mouth.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-lower-mouth.png new file mode 100644 index 0000000..b92d456 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-lower-mouth.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-1-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-1-4m-interior-wall.png new file mode 100644 index 0000000..d3dd865 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-1-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-1-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-1-4m-outside.png new file mode 100644 index 0000000..6063485 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-1-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-1-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-1-view-1.png new file mode 100644 index 0000000..ebc06e2 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-1-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-1-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-1-view-2.png new file mode 100644 index 0000000..03c8f4c Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-1-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-1-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-1-view-3.png new file mode 100644 index 0000000..cb3041d Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-1-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-2-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-2-4m-interior-wall.png new file mode 100644 index 0000000..6b059f0 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-2-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-2-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-2-4m-outside.png new file mode 100644 index 0000000..fa1c550 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-2-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-2-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-2-view-1.png new file mode 100644 index 0000000..0cefe5d Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-2-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-2-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-2-view-2.png new file mode 100644 index 0000000..39e0e17 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-2-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-2-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-2-view-3.png new file mode 100644 index 0000000..85497d2 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-2-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-3-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-3-4m-interior-wall.png new file mode 100644 index 0000000..8ce668f Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-3-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-3-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-3-4m-outside.png new file mode 100644 index 0000000..94fa718 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-3-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-3-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-3-view-1.png new file mode 100644 index 0000000..c620f79 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-3-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-3-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-3-view-2.png new file mode 100644 index 0000000..cafe41f Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-3-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-3-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-3-view-3.png new file mode 100644 index 0000000..84d143a Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-3-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-station-25.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-station-25.png new file mode 100644 index 0000000..2644889 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-station-25.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-station-50.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-station-50.png new file mode 100644 index 0000000..acab4a8 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-station-50.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-station-75.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-station-75.png new file mode 100644 index 0000000..62b7f2c Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-station-75.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-upper-mouth.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-upper-mouth.png new file mode 100644 index 0000000..f90d319 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-upper-mouth.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-lower-mouth.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-lower-mouth.png new file mode 100644 index 0000000..1b7d858 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-lower-mouth.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-openair-1-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-openair-1-4m-interior-wall.png new file mode 100644 index 0000000..b6af8b7 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-openair-1-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-openair-1-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-openair-1-4m-outside.png new file mode 100644 index 0000000..b43f9a8 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-openair-1-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-openair-1-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-openair-1-view-1.png new file mode 100644 index 0000000..5bc0a43 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-openair-1-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-openair-1-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-openair-1-view-2.png new file mode 100644 index 0000000..fd9adfd Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-openair-1-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-openair-1-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-openair-1-view-3.png new file mode 100644 index 0000000..f6561bc Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-openair-1-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-openair-2-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-openair-2-4m-interior-wall.png new file mode 100644 index 0000000..e78b529 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-openair-2-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-openair-2-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-openair-2-4m-outside.png new file mode 100644 index 0000000..2b0f1b4 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-openair-2-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-openair-2-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-openair-2-view-1.png new file mode 100644 index 0000000..5ebd8cf Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-openair-2-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-openair-2-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-openair-2-view-2.png new file mode 100644 index 0000000..9404bde Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-openair-2-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-openair-2-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-openair-2-view-3.png new file mode 100644 index 0000000..bf98407 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-openair-2-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-station-25.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-station-25.png new file mode 100644 index 0000000..6f16ad3 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-station-25.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-station-50.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-station-50.png new file mode 100644 index 0000000..27c7676 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-station-50.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-station-75.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-station-75.png new file mode 100644 index 0000000..0b298b1 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-station-75.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-upper-mouth.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-upper-mouth.png new file mode 100644 index 0000000..c630f13 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-upper-mouth.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-lower-mouth.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-lower-mouth.png new file mode 100644 index 0000000..85f9c8d Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-lower-mouth.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-openair-1-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-openair-1-4m-interior-wall.png new file mode 100644 index 0000000..df09682 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-openair-1-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-openair-1-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-openair-1-4m-outside.png new file mode 100644 index 0000000..64c312b Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-openair-1-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-openair-1-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-openair-1-view-1.png new file mode 100644 index 0000000..0a51c50 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-openair-1-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-openair-1-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-openair-1-view-2.png new file mode 100644 index 0000000..6420b2b Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-openair-1-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-openair-1-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-openair-1-view-3.png new file mode 100644 index 0000000..288d9b9 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-openair-1-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-openair-2-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-openair-2-4m-interior-wall.png new file mode 100644 index 0000000..6796fba Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-openair-2-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-openair-2-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-openair-2-4m-outside.png new file mode 100644 index 0000000..90432a5 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-openair-2-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-openair-2-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-openair-2-view-1.png new file mode 100644 index 0000000..2542602 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-openair-2-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-openair-2-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-openair-2-view-2.png new file mode 100644 index 0000000..c14813a Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-openair-2-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-openair-2-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-openair-2-view-3.png new file mode 100644 index 0000000..fc56edb Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-openair-2-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-station-25.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-station-25.png new file mode 100644 index 0000000..794aeb3 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-station-25.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-station-50.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-station-50.png new file mode 100644 index 0000000..581b53b Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-station-50.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-station-75.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-station-75.png new file mode 100644 index 0000000..144c5ce Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-station-75.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-upper-mouth.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-upper-mouth.png new file mode 100644 index 0000000..2c79742 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-upper-mouth.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-lower-mouth.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-lower-mouth.png new file mode 100644 index 0000000..eccd3c0 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-lower-mouth.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-1-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-1-4m-interior-wall.png new file mode 100644 index 0000000..e10071a Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-1-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-1-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-1-4m-outside.png new file mode 100644 index 0000000..a25faeb Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-1-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-1-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-1-view-1.png new file mode 100644 index 0000000..b2f9837 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-1-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-1-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-1-view-2.png new file mode 100644 index 0000000..3b394f1 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-1-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-1-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-1-view-3.png new file mode 100644 index 0000000..7bc7c9f Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-1-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-2-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-2-4m-interior-wall.png new file mode 100644 index 0000000..e7ac719 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-2-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-2-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-2-4m-outside.png new file mode 100644 index 0000000..58e65cb Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-2-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-2-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-2-view-1.png new file mode 100644 index 0000000..87476c9 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-2-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-2-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-2-view-2.png new file mode 100644 index 0000000..c904473 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-2-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-2-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-2-view-3.png new file mode 100644 index 0000000..8e8a59f Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-2-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-3-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-3-4m-interior-wall.png new file mode 100644 index 0000000..b370fe5 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-3-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-3-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-3-4m-outside.png new file mode 100644 index 0000000..eea6716 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-3-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-3-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-3-view-1.png new file mode 100644 index 0000000..20f5ecd Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-3-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-3-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-3-view-2.png new file mode 100644 index 0000000..2dc7280 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-3-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-3-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-3-view-3.png new file mode 100644 index 0000000..6d222d2 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-openair-3-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-station-25.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-station-25.png new file mode 100644 index 0000000..6d5b759 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-station-25.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-station-50.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-station-50.png new file mode 100644 index 0000000..44c7050 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-station-50.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-station-75.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-station-75.png new file mode 100644 index 0000000..72f1e02 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-station-75.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-upper-mouth.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-upper-mouth.png new file mode 100644 index 0000000..4a21f52 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-0-1-0-upper-mouth.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-lower-mouth.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-lower-mouth.png new file mode 100644 index 0000000..2ab98a0 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-lower-mouth.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-openair-1-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-openair-1-4m-interior-wall.png new file mode 100644 index 0000000..2e156af Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-openair-1-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-openair-1-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-openair-1-4m-outside.png new file mode 100644 index 0000000..b4da33f Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-openair-1-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-openair-1-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-openair-1-view-1.png new file mode 100644 index 0000000..8d8bbd7 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-openair-1-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-openair-1-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-openair-1-view-2.png new file mode 100644 index 0000000..9dafe3d Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-openair-1-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-openair-1-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-openair-1-view-3.png new file mode 100644 index 0000000..43909f5 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-openair-1-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-openair-2-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-openair-2-4m-interior-wall.png new file mode 100644 index 0000000..9d1043a Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-openair-2-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-openair-2-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-openair-2-4m-outside.png new file mode 100644 index 0000000..e89577e Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-openair-2-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-openair-2-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-openair-2-view-1.png new file mode 100644 index 0000000..8fc4c66 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-openair-2-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-openair-2-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-openair-2-view-2.png new file mode 100644 index 0000000..226da7d Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-openair-2-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-openair-2-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-openair-2-view-3.png new file mode 100644 index 0000000..f171a9b Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-openair-2-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-station-25.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-station-25.png new file mode 100644 index 0000000..aeeed93 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-station-25.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-station-50.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-station-50.png new file mode 100644 index 0000000..6422188 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-station-50.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-station-75.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-station-75.png new file mode 100644 index 0000000..5b2f35c Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-station-75.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-upper-mouth.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-upper-mouth.png new file mode 100644 index 0000000..a0c4f1a Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-1-2-0-upper-mouth.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-lower-mouth.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-lower-mouth.png new file mode 100644 index 0000000..70a3431 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-lower-mouth.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-openair-1-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-openair-1-4m-interior-wall.png new file mode 100644 index 0000000..0829ac3 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-openair-1-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-openair-1-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-openair-1-4m-outside.png new file mode 100644 index 0000000..23440bc Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-openair-1-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-openair-1-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-openair-1-view-1.png new file mode 100644 index 0000000..96e6e48 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-openair-1-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-openair-1-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-openair-1-view-2.png new file mode 100644 index 0000000..5b6337f Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-openair-1-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-openair-1-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-openair-1-view-3.png new file mode 100644 index 0000000..1f19638 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-openair-1-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-openair-2-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-openair-2-4m-interior-wall.png new file mode 100644 index 0000000..e54a164 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-openair-2-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-openair-2-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-openair-2-4m-outside.png new file mode 100644 index 0000000..69e235d Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-openair-2-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-openair-2-view-1.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-openair-2-view-1.png new file mode 100644 index 0000000..b06dba2 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-openair-2-view-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-openair-2-view-2.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-openair-2-view-2.png new file mode 100644 index 0000000..6ddebea Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-openair-2-view-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-openair-2-view-3.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-openair-2-view-3.png new file mode 100644 index 0000000..c76a392 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-openair-2-view-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-station-25.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-station-25.png new file mode 100644 index 0000000..794aeb3 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-station-25.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-station-50.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-station-50.png new file mode 100644 index 0000000..897b55b Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-station-50.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-station-75.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-station-75.png new file mode 100644 index 0000000..bbf4e47 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-station-75.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-upper-mouth.png b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-upper-mouth.png new file mode 100644 index 0000000..50b6f6e Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux113/captures/before/passage-2-3-0-upper-mouth.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux113/captures/capture-index.json b/Standalone/Research/WorldAssemblerM3/Linux113/captures/capture-index.json new file mode 100644 index 0000000..1b1ca9b --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux113/captures/capture-index.json @@ -0,0 +1,6272 @@ +{ + "open_air_sections_by_variant": { + "before": [ + { + "passage": "passage/0-1/0", + "section": 1, + "start_m": 6.905, + "end_m": 9.618, + "samples": 12, + "midpoint": [ + 7.282, + 7.839, + -373.185 + ], + "radius_m": 1.93 + }, + { + "passage": "passage/0-1/0", + "section": 2, + "start_m": 13.078, + "end_m": 15.794, + "samples": 12, + "midpoint": [ + 6.611, + 1.753, + -374.166 + ], + "radius_m": 2.253 + }, + { + "passage": "passage/0-1/0", + "section": 3, + "start_m": 1041.174, + "end_m": 1489.448, + "samples": 1979, + "midpoint": [ + -22.039, + -12.355, + -599.25 + ], + "radius_m": 3.5 + }, + { + "passage": "passage/1-2/0", + "section": 1, + "start_m": 81.367, + "end_m": 85.596, + "samples": 19, + "midpoint": [ + -9.52, + -9.729, + -745.879 + ], + "radius_m": 3.0 + }, + { + "passage": "passage/1-2/0", + "section": 2, + "start_m": 104.041, + "end_m": 104.778, + "samples": 4, + "midpoint": [ + 9.488, + -11.155, + -749.755 + ], + "radius_m": 3.139 + }, + { + "passage": "passage/2-3/0", + "section": 1, + "start_m": 7.733, + "end_m": 25.281, + "samples": 74, + "midpoint": [ + -7.267, + -11.478, + -813.609 + ], + "radius_m": 3.0 + }, + { + "passage": "passage/2-3/0", + "section": 2, + "start_m": 372.675, + "end_m": 377.341, + "samples": 21, + "midpoint": [ + -9.548, + 9.557, + -877.478 + ], + "radius_m": 3.0 + } + ], + "after": [ + { + "passage": "passage/0-1/0", + "section": 1, + "start_m": 6.994, + "end_m": 9.715, + "samples": 13, + "midpoint": [ + 7.272, + 7.748, + -373.197 + ], + "radius_m": 1.935 + }, + { + "passage": "passage/0-1/0", + "section": 2, + "start_m": 13.106, + "end_m": 15.879, + "samples": 13, + "midpoint": [ + 6.603, + 1.698, + -374.149 + ], + "radius_m": 2.256 + }, + { + "passage": "passage/0-1/0", + "section": 3, + "start_m": 1041.112, + "end_m": 1489.573, + "samples": 1945, + "midpoint": [ + -22.1, + -12.258, + -599.244 + ], + "radius_m": 3.5 + }, + { + "passage": "passage/1-2/0", + "section": 1, + "start_m": 81.397, + "end_m": 85.611, + "samples": 19, + "midpoint": [ + -9.518, + -9.731, + -745.88 + ], + "radius_m": 3.0 + }, + { + "passage": "passage/1-2/0", + "section": 2, + "start_m": 103.901, + "end_m": 104.823, + "samples": 5, + "midpoint": [ + 9.43, + -11.181, + -749.743 + ], + "radius_m": 3.136 + }, + { + "passage": "passage/2-3/0", + "section": 1, + "start_m": 7.72, + "end_m": 25.513, + "samples": 75, + "midpoint": [ + -7.178, + -11.528, + -813.627 + ], + "radius_m": 3.0 + }, + { + "passage": "passage/2-3/0", + "section": 2, + "start_m": 372.601, + "end_m": 377.257, + "samples": 21, + "midpoint": [ + -9.548, + 9.556, + -877.478 + ], + "radius_m": 3.0 + } + ] + }, + "captures": [ + { + "name": "passage-0-1-0-upper-mouth", + "passage": "passage/0-1/0", + "kind": "mouth", + "station": "upper-mouth", + "camera": [ + 8.335073547378155, + 20.44994601927027, + -371.842578125 + ], + "target": [ + 7.851078423387487, + 14.022246213657658, + -371.942578125 + ], + "yaw": -175.69384905314672, + "pitch": -0.8888009211775196, + "focus": [ + 8.0, + 16.0, + -372.1224609375 + ], + "center_z": -372.1224609375, + "variant": "before", + "capture": "captures/before/passage-0-1-0-upper-mouth.png", + "scene": "Saved/Linux/l112/captures/after/passage-0-1-0-upper-mouth.vfmesh", + "drawn_triangles": 244874, + "source_triangles": 300692, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": null, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 8.335073547378155, + 20.44994601927027, + -371.842578125 + ], + "target_actual_m": [ + 7.851078423387487, + 14.022246213657658, + -371.942578125 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-0-1-0-upper-mouth-mesh.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-upper-mouth-render.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-upper-mouth-quality.log", + "Saved/Linux/l113/captures/before/passage-0-1-0-upper-mouth-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-upper-mouth.png", + "source_sha256": "d4c5e82a66ed3bd9270f599d368f18062b16f514e775303d714e2ff51b4481e1" + }, + { + "name": "passage-0-1-0-lower-mouth", + "passage": "passage/0-1/0", + "kind": "mouth", + "station": "lower-mouth", + "camera": [ + 32.6815683216108, + 9.56067063407582, + -735.4811957974861 + ], + "target": [ + 24.395934218476675, + 1.8599657217735117, + -736.6798828125 + ], + "yaw": -132.9045214795435, + "pitch": -6.049035133760526, + "focus": [ + 25.8369140625, + 3.19921875, + -736.2942543532574 + ], + "center_z": -736.2942543532574, + "variant": "before", + "capture": "captures/before/passage-0-1-0-lower-mouth.png", + "scene": "Saved/Linux/l112/captures/after/passage-0-1-0-lower-mouth.vfmesh", + "drawn_triangles": 551596, + "source_triangles": 601134, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": null, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 32.6815683216108, + 9.56067063407582, + -735.4811957974861 + ], + "target_actual_m": [ + 24.395934218476675, + 1.8599657217735117, + -736.6798828125 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-0-1-0-lower-mouth-mesh.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-lower-mouth-render.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-lower-mouth-quality.log", + "Saved/Linux/l113/captures/before/passage-0-1-0-lower-mouth-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-lower-mouth.png", + "source_sha256": "5e2fb43a735cb326fb2c90120655710d9933b34baec96a59c7988150f4686a4b" + }, + { + "name": "passage-0-1-0-station-25", + "passage": "passage/0-1/0", + "kind": "station", + "station": "25%", + "camera": [ + -14.773420908313007, + -19.15622259434896, + -462.9505434032349 + ], + "target": [ + -22.332571996402073, + -8.365303107352405, + -465.2710323468326 + ], + "yaw": -35.01164133311156, + "pitch": -9.988838244260211, + "focus": [ + -14.252149448584996, + -18.61698603654429, + -462.71491494399237 + ], + "center_z": -462.71491494399237, + "route_distance_m": 506.6753072603284, + "route_length_m": 2026.7012290413136, + "requested_route_distance_m": 506.6753072603284, + "variant": "before", + "capture": "captures/before/passage-0-1-0-station-25.png", + "scene": "Saved/Linux/l112/captures/after/passage-0-1-0-station-25.vfmesh", + "drawn_triangles": 135136, + "source_triangles": 181364, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 506.6753072603284, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -14.773420908313007, + -19.15622259434896, + -462.9505434032349 + ], + "target_actual_m": [ + -22.332571996402073, + -8.365303107352405, + -465.2710323468326 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-0-1-0-station-25-mesh.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-station-25-render.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-station-25-quality.log", + "Saved/Linux/l113/captures/before/passage-0-1-0-station-25-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-station-25.png", + "source_sha256": "e030eee4969551f1f4232cfbe907285bf8a14521ece09a414dd0be443f206787" + }, + { + "name": "passage-0-1-0-station-50", + "passage": "passage/0-1/0", + "kind": "station", + "station": "50%", + "camera": [ + -5.87968914032497, + 21.857993246713395, + -554.13630134032 + ], + "target": [ + 7.315979337237899, + 21.580426280018035, + -556.4572725224375 + ], + "yaw": 91.20502199933122, + "pitch": -9.973491174456086, + "focus": [ + -5.762536970286937, + 21.11719950412685, + -553.9006728810774 + ], + "center_z": -553.9006728810774, + "route_distance_m": 1013.3506145206568, + "route_length_m": 2026.7012290413136, + "requested_route_distance_m": 1013.3506145206568, + "variant": "before", + "capture": "captures/before/passage-0-1-0-station-50.png", + "scene": "Saved/Linux/l112/captures/after/passage-0-1-0-station-50.vfmesh", + "drawn_triangles": 316508, + "source_triangles": 404356, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1013.3506145206568, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -5.87968914032497, + 21.857993246713395, + -554.13630134032 + ], + "target_actual_m": [ + 7.315979337237899, + 21.580426280018035, + -556.4572725224375 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-0-1-0-station-50-mesh.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-station-50-render.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-station-50-quality.log", + "Saved/Linux/l113/captures/before/passage-0-1-0-station-50-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-station-50.png", + "source_sha256": "a63888def06ae489f9e0d2224ce307640a34718ba1f37592acfe402afd014ab7" + }, + { + "name": "passage-0-1-0-station-75", + "passage": "passage/0-1/0", + "kind": "station", + "station": "75%", + "camera": [ + 16.79632298277704, + -13.630908634595473, + -645.3200745693888 + ], + "target": [ + 6.584565856030696, + -21.9376366230758, + -647.640607952583 + ], + "yaw": -129.12654304255443, + "pitch": -9.997579084277536, + "focus": [ + 16.22588361858051, + -13.143980578538871, + -645.0844461101462 + ], + "center_z": -645.0844461101462, + "route_distance_m": 1520.0259217809853, + "route_length_m": 2026.7012290413136, + "requested_route_distance_m": 1520.0259217809853, + "variant": "before", + "capture": "captures/before/passage-0-1-0-station-75.png", + "scene": "Saved/Linux/l112/captures/after/passage-0-1-0-station-75.vfmesh", + "drawn_triangles": 257040, + "source_triangles": 329218, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1520.0259217809853, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 16.79632298277704, + -13.630908634595473, + -645.3200745693888 + ], + "target_actual_m": [ + 6.584565856030696, + -21.9376366230758, + -647.640607952583 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-0-1-0-station-75-mesh.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-station-75-render.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-station-75-quality.log", + "Saved/Linux/l113/captures/before/passage-0-1-0-station-75-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-station-75.png", + "source_sha256": "fd26c9baf02f4f4bc886a416a49d0857a5e19da8787fa470816dfc5ce324a601" + }, + { + "name": "passage-0-1-0-openair-1-view-1", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-1/view-1", + "camera": [ + 14.177038985763101, + 7.143775299052934, + -371.985 + ], + "target": [ + 7.282, + 7.839, + -373.085 + ], + "yaw": -84.24234320176159, + "pitch": -9.01932243138141, + "focus": [ + 7.282, + 7.839, + -373.185 + ], + "center_z": -373.185, + "open_air_section": 1, + "route_distance_m": 8.2615, + "requested_route_distance_m": 8.2615, + "route_length_m": 2026.7012290413136, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-1-view-1.png", + "scene": "Saved/Linux/l112/captures/after/passage-0-1-0-openair-1-view-1.vfmesh", + "drawn_triangles": 278629, + "source_triangles": 346431, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 8.2615, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 14.177038985763101, + 7.143775299052934, + -371.985 + ], + "target_actual_m": [ + 7.282, + 7.839, + -373.085 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-1-view-1-mesh.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-1-view-1-render.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-1-view-1-quality.log", + "Saved/Linux/l113/captures/before/passage-0-1-0-openair-1-view-1-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-1-view-1.png", + "source_sha256": "684e259880454311fd8d91fa06256097cabc96c7d330e35f20b069349f66c6ef" + }, + { + "name": "passage-0-1-0-openair-1-view-2", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-1/view-2", + "camera": [ + 1.8793936951380026, + 8.383743163945537, + -369.185 + ], + "target": [ + 7.083023812394741, + 5.865611297170759, + -373.44218768304876 + ], + "yaw": 115.82318961848594, + "pitch": -36.368805894026266, + "focus": [ + 7.282, + 7.839, + -373.185 + ], + "center_z": -373.185, + "open_air_section": 1, + "route_distance_m": 8.2615, + "requested_route_distance_m": 8.2615, + "route_length_m": 2026.7012290413136, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-1-view-2.png", + "scene": "Saved/Linux/l112/captures/after/passage-0-1-0-openair-1-view-2.vfmesh", + "drawn_triangles": 287396, + "source_triangles": 358400, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 8.2615, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 1.8793936951380026, + 8.383743163945537, + -369.185 + ], + "target_actual_m": [ + 7.083023812394741, + 5.865611297170759, + -373.44218768304876 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-1-view-2-mesh.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-1-view-2-render.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-1-view-2-quality.log", + "Saved/Linux/l113/captures/before/passage-0-1-0-openair-1-view-2-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-1-view-2.png", + "source_sha256": "20517ba18981701304f2beeef4847510fb0a02d1c2d5321b31819ea969fbac0f" + }, + { + "name": "passage-0-1-0-openair-1-view-3", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-1/view-3", + "camera": [ + 7.282, + 7.839, + -373.635 + ], + "target": [ + 6.585583343381591, + 0.9321395400976531, + -374.5351568906707 + ], + "yaw": -174.2423432017616, + "pitch": -7.388343353280002, + "focus": [ + 7.282, + 7.839, + -373.185 + ], + "center_z": -373.185, + "open_air_section": 1, + "route_distance_m": 8.2615, + "requested_route_distance_m": 8.2615, + "route_length_m": 2026.7012290413136, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-1-view-3.png", + "scene": "Saved/Linux/l112/captures/after/passage-0-1-0-openair-1-view-3.vfmesh", + "drawn_triangles": 311780, + "source_triangles": 392506, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 8.2615, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 7.282, + 7.839, + -373.635 + ], + "target_actual_m": [ + 6.585583343381591, + 0.9321395400976531, + -374.5351568906707 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-1-view-3-mesh.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-1-view-3-render.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-1-view-3-quality.log", + "Saved/Linux/l113/captures/before/passage-0-1-0-openair-1-view-3-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-1-view-3.png", + "source_sha256": "9a8d8894ba248e15366494e998a85e1d7ed60cafb07719c6efe424149c7fc21e" + }, + { + "name": "passage-0-1-0-openair-1-4m-outside", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-1/4m-outside", + "camera": [ + 13.182083865162365, + 7.244096323720621, + -374.385 + ], + "target": [ + 9.202263382759421, + 7.645380422391366, + -374.385 + ], + "yaw": -84.24234320176159, + "pitch": 0.0, + "focus": [ + 7.282, + 7.839, + -373.185 + ], + "center_z": -373.185, + "open_air_section": 1, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.9949551206007362, + -0.10032102466768629, + 0.0 + ], + "camera_target_distance_m": 3.9999999999999996, + "route_distance_m": 8.2615, + "requested_route_distance_m": 8.2615, + "route_length_m": 2026.7012290413136, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-1-4m-outside.png", + "scene": "Saved/Linux/l112/captures/after/passage-0-1-0-openair-1-4m-outside.vfmesh", + "drawn_triangles": 278629, + "source_triangles": 346431, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 8.2615, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.9999999999999996, + "closeup_target_surface_distance_m": 0.7515085626476259, + "closeup_predicted_target_offset_m": 0.7515085626476259, + "closeup_wall_normal_alignment": 0.9914561643267705, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 13.001904038143014, + 8.028532071234862, + -374.0476239046015 + ], + "target_actual_m": [ + 9.013093948364258, + 8.0, + -373.75 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-1-4m-outside-mesh.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-1-4m-outside-render.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-1-4m-outside-quality.log", + "Saved/Linux/l113/captures/before/passage-0-1-0-openair-1-4m-outside-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-1-4m-outside.png", + "source_sha256": "71d1cda2f55cf259f1174e9dde2d7edfbb2a40bc03a2676c6169239f30b65a8c" + }, + { + "name": "passage-0-1-0-openair-1-4m-interior-wall", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-1/4m-interior-wall", + "camera": [ + 7.405691935288184, + 3.966226119787983, + -374.8830418066488 + ], + "target": [ + 8.785962786332426, + 7.687355885946053, + -374.385 + ], + "yaw": 20.351222510561445, + "pitch": 7.1524858702584835, + "focus": [ + 7.282, + 7.839, + -373.185 + ], + "center_z": -373.185, + "open_air_section": 1, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.9949551206007362, + 0.10032102466768629, + -0.0 + ], + "camera_target_distance_m": 4.000000000000003, + "route_distance_m": 8.2615, + "requested_route_distance_m": 8.2615, + "route_length_m": 2026.7012290413136, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-1-4m-interior-wall.png", + "scene": "Saved/Linux/l112/captures/after/passage-0-1-0-openair-1-4m-interior-wall.vfmesh", + "drawn_triangles": 311780, + "source_triangles": 392506, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 8.2615, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.9999999999999987, + "closeup_target_surface_distance_m": 0.743343733960606, + "closeup_predicted_target_offset_m": 0.743343733960606, + "closeup_wall_normal_alignment": 0.9914561643267705, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 5.024283858585503, + 7.971467928765139, + -373.4523760953985 + ], + "target_actual_m": [ + 9.013093948364258, + 8.0, + -373.75 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-1-4m-interior-wall-mesh.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-1-4m-interior-wall-render.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-1-4m-interior-wall-quality.log", + "Saved/Linux/l113/captures/before/passage-0-1-0-openair-1-4m-interior-wall-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-1-4m-interior-wall.png", + "source_sha256": "b264bc37e74fe4b2af36cfcd10bdba02b077f200eea1a3b2b7d31dd67b9836fa" + }, + { + "name": "passage-0-1-0-openair-2-view-1", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-2/view-1", + "camera": [ + 13.81216559375693, + 0.8874232608882145, + -372.966 + ], + "target": [ + 6.611, + 1.753, + -374.066 + ], + "yaw": -83.14595676247222, + "pitch": -8.623838343279465, + "focus": [ + 6.611, + 1.753, + -374.166 + ], + "center_z": -374.166, + "open_air_section": 2, + "route_distance_m": 14.436, + "requested_route_distance_m": 14.436, + "route_length_m": 2026.7012290413136, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-2-view-1.png", + "scene": "Saved/Linux/l112/captures/after/passage-0-1-0-openair-2-view-1.vfmesh", + "drawn_triangles": 278629, + "source_triangles": 346431, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 14.436, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 13.81216559375693, + 0.8874232608882145, + -372.966 + ], + "target_actual_m": [ + 6.611, + 1.753, + -374.066 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-2-view-1-mesh.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-2-view-1-render.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-2-view-1-quality.log", + "Saved/Linux/l113/captures/before/passage-0-1-0-openair-2-view-1-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-2-view-1.png", + "source_sha256": "2cc7a56fe1be43d69a51bef9a36c8d297856a5b49f2323dd32d7c065f4107968" + }, + { + "name": "passage-0-1-0-openair-2-view-2", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-2/view-2", + "camera": [ + 0.8991144821613641, + 2.4395659699586516, + -370.166 + ], + "target": [ + 6.3761872034956015, + -0.2005250368401441, + -374.52461243848546 + ], + "yaw": 115.73527173937683, + "pitch": -35.63513396653433, + "focus": [ + 6.611, + 1.753, + -374.166 + ], + "center_z": -374.166, + "open_air_section": 2, + "route_distance_m": 14.436, + "requested_route_distance_m": 14.436, + "route_length_m": 2026.7012290413136, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-2-view-2.png", + "scene": "Saved/Linux/l112/captures/after/passage-0-1-0-openair-2-view-2.vfmesh", + "drawn_triangles": 311780, + "source_triangles": 392506, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 14.436, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 0.8991144821613641, + 2.4395659699586516, + -370.166 + ], + "target_actual_m": [ + 6.3761872034956015, + -0.2005250368401441, + -374.52461243848546 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-2-view-2-mesh.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-2-view-2-render.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-2-view-2-quality.log", + "Saved/Linux/l113/captures/before/passage-0-1-0-openair-2-view-2-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-2-view-2.png", + "source_sha256": "ef628add5c8cd85ba1c37da875220be83a18d05e73996dfcbf98aff5dd834585" + }, + { + "name": "passage-0-1-0-openair-2-view-3", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-2/view-3", + "camera": [ + 6.611, + 1.753, + -374.75162845924257 + ], + "target": [ + 5.789155212234605, + -5.084337628940504, + -376.00677199394175 + ], + "yaw": -173.14595676247222, + "pitch": -10.329351655646626, + "focus": [ + 6.611, + 1.753, + -374.166 + ], + "center_z": -374.166, + "open_air_section": 2, + "route_distance_m": 14.436, + "requested_route_distance_m": 14.436, + "route_length_m": 2026.7012290413136, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-2-view-3.png", + "scene": "Saved/Linux/l112/captures/after/passage-0-1-0-openair-2-view-3.vfmesh", + "drawn_triangles": 311780, + "source_triangles": 392506, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 14.436, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 6.611, + 1.753, + -374.75162845924257 + ], + "target_actual_m": [ + 5.789155212234605, + -5.084337628940504, + -376.00677199394175 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-2-view-3-mesh.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-2-view-3-render.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-2-view-3-quality.log", + "Saved/Linux/l113/captures/before/passage-0-1-0-openair-2-view-3-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-2-view-3.png", + "source_sha256": "ab61f0be9db7e90b8d55032dc5ff2fe0162d6ce76bef28237d4350869ae9a11d" + }, + { + "name": "passage-0-1-0-openair-2-4m-outside", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-2/4m-outside", + "camera": [ + 12.8193122098114, + 1.0067637736569703, + -375.50162845924257 + ], + "target": [ + 8.84789867402928, + 1.4841258247319933, + -375.50162845924257 + ], + "yaw": -83.14595676247222, + "pitch": 0.0, + "focus": [ + 6.611, + 1.753, + -374.166 + ], + "center_z": -374.166, + "open_air_section": 2, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.9928533839455302, + -0.11934051276875574, + 0.0 + ], + "camera_target_distance_m": 4.0, + "route_distance_m": 14.436, + "requested_route_distance_m": 14.436, + "route_length_m": 2026.7012290413136, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-2-4m-outside.png", + "scene": "Saved/Linux/l112/captures/after/passage-0-1-0-openair-2-4m-outside.vfmesh", + "drawn_triangles": 278629, + "source_triangles": 346431, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 14.436, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.000000000000009, + "closeup_target_surface_distance_m": 1.0954207812570795, + "closeup_predicted_target_offset_m": 1.0954207812570795, + "closeup_wall_normal_alignment": 0.5096506905478002, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 10.316430262687657, + 3.180776532410437, + -378.42551295829554 + ], + "target_actual_m": [ + 8.001025199890137, + 1.0, + -376.0 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-2-4m-outside-mesh.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-2-4m-outside-render.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-2-4m-outside-quality.log", + "Saved/Linux/l113/captures/before/passage-0-1-0-openair-2-4m-outside-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-2-4m-outside.png", + "source_sha256": "a7f4136d1e74b84403ed0c8a666a259e4293d516ea4ed64c279bdc076a09da1b" + }, + { + "name": "passage-0-1-0-openair-2-4m-interior-wall", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-2/4m-interior-wall", + "camera": [ + 6.964882710490212, + -2.1271777965928074, + -376.1960784602411 + ], + "target": [ + 8.412449119604705, + 1.5364666576789914, + -375.50162845924257 + ], + "yaw": 21.55979422592298, + "pitch": 9.997924306647324, + "focus": [ + 6.611, + 1.753, + -374.166 + ], + "center_z": -374.166, + "open_air_section": 2, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.9928533839455302, + 0.11934051276875574, + -0.0 + ], + "camera_target_distance_m": 3.9999999999999987, + "route_distance_m": 14.436, + "requested_route_distance_m": 14.436, + "route_length_m": 2026.7012290413136, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-2-4m-interior-wall.png", + "scene": "Saved/Linux/l112/captures/after/passage-0-1-0-openair-2-4m-interior-wall.vfmesh", + "drawn_triangles": 350192, + "source_triangles": 445232, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 14.436, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.999999999999987, + "closeup_target_surface_distance_m": 0.8280897194612481, + "closeup_predicted_target_offset_m": 0.8280897194612481, + "closeup_wall_normal_alignment": 0.6621482949540899, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 5.041511761376583, + 1.1856761795197162, + -373.0783207113634 + ], + "target_actual_m": [ + 7.751120738544031, + 1.534688106544318, + -376.0 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-2-4m-interior-wall-mesh.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-2-4m-interior-wall-render.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-2-4m-interior-wall-quality.log", + "Saved/Linux/l113/captures/before/passage-0-1-0-openair-2-4m-interior-wall-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-2-4m-interior-wall.png", + "source_sha256": "c662a24dc7de9347bcf8fb1e168bfe28c3e56257c75d97b086c7d25fbad72170" + }, + { + "name": "passage-0-1-0-openair-3-view-1", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-3/view-1", + "camera": [ + -29.016924787180837, + -17.208716685638674, + -598.05 + ], + "target": [ + -22.039, + -12.355, + -599.15 + ], + "yaw": 55.178232541175774, + "pitch": -7.373766361330367, + "focus": [ + -22.039, + -12.355, + -599.25 + ], + "center_z": -599.25, + "open_air_section": 3, + "route_distance_m": 1265.3110000000001, + "requested_route_distance_m": 1265.3110000000001, + "route_length_m": 2026.7012290413136, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-3-view-1.png", + "scene": "Saved/Linux/l112/captures/after/passage-0-1-0-openair-3-view-1.vfmesh", + "drawn_triangles": 210501, + "source_triangles": 262807, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1265.3110000000001, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -29.016924787180837, + -17.208716685638674, + -598.05 + ], + "target_actual_m": [ + -22.039, + -12.355, + -599.15 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-3-view-1-mesh.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-3-view-1-render.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-3-view-1-quality.log", + "Saved/Linux/l113/captures/before/passage-0-1-0-openair-3-view-1-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-3-view-1.png", + "source_sha256": "36df0b620c8fdb8ef8520eb956f1181d7c32c4664d8b014adcb1d111fac4aec3" + }, + { + "name": "passage-0-1-0-openair-3-view-2", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-3/view-2", + "camera": [ + -16.292473704674606, + -8.357821553003445, + -595.25 + ], + "target": [ + -23.162403628923403, + -10.739943634747398, + -599.6099405834007 + ], + "yaw": -109.12379416410603, + "pitch": -30.947627602730336, + "focus": [ + -22.039, + -12.355, + -599.25 + ], + "center_z": -599.25, + "open_air_section": 3, + "route_distance_m": 1265.3110000000001, + "requested_route_distance_m": 1265.3110000000001, + "route_length_m": 2026.7012290413136, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-3-view-2.png", + "scene": "Saved/Linux/l112/captures/after/passage-0-1-0-openair-3-view-2.vfmesh", + "drawn_triangles": 189354, + "source_triangles": 238324, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1265.3110000000001, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -16.292473704674606, + -8.357821553003445, + -595.25 + ], + "target_actual_m": [ + -23.162403628923403, + -10.739943634747398, + -599.6099405834007 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-3-view-2-mesh.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-3-view-2-render.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-3-view-2-quality.log", + "Saved/Linux/l113/captures/before/passage-0-1-0-openair-3-view-2-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-3-view-2.png", + "source_sha256": "1166a83fc7d2608c88706d77f08989af34e2f74924eb48526d199f2a7a4a0a17" + }, + { + "name": "passage-0-1-0-openair-3-view-3", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-3/view-3", + "camera": [ + -22.039, + -12.355, + -599.8356284592426 + ], + "target": [ + -25.970912701231907, + -6.70230272161589, + -601.0954205011448 + ], + "yaw": -34.821767458824226, + "pitch": -10.368029386382458, + "focus": [ + -22.039, + -12.355, + -599.25 + ], + "center_z": -599.25, + "open_air_section": 3, + "route_distance_m": 1265.3110000000001, + "requested_route_distance_m": 1265.3110000000001, + "route_length_m": 2026.7012290413136, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-3-view-3.png", + "scene": "Saved/Linux/l112/captures/after/passage-0-1-0-openair-3-view-3.vfmesh", + "drawn_triangles": 189354, + "source_triangles": 238324, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1265.3110000000001, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -22.039, + -12.355, + -599.8356284592426 + ], + "target_actual_m": [ + -25.970912701231907, + -6.70230272161589, + -601.0954205011448 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-3-view-3-mesh.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-3-view-3-render.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-3-view-3-quality.log", + "Saved/Linux/l113/captures/before/passage-0-1-0-openair-3-view-3-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-3-view-3.png", + "source_sha256": "d96da8ee5d8ca7a8ff1051d9085640b14c1e10d4eb23ab6e0a549f9797bf13dc" + }, + { + "name": "passage-0-1-0-openair-3-4m-outside", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-3/4m-outside", + "camera": [ + -28.19599245927721, + -16.637691193210596, + -600.5856284592426 + ], + "target": [ + -24.9122631476627, + -14.353589223498279, + -600.5856284592426 + ], + "yaw": 55.17823254117577, + "pitch": 0.0, + "focus": [ + -22.039, + -12.355, + -599.25 + ], + "center_z": -599.25, + "open_air_section": 3, + "closeup_side": "outside", + "closeup_preferred_normal": [ + -0.8209323279036278, + -0.5710254924280793, + 0.0 + ], + "camera_target_distance_m": 4.0, + "route_distance_m": 1265.3110000000001, + "requested_route_distance_m": 1265.3110000000001, + "route_length_m": 2026.7012290413136, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-3-4m-outside.png", + "scene": "Saved/Linux/l112/captures/after/passage-0-1-0-openair-3-4m-outside.vfmesh", + "drawn_triangles": 156696, + "source_triangles": 196328, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1265.3110000000001, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.999999999999989, + "closeup_target_surface_distance_m": 0.19024061574976878, + "closeup_predicted_target_offset_m": 0.19024061574976878, + "closeup_wall_normal_alignment": 0.8867453188356844, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -27.424064445340754, + -16.658813034913997, + -602.2859722225862 + ], + "target_actual_m": [ + -24.785626505535024, + -14.240353099760217, + -600.5 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-3-4m-outside-mesh.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-3-4m-outside-render.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-3-4m-outside-quality.log", + "Saved/Linux/l113/captures/before/passage-0-1-0-openair-3-4m-outside-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-3-4m-outside.png", + "source_sha256": "14579b76ea8a19d604cb6a47575e249b5d120cbdb7dd4bdc53f73c584ef24635" + }, + { + "name": "passage-0-1-0-openair-3-4m-interior-wall", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-3/4m-interior-wall", + "camera": [ + -26.04935611703069, + -10.503775697900165, + -601.28265040181 + ], + "target": [ + -24.694826671989663, + -14.202344393233052, + -600.5856284592426 + ], + "yaw": 159.88571784104565, + "pitch": 10.035334894495504, + "focus": [ + -22.039, + -12.355, + -599.25 + ], + "center_z": -599.25, + "open_air_section": 3, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + 0.8209323279036278, + 0.5710254924280793, + -0.0 + ], + "camera_target_distance_m": 4.0, + "route_distance_m": 1265.3110000000001, + "requested_route_distance_m": 1265.3110000000001, + "route_length_m": 2026.7012290413136, + "variant": "before", + "capture": "captures/before/passage-0-1-0-openair-3-4m-interior-wall.png", + "scene": "Saved/Linux/l112/captures/after/passage-0-1-0-openair-3-4m-interior-wall.vfmesh", + "drawn_triangles": 156658, + "source_triangles": 198088, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1265.3110000000001, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.999999999999988, + "closeup_target_surface_distance_m": 0.03447160931397061, + "closeup_predicted_target_offset_m": 0.03447160931397061, + "closeup_wall_normal_alignment": 0.8640470577938766, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -22.16608291175724, + -11.835991531939918, + -598.6539123835992 + ], + "target_actual_m": [ + -24.716274302444134, + -14.222318752507483, + -600.6037755242438 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-3-4m-interior-wall-mesh.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-3-4m-interior-wall-render.log", + "Saved/Linux/l112/captures/after/passage-0-1-0-openair-3-4m-interior-wall-quality.log", + "Saved/Linux/l113/captures/before/passage-0-1-0-openair-3-4m-interior-wall-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-0-1-0-openair-3-4m-interior-wall.png", + "source_sha256": "4064918eb5e1bcfbfe87261f066409ccc9c9a30b7bef9e53a8de25daf9e20545" + }, + { + "name": "passage-1-2-0-upper-mouth", + "passage": "passage/1-2/0", + "kind": "mouth", + "station": "upper-mouth", + "camera": [ + 23.382701629372992, + -15.537907964013215, + -731.7810546875 + ], + "target": [ + 17.291932956389783, + -13.605656356271904, + -731.8810546875 + ], + "yaw": -72.39875236992931, + "pitch": -0.8965858034836333, + "focus": [ + 19.166015625, + -14.2001953125, + -730.5610546875 + ], + "center_z": -730.5610546875, + "variant": "before", + "capture": "captures/before/passage-1-2-0-upper-mouth.png", + "scene": "Saved/Linux/l112/captures/after/passage-1-2-0-upper-mouth.vfmesh", + "drawn_triangles": 595932, + "source_triangles": 664560, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": null, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 23.382701629372992, + -15.537907964013215, + -731.7810546875 + ], + "target_actual_m": [ + 17.291932956389783, + -13.605656356271904, + -731.8810546875 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-1-2-0-upper-mouth-mesh.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-upper-mouth-render.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-upper-mouth-quality.log", + "Saved/Linux/l113/captures/before/passage-1-2-0-upper-mouth-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-upper-mouth.png", + "source_sha256": "9d7a25b15dec44d1adbbaee20428e706d206a043a3eac9cab83387af50e30aab" + }, + { + "name": "passage-1-2-0-lower-mouth", + "passage": "passage/1-2/0", + "kind": "mouth", + "station": "lower-mouth", + "camera": [ + 27.171071433601465, + -19.00546282978966, + -751.8773596007359 + ], + "target": [ + 17.480740717926007, + -13.188560045702177, + -753.05390625 + ], + "yaw": -59.02448758369992, + "pitch": -5.943042074548474, + "focus": [ + 19.166015625, + -14.2001953125, + -751.73390625 + ], + "center_z": -751.73390625, + "variant": "before", + "capture": "captures/before/passage-1-2-0-lower-mouth.png", + "scene": "Saved/Linux/l112/captures/after/passage-1-2-0-lower-mouth.vfmesh", + "drawn_triangles": 546268, + "source_triangles": 592894, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": null, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 27.171071433601465, + -19.00546282978966, + -751.8773596007359 + ], + "target_actual_m": [ + 17.480740717926007, + -13.188560045702177, + -753.05390625 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-1-2-0-lower-mouth-mesh.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-lower-mouth-render.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-lower-mouth-quality.log", + "Saved/Linux/l113/captures/before/passage-1-2-0-lower-mouth-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-lower-mouth.png", + "source_sha256": "b888d91d8c393e44a5728445c50800249be844af4bd8f7ae25d35ace7722fa74" + }, + { + "name": "passage-1-2-0-station-25", + "passage": "passage/1-2/0", + "kind": "station", + "station": "25%", + "camera": [ + 14.113736360885516, + 6.28488001817556, + -736.9318566664899 + ], + "target": [ + 2.8375390569633967, + 14.668469005956942, + -739.318388075095 + ], + "yaw": -53.37006031730614, + "pitch": -9.639411679864782, + "focus": [ + 14.810173613706882, + 6.563223605999366, + -735.76185666649 + ], + "center_z": -735.76185666649, + "route_distance_m": 28.742403046133614, + "route_length_m": 114.96961218453445, + "requested_route_distance_m": 28.742403046133614, + "variant": "before", + "capture": "captures/before/passage-1-2-0-station-25.png", + "scene": "Saved/Linux/l112/captures/after/passage-1-2-0-station-25.vfmesh", + "drawn_triangles": 655074, + "source_triangles": 754544, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 28.742403046133614, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 14.113736360885516, + 6.28488001817556, + -736.9318566664899 + ], + "target_actual_m": [ + 2.8375390569633967, + 14.668469005956942, + -739.318388075095 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-1-2-0-station-25-mesh.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-station-25-render.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-station-25-quality.log", + "Saved/Linux/l113/captures/before/passage-1-2-0-station-25-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-station-25.png", + "source_sha256": "5c92ab07e15225f800764f0eaf9f5c83ef7d190dc3da251533f20e142a184e75" + }, + { + "name": "passage-1-2-0-station-50", + "passage": "passage/1-2/0", + "kind": "station", + "station": "50%", + "camera": [ + -8.167639189328659, + 12.234449393806269, + -742.2421769171431 + ], + "target": [ + -12.719097109722199, + -1.058412445588001, + -744.6306758761227 + ], + "yaw": -161.09886549116882, + "pitch": -9.647718818107231, + "focus": [ + -8.641894120979037, + 12.815467689391955, + -741.0721769171431 + ], + "center_z": -741.0721769171431, + "route_distance_m": 57.48480609226723, + "route_length_m": 114.96961218453445, + "requested_route_distance_m": 57.48480609226723, + "variant": "before", + "capture": "captures/before/passage-1-2-0-station-50.png", + "scene": "Saved/Linux/l112/captures/after/passage-1-2-0-station-50.vfmesh", + "drawn_triangles": 604662, + "source_triangles": 685224, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 57.48480609226723, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -8.167639189328659, + 12.234449393806269, + -742.2421769171431 + ], + "target_actual_m": [ + -12.719097109722199, + -1.058412445588001, + -744.6306758761227 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-1-2-0-station-50-mesh.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-station-50-render.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-station-50-quality.log", + "Saved/Linux/l113/captures/before/passage-1-2-0-station-50-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-station-50.png", + "source_sha256": "e5c000134f71b9f2b4eae8ecfe4d9a979dbeb8aaca16eccdf452219caa8ebf0e" + }, + { + "name": "passage-1-2-0-station-75", + "passage": "passage/1-2/0", + "kind": "station", + "station": "75%", + "camera": [ + -6.988640302303379, + -10.765776249210223, + -747.5570701728814 + ], + "target": [ + 7.082949158733629, + -11.036833196961979, + -749.9491196202687 + ], + "yaw": 91.10353551175237, + "pitch": -9.645811664959123, + "focus": [ + -7.4007113577862444, + -11.392432012156066, + -746.3870701728814 + ], + "center_z": -746.3870701728814, + "route_distance_m": 86.22720913840084, + "route_length_m": 114.96961218453445, + "requested_route_distance_m": 86.22720913840084, + "variant": "before", + "capture": "captures/before/passage-1-2-0-station-75.png", + "scene": "Saved/Linux/l112/captures/after/passage-1-2-0-station-75.vfmesh", + "drawn_triangles": 612135, + "source_triangles": 691923, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 86.22720913840084, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -6.988640302303379, + -10.765776249210223, + -747.5570701728814 + ], + "target_actual_m": [ + 7.082949158733629, + -11.036833196961979, + -749.9491196202687 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-1-2-0-station-75-mesh.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-station-75-render.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-station-75-quality.log", + "Saved/Linux/l113/captures/before/passage-1-2-0-station-75-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-station-75.png", + "source_sha256": "1fec685863efd0eff15a964689690c1b9082815bdc91197692ab25624cd16c01" + }, + { + "name": "passage-1-2-0-openair-1-view-1", + "passage": "passage/1-2/0", + "kind": "open-air", + "station": "section-1/view-1", + "camera": [ + -4.012736377201166, + -3.9264102860018895, + -744.679 + ], + "target": [ + -9.52, + -9.729, + -745.779 + ], + "yaw": -136.49578370469135, + "pitch": -7.829076510059767, + "focus": [ + -9.52, + -9.729, + -745.879 + ], + "center_z": -745.879, + "open_air_section": 1, + "route_distance_m": 83.48150000000001, + "requested_route_distance_m": 83.48150000000001, + "route_length_m": 114.96961218453445, + "variant": "before", + "capture": "captures/before/passage-1-2-0-openair-1-view-1.png", + "scene": "Saved/Linux/l112/captures/after/passage-1-2-0-openair-1-view-1.vfmesh", + "drawn_triangles": 623352, + "source_triangles": 711724, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 83.48150000000001, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -4.012736377201166, + -3.9264102860018895, + -744.679 + ], + "target_actual_m": [ + -9.52, + -9.729, + -745.779 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-1-view-1-mesh.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-1-view-1-render.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-1-view-1-quality.log", + "Saved/Linux/l113/captures/before/passage-1-2-0-openair-1-view-1-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-openair-1-view-1.png", + "source_sha256": "fdd558299b1b2102c7dae6b6fd169080781f6bf7aa3d07f128f6ea82ccc8000b" + }, + { + "name": "passage-1-2-0-openair-1-view-2", + "passage": "passage/1-2/0", + "kind": "open-air", + "station": "section-1/view-2", + "camera": [ + -13.994651693524052, + -14.443604142623464, + -741.879 + ], + "target": [ + -8.094413332043812, + -11.082030626763467, + -746.2491496659267 + ], + "yaw": 60.32831225573483, + "pitch": -32.76344960660182, + "focus": [ + -9.52, + -9.729, + -745.879 + ], + "center_z": -745.879, + "open_air_section": 1, + "route_distance_m": 83.48150000000001, + "requested_route_distance_m": 83.48150000000001, + "route_length_m": 114.96961218453445, + "variant": "before", + "capture": "captures/before/passage-1-2-0-openair-1-view-2.png", + "scene": "Saved/Linux/l112/captures/after/passage-1-2-0-openair-1-view-2.vfmesh", + "drawn_triangles": 576164, + "source_triangles": 644692, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 83.48150000000001, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -13.994651693524052, + -14.443604142623464, + -741.879 + ], + "target_actual_m": [ + -8.094413332043812, + -11.082030626763467, + -746.2491496659267 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-1-view-2-mesh.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-1-view-2-render.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-1-view-2-quality.log", + "Saved/Linux/l113/captures/before/passage-1-2-0-openair-1-view-2-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-openair-1-view-2.png", + "source_sha256": "1e57e6948e635f3b32f5d3d802704d03e37a38af770b817e750575a3d206389b" + }, + { + "name": "passage-1-2-0-openair-1-view-3", + "passage": "passage/1-2/0", + "kind": "open-air", + "station": "section-1/view-3", + "camera": [ + -9.52, + -9.729, + -747.399 + ], + "target": [ + -4.5304466621533415, + -14.464607193672137, + -748.6945238307434 + ], + "yaw": 133.50421629530865, + "pitch": -10.665495352457787, + "focus": [ + -9.52, + -9.729, + -745.879 + ], + "center_z": -745.879, + "open_air_section": 1, + "route_distance_m": 83.48150000000001, + "requested_route_distance_m": 83.48150000000001, + "route_length_m": 114.96961218453445, + "variant": "before", + "capture": "captures/before/passage-1-2-0-openair-1-view-3.png", + "scene": "Saved/Linux/l112/captures/after/passage-1-2-0-openair-1-view-3.vfmesh", + "drawn_triangles": 570605, + "source_triangles": 638189, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 83.48150000000001, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -9.52, + -9.729, + -747.399 + ], + "target_actual_m": [ + -4.5304466621533415, + -14.464607193672137, + -748.6945238307434 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-1-view-3-mesh.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-1-view-3-render.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-1-view-3-quality.log", + "Saved/Linux/l113/captures/before/passage-1-2-0-openair-1-view-3-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-openair-1-view-3.png", + "source_sha256": "6dbd8eae6338d6dea67c2043ee718232672611c6bce231bf60531e026724f7be" + }, + { + "name": "passage-1-2-0-openair-1-4m-outside", + "passage": "passage/1-2/0", + "kind": "open-air-close", + "station": "section-1/4m-outside", + "camera": [ + -4.7011443300510205, + -4.651734000251653, + -748.149 + ], + "target": [ + -7.454776141450437, + -7.553028857250708, + -748.149 + ], + "yaw": -136.49578370469135, + "pitch": 0.0, + "focus": [ + -9.52, + -9.729, + -745.879 + ], + "center_z": -745.879, + "open_air_section": 1, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.6884079528498542, + 0.7253237142497637, + 0.0 + ], + "camera_target_distance_m": 3.9999999999999996, + "route_distance_m": 83.48150000000001, + "requested_route_distance_m": 83.48150000000001, + "route_length_m": 114.96961218453445, + "variant": "before", + "capture": "captures/before/passage-1-2-0-openair-1-4m-outside.png", + "scene": "Saved/Linux/l112/captures/after/passage-1-2-0-openair-1-4m-outside.vfmesh", + "drawn_triangles": 623352, + "source_triangles": 711724, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 83.48150000000001, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.000000000000037, + "closeup_target_surface_distance_m": 0.5979370452655519, + "closeup_predicted_target_offset_m": 0.5979370452655519, + "closeup_wall_normal_alignment": 0.42190567041017063, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -5.2402003673605835, + -7.419699358529216, + -744.2592769877698 + ], + "target_actual_m": [ + -7.5, + -7.601630046981916, + -747.5547597816745 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-1-4m-outside-mesh.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-1-4m-outside-render.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-1-4m-outside-quality.log", + "Saved/Linux/l113/captures/before/passage-1-2-0-openair-1-4m-outside-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-openair-1-4m-outside.png", + "source_sha256": "3672a5d7e1429d61dd6ca4f9e47eb7b426bf5a1d2bd89928ce2d19e631aadb98" + }, + { + "name": "passage-1-2-0-openair-1-4m-interior-wall", + "passage": "passage/1-2/0", + "kind": "open-air-close", + "station": "section-1/4m-interior-wall", + "camera": [ + -6.097526120437678, + -11.651804466912369, + -748.8657917458692 + ], + "target": [ + -8.169754879372643, + -8.306348210480857, + -748.149 + ], + "yaw": -31.774732032092412, + "pitch": 10.323045367792538, + "focus": [ + -9.52, + -9.729, + -745.879 + ], + "center_z": -745.879, + "open_air_section": 1, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.6884079528498542, + -0.7253237142497637, + -0.0 + ], + "camera_target_distance_m": 4.000000000000005, + "route_distance_m": 83.48150000000001, + "requested_route_distance_m": 83.48150000000001, + "route_length_m": 114.96961218453445, + "variant": "before", + "capture": "captures/before/passage-1-2-0-openair-1-4m-interior-wall.png", + "scene": "Saved/Linux/l112/captures/after/passage-1-2-0-openair-1-4m-interior-wall.vfmesh", + "drawn_triangles": 612135, + "source_triangles": 691923, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 83.48150000000001, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.000000000000001, + "closeup_target_surface_distance_m": 0.6529446089467095, + "closeup_predicted_target_offset_m": 0.6529446089467095, + "closeup_wall_normal_alignment": 0.781464055310911, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -8.531084729501915, + -12.940973897704662, + -748.3218199263141 + ], + "target_actual_m": [ + -8.186284222607911, + -8.958624012538072, + -748.1734892060998 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-1-4m-interior-wall-mesh.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-1-4m-interior-wall-render.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-1-4m-interior-wall-quality.log", + "Saved/Linux/l113/captures/before/passage-1-2-0-openair-1-4m-interior-wall-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-openair-1-4m-interior-wall.png", + "source_sha256": "1dca4111776fe6c77b46efc8752eb183ff61022888bf4565a1e6dc200cf4e8cc" + }, + { + "name": "passage-1-2-0-openair-2-view-1", + "passage": "passage/1-2/0", + "kind": "open-air", + "station": "section-2/view-1", + "camera": [ + 6.37266079290948, + -3.635825668681128, + -748.555 + ], + "target": [ + 9.488, + -11.155, + -749.655 + ], + "yaw": 157.49482804323503, + "pitch": -7.696985964433935, + "focus": [ + 9.488, + -11.155, + -749.755 + ], + "center_z": -749.755, + "open_air_section": 2, + "route_distance_m": 104.40950000000001, + "requested_route_distance_m": 104.40950000000001, + "route_length_m": 114.96961218453445, + "variant": "before", + "capture": "captures/before/passage-1-2-0-openair-2-view-1.png", + "scene": "Saved/Linux/l112/captures/after/passage-1-2-0-openair-2-view-1.vfmesh", + "drawn_triangles": 628316, + "source_triangles": 719702, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 104.40950000000001, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 6.37266079290948, + -3.635825668681128, + -748.555 + ], + "target_actual_m": [ + 9.488, + -11.155, + -749.655 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-2-view-1-mesh.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-2-view-1-render.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-2-view-1-quality.log", + "Saved/Linux/l113/captures/before/passage-1-2-0-openair-2-view-1-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-openair-2-view-1.png", + "source_sha256": "ffa18a5c8863af55a3e0b2d47dfed477deef6e002345b70d9fa613e31a1048aa" + }, + { + "name": "passage-1-2-0-openair-2-view-2", + "passage": "passage/1-2/0", + "kind": "open-air", + "station": "section-2/view-2", + "camera": [ + 12.029188966196578, + -17.288406854113035, + -745.755 + ], + "target": [ + 11.303971870631361, + -10.402607766721497, + -750.1239879298538 + ], + "yaw": -6.01226603270804, + "pitch": -32.25202716463738, + "focus": [ + 9.488, + -11.155, + -749.755 + ], + "center_z": -749.755, + "open_air_section": 2, + "route_distance_m": 104.40950000000001, + "requested_route_distance_m": 104.40950000000001, + "route_length_m": 114.96961218453445, + "variant": "before", + "capture": "captures/before/passage-1-2-0-openair-2-view-2.png", + "scene": "Saved/Linux/l112/captures/after/passage-1-2-0-openair-2-view-2.vfmesh", + "drawn_triangles": 585440, + "source_triangles": 649826, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 104.40950000000001, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 12.029188966196578, + -17.288406854113035, + -745.755 + ], + "target_actual_m": [ + 11.303971870631361, + -10.402607766721497, + -750.1239879298538 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-2-view-2-mesh.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-2-view-2-render.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-2-view-2-quality.log", + "Saved/Linux/l113/captures/before/passage-1-2-0-openair-2-view-2-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-openair-2-view-2.png", + "source_sha256": "45e264923bd744472129ed4d4af4599abd78c87ec4ff6b198b80bd9372fec748" + }, + { + "name": "passage-1-2-0-openair-2-view-3", + "passage": "passage/1-2/0", + "kind": "open-air", + "station": "section-2/view-3", + "camera": [ + 9.488, + -11.155, + -751.275 + ], + "target": [ + 15.843901547209768, + -8.52162718352524, + -752.5664577544884 + ], + "yaw": 67.49482804323503, + "pitch": -10.63163088784527, + "focus": [ + 9.488, + -11.155, + -749.755 + ], + "center_z": -749.755, + "open_air_section": 2, + "route_distance_m": 104.40950000000001, + "requested_route_distance_m": 104.40950000000001, + "route_length_m": 114.96961218453445, + "variant": "before", + "capture": "captures/before/passage-1-2-0-openair-2-view-3.png", + "scene": "Saved/Linux/l112/captures/after/passage-1-2-0-openair-2-view-3.vfmesh", + "drawn_triangles": 613722, + "source_triangles": 693804, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 104.40950000000001, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 9.488, + -11.155, + -751.275 + ], + "target_actual_m": [ + 15.843901547209768, + -8.52162718352524, + -752.5664577544884 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-2-view-3-mesh.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-2-view-3-render.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-2-view-3-quality.log", + "Saved/Linux/l113/captures/before/passage-1-2-0-openair-2-view-3-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-openair-2-view-3.png", + "source_sha256": "8822364bec7709ed4a2f4d7ad9391fddb7e4d4fd5f2901639765e0ef6bbbbbd3" + }, + { + "name": "passage-1-2-0-openair-2-4m-outside", + "passage": "passage/1-2/0", + "kind": "open-air-close", + "station": "section-2/4m-outside", + "camera": [ + 6.755427620172105, + -4.559670653485019, + -752.025 + ], + "target": [ + 8.286494929222613, + -8.255050592700584, + -752.025 + ], + "yaw": 157.49482804323503, + "pitch": 0.0, + "focus": [ + 9.488, + -11.155, + -749.755 + ], + "center_z": -749.755, + "open_air_section": 2, + "closeup_side": "outside", + "closeup_preferred_normal": [ + -0.3827668272626269, + 0.9238449848038914, + 0.0 + ], + "camera_target_distance_m": 4.0, + "route_distance_m": 104.40950000000001, + "requested_route_distance_m": 104.40950000000001, + "route_length_m": 114.96961218453445, + "variant": "before", + "capture": "captures/before/passage-1-2-0-openair-2-4m-outside.png", + "scene": "Saved/Linux/l112/captures/after/passage-1-2-0-openair-2-4m-outside.vfmesh", + "drawn_triangles": 585802, + "source_triangles": 657076, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 104.40950000000001, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.0, + "closeup_target_surface_distance_m": 0.5569723033142947, + "closeup_predicted_target_offset_m": 0.5569723033142947, + "closeup_wall_normal_alignment": 0.8300132989203148, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 5.456826350119467, + -6.285898707784279, + -752.1262448423768 + ], + "target_actual_m": [ + 8.786704307765559, + -8.5, + -752.027917557296 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-2-4m-outside-mesh.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-2-4m-outside-render.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-2-4m-outside-quality.log", + "Saved/Linux/l113/captures/before/passage-1-2-0-openair-2-4m-outside-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-openair-2-4m-outside.png", + "source_sha256": "ac635381a0fad1e45ebe4ad2ba840ee7baa36386807843a260d747df8f555d11" + }, + { + "name": "passage-1-2-0-openair-2-4m-interior-wall", + "passage": "passage/1-2/0", + "kind": "open-air-close", + "station": "section-2/4m-interior-wall", + "camera": [ + 12.557525361540653, + -8.61890578995272, + -752.7395420536377 + ], + "target": [ + 8.658144128209829, + -9.15206209980055, + -752.025 + ], + "yaw": -97.78568510593111, + "pitch": 10.290292405231583, + "focus": [ + 9.488, + -11.155, + -749.755 + ], + "center_z": -749.755, + "open_air_section": 2, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + 0.3827668272626269, + -0.9238449848038914, + -0.0 + ], + "camera_target_distance_m": 4.000000000000001, + "route_distance_m": 104.40950000000001, + "requested_route_distance_m": 104.40950000000001, + "route_length_m": 114.96961218453445, + "variant": "before", + "capture": "captures/before/passage-1-2-0-openair-2-4m-interior-wall.png", + "scene": "Saved/Linux/l112/captures/after/passage-1-2-0-openair-2-4m-interior-wall.vfmesh", + "drawn_triangles": 574472, + "source_triangles": 635712, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 104.40950000000001, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.000000000000001, + "closeup_target_surface_distance_m": 0.3789200867234511, + "closeup_predicted_target_offset_m": 0.3789200867234511, + "closeup_wall_normal_alignment": 0.9970173084578355, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 10.235234629238544, + -12.420762087601563, + -752.017966381381 + ], + "target_actual_m": [ + 8.423532662676926, + -8.854568760433747, + -752.0190329743256 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-2-4m-interior-wall-mesh.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-2-4m-interior-wall-render.log", + "Saved/Linux/l112/captures/after/passage-1-2-0-openair-2-4m-interior-wall-quality.log", + "Saved/Linux/l113/captures/before/passage-1-2-0-openair-2-4m-interior-wall-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-1-2-0-openair-2-4m-interior-wall.png", + "source_sha256": "20a0332cf4120a07631172161a6f995386b7077c40cfd227f969a7c3500e4724" + }, + { + "name": "passage-2-3-0-upper-mouth", + "passage": "passage/2-3/0", + "kind": "mouth", + "station": "upper-mouth", + "camera": [ + -24.46109203696401, + -5.5818896409784315, + -811.975390625 + ], + "target": [ + -18.107570205793774, + -4.840123701231809, + -812.075390625 + ], + "yaw": 83.34093327385727, + "pitch": -0.8956388887564393, + "focus": [ + -20.0625, + -5.068359375, + -810.755390625 + ], + "center_z": -810.755390625, + "variant": "before", + "capture": "captures/before/passage-2-3-0-upper-mouth.png", + "scene": "Saved/Linux/l112/captures/after/passage-2-3-0-upper-mouth.vfmesh", + "drawn_triangles": 59568, + "source_triangles": 71508, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": null, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -24.46109203696401, + -5.5818896409784315, + -811.975390625 + ], + "target_actual_m": [ + -18.107570205793774, + -4.840123701231809, + -812.075390625 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-2-3-0-upper-mouth-mesh.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-upper-mouth-render.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-upper-mouth-quality.log", + "Saved/Linux/l113/captures/before/passage-2-3-0-upper-mouth-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-upper-mouth.png", + "source_sha256": "137f34e7137b7c77d5bf013e187e27c32927641d1df4f9b8e6df9c72854ab83b" + }, + { + "name": "passage-2-3-0-lower-mouth", + "passage": "passage/2-3/0", + "kind": "mouth", + "station": "lower-mouth", + "camera": [ + -28.636475339787903, + -1.3354368899879738, + -898.8144448742513 + ], + "target": [ + -18.25745256004465, + -5.854237792897269, + -900.0333984375 + ], + "yaw": 113.5272620393567, + "pitch": -6.145978083088789, + "focus": [ + -20.0625, + -5.068359375, + -898.7133984375 + ], + "center_z": -898.7133984375, + "variant": "before", + "capture": "captures/before/passage-2-3-0-lower-mouth.png", + "scene": "Saved/Linux/l112/captures/after/passage-2-3-0-lower-mouth.vfmesh", + "drawn_triangles": 294004, + "source_triangles": 314734, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": null, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -28.636475339787903, + -1.3354368899879738, + -898.8144448742513 + ], + "target_actual_m": [ + -18.25745256004465, + -5.854237792897269, + -900.0333984375 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-2-3-0-lower-mouth-mesh.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-lower-mouth-render.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-lower-mouth-quality.log", + "Saved/Linux/l113/captures/before/passage-2-3-0-lower-mouth-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-lower-mouth.png", + "source_sha256": "d3b5b02bea541e0454cbebf351765cfd8c3871cbac5bada269cf071e3c63e19c" + }, + { + "name": "passage-2-3-0-station-25", + "passage": "passage/2-3/0", + "kind": "station", + "station": "25%", + "camera": [ + 3.019701774592388, + -13.591453110374651, + -833.8488531811187 + ], + "target": [ + 14.00155446639769, + -4.75985656647419, + -836.142478466213 + ], + "yaw": 51.19378873289192, + "pitch": -9.244130451366324, + "focus": [ + 3.0967290150193443, + -14.33748716069153, + -832.6788531811187 + ], + "center_z": -832.6788531811187, + "route_distance_m": 123.53373286582855, + "route_length_m": 494.1349314633142, + "requested_route_distance_m": 123.53373286582855, + "variant": "before", + "capture": "captures/before/passage-2-3-0-station-25.png", + "scene": "Saved/Linux/l112/captures/after/passage-2-3-0-station-25.vfmesh", + "drawn_triangles": 55514, + "source_triangles": 66412, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 123.53373286582855, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 3.019701774592388, + -13.591453110374651, + -833.8488531811187 + ], + "target_actual_m": [ + 14.00155446639769, + -4.75985656647419, + -836.142478466213 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-2-3-0-station-25-mesh.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-station-25-render.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-station-25-quality.log", + "Saved/Linux/l113/captures/before/passage-2-3-0-station-25-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-station-25.png", + "source_sha256": "6dc7352c58848cb48410097af30e682ae077ee02e05c4e610b54fff470347bf7" + }, + { + "name": "passage-2-3-0-station-50", + "passage": "passage/2-3/0", + "kind": "station", + "station": "50%", + "camera": [ + 15.037366176324477, + 4.106782632885063, + -855.8546237305741 + ], + "target": [ + 4.302090316791295, + 13.21257795312749, + -858.1474627779044 + ], + "yaw": -49.69497333173356, + "pitch": -9.251013429114066, + "focus": [ + 15.752039052912956, + 4.334252805586342, + -854.6846237305741 + ], + "center_z": -854.6846237305741, + "route_distance_m": 247.0674657316571, + "route_length_m": 494.1349314633142, + "requested_route_distance_m": 247.0674657316571, + "variant": "before", + "capture": "captures/before/passage-2-3-0-station-50.png", + "scene": "Saved/Linux/l112/captures/after/passage-2-3-0-station-50.vfmesh", + "drawn_triangles": 458230, + "source_triangles": 479098, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 247.0674657316571, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 15.037366176324477, + 4.106782632885063, + -855.8546237305741 + ], + "target_actual_m": [ + 4.302090316791295, + 13.21257795312749, + -858.1474627779044 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-2-3-0-station-50-mesh.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-station-50-render.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-station-50-quality.log", + "Saved/Linux/l113/captures/before/passage-2-3-0-station-50-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-station-50.png", + "source_sha256": "d19a8e11ca25401d1bdac86951e92a960ab73fa1c99c520c5e9f90bbcacabde4" + }, + { + "name": "passage-2-3-0-station-75", + "passage": "passage/2-3/0", + "kind": "station", + "station": "75%", + "camera": [ + -5.729592517417305, + 11.518390950074156, + -877.8627102922013 + ], + "target": [ + -12.468742929423927, + -0.8048224106496764, + -880.1601105631271 + ], + "yaw": -151.3272360910958, + "pitch": -9.289478775200905, + "focus": [ + -6.104061615549714, + 12.168216230087099, + -876.6927102922014 + ], + "center_z": -876.6927102922014, + "route_distance_m": 370.6011985974857, + "route_length_m": 494.1349314633142, + "requested_route_distance_m": 370.6011985974857, + "variant": "before", + "capture": "captures/before/passage-2-3-0-station-75.png", + "scene": "Saved/Linux/l112/captures/after/passage-2-3-0-station-75.vfmesh", + "drawn_triangles": 475838, + "source_triangles": 506104, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 370.6011985974857, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -5.729592517417305, + 11.518390950074156, + -877.8627102922013 + ], + "target_actual_m": [ + -12.468742929423927, + -0.8048224106496764, + -880.1601105631271 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-2-3-0-station-75-mesh.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-station-75-render.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-station-75-quality.log", + "Saved/Linux/l113/captures/before/passage-2-3-0-station-75-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-station-75.png", + "source_sha256": "64c817d4fcfa4fda09f6b81532da413610fd843a9c40e7da71268b58a1a0d79d" + }, + { + "name": "passage-2-3-0-openair-1-view-1", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-1/view-1", + "camera": [ + -2.9979042861664693, + -4.712290740348933, + -812.409 + ], + "target": [ + -7.267, + -11.478, + -813.509 + ], + "yaw": -147.74847917454895, + "pitch": -7.829076510059765, + "focus": [ + -7.267, + -11.478, + -813.609 + ], + "center_z": -813.609, + "open_air_section": 1, + "route_distance_m": 16.506999999999998, + "requested_route_distance_m": 16.506999999999998, + "route_length_m": 494.1349314633142, + "variant": "before", + "capture": "captures/before/passage-2-3-0-openair-1-view-1.png", + "scene": "Saved/Linux/l112/captures/after/passage-2-3-0-openair-1-view-1.vfmesh", + "drawn_triangles": 104612, + "source_triangles": 129352, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 16.506999999999998, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -2.9979042861664693, + -4.712290740348933, + -812.409 + ], + "target_actual_m": [ + -7.267, + -11.478, + -813.509 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-1-view-1-mesh.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-1-view-1-render.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-1-view-1-quality.log", + "Saved/Linux/l113/captures/before/passage-2-3-0-openair-1-view-1-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-openair-1-view-1.png", + "source_sha256": "fa111e521ff09b52095798cb3a3597f206a01f3f133fdd3c6d986556d2d32787" + }, + { + "name": "passage-2-3-0-openair-1-view-2", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-1/view-2", + "camera": [ + -10.735640267489744, + -16.97513877346649, + -809.609 + ], + "target": [ + -5.6026931633198105, + -12.528161174579008, + -813.9657131351471 + ], + "yaw": 49.09566798491317, + "pitch": -32.68045244303501, + "focus": [ + -7.267, + -11.478, + -813.609 + ], + "center_z": -813.609, + "open_air_section": 1, + "route_distance_m": 16.506999999999998, + "requested_route_distance_m": 16.506999999999998, + "route_length_m": 494.1349314633142, + "variant": "before", + "capture": "captures/before/passage-2-3-0-openair-1-view-2.png", + "scene": "Saved/Linux/l112/captures/after/passage-2-3-0-openair-1-view-2.vfmesh", + "drawn_triangles": 76426, + "source_triangles": 93942, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 16.506999999999998, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -10.735640267489744, + -16.97513877346649, + -809.609 + ], + "target_actual_m": [ + -5.6026931633198105, + -12.528161174579008, + -813.9657131351471 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-1-view-2-mesh.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-1-view-2-render.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-1-view-2-quality.log", + "Saved/Linux/l113/captures/before/passage-2-3-0-openair-1-view-2-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-openair-1-view-2.png", + "source_sha256": "33da1fe5fa5744bb9a1f530d0407797c5e9cce6627aa1ca2e20c2594b59244b6" + }, + { + "name": "passage-2-3-0-openair-1-view-3", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-1/view-3", + "camera": [ + -7.267, + -11.478, + -815.129 + ], + "target": [ + -1.441926071619335, + -15.153564111026531, + -816.3774959730146 + ], + "yaw": 122.25152082545104, + "pitch": -10.27404912928437, + "focus": [ + -7.267, + -11.478, + -813.609 + ], + "center_z": -813.609, + "open_air_section": 1, + "route_distance_m": 16.506999999999998, + "requested_route_distance_m": 16.506999999999998, + "route_length_m": 494.1349314633142, + "variant": "before", + "capture": "captures/before/passage-2-3-0-openair-1-view-3.png", + "scene": "Saved/Linux/l112/captures/after/passage-2-3-0-openair-1-view-3.vfmesh", + "drawn_triangles": 94962, + "source_triangles": 118054, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 16.506999999999998, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -7.267, + -11.478, + -815.129 + ], + "target_actual_m": [ + -1.441926071619335, + -15.153564111026531, + -816.3774959730146 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-1-view-3-mesh.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-1-view-3-render.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-1-view-3-quality.log", + "Saved/Linux/l113/captures/before/passage-2-3-0-openair-1-view-3-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-openair-1-view-3.png", + "source_sha256": "bca84ec94352c8a6dc9c0b81a4f99c5a53947d0421d6e68a803e14911b6331c7" + }, + { + "name": "passage-2-3-0-openair-1-4m-outside", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-1/4m-outside", + "camera": [ + -3.5315412503956605, + -5.558004397805316, + -815.879 + ], + "target": [ + -5.666089107312426, + -8.94085902763085, + -815.879 + ], + "yaw": -147.74847917454895, + "pitch": 0.0, + "focus": [ + -7.267, + -11.478, + -813.609 + ], + "center_z": -813.609, + "open_air_section": 1, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.5336369642291914, + 0.8457136574563834, + 0.0 + ], + "camera_target_distance_m": 4.000000000000001, + "route_distance_m": 16.506999999999998, + "requested_route_distance_m": 16.506999999999998, + "route_length_m": 494.1349314633142, + "variant": "before", + "capture": "captures/before/passage-2-3-0-openair-1-4m-outside.png", + "scene": "Saved/Linux/l112/captures/after/passage-2-3-0-openair-1-4m-outside.vfmesh", + "drawn_triangles": 104612, + "source_triangles": 129352, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 16.506999999999998, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.999999999999996, + "closeup_target_surface_distance_m": 0.29683911895713316, + "closeup_predicted_target_offset_m": 0.29683911895713316, + "closeup_wall_normal_alignment": 0.67494340532841, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -3.8308683215077686, + -7.14211062127575, + -813.2125534154507 + ], + "target_actual_m": [ + -5.8142006488753735, + -9.08294977482132, + -816.0934449891276 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-1-4m-outside-mesh.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-1-4m-outside-render.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-1-4m-outside-quality.log", + "Saved/Linux/l113/captures/before/passage-2-3-0-openair-1-4m-outside-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-openair-1-4m-outside.png", + "source_sha256": "47aedc9199b4b218be36536e2e6371fb82038f5f9931ae99286f3d36ecd982de" + }, + { + "name": "passage-2-3-0-openair-1-4m-interior-wall", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-1/4m-interior-wall", + "camera": [ + -3.5310437260816867, + -12.698557095195458, + -816.5697720158989 + ], + "target": [ + -6.220323092573257, + -9.819215067750013, + -815.879 + ], + "yaw": -43.04519612653523, + "pitch": 9.944433062490045, + "focus": [ + -7.267, + -11.478, + -813.609 + ], + "center_z": -813.609, + "open_air_section": 1, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.5336369642291914, + -0.8457136574563834, + -0.0 + ], + "camera_target_distance_m": 3.9999999999999996, + "route_distance_m": 16.506999999999998, + "requested_route_distance_m": 16.506999999999998, + "route_length_m": 494.1349314633142, + "variant": "before", + "capture": "captures/before/passage-2-3-0-openair-1-4m-interior-wall.png", + "scene": "Saved/Linux/l112/captures/after/passage-2-3-0-openair-1-4m-interior-wall.vfmesh", + "drawn_triangles": 94962, + "source_triangles": 118054, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 16.506999999999998, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.9999999999999925, + "closeup_target_surface_distance_m": 0.41884655036552404, + "closeup_predicted_target_offset_m": 0.41884655036552404, + "closeup_wall_normal_alignment": 0.7463542809089274, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -8.06908339833993, + -11.810743463701222, + -818.2117291711875 + ], + "target_actual_m": [ + -6.01271131624994, + -9.578237281759943, + -815.6064940555799 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-1-4m-interior-wall-mesh.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-1-4m-interior-wall-render.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-1-4m-interior-wall-quality.log", + "Saved/Linux/l113/captures/before/passage-2-3-0-openair-1-4m-interior-wall-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-openair-1-4m-interior-wall.png", + "source_sha256": "9911a7e628325e7ab7c1cf5c55a08b3bf8e5b0966f18b6e08adf758f93115bbb" + }, + { + "name": "passage-2-3-0-openair-2-view-1", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-2/view-1", + "camera": [ + -3.8431494955986567, + 3.9485527351653085, + -876.2779999999999 + ], + "target": [ + -9.548, + 9.557, + -877.3779999999999 + ], + "yaw": -45.48821883657469, + "pitch": -7.829076510059767, + "focus": [ + -9.548, + 9.557, + -877.478 + ], + "center_z": -877.478, + "open_air_section": 2, + "route_distance_m": 375.00800000000004, + "requested_route_distance_m": 375.00800000000004, + "route_length_m": 494.1349314633142, + "variant": "before", + "capture": "captures/before/passage-2-3-0-openair-2-view-1.png", + "scene": "Saved/Linux/l112/captures/after/passage-2-3-0-openair-2-view-1.vfmesh", + "drawn_triangles": 476214, + "source_triangles": 507486, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 375.00800000000004, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -3.8431494955986567, + 3.9485527351653085, + -876.2779999999999 + ], + "target_actual_m": [ + -9.548, + 9.557, + -877.3779999999999 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-2-view-1-mesh.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-2-view-1-render.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-2-view-1-quality.log", + "Saved/Linux/l113/captures/before/passage-2-3-0-openair-2-view-1-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-openair-2-view-1.png", + "source_sha256": "08b7b455da21dfd8549eedc0c4bc2d217d19709b6e8a6e298a828b00279fa1ef" + }, + { + "name": "passage-2-3-0-openair-2-view-2", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-2/view-2", + "camera": [ + -14.183191034826091, + 14.113863402678188, + -873.478 + ], + "target": [ + -10.927615416535147, + 8.153670462741282, + -877.8348298086144 + ], + "yaw": 151.35575752769614, + "pitch": -32.6811732818988, + "focus": [ + -9.548, + 9.557, + -877.478 + ], + "center_z": -877.478, + "open_air_section": 2, + "route_distance_m": 375.00800000000004, + "requested_route_distance_m": 375.00800000000004, + "route_length_m": 494.1349314633142, + "variant": "before", + "capture": "captures/before/passage-2-3-0-openair-2-view-2.png", + "scene": "Saved/Linux/l112/captures/after/passage-2-3-0-openair-2-view-2.vfmesh", + "drawn_triangles": 479366, + "source_triangles": 505714, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 375.00800000000004, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -14.183191034826091, + 14.113863402678188, + -873.478 + ], + "target_actual_m": [ + -10.927615416535147, + 8.153670462741282, + -877.8348298086144 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-2-view-2-mesh.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-2-view-2-render.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-2-view-2-quality.log", + "Saved/Linux/l113/captures/before/passage-2-3-0-openair-2-view-2-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-openair-2-view-2.png", + "source_sha256": "22936fbc200b0e30fe834b97c62135b12b9affa4d1f2a3667e527379b10e23a0" + }, + { + "name": "passage-2-3-0-openair-2-view-3", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-2/view-3", + "camera": [ + -9.548, + 9.557, + -878.9979999999999 + ], + "target": [ + -14.376653957873012, + 4.645346619594482, + -880.2469043301503 + ], + "yaw": -135.4882188365747, + "pitch": -10.277446062572244, + "focus": [ + -9.548, + 9.557, + -877.478 + ], + "center_z": -877.478, + "open_air_section": 2, + "route_distance_m": 375.00800000000004, + "requested_route_distance_m": 375.00800000000004, + "route_length_m": 494.1349314633142, + "variant": "before", + "capture": "captures/before/passage-2-3-0-openair-2-view-3.png", + "scene": "Saved/Linux/l112/captures/after/passage-2-3-0-openair-2-view-3.vfmesh", + "drawn_triangles": 479366, + "source_triangles": 505714, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 375.00800000000004, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -9.548, + 9.557, + -878.9979999999999 + ], + "target_actual_m": [ + -14.376653957873012, + 4.645346619594482, + -880.2469043301503 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-2-view-3-mesh.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-2-view-3-render.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-2-view-3-quality.log", + "Saved/Linux/l113/captures/before/passage-2-3-0-openair-2-view-3-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-openair-2-view-3.png", + "source_sha256": "d36e2494bf1082ac878af2d811026ab60ed985f037af90439b22da4f27ac3f70" + }, + { + "name": "passage-2-3-0-openair-2-4m-outside", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-2/4m-outside", + "camera": [ + -4.5562558086488245, + 4.649608643269644, + -879.7479999999999 + ], + "target": [ + -7.408681060849496, + 7.453832275686991, + -879.7479999999999 + ], + "yaw": -45.48821883657468, + "pitch": 0.0, + "focus": [ + -9.548, + 9.557, + -877.478 + ], + "center_z": -877.478, + "open_air_section": 2, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.7131063130501679, + -0.7010559081043365, + 0.0 + ], + "camera_target_distance_m": 4.0, + "route_distance_m": 375.00800000000004, + "requested_route_distance_m": 375.00800000000004, + "route_length_m": 494.1349314633142, + "variant": "before", + "capture": "captures/before/passage-2-3-0-openair-2-4m-outside.png", + "scene": "Saved/Linux/l112/captures/after/passage-2-3-0-openair-2-4m-outside.vfmesh", + "drawn_triangles": 476214, + "source_triangles": 507486, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 375.00800000000004, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.000000000000001, + "closeup_target_surface_distance_m": 1.7270706511220406, + "closeup_predicted_target_offset_m": 1.7270706511220406, + "closeup_wall_normal_alignment": 0.6707823544913467, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -7.471987180266219, + 5.182171434598743, + -879.6783661883575 + ], + "target_actual_m": [ + -7.306491283931798, + 9.177780848974395, + -879.7662098907449 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-2-4m-outside-mesh.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-2-4m-outside-render.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-2-4m-outside-quality.log", + "Saved/Linux/l113/captures/before/passage-2-3-0-openair-2-4m-outside-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-openair-2-4m-outside.png", + "source_sha256": "0c21eed2003099629a6394420a11a93d2e300dbeb9374d830f9afcbc74a6c463" + }, + { + "name": "passage-2-3-0-openair-2-4m-interior-wall", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-2/4m-interior-wall", + "camera": [ + -11.53403153171888, + 6.16546709214774, + -880.4389979530969 + ], + "target": [ + -8.149311452462896, + 8.181947147565394, + -879.7479999999999 + ], + "yaw": 59.21521540250373, + "pitch": 9.947718755981942, + "focus": [ + -9.548, + 9.557, + -877.478 + ], + "center_z": -877.478, + "open_air_section": 2, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.7131063130501679, + 0.7010559081043365, + -0.0 + ], + "camera_target_distance_m": 3.9999999999999964, + "route_distance_m": 375.00800000000004, + "requested_route_distance_m": 375.00800000000004, + "route_length_m": 494.1349314633142, + "variant": "before", + "capture": "captures/before/passage-2-3-0-openair-2-4m-interior-wall.png", + "scene": "Saved/Linux/l112/captures/after/passage-2-3-0-openair-2-4m-interior-wall.vfmesh", + "drawn_triangles": 486990, + "source_triangles": 515888, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 375.00800000000004, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.9999999999999996, + "closeup_target_surface_distance_m": 1.0276132856323636, + "closeup_predicted_target_offset_m": 1.0276132856323636, + "closeup_wall_normal_alignment": 0.7200130865712391, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -8.257090453232413, + 13.208090455668112, + -879.7612152592583 + ], + "target_actual_m": [ + -8.149311452462896, + 9.209558486938477, + -879.75 + ], + "logs": [ + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-2-4m-interior-wall-mesh.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-2-4m-interior-wall-render.log", + "Saved/Linux/l112/captures/after/passage-2-3-0-openair-2-4m-interior-wall-quality.log", + "Saved/Linux/l113/captures/before/passage-2-3-0-openair-2-4m-interior-wall-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux112/captures/after/passage-2-3-0-openair-2-4m-interior-wall.png", + "source_sha256": "63962ed7fd2758a78ce907f9ed89b55ee0b986be260ba4f11f8d1f9b9ca7d04e" + }, + { + "name": "passage-0-1-0-upper-mouth", + "passage": "passage/0-1/0", + "kind": "mouth", + "station": "upper-mouth", + "camera": [ + 8.324777182667596, + 20.450707805615995, + -371.842578125 + ], + "target": [ + 7.855654585481068, + 14.021907641948447, + -371.942578125 + ], + "yaw": -175.82640818958697, + "pitch": -0.8888012261216656, + "focus": [ + 8.0, + 16.0, + -372.1224609375 + ], + "center_z": -372.1224609375, + "variant": "after", + "capture": "captures/after/passage-0-1-0-upper-mouth.png", + "scene": "Saved/Linux/l113/captures/after/passage-0-1-0-upper-mouth.vfmesh", + "drawn_triangles": 245708, + "source_triangles": 301620, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": null, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 8.324777182667596, + 20.450707805615995, + -371.842578125 + ], + "target_actual_m": [ + 7.855654585481068, + 14.021907641948447, + -371.942578125 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-0-1-0-upper-mouth-mesh.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-upper-mouth-render.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-upper-mouth-quality.log" + ] + }, + { + "name": "passage-0-1-0-lower-mouth", + "passage": "passage/0-1/0", + "kind": "mouth", + "station": "lower-mouth", + "camera": [ + 32.68834531966199, + 9.553722879000034, + -735.4805084803569 + ], + "target": [ + 24.394507482044844, + 1.8614284070526241, + -736.6798828125 + ], + "yaw": -132.84502956130385, + "pitch": -6.05232406255234, + "focus": [ + 25.8369140625, + 3.19921875, + -736.2672500132622 + ], + "center_z": -736.2672500132622, + "variant": "after", + "capture": "captures/after/passage-0-1-0-lower-mouth.png", + "scene": "Saved/Linux/l113/captures/after/passage-0-1-0-lower-mouth.vfmesh", + "drawn_triangles": 551698, + "source_triangles": 602158, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": null, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 32.68834531966199, + 9.553722879000034, + -735.4805084803569 + ], + "target_actual_m": [ + 24.394507482044844, + 1.8614284070526241, + -736.6798828125 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-0-1-0-lower-mouth-mesh.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-lower-mouth-render.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-lower-mouth-quality.log" + ] + }, + { + "name": "passage-0-1-0-station-25", + "passage": "passage/0-1/0", + "kind": "station", + "station": "25%", + "camera": [ + -14.78808365101151, + -19.14058791856569, + -462.9516351755408 + ], + "target": [ + -22.365365057702377, + -8.32444898094667, + -465.2722094791618 + ], + "yaw": -35.01328952398061, + "pitch": -9.966177674774675, + "focus": [ + -14.255772720724048, + -18.612246103547704, + -462.68900237630305 + ], + "center_z": -462.68900237630305, + "route_distance_m": 506.6559510038529, + "route_length_m": 2026.6238040154117, + "requested_route_distance_m": 506.6559510038529, + "variant": "after", + "capture": "captures/after/passage-0-1-0-station-25.png", + "scene": "Saved/Linux/l113/captures/after/passage-0-1-0-station-25.vfmesh", + "drawn_triangles": 134404, + "source_triangles": 181048, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 506.6559510038529, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -14.78808365101151, + -19.14058791856569, + -462.9516351755408 + ], + "target_actual_m": [ + -22.365365057702377, + -8.32444898094667, + -465.2722094791618 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-0-1-0-station-25-mesh.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-station-25-render.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-station-25-quality.log" + ] + }, + { + "name": "passage-0-1-0-station-50", + "passage": "passage/0-1/0", + "kind": "station", + "station": "50%", + "camera": [ + -5.842575724534995, + 21.863949924887685, + -554.1407724137848 + ], + "target": [ + 7.380291766383868, + 21.57573157504241, + -556.4619792527176 + ], + "yaw": 91.24867624366509, + "pitch": -9.954217908601981, + "focus": [ + -5.738491686463744, + 21.12120736314857, + -553.8781396145471 + ], + "center_z": -553.8781396145471, + "route_distance_m": 1013.3119020077058, + "route_length_m": 2026.6238040154117, + "requested_route_distance_m": 1013.3119020077058, + "variant": "after", + "capture": "captures/after/passage-0-1-0-station-50.png", + "scene": "Saved/Linux/l113/captures/after/passage-0-1-0-station-50.vfmesh", + "drawn_triangles": 314118, + "source_triangles": 400638, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1013.3119020077058, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -5.842575724534995, + 21.863949924887685, + -554.1407724137848 + ], + "target_actual_m": [ + 7.380291766383868, + 21.57573157504241, + -556.4619792527176 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-0-1-0-station-50-mesh.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-station-50-render.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-station-50-quality.log" + ] + }, + { + "name": "passage-0-1-0-station-75", + "passage": "passage/0-1/0", + "kind": "station", + "station": "75%", + "camera": [ + 16.763485216854995, + -13.640943979476505, + -645.3279593243624 + ], + "target": [ + 6.569824394878262, + -21.9100022794575, + -647.6488325282868 + ], + "yaw": -129.04883094075703, + "pitch": -10.027223169087986, + "focus": [ + 16.183682248926296, + -13.165204010185432, + -645.0653265251246 + ], + "center_z": -645.0653265251246, + "route_distance_m": 1519.9678530115589, + "route_length_m": 2026.6238040154117, + "requested_route_distance_m": 1519.9678530115589, + "variant": "after", + "capture": "captures/after/passage-0-1-0-station-75.png", + "scene": "Saved/Linux/l113/captures/after/passage-0-1-0-station-75.vfmesh", + "drawn_triangles": 255252, + "source_triangles": 326582, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1519.9678530115589, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 16.763485216854995, + -13.640943979476505, + -645.3279593243624 + ], + "target_actual_m": [ + 6.569824394878262, + -21.9100022794575, + -647.6488325282868 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-0-1-0-station-75-mesh.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-station-75-render.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-station-75-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-1-view-1", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-1/view-1", + "camera": [ + 14.171597054271547, + 7.048153239139165, + -371.997 + ], + "target": [ + 7.272, + 7.748, + -373.097 + ], + "yaw": -84.20812706837869, + "pitch": -9.012926456869502, + "focus": [ + 7.272, + 7.748, + -373.197 + ], + "center_z": -373.197, + "open_air_section": 1, + "route_distance_m": 8.3545, + "requested_route_distance_m": 8.3545, + "route_length_m": 2026.6238040154117, + "variant": "after", + "capture": "captures/after/passage-0-1-0-openair-1-view-1.png", + "scene": "Saved/Linux/l113/captures/after/passage-0-1-0-openair-1-view-1.vfmesh", + "drawn_triangles": 279171, + "source_triangles": 346937, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 8.3545, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 14.171597054271547, + 7.048153239139165, + -371.997 + ], + "target_actual_m": [ + 7.272, + 7.748, + -373.097 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-1-view-1-mesh.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-1-view-1-render.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-1-view-1-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-1-view-2", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-1/view-2", + "camera": [ + 1.8647454953185498, + 8.296473993551354, + -369.197 + ], + "target": [ + 7.071844918470327, + 5.7747260089609505, + -373.4541530665317 + ], + "yaw": 115.84045885980866, + "pitch": -36.34636101909703, + "focus": [ + 7.272, + 7.748, + -373.197 + ], + "center_z": -373.197, + "open_air_section": 1, + "route_distance_m": 8.3545, + "requested_route_distance_m": 8.3545, + "route_length_m": 2026.6238040154117, + "variant": "after", + "capture": "captures/after/passage-0-1-0-openair-1-view-2.png", + "scene": "Saved/Linux/l113/captures/after/passage-0-1-0-openair-1-view-2.vfmesh", + "drawn_triangles": 287908, + "source_triangles": 358976, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 8.3545, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 1.8647454953185498, + 8.296473993551354, + -369.197 + ], + "target_actual_m": [ + 7.071844918470327, + 5.7747260089609505, + -373.4541530665317 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-1-view-2-mesh.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-1-view-2-render.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-1-view-2-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-1-view-3", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-1/view-3", + "camera": [ + 7.272, + 7.748, + -373.652 + ], + "target": [ + 6.571457214646145, + 0.8415410313633265, + -374.55203573286104 + ], + "yaw": -174.2081270683787, + "pitch": -7.3873433616526025, + "focus": [ + 7.272, + 7.748, + -373.197 + ], + "center_z": -373.197, + "open_air_section": 1, + "route_distance_m": 8.3545, + "requested_route_distance_m": 8.3545, + "route_length_m": 2026.6238040154117, + "variant": "after", + "capture": "captures/after/passage-0-1-0-openair-1-view-3.png", + "scene": "Saved/Linux/l113/captures/after/passage-0-1-0-openair-1-view-3.vfmesh", + "drawn_triangles": 312014, + "source_triangles": 392572, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 8.3545, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 7.272, + 7.748, + -373.652 + ], + "target_actual_m": [ + 6.571457214646145, + 0.8415410313633265, + -374.55203573286104 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-1-view-3-mesh.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-1-view-3-render.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-1-view-3-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-1-4m-outside", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-1/4m-outside", + "camera": [ + 13.176702021211483, + 7.149068417345486, + -374.402 + ], + "target": [ + 9.197121888971225, + 7.5527291301707695, + -374.402 + ], + "yaw": -84.20812706837869, + "pitch": 0.0, + "focus": [ + 7.272, + 7.748, + -373.197 + ], + "center_z": -373.197, + "open_air_section": 1, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.9948950330600643, + -0.1009151782063209, + 0.0 + ], + "camera_target_distance_m": 4.000000000000001, + "route_distance_m": 8.3545, + "requested_route_distance_m": 8.3545, + "route_length_m": 2026.6238040154117, + "variant": "after", + "capture": "captures/after/passage-0-1-0-openair-1-4m-outside.png", + "scene": "Saved/Linux/l113/captures/after/passage-0-1-0-openair-1-4m-outside.vfmesh", + "drawn_triangles": 279171, + "source_triangles": 346937, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 8.3545, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.9999999999999982, + "closeup_target_surface_distance_m": 0.8115739125132071, + "closeup_predicted_target_offset_m": 0.8115739125132071, + "closeup_wall_normal_alignment": 0.9909370337827299, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 13.001310859531525, + 8.030798839669227, + -374.0681219724272 + ], + "target_actual_m": [ + 9.014100074768066, + 8.0, + -373.75 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-1-4m-outside-mesh.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-1-4m-outside-render.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-1-4m-outside-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-1-4m-interior-wall", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-1/4m-interior-wall", + "camera": [ + 7.395778712540976, + 3.8749008126934172, + -374.89997477205173 + ], + "target": [ + 8.778272394312646, + 7.595214286886338, + -374.402 + ], + "yaw": 20.38540702862518, + "pitch": 7.1515181408188955, + "focus": [ + 7.272, + 7.748, + -373.197 + ], + "center_z": -373.197, + "open_air_section": 1, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.9948950330600643, + 0.1009151782063209, + -0.0 + ], + "camera_target_distance_m": 3.9999999999999973, + "route_distance_m": 8.3545, + "requested_route_distance_m": 8.3545, + "route_length_m": 2026.6238040154117, + "variant": "after", + "capture": "captures/after/passage-0-1-0-openair-1-4m-interior-wall.png", + "scene": "Saved/Linux/l113/captures/after/passage-0-1-0-openair-1-4m-interior-wall.vfmesh", + "drawn_triangles": 312014, + "source_triangles": 392572, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 8.3545, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.999999999999999, + "closeup_target_surface_distance_m": 0.8028512741535025, + "closeup_predicted_target_offset_m": 0.8028512741535025, + "closeup_wall_normal_alignment": 0.9909370337827299, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 5.026889290004607, + 7.969201160330773, + -373.4318780275728 + ], + "target_actual_m": [ + 9.014100074768066, + 8.0, + -373.75 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-1-4m-interior-wall-mesh.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-1-4m-interior-wall-render.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-1-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-2-view-1", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-2/view-1", + "camera": [ + 13.806920171614387, + 0.8302038482412197, + -372.949 + ], + "target": [ + 6.603, + 1.698, + -374.049 + ], + "yaw": -83.1311525734364, + "pitch": -8.620326383568274, + "focus": [ + 6.603, + 1.698, + -374.149 + ], + "center_z": -374.149, + "open_air_section": 2, + "route_distance_m": 14.4925, + "requested_route_distance_m": 14.4925, + "route_length_m": 2026.6238040154117, + "variant": "after", + "capture": "captures/after/passage-0-1-0-openair-2-view-1.png", + "scene": "Saved/Linux/l113/captures/after/passage-0-1-0-openair-2-view-1.vfmesh", + "drawn_triangles": 279171, + "source_triangles": 346937, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 14.4925, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 13.806920171614387, + 0.8302038482412197, + -372.949 + ], + "target_actual_m": [ + 6.603, + 1.698, + -374.049 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-2-view-1-mesh.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-2-view-1-render.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-2-view-1-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-2-view-2", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-2/view-2", + "camera": [ + 0.8883136014591493, + 2.3864005856564967, + -370.149 + ], + "target": [ + 6.367681865010997, + -0.25546920582469834, + -374.5075853276975 + ], + "yaw": 115.74097579560643, + "pitch": -35.62229543250913, + "focus": [ + 6.603, + 1.698, + -374.149 + ], + "center_z": -374.149, + "open_air_section": 2, + "route_distance_m": 14.4925, + "requested_route_distance_m": 14.4925, + "route_length_m": 2026.6238040154117, + "variant": "after", + "capture": "captures/after/passage-0-1-0-openair-2-view-2.png", + "scene": "Saved/Linux/l113/captures/after/passage-0-1-0-openair-2-view-2.vfmesh", + "drawn_triangles": 312014, + "source_triangles": 392572, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 14.4925, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 0.8883136014591493, + 2.3864005856564967, + -370.149 + ], + "target_actual_m": [ + 6.367681865010997, + -0.25546920582469834, + -374.5075853276975 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-2-view-2-mesh.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-2-view-2-render.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-2-view-2-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-2-view-3", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-2/view-3", + "camera": [ + 6.603, + 1.698, + -374.76163279923776 + ], + "target": [ + 5.77938652753849, + -5.139142220386445, + -376.016681446179 + ], + "yaw": -173.1311525734364, + "pitch": -10.32856219521722, + "focus": [ + 6.603, + 1.698, + -374.149 + ], + "center_z": -374.149, + "open_air_section": 2, + "route_distance_m": 14.4925, + "requested_route_distance_m": 14.4925, + "route_length_m": 2026.6238040154117, + "variant": "after", + "capture": "captures/after/passage-0-1-0-openair-2-view-3.png", + "scene": "Saved/Linux/l113/captures/after/passage-0-1-0-openair-2-view-3.vfmesh", + "drawn_triangles": 312014, + "source_triangles": 392572, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 14.4925, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 6.603, + 1.698, + -374.76163279923776 + ], + "target_actual_m": [ + 5.77938652753849, + -5.139142220386445, + -376.016681446179 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-2-view-3-mesh.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-2-view-3-render.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-2-view-3-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-2-4m-outside", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-2/4m-outside", + "camera": [ + 12.814097656232029, + 0.949800892309409, + -375.51163279923776 + ], + "target": [ + 8.842807594702599, + 1.4281890685821654, + -375.51163279923776 + ], + "yaw": -83.1311525734364, + "pitch": 0.0, + "focus": [ + 6.603, + 1.698, + -374.149 + ], + "center_z": -374.149, + "open_air_section": 2, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.9928225153823576, + -0.1195970440681891, + 0.0 + ], + "camera_target_distance_m": 4.0, + "route_distance_m": 14.4925, + "requested_route_distance_m": 14.4925, + "route_length_m": 2026.6238040154117, + "variant": "after", + "capture": "captures/after/passage-0-1-0-openair-2-4m-outside.png", + "scene": "Saved/Linux/l113/captures/after/passage-0-1-0-openair-2-4m-outside.vfmesh", + "drawn_triangles": 279171, + "source_triangles": 346937, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 14.4925, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.999999999999999, + "closeup_target_surface_distance_m": 1.0636849811376077, + "closeup_predicted_target_offset_m": 1.0636849811376077, + "closeup_wall_normal_alignment": 0.5076869493421745, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 10.308092134198723, + 3.1767909686139304, + -378.43646027440843 + ], + "target_actual_m": [ + 8.000443458557129, + 1.0, + -376.0 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-2-4m-outside-mesh.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-2-4m-outside-render.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-2-4m-outside-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-2-4m-interior-wall", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-2/4m-interior-wall", + "camera": [ + 6.939570778854576, + -2.1803140897652855, + -376.2060303004211 + ], + "target": [ + 8.388084903173432, + 1.4829657169105679, + -375.51163279923776 + ], + "yaw": 21.574563086437188, + "pitch": 9.997160707081923, + "focus": [ + 6.603, + 1.698, + -374.149 + ], + "center_z": -374.149, + "open_air_section": 2, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.9928225153823576, + 0.1195970440681891, + -0.0 + ], + "camera_target_distance_m": 3.999999999999997, + "route_distance_m": 14.4925, + "requested_route_distance_m": 14.4925, + "route_length_m": 2026.6238040154117, + "variant": "after", + "capture": "captures/after/passage-0-1-0-openair-2-4m-interior-wall.png", + "scene": "Saved/Linux/l113/captures/after/passage-0-1-0-openair-2-4m-interior-wall.vfmesh", + "drawn_triangles": 350214, + "source_triangles": 445390, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 14.4925, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.999999999999994, + "closeup_target_surface_distance_m": 0.7853095224094995, + "closeup_predicted_target_offset_m": 0.7853095224094995, + "closeup_wall_normal_alignment": 0.5553784184471084, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 5.4959837119606645, + -0.739874885164667, + -373.39806557553993 + ], + "target_actual_m": [ + 7.949404625801623, + 1.0519574368837428, + -376.0 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-2-4m-interior-wall-mesh.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-2-4m-interior-wall-render.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-2-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-3-view-1", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-3/view-1", + "camera": [ + -29.152636206395663, + -17.00250445676227, + -598.044 + ], + "target": [ + -22.1, + -12.258, + -599.144 + ], + "yaw": 56.07018168236041, + "pitch": -7.373766361330365, + "focus": [ + -22.1, + -12.258, + -599.244 + ], + "center_z": -599.244, + "open_air_section": 3, + "route_distance_m": 1265.3425000000002, + "requested_route_distance_m": 1265.3425000000002, + "route_length_m": 2026.6238040154117, + "variant": "after", + "capture": "captures/after/passage-0-1-0-openair-3-view-1.png", + "scene": "Saved/Linux/l113/captures/after/passage-0-1-0-openair-3-view-1.vfmesh", + "drawn_triangles": 207429, + "source_triangles": 257263, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1265.3425000000002, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -29.152636206395663, + -17.00250445676227, + -598.044 + ], + "target_actual_m": [ + -22.1, + -12.258, + -599.144 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-3-view-1-mesh.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-3-view-1-render.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-3-view-1-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-3-view-2", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-3/view-2", + "camera": [ + -16.29194665355652, + -8.35076103560754, + -595.244 + ], + "target": [ + -23.198124843266566, + -10.625653545413794, + -599.6039539981729 + ], + "yaw": -108.23186364164575, + "pitch": -30.947707661773293, + "focus": [ + -22.1, + -12.258, + -599.244 + ], + "center_z": -599.244, + "open_air_section": 3, + "route_distance_m": 1265.3425000000002, + "requested_route_distance_m": 1265.3425000000002, + "route_length_m": 2026.6238040154117, + "variant": "after", + "capture": "captures/after/passage-0-1-0-openair-3-view-2.png", + "scene": "Saved/Linux/l113/captures/after/passage-0-1-0-openair-3-view-2.vfmesh", + "drawn_triangles": 185112, + "source_triangles": 230374, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1265.3425000000002, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -16.29194665355652, + -8.35076103560754, + -595.244 + ], + "target_actual_m": [ + -23.198124843266566, + -10.625653545413794, + -599.6039539981729 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-3-view-2-mesh.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-3-view-2-render.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-3-view-2-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-3-view-3", + "passage": "passage/0-1/0", + "kind": "open-air", + "station": "section-3/view-3", + "camera": [ + -22.1, + -12.258, + -599.8566327992378 + ], + "target": [ + -25.943436951432982, + -6.544787408948284, + -601.1164717928428 + ], + "yaw": -33.9298183176396, + "pitch": -10.368420070612796, + "focus": [ + -22.1, + -12.258, + -599.244 + ], + "center_z": -599.244, + "open_air_section": 3, + "route_distance_m": 1265.3425000000002, + "requested_route_distance_m": 1265.3425000000002, + "route_length_m": 2026.6238040154117, + "variant": "after", + "capture": "captures/after/passage-0-1-0-openair-3-view-3.png", + "scene": "Saved/Linux/l113/captures/after/passage-0-1-0-openair-3-view-3.vfmesh", + "drawn_triangles": 185112, + "source_triangles": 230374, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1265.3425000000002, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -22.1, + -12.258, + -599.8566327992378 + ], + "target_actual_m": [ + -25.943436951432982, + -6.544787408948284, + -601.1164717928428 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-3-view-3-mesh.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-3-view-3-render.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-3-view-3-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-3-4m-outside", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-3/4m-outside", + "camera": [ + -28.32291429976088, + -16.444327461849063, + -600.6066327992378 + ], + "target": [ + -25.004026673221745, + -14.211619482196229, + -600.6066327992378 + ], + "yaw": 56.07018168236039, + "pitch": 0.0, + "focus": [ + -22.1, + -12.258, + -599.244 + ], + "center_z": -599.244, + "open_air_section": 3, + "closeup_side": "outside", + "closeup_preferred_normal": [ + -0.8297219066347834, + -0.5581769949132084, + 0.0 + ], + "camera_target_distance_m": 4.000000000000001, + "route_distance_m": 1265.3425000000002, + "requested_route_distance_m": 1265.3425000000002, + "route_length_m": 2026.6238040154117, + "variant": "after", + "capture": "captures/after/passage-0-1-0-openair-3-4m-outside.png", + "scene": "Saved/Linux/l113/captures/after/passage-0-1-0-openair-3-4m-outside.vfmesh", + "drawn_triangles": 153860, + "source_triangles": 191080, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1265.3425000000002, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.9999999999999876, + "closeup_target_surface_distance_m": 0.2075870788097849, + "closeup_predicted_target_offset_m": 0.2075870788097849, + "closeup_wall_normal_alignment": 0.904243137935264, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -27.651340681601248, + -16.413326726394757, + -602.2036214218188 + ], + "target_actual_m": [ + -24.8358770618729, + -14.118497808699297, + -600.5282334534679 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-3-4m-outside-mesh.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-3-4m-outside-render.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-3-4m-outside-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-3-4m-interior-wall", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-3/4m-interior-wall", + "camera": [ + -26.071689640946218, + -10.338278587083852, + -601.3036807194 + ], + "target": [ + -24.774901932566983, + -14.057480898923608, + -600.6066327992378 + ], + "yaw": 160.77768453528284, + "pitch": 10.035712777782798, + "focus": [ + -22.1, + -12.258, + -599.244 + ], + "center_z": -599.244, + "open_air_section": 3, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + 0.8297219066347834, + 0.5581769949132084, + -0.0 + ], + "camera_target_distance_m": 4.000000000000005, + "route_distance_m": 1265.3425000000002, + "requested_route_distance_m": 1265.3425000000002, + "route_length_m": 2026.6238040154117, + "variant": "after", + "capture": "captures/after/passage-0-1-0-openair-3-4m-interior-wall.png", + "scene": "Saved/Linux/l113/captures/after/passage-0-1-0-openair-3-4m-interior-wall.vfmesh", + "drawn_triangles": 152882, + "source_triangles": 191476, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1265.3425000000002, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.999999999999989, + "closeup_target_surface_distance_m": 0.04715362672685941, + "closeup_predicted_target_offset_m": 0.04715362672685941, + "closeup_wall_normal_alignment": 0.8914972029009958, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -22.090001742014795, + -11.737840633493331, + -598.8622157263953 + ], + "target_actual_m": [ + -24.81309729642714, + -14.078633586544772, + -600.6244412943872 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-3-4m-interior-wall-mesh.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-3-4m-interior-wall-render.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-3-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-1-2-0-upper-mouth", + "passage": "passage/1-2/0", + "kind": "mouth", + "station": "upper-mouth", + "camera": [ + 23.39180762797774, + -15.509524798921928, + -731.7810546875 + ], + "target": [ + 17.28788584589878, + -13.618271096312476, + -731.8810546875 + ], + "yaw": -72.7848029211395, + "pitch": -0.8965458221544697, + "focus": [ + 19.166015625, + -14.2001953125, + -730.5610546875 + ], + "center_z": -730.5610546875, + "variant": "after", + "capture": "captures/after/passage-1-2-0-upper-mouth.png", + "scene": "Saved/Linux/l113/captures/after/passage-1-2-0-upper-mouth.vfmesh", + "drawn_triangles": 595672, + "source_triangles": 665178, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": null, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 23.39180762797774, + -15.509524798921928, + -731.7810546875 + ], + "target_actual_m": [ + 17.28788584589878, + -13.618271096312476, + -731.8810546875 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-1-2-0-upper-mouth-mesh.log", + "Saved/Linux/l113/captures/after/passage-1-2-0-upper-mouth-render.log", + "Saved/Linux/l113/captures/after/passage-1-2-0-upper-mouth-quality.log" + ] + }, + { + "name": "passage-1-2-0-lower-mouth", + "passage": "passage/1-2/0", + "kind": "mouth", + "station": "lower-mouth", + "camera": [ + 27.129937681588373, + -19.073450175278364, + -751.8771866414096 + ], + "target": [ + 17.48940045519192, + -13.174246920336135, + -753.05390625 + ], + "yaw": -58.53685078395012, + "pitch": -5.943870452561027, + "focus": [ + 19.166015625, + -14.2001953125, + -751.73390625 + ], + "center_z": -751.73390625, + "variant": "after", + "capture": "captures/after/passage-1-2-0-lower-mouth.png", + "scene": "Saved/Linux/l113/captures/after/passage-1-2-0-lower-mouth.vfmesh", + "drawn_triangles": 546142, + "source_triangles": 593592, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": null, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 27.129937681588373, + -19.073450175278364, + -751.8771866414096 + ], + "target_actual_m": [ + 17.48940045519192, + -13.174246920336135, + -753.05390625 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-1-2-0-lower-mouth-mesh.log", + "Saved/Linux/l113/captures/after/passage-1-2-0-lower-mouth-render.log", + "Saved/Linux/l113/captures/after/passage-1-2-0-lower-mouth-quality.log" + ] + }, + { + "name": "passage-1-2-0-station-25", + "passage": "passage/1-2/0", + "kind": "station", + "station": "25%", + "camera": [ + 14.123536467456244, + 6.240983804873839, + -736.9266568574585 + ], + "target": [ + 2.8803137791411038, + 14.614332686305787, + -739.3139366342602 + ], + "yaw": -53.32323690581729, + "pitch": -9.66435626972965, + "focus": [ + 14.813654134436735, + 6.534646205806277, + -735.7566568574586 + ], + "center_z": -735.7566568574586, + "route_distance_m": 28.747657939523272, + "route_length_m": 114.99063175809309, + "requested_route_distance_m": 28.747657939523272, + "variant": "after", + "capture": "captures/after/passage-1-2-0-station-25.png", + "scene": "Saved/Linux/l113/captures/after/passage-1-2-0-station-25.vfmesh", + "drawn_triangles": 654984, + "source_triangles": 755070, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 28.747657939523272, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 14.123536467456244, + 6.240983804873839, + -736.9266568574585 + ], + "target_actual_m": [ + 2.8803137791411038, + 14.614332686305787, + -739.3139366342602 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-1-2-0-station-25-mesh.log", + "Saved/Linux/l113/captures/after/passage-1-2-0-station-25-render.log", + "Saved/Linux/l113/captures/after/passage-1-2-0-station-25-quality.log" + ] + }, + { + "name": "passage-1-2-0-station-50", + "passage": "passage/1-2/0", + "kind": "station", + "station": "50%", + "camera": [ + -8.14430619211178, + 12.235240826338718, + -742.2394815085395 + ], + "target": [ + -12.700487024811965, + -1.038727127296823, + -744.628569343647 + ], + "yaw": -161.05563621352672, + "pitch": -9.661077464733383, + "focus": [ + -8.621845503855653, + 12.813562713992287, + -741.0694815085395 + ], + "center_z": -741.0694815085395, + "route_distance_m": 57.495315879046544, + "route_length_m": 114.99063175809309, + "requested_route_distance_m": 57.495315879046544, + "variant": "after", + "capture": "captures/after/passage-1-2-0-station-50.png", + "scene": "Saved/Linux/l113/captures/after/passage-1-2-0-station-50.vfmesh", + "drawn_triangles": 604712, + "source_triangles": 685166, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 57.495315879046544, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -8.14430619211178, + 12.235240826338718, + -742.2394815085395 + ], + "target_actual_m": [ + -12.700487024811965, + -1.038727127296823, + -744.628569343647 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-1-2-0-station-50-mesh.log", + "Saved/Linux/l113/captures/after/passage-1-2-0-station-50-render.log", + "Saved/Linux/l113/captures/after/passage-1-2-0-station-50-quality.log" + ] + }, + { + "name": "passage-1-2-0-station-75", + "passage": "passage/1-2/0", + "kind": "station", + "station": "75%", + "camera": [ + -6.987446947881857, + -10.765115248422655, + -747.5564684387438 + ], + "target": [ + 7.091762142236872, + -11.042713876861228, + -749.9489555153405 + ], + "yaw": 91.12954989855486, + "pitch": -9.642336322206393, + "focus": [ + -7.402667393484897, + -11.38968868810226, + -746.3864684387438 + ], + "center_z": -746.3864684387438, + "route_distance_m": 86.24297381856982, + "route_length_m": 114.99063175809309, + "requested_route_distance_m": 86.24297381856982, + "variant": "after", + "capture": "captures/after/passage-1-2-0-station-75.png", + "scene": "Saved/Linux/l113/captures/after/passage-1-2-0-station-75.vfmesh", + "drawn_triangles": 612097, + "source_triangles": 692301, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 86.24297381856982, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -6.987446947881857, + -10.765115248422655, + -747.5564684387438 + ], + "target_actual_m": [ + 7.091762142236872, + -11.042713876861228, + -749.9489555153405 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-1-2-0-station-75-mesh.log", + "Saved/Linux/l113/captures/after/passage-1-2-0-station-75-render.log", + "Saved/Linux/l113/captures/after/passage-1-2-0-station-75-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-1-view-1", + "passage": "passage/1-2/0", + "kind": "open-air", + "station": "section-1/view-1", + "camera": [ + -4.010662222207793, + -3.928480667735541, + -744.68 + ], + "target": [ + -9.518, + -9.731, + -745.78 + ], + "yaw": -136.49505148095557, + "pitch": -7.829076510059767, + "focus": [ + -9.518, + -9.731, + -745.88 + ], + "center_z": -745.88, + "open_air_section": 1, + "route_distance_m": 83.504, + "requested_route_distance_m": 83.504, + "route_length_m": 114.99063175809309, + "variant": "after", + "capture": "captures/after/passage-1-2-0-openair-1-view-1.png", + "scene": "Saved/Linux/l113/captures/after/passage-1-2-0-openair-1-view-1.vfmesh", + "drawn_triangles": 623418, + "source_triangles": 711740, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 83.504, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -4.010662222207793, + -3.928480667735541, + -744.68 + ], + "target_actual_m": [ + -9.518, + -9.731, + -745.78 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-1-2-0-openair-1-view-1-mesh.log", + "Saved/Linux/l113/captures/after/passage-1-2-0-openair-1-view-1-render.log", + "Saved/Linux/l113/captures/after/passage-1-2-0-openair-1-view-1-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-1-view-2", + "passage": "passage/1-2/0", + "kind": "open-air", + "station": "section-1/view-2", + "camera": [ + -13.99271194445617, + -14.445546957464874, + -741.88 + ], + "target": [ + -8.092470510849907, + -11.08401098702058, + -746.2504415535075 + ], + "yaw": 60.328600337066774, + "pitch": -32.76525220659009, + "focus": [ + -9.518, + -9.731, + -745.88 + ], + "center_z": -745.88, + "open_air_section": 1, + "route_distance_m": 83.504, + "requested_route_distance_m": 83.504, + "route_length_m": 114.99063175809309, + "variant": "after", + "capture": "captures/after/passage-1-2-0-openair-1-view-2.png", + "scene": "Saved/Linux/l113/captures/after/passage-1-2-0-openair-1-view-2.vfmesh", + "drawn_triangles": 575936, + "source_triangles": 644954, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 83.504, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -13.99271194445617, + -14.445546957464874, + -741.88 + ], + "target_actual_m": [ + -8.092470510849907, + -11.08401098702058, + -746.2504415535075 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-1-2-0-openair-1-view-2-mesh.log", + "Saved/Linux/l113/captures/after/passage-1-2-0-openair-1-view-2-render.log", + "Saved/Linux/l113/captures/after/passage-1-2-0-openair-1-view-2-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-1-view-3", + "passage": "passage/1-2/0", + "kind": "open-air", + "station": "section-1/view-3", + "camera": [ + -9.518, + -9.731, + -747.4 + ], + "target": [ + -4.528646787974676, + -14.466538454572031, + -748.6965454372763 + ], + "yaw": 133.50494851904446, + "pitch": -10.674004431858014, + "focus": [ + -9.518, + -9.731, + -745.88 + ], + "center_z": -745.88, + "open_air_section": 1, + "route_distance_m": 83.504, + "requested_route_distance_m": 83.504, + "route_length_m": 114.99063175809309, + "variant": "after", + "capture": "captures/after/passage-1-2-0-openair-1-view-3.png", + "scene": "Saved/Linux/l113/captures/after/passage-1-2-0-openair-1-view-3.vfmesh", + "drawn_triangles": 570541, + "source_triangles": 638615, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 83.504, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -9.518, + -9.731, + -747.4 + ], + "target_actual_m": [ + -4.528646787974676, + -14.466538454572031, + -748.6965454372763 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-1-2-0-openair-1-view-3-mesh.log", + "Saved/Linux/l113/captures/after/passage-1-2-0-openair-1-view-3-render.log", + "Saved/Linux/l113/captures/after/passage-1-2-0-openair-1-view-3-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-1-4m-outside", + "passage": "passage/1-2/0", + "kind": "open-air-close", + "station": "section-1/4m-outside", + "camera": [ + -4.699079444431819, + -4.6537955842685985, + -748.15 + ], + "target": [ + -7.452748333327923, + -7.555055250400828, + -748.15 + ], + "yaw": -136.49505148095557, + "pitch": 0.0, + "focus": [ + -9.518, + -9.731, + -745.88 + ], + "center_z": -745.88, + "open_air_section": 1, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.688417222224026, + 0.7253149165330574, + 0.0 + ], + "camera_target_distance_m": 4.000000000000001, + "route_distance_m": 83.504, + "requested_route_distance_m": 83.504, + "route_length_m": 114.99063175809309, + "variant": "after", + "capture": "captures/after/passage-1-2-0-openair-1-4m-outside.png", + "scene": "Saved/Linux/l113/captures/after/passage-1-2-0-openair-1-4m-outside.vfmesh", + "drawn_triangles": 623418, + "source_triangles": 711740, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 83.504, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.99999999999999, + "closeup_target_surface_distance_m": 0.694202433854289, + "closeup_predicted_target_offset_m": 0.694202433854289, + "closeup_wall_normal_alignment": 0.6320955190222977, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -4.078884776303333, + -7.574630837765809, + -745.9346460853614 + ], + "target_actual_m": [ + -7.75, + -7.576179311817557, + -747.523013365486 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-1-2-0-openair-1-4m-outside-mesh.log", + "Saved/Linux/l113/captures/after/passage-1-2-0-openair-1-4m-outside-render.log", + "Saved/Linux/l113/captures/after/passage-1-2-0-openair-1-4m-outside-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-1-4m-interior-wall", + "passage": "passage/1-2/0", + "kind": "open-air-close", + "station": "section-1/4m-interior-wall", + "camera": [ + -6.0956279351195075, + -11.653774892861163, + -748.8673569837389 + ], + "target": [ + -8.16773669839842, + -8.308365466344922, + -748.15 + ], + "yaw": -31.773605793127505, + "pitch": 10.331275124559749, + "focus": [ + -9.518, + -9.731, + -745.88 + ], + "center_z": -745.88, + "open_air_section": 1, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.688417222224026, + -0.7253149165330574, + -0.0 + ], + "camera_target_distance_m": 3.999999999999997, + "route_distance_m": 83.504, + "requested_route_distance_m": 83.504, + "route_length_m": 114.99063175809309, + "variant": "after", + "capture": "captures/after/passage-1-2-0-openair-1-4m-interior-wall.png", + "scene": "Saved/Linux/l113/captures/after/passage-1-2-0-openair-1-4m-interior-wall.vfmesh", + "drawn_triangles": 612097, + "source_triangles": 692301, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 83.504, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.999999999999999, + "closeup_target_surface_distance_m": 0.6509430039577998, + "closeup_predicted_target_offset_m": 0.6509430039577998, + "closeup_wall_normal_alignment": 0.7808473937095911, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -8.525095579521167, + -12.94135557024142, + -748.3220319510015 + ], + "target_actual_m": [ + -8.18421537084871, + -8.958641713644115, + -748.1744141343152 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-1-2-0-openair-1-4m-interior-wall-mesh.log", + "Saved/Linux/l113/captures/after/passage-1-2-0-openair-1-4m-interior-wall-render.log", + "Saved/Linux/l113/captures/after/passage-1-2-0-openair-1-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-2-view-1", + "passage": "passage/1-2/0", + "kind": "open-air", + "station": "section-2/view-1", + "camera": [ + 6.13292788028755, + -3.743002188934521, + -748.543 + ], + "target": [ + 9.43, + -11.181, + -749.643 + ], + "yaw": 156.09352823535562, + "pitch": -7.6997900448953684, + "focus": [ + 9.43, + -11.181, + -749.743 + ], + "center_z": -749.743, + "open_air_section": 2, + "route_distance_m": 104.362, + "requested_route_distance_m": 104.362, + "route_length_m": 114.99063175809309, + "variant": "after", + "capture": "captures/after/passage-1-2-0-openair-2-view-1.png", + "scene": "Saved/Linux/l113/captures/after/passage-1-2-0-openair-2-view-1.vfmesh", + "drawn_triangles": 628096, + "source_triangles": 720280, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 104.362, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 6.13292788028755, + -3.743002188934521, + -748.543 + ], + "target_actual_m": [ + 9.43, + -11.181, + -749.643 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-1-2-0-openair-2-view-1-mesh.log", + "Saved/Linux/l113/captures/after/passage-1-2-0-openair-2-view-1-render.log", + "Saved/Linux/l113/captures/after/passage-1-2-0-openair-2-view-1-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-2-view-2", + "passage": "passage/1-2/0", + "kind": "open-air", + "station": "section-2/view-2", + "camera": [ + 12.119204841004402, + -17.24768553026432, + -745.743 + ], + "target": [ + 11.227153830879562, + -10.384368172304068, + -750.111260558921 + ], + "yaw": -7.405432412441471, + "pitch": -32.25832231519941, + "focus": [ + 9.43, + -11.181, + -749.743 + ], + "center_z": -749.743, + "open_air_section": 2, + "route_distance_m": 104.362, + "requested_route_distance_m": 104.362, + "route_length_m": 114.99063175809309, + "variant": "after", + "capture": "captures/after/passage-1-2-0-openair-2-view-2.png", + "scene": "Saved/Linux/l113/captures/after/passage-1-2-0-openair-2-view-2.vfmesh", + "drawn_triangles": 585354, + "source_triangles": 650680, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 104.362, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 12.119204841004402, + -17.24768553026432, + -745.743 + ], + "target_actual_m": [ + 11.227153830879562, + -10.384368172304068, + -750.111260558921 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-1-2-0-openair-2-view-2-mesh.log", + "Saved/Linux/l113/captures/after/passage-1-2-0-openair-2-view-2-render.log", + "Saved/Linux/l113/captures/after/passage-1-2-0-openair-2-view-2-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-2-view-3", + "passage": "passage/1-2/0", + "kind": "open-air", + "station": "section-2/view-3", + "camera": [ + 9.43, + -11.181, + -751.263 + ], + "target": [ + 15.72003840807847, + -8.392788603064238, + -752.5519119562233 + ], + "yaw": 66.09352823535562, + "pitch": -10.61043002727037, + "focus": [ + 9.43, + -11.181, + -749.743 + ], + "center_z": -749.743, + "open_air_section": 2, + "route_distance_m": 104.362, + "requested_route_distance_m": 104.362, + "route_length_m": 114.99063175809309, + "variant": "after", + "capture": "captures/after/passage-1-2-0-openair-2-view-3.png", + "scene": "Saved/Linux/l113/captures/after/passage-1-2-0-openair-2-view-3.vfmesh", + "drawn_triangles": 613434, + "source_triangles": 694694, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 104.362, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 9.43, + -11.181, + -751.263 + ], + "target_actual_m": [ + 15.72003840807847, + -8.392788603064238, + -752.5519119562233 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-1-2-0-openair-2-view-3-mesh.log", + "Saved/Linux/l113/captures/after/passage-1-2-0-openair-2-view-3-render.log", + "Saved/Linux/l113/captures/after/passage-1-2-0-openair-2-view-3-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-2-4m-outside", + "passage": "passage/1-2/0", + "kind": "open-air-close", + "station": "section-2/4m-outside", + "camera": [ + 6.53817273275958, + -4.657210376135293, + -752.013 + ], + "target": [ + 8.159152142647708, + -8.31404312493838, + -752.013 + ], + "yaw": 156.09352823535562, + "pitch": 0.0, + "focus": [ + 9.43, + -11.181, + -749.743 + ], + "center_z": -749.743, + "open_air_section": 2, + "closeup_side": "outside", + "closeup_preferred_normal": [ + -0.40524485247203174, + 0.9142081872007717, + 0.0 + ], + "camera_target_distance_m": 4.0, + "route_distance_m": 104.362, + "requested_route_distance_m": 104.362, + "route_length_m": 114.99063175809309, + "variant": "after", + "capture": "captures/after/passage-1-2-0-openair-2-4m-outside.png", + "scene": "Saved/Linux/l113/captures/after/passage-1-2-0-openair-2-4m-outside.vfmesh", + "drawn_triangles": 585844, + "source_triangles": 657940, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 104.362, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.000000000000001, + "closeup_target_surface_distance_m": 0.5914642210657065, + "closeup_predicted_target_offset_m": 0.5914642210657065, + "closeup_wall_normal_alignment": 0.9891491270971497, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 6.36017623097692, + -5.41779354635724, + -752.0611111978326 + ], + "target_actual_m": [ + 8.5, + -8.797159410771899, + -752.028852990306 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-1-2-0-openair-2-4m-outside-mesh.log", + "Saved/Linux/l113/captures/after/passage-1-2-0-openair-2-4m-outside-render.log", + "Saved/Linux/l113/captures/after/passage-1-2-0-openair-2-4m-outside-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-2-4m-interior-wall", + "passage": "passage/1-2/0", + "kind": "open-air-close", + "station": "section-2/4m-interior-wall", + "camera": [ + 12.438590152225206, + -8.574465388721983, + -752.7261335058829 + ], + "target": [ + 8.55317187096847, + -9.20292810238377, + -752.013 + ], + "yaw": -99.18796190221158, + "pitch": 10.269787281460902, + "focus": [ + 9.43, + -11.181, + -749.743 + ], + "center_z": -749.743, + "open_air_section": 2, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + 0.40524485247203174, + -0.9142081872007717, + -0.0 + ], + "camera_target_distance_m": 3.9999999999999973, + "route_distance_m": 104.362, + "requested_route_distance_m": 104.362, + "route_length_m": 114.99063175809309, + "variant": "after", + "capture": "captures/after/passage-1-2-0-openair-2-4m-interior-wall.png", + "scene": "Saved/Linux/l113/captures/after/passage-1-2-0-openair-2-4m-interior-wall.vfmesh", + "drawn_triangles": 574404, + "source_triangles": 636814, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 104.362, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.000000000000001, + "closeup_target_surface_distance_m": 0.3527379880998657, + "closeup_predicted_target_offset_m": 0.3527379880998657, + "closeup_wall_normal_alignment": 0.9984886840143513, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 9.755455381073956, + -12.664189280507138, + -752.0262323451956 + ], + "target_actual_m": [ + 8.337158675455406, + -8.924125097427853, + -752.0074078590392 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-1-2-0-openair-2-4m-interior-wall-mesh.log", + "Saved/Linux/l113/captures/after/passage-1-2-0-openair-2-4m-interior-wall-render.log", + "Saved/Linux/l113/captures/after/passage-1-2-0-openair-2-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-2-3-0-upper-mouth", + "passage": "passage/2-3/0", + "kind": "mouth", + "station": "upper-mouth", + "camera": [ + -24.455025526892644, + -5.631774473341657, + -811.975390625 + ], + "target": [ + -18.110266432492157, + -4.81795266462593, + -812.075390625 + ], + "yaw": 82.6907653180847, + "pitch": -0.8956299428824654, + "focus": [ + -20.0625, + -5.068359375, + -810.755390625 + ], + "center_z": -810.755390625, + "variant": "after", + "capture": "captures/after/passage-2-3-0-upper-mouth.png", + "scene": "Saved/Linux/l113/captures/after/passage-2-3-0-upper-mouth.vfmesh", + "drawn_triangles": 59570, + "source_triangles": 71526, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": null, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -24.455025526892644, + -5.631774473341657, + -811.975390625 + ], + "target_actual_m": [ + -18.110266432492157, + -4.81795266462593, + -812.075390625 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-2-3-0-upper-mouth-mesh.log", + "Saved/Linux/l113/captures/after/passage-2-3-0-upper-mouth-render.log", + "Saved/Linux/l113/captures/after/passage-2-3-0-upper-mouth-quality.log" + ] + }, + { + "name": "passage-2-3-0-lower-mouth", + "passage": "passage/2-3/0", + "kind": "mouth", + "station": "lower-mouth", + "camera": [ + -28.589162628136368, + -1.22631300593053, + -898.8116843726575 + ], + "target": [ + -18.26741313091866, + -5.87721124217252, + -900.0333984375 + ], + "yaw": 114.25594846721253, + "pitch": -6.159177031829821, + "focus": [ + -20.0625, + -5.068359375, + -898.7133984375 + ], + "center_z": -898.7133984375, + "variant": "after", + "capture": "captures/after/passage-2-3-0-lower-mouth.png", + "scene": "Saved/Linux/l113/captures/after/passage-2-3-0-lower-mouth.vfmesh", + "drawn_triangles": 293916, + "source_triangles": 314604, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": null, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -28.589162628136368, + -1.22631300593053, + -898.8116843726575 + ], + "target_actual_m": [ + -18.26741313091866, + -5.87721124217252, + -900.0333984375 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-2-3-0-lower-mouth-mesh.log", + "Saved/Linux/l113/captures/after/passage-2-3-0-lower-mouth-render.log", + "Saved/Linux/l113/captures/after/passage-2-3-0-lower-mouth-quality.log" + ] + }, + { + "name": "passage-2-3-0-station-25", + "passage": "passage/2-3/0", + "kind": "station", + "station": "25%", + "camera": [ + 3.0350580952420283, + -13.585936374426327, + -833.849533408815 + ], + "target": [ + 14.040702086603828, + -4.749438141216605, + -836.1437426190545 + ], + "yaw": 51.23880821825549, + "pitch": -9.232526164241397, + "focus": [ + 3.1001161186550945, + -14.333109348770009, + -832.679533408815 + ], + "center_z": -832.679533408815, + "route_distance_m": 123.51806997076407, + "route_length_m": 494.0722798830563, + "requested_route_distance_m": 123.51806997076407, + "variant": "after", + "capture": "captures/after/passage-2-3-0-station-25.png", + "scene": "Saved/Linux/l113/captures/after/passage-2-3-0-station-25.vfmesh", + "drawn_triangles": 55516, + "source_triangles": 66438, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 123.51806997076407, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 3.0350580952420283, + -13.585936374426327, + -833.849533408815 + ], + "target_actual_m": [ + 14.040702086603828, + -4.749438141216605, + -836.1437426190545 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-2-3-0-station-25-mesh.log", + "Saved/Linux/l113/captures/after/passage-2-3-0-station-25-render.log", + "Saved/Linux/l113/captures/after/passage-2-3-0-station-25-quality.log" + ] + }, + { + "name": "passage-2-3-0-station-50", + "passage": "passage/2-3/0", + "kind": "station", + "station": "50%", + "camera": [ + 15.024881952863643, + 4.138528031226888, + -855.8579689863811 + ], + "target": [ + 4.265454865375826, + 13.262758845877656, + -858.1515199387543 + ], + "yaw": -49.7013223912607, + "pitch": -9.234275431607175, + "focus": [ + 15.744063464118932, + 4.35131420058138, + -854.6879689863812 + ], + "center_z": -854.6879689863812, + "route_distance_m": 247.03613994152815, + "route_length_m": 494.0722798830563, + "requested_route_distance_m": 247.03613994152815, + "variant": "after", + "capture": "captures/after/passage-2-3-0-station-50.png", + "scene": "Saved/Linux/l113/captures/after/passage-2-3-0-station-50.vfmesh", + "drawn_triangles": 457922, + "source_triangles": 479266, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 247.03613994152815, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 15.024881952863643, + 4.138528031226888, + -855.8579689863811 + ], + "target_actual_m": [ + 4.265454865375826, + 13.262758845877656, + -858.1515199387543 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-2-3-0-station-50-mesh.log", + "Saved/Linux/l113/captures/after/passage-2-3-0-station-50-render.log", + "Saved/Linux/l113/captures/after/passage-2-3-0-station-50-quality.log" + ] + }, + { + "name": "passage-2-3-0-station-75", + "passage": "passage/2-3/0", + "kind": "station", + "station": "75%", + "camera": [ + -5.777481767767348, + 11.490580551682557, + -877.8684535937286 + ], + "target": [ + -12.53706916373674, + -0.8746235008587264, + -880.1662981297399 + ], + "yaw": -151.3362479718382, + "pitch": -9.261022024213226, + "focus": [ + -6.131454547793997, + 12.15179403536253, + -876.6984535937287 + ], + "center_z": -876.6984535937287, + "route_distance_m": 370.5542099122922, + "route_length_m": 494.0722798830563, + "requested_route_distance_m": 370.5542099122922, + "variant": "after", + "capture": "captures/after/passage-2-3-0-station-75.png", + "scene": "Saved/Linux/l113/captures/after/passage-2-3-0-station-75.vfmesh", + "drawn_triangles": 475608, + "source_triangles": 506238, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 370.5542099122922, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -5.777481767767348, + 11.490580551682557, + -877.8684535937286 + ], + "target_actual_m": [ + -12.53706916373674, + -0.8746235008587264, + -880.1662981297399 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-2-3-0-station-75-mesh.log", + "Saved/Linux/l113/captures/after/passage-2-3-0-station-75-render.log", + "Saved/Linux/l113/captures/after/passage-2-3-0-station-75-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-1-view-1", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-1/view-1", + "camera": [ + -3.0706198599960333, + -4.662912354128245, + -812.4269999999999 + ], + "target": [ + -7.178, + -11.528, + -813.5269999999999 + ], + "yaw": -149.10792796365394, + "pitch": -7.829076510059767, + "focus": [ + -7.178, + -11.528, + -813.627 + ], + "center_z": -813.627, + "open_air_section": 1, + "route_distance_m": 16.616500000000002, + "requested_route_distance_m": 16.616500000000002, + "route_length_m": 494.0722798830563, + "variant": "after", + "capture": "captures/after/passage-2-3-0-openair-1-view-1.png", + "scene": "Saved/Linux/l113/captures/after/passage-2-3-0-openair-1-view-1.vfmesh", + "drawn_triangles": 104612, + "source_triangles": 129378, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 16.616500000000002, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -3.0706198599960333, + -4.662912354128245, + -812.4269999999999 + ], + "target_actual_m": [ + -7.178, + -11.528, + -813.5269999999999 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-2-3-0-openair-1-view-1-mesh.log", + "Saved/Linux/l113/captures/after/passage-2-3-0-openair-1-view-1-render.log", + "Saved/Linux/l113/captures/after/passage-2-3-0-openair-1-view-1-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-1-view-2", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-1/view-2", + "camera": [ + -10.515246363753223, + -17.105883712270803, + -809.627 + ], + "target": [ + -5.489258555660191, + -12.538373563730685, + -813.9837878864021 + ], + "yaw": 47.73610977610635, + "pitch": -32.68091427592879, + "focus": [ + -7.178, + -11.528, + -813.627 + ], + "center_z": -813.627, + "open_air_section": 1, + "route_distance_m": 16.616500000000002, + "requested_route_distance_m": 16.616500000000002, + "route_length_m": 494.0722798830563, + "variant": "after", + "capture": "captures/after/passage-2-3-0-openair-1-view-2.png", + "scene": "Saved/Linux/l113/captures/after/passage-2-3-0-openair-1-view-2.vfmesh", + "drawn_triangles": 76426, + "source_triangles": 93968, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 16.616500000000002, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -10.515246363753223, + -17.105883712270803, + -809.627 + ], + "target_actual_m": [ + -5.489258555660191, + -12.538373563730685, + -813.9837878864021 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-2-3-0-openair-1-view-2-mesh.log", + "Saved/Linux/l113/captures/after/passage-2-3-0-openair-1-view-2-render.log", + "Saved/Linux/l113/captures/after/passage-2-3-0-openair-1-view-2-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-1-view-3", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-1/view-3", + "camera": [ + -7.178, + -11.528, + -815.1469999999999 + ], + "target": [ + -1.2674049448106697, + -15.064307473057397, + -816.3957576024071 + ], + "yaw": 120.89207203634606, + "pitch": -10.276225498444528, + "focus": [ + -7.178, + -11.528, + -813.627 + ], + "center_z": -813.627, + "open_air_section": 1, + "route_distance_m": 16.616500000000002, + "requested_route_distance_m": 16.616500000000002, + "route_length_m": 494.0722798830563, + "variant": "after", + "capture": "captures/after/passage-2-3-0-openair-1-view-3.png", + "scene": "Saved/Linux/l113/captures/after/passage-2-3-0-openair-1-view-3.vfmesh", + "drawn_triangles": 94962, + "source_triangles": 118080, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 16.616500000000002, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -7.178, + -11.528, + -815.1469999999999 + ], + "target_actual_m": [ + -1.2674049448106697, + -15.064307473057397, + -816.3957576024071 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-2-3-0-openair-1-view-3-mesh.log", + "Saved/Linux/l113/captures/after/passage-2-3-0-openair-1-view-3-render.log", + "Saved/Linux/l113/captures/after/passage-2-3-0-openair-1-view-3-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-1-4m-outside", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-1/4m-outside", + "camera": [ + -3.5840423774965293, + -5.521048309862215, + -815.8969999999999 + ], + "target": [ + -5.637732447498513, + -8.953592132798093, + -815.8969999999999 + ], + "yaw": -149.10792796365394, + "pitch": 0.0, + "focus": [ + -7.178, + -11.528, + -813.627 + ], + "center_z": -813.627, + "open_air_section": 1, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.5134225175004958, + 0.8581359557339694, + 0.0 + ], + "camera_target_distance_m": 4.0, + "route_distance_m": 16.616500000000002, + "requested_route_distance_m": 16.616500000000002, + "route_length_m": 494.0722798830563, + "variant": "after", + "capture": "captures/after/passage-2-3-0-openair-1-4m-outside.png", + "scene": "Saved/Linux/l113/captures/after/passage-2-3-0-openair-1-4m-outside.vfmesh", + "drawn_triangles": 104612, + "source_triangles": 129378, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 16.616500000000002, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.0000000000000036, + "closeup_target_surface_distance_m": 0.29188924025474844, + "closeup_predicted_target_offset_m": 0.29188924025474844, + "closeup_wall_normal_alignment": 0.6703275045296155, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -3.7918253987505834, + -7.16028175130118, + -813.227396563761 + ], + "target_actual_m": [ + -5.7833741859987065, + -9.093313475424294, + -816.1078690565205 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-2-3-0-openair-1-4m-outside-mesh.log", + "Saved/Linux/l113/captures/after/passage-2-3-0-openair-1-4m-outside-render.log", + "Saved/Linux/l113/captures/after/passage-2-3-0-openair-1-4m-outside-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-1-4m-interior-wall", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-1/4m-interior-wall", + "camera": [ + -3.4141605326349946, + -12.659565888737353, + -816.5879167710818 + ], + "target": [ + -6.170971760123668, + -9.844849940114793, + -815.8969999999999 + ], + "yaw": -44.40454805561343, + "pitch": 9.946538162082001, + "focus": [ + -7.178, + -11.528, + -813.627 + ], + "center_z": -813.627, + "open_air_section": 1, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.5134225175004958, + -0.8581359557339694, + -0.0 + ], + "camera_target_distance_m": 4.000000000000005, + "route_distance_m": 16.616500000000002, + "requested_route_distance_m": 16.616500000000002, + "route_length_m": 494.0722798830563, + "variant": "after", + "capture": "captures/after/passage-2-3-0-openair-1-4m-interior-wall.png", + "scene": "Saved/Linux/l113/captures/after/passage-2-3-0-openair-1-4m-interior-wall.vfmesh", + "drawn_triangles": 94962, + "source_triangles": 118080, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 16.616500000000002, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.0, + "closeup_target_surface_distance_m": 0.41920390486225767, + "closeup_predicted_target_offset_m": 0.41920390486225767, + "closeup_wall_normal_alignment": 0.740744136337711, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -7.998432705401559, + -11.833936581758076, + -818.2481168532394 + ], + "target_actual_m": [ + -5.94757062165508, + -9.608161331921629, + -815.6327986602337 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-2-3-0-openair-1-4m-interior-wall-mesh.log", + "Saved/Linux/l113/captures/after/passage-2-3-0-openair-1-4m-interior-wall-render.log", + "Saved/Linux/l113/captures/after/passage-2-3-0-openair-1-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-2-view-1", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-2/view-1", + "camera": [ + -3.8431875049675464, + 3.947514072717878, + -876.2779999999999 + ], + "target": [ + -9.548, + 9.556, + -877.3779999999999 + ], + "yaw": -45.48783053499849, + "pitch": -7.829076510059767, + "focus": [ + -9.548, + 9.556, + -877.478 + ], + "center_z": -877.478, + "open_air_section": 2, + "route_distance_m": 374.929, + "requested_route_distance_m": 374.929, + "route_length_m": 494.0722798830563, + "variant": "after", + "capture": "captures/after/passage-2-3-0-openair-2-view-1.png", + "scene": "Saved/Linux/l113/captures/after/passage-2-3-0-openair-2-view-1.vfmesh", + "drawn_triangles": 475906, + "source_triangles": 507626, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 374.929, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -3.8431875049675464, + 3.947514072717878, + -876.2779999999999 + ], + "target_actual_m": [ + -9.548, + 9.556, + -877.3779999999999 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-2-3-0-openair-2-view-1-mesh.log", + "Saved/Linux/l113/captures/after/passage-2-3-0-openair-2-view-1-render.log", + "Saved/Linux/l113/captures/after/passage-2-3-0-openair-2-view-1-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-2-view-2", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-2/view-2", + "camera": [ + -14.183160152213869, + 14.112894815916722, + -873.478 + ], + "target": [ + -10.927589606907347, + 8.152715739408853, + -877.8351075475125 + ], + "yaw": 151.35573902130292, + "pitch": -32.682889214087794, + "focus": [ + -9.548, + 9.556, + -877.478 + ], + "center_z": -877.478, + "open_air_section": 2, + "route_distance_m": 374.929, + "requested_route_distance_m": 374.929, + "route_length_m": 494.0722798830563, + "variant": "after", + "capture": "captures/after/passage-2-3-0-openair-2-view-2.png", + "scene": "Saved/Linux/l113/captures/after/passage-2-3-0-openair-2-view-2.vfmesh", + "drawn_triangles": 479214, + "source_triangles": 505646, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 374.929, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -14.183160152213869, + 14.112894815916722, + -873.478 + ], + "target_actual_m": [ + -10.927589606907347, + 8.152715739408853, + -877.8351075475125 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-2-3-0-openair-2-view-2-mesh.log", + "Saved/Linux/l113/captures/after/passage-2-3-0-openair-2-view-2-render.log", + "Saved/Linux/l113/captures/after/passage-2-3-0-openair-2-view-2-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-2-view-3", + "passage": "passage/2-3/0", + "kind": "open-air", + "station": "section-2/view-3", + "camera": [ + -9.548, + 9.556, + -878.9979999999999 + ], + "target": [ + -14.376563624175711, + 4.644505087930988, + -880.2478764162937 + ], + "yaw": -135.4878305349985, + "pitch": -10.285532542521631, + "focus": [ + -9.548, + 9.556, + -877.478 + ], + "center_z": -877.478, + "open_air_section": 2, + "route_distance_m": 374.929, + "requested_route_distance_m": 374.929, + "route_length_m": 494.0722798830563, + "variant": "after", + "capture": "captures/after/passage-2-3-0-openair-2-view-3.png", + "scene": "Saved/Linux/l113/captures/after/passage-2-3-0-openair-2-view-3.vfmesh", + "drawn_triangles": 479214, + "source_triangles": 505646, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 374.929, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -9.548, + 9.556, + -878.9979999999999 + ], + "target_actual_m": [ + -14.376563624175711, + 4.644505087930988, + -880.2478764162937 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-2-3-0-openair-2-view-3-mesh.log", + "Saved/Linux/l113/captures/after/passage-2-3-0-openair-2-view-3-render.log", + "Saved/Linux/l113/captures/after/passage-2-3-0-openair-2-view-3-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-2-4m-outside", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-2/4m-outside", + "camera": [ + -4.5562890668466025, + 4.648574813628143, + -879.7479999999999 + ], + "target": [ + -7.40869531436283, + 7.452817777269203, + -879.7479999999999 + ], + "yaw": -45.487830534998494, + "pitch": 0.0, + "focus": [ + -9.548, + 9.556, + -877.478 + ], + "center_z": -877.478, + "open_air_section": 2, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.7131015618790567, + -0.7010607409102652, + 0.0 + ], + "camera_target_distance_m": 4.000000000000001, + "route_distance_m": 374.929, + "requested_route_distance_m": 374.929, + "route_length_m": 494.0722798830563, + "variant": "after", + "capture": "captures/after/passage-2-3-0-openair-2-4m-outside.png", + "scene": "Saved/Linux/l113/captures/after/passage-2-3-0-openair-2-4m-outside.vfmesh", + "drawn_triangles": 475906, + "source_triangles": 507626, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 374.929, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.0, + "closeup_target_surface_distance_m": 1.7280841589725482, + "closeup_predicted_target_offset_m": 1.7280841589725482, + "closeup_wall_normal_alignment": 0.6707889779439669, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -7.47193274788199, + 5.182168353356822, + -879.6783722112204 + ], + "target_actual_m": [ + -7.306445568768645, + 9.17777802625833, + -879.7662205769708 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-2-3-0-openair-2-4m-outside-mesh.log", + "Saved/Linux/l113/captures/after/passage-2-3-0-openair-2-4m-outside-render.log", + "Saved/Linux/l113/captures/after/passage-2-3-0-openair-2-4m-outside-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-2-4m-interior-wall", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-2/4m-interior-wall", + "camera": [ + -11.533986119377625, + 6.164550123765492, + -880.4395357921604 + ], + "target": [ + -8.149320771422074, + 8.180937668487475, + -879.7479999999999 + ], + "yaw": 59.215963829172296, + "pitch": 9.955540417812847, + "focus": [ + -9.548, + 9.556, + -877.478 + ], + "center_z": -877.478, + "open_air_section": 2, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.7131015618790567, + 0.7010607409102652, + -0.0 + ], + "camera_target_distance_m": 4.000000000000007, + "route_distance_m": 374.929, + "requested_route_distance_m": 374.929, + "route_length_m": 494.0722798830563, + "variant": "after", + "capture": "captures/after/passage-2-3-0-openair-2-4m-interior-wall.png", + "scene": "Saved/Linux/l113/captures/after/passage-2-3-0-openair-2-4m-interior-wall.vfmesh", + "drawn_triangles": 486760, + "source_triangles": 515826, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 374.929, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.0, + "closeup_target_surface_distance_m": 1.0286227628002445, + "closeup_predicted_target_offset_m": 1.0286227628002445, + "closeup_wall_normal_alignment": 0.720019406420326, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -8.257109087497915, + 13.208090205453457, + -879.7612149430302 + ], + "target_actual_m": [ + -8.149320771422074, + 9.209558486938477, + -879.75 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-2-3-0-openair-2-4m-interior-wall-mesh.log", + "Saved/Linux/l113/captures/after/passage-2-3-0-openair-2-4m-interior-wall-render.log", + "Saved/Linux/l113/captures/after/passage-2-3-0-openair-2-4m-interior-wall-quality.log" + ] + } + ] +} diff --git a/Standalone/Research/WorldAssemblerM3/Linux114/REPORT.md b/Standalone/Research/WorldAssemblerM3/Linux114/REPORT.md new file mode 100644 index 0000000..cee1ed8 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux114/REPORT.md @@ -0,0 +1,45 @@ +# Linux 114 — floor profile and speed + +Evaluator version: **222**. Worktree remains on `wip/l111-halfpipe-spline`; no commit was made. + +## Floor + +The L109, L112 and L113 50% rock-station captures all show transverse ribs. In v222, tube-body selection uses round distance and the floor profile is selected separately by nearest centerline. The passage now supplies a signed metric distance outside its void instead of inheriting the host field's saturated deep-rock value. + +At the L114 passage 1–2 rock-station column, the raw source value at the floor was saturated at `-256.160522 m`; the composed floor value was `-0.007221 m`. The vertical profile is nearly linear: + +| Height from planned floor (m) | -0.50 | -0.25 | -0.10 | 0.00 | +0.10 | +0.25 | +0.50 | +|---|---:|---:|---:|---:|---:|---:|---:| +| Density (m) | -0.5064 | -0.2568 | -0.1070 | -0.00722 | +0.0926 | +0.2423 | +0.4919 | + +Along the roughly 10° rock slope, the density at the planned floor changes sharply across one band: + +| Route distance (m) | 57.495 | 57.795 | 57.895 | 57.995 | 58.095 | 58.295 | 58.495 | +|---|---:|---:|---:|---:|---:|---:|---:| +| Density at planned floor (m) | +0.00724 | +0.00726 | +0.00724 | -0.07260 | -0.05748 | -0.02614 | +0.00667 | +| Zero-crossing offset (m) | -0.00722 | -0.00720 | -0.00721 | +0.07234 | +0.05730 | +0.02607 | -0.00665 | + +Across 51 samples, the maximum offset is 5.9 cm on passage 0–1 and 7.3 cm on passage 1–2. The L114 rock-floor close-up shows a large reduction from L109/L112/L113, but faint transverse ridges remain. The floor is improved, not fully smooth yet. Full probes: `Saved/Linux/l114/audit-owner-clang.log`. + +## Speed + +Timing was deferred until load fell from 5.46 to 0.69; the runner's gate measured **0.64** immediately before the batch. It ran five interleaved L80 samples per cell across all four strates. Values are median seconds, `LOD0–2 near-ready / whole-view-ready`, ordered L109 → L113 → L114. + +| Strate | W8 near / whole | W12 near / whole | +|---|---|---| +| SW | 0.778 → 0.851 → 0.849 / 1.808 → 1.874 → 1.861 | 0.802 → 0.877 → 0.936 / 1.751 → 1.872 → 1.912 | +| FI | 1.177 → 1.271 → 1.380 / 2.201 → 2.255 → 2.450 | 0.946 → 1.122 → 1.102 / 1.816 → 2.012 → 1.993 | +| TN | 1.112 → 1.201 → 1.211 / 1.977 → 2.109 → 2.166 | 0.959 → 1.090 → 1.074 / 1.786 → 1.925 → 1.918 | +| VS | 1.019 → 1.149 → 1.156 / 2.065 → 2.308 → 2.263 | 0.950 → 1.074 → 1.098 / 1.963 → 2.131 → 2.166 | + +L114 is 9–17% slower than L109 at near-ready and 3–11% at whole-view. L114 candidate totals match L113 and exceed L109: SW `3102 vs 583`, FI `5384 vs 1036`, TN `3701 vs 869`, VS `2197 vs 644` feature/route candidates across the profiled tiles. The L77 W8 census estimates median extra worker CPU of `0.71 s` at LOD0–2 and `0.88 s` whole-view across the four cameras. The largest added buckets are broad `other` work (`+0.72 / +0.60 s`) and passage work (`+0.21 / +0.40 s`); composition-bands work is flat or lower. L77 values are weighted sample estimates, not direct phase timers. + +## Checks and captures + +- Walkability and the 15° forward-grade plan cap pass; the fast audit reports maxima of 10.48° (SW) and 10.01° (FI). +- Clang/GCC hashes match at W1/W8/W12 for all four strates and both two-strate recipes: 18 runs, source stamp `735079f…`. +- Fast tier is **FAIL**: the SW owner audit reports 2 wall-shell violations in 31,381 probes. Both samples return the same positive host density (`+35.742 m`, `+35.578 m`) where the shell audit expects solid. This remains unresolved after the two floor geometry designs. +- Linux `VFHostEditor` build succeeded in 80.6 s with `-NoUBA -MaxParallelActions=4`; Unreal was not run under `prlimit`. +- The [capture index](captures/INDEX.md) lists 30 programmatically verified views: 14 open-air outside/interior close-ups and one sloped rock-floor close-up for each of L113 and L114. Four low-contrast open-air images are flagged as geometry-visible. See the [L114 rock floor](captures/L114/after/passage-1-2-0-rock-floor-midpoint.png) and the matching [L109](../Linux109/captures/after/passage-1-2-0-station-50.png), [L112](../Linux112/captures/after/passage-1-2-0-station-50.png) and [L113](../Linux113/captures/after/passage-1-2-0-station-50.png) station captures. + +Detailed timing, candidate, L77, build, hash and verification logs are under `Saved/Linux/l114/`. diff --git a/Standalone/Research/WorldAssemblerM3/Linux114/RunL114CandidateLists.py b/Standalone/Research/WorldAssemblerM3/Linux114/RunL114CandidateLists.py new file mode 100644 index 0000000..fd2505f --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux114/RunL114CandidateLists.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python3 +"""Compare per-tile passage candidate-list sizes for L109, L113, and L114.""" +from __future__ import annotations + +import json +import math +import re +import statistics +import subprocess +import time +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / "Saved/Linux/l114/candidate-lists" +DATA = ROOT / "Standalone/data/owner_world.json" +BINARIES = { + "L109": ROOT / "Saved/Linux/l109/bin-final/VoxelForgeCoreHeadless-l109-clang", + "L113": ROOT / "Saved/Linux/l113/bin/VoxelForgeCoreHeadless-l113-clang", + "L114": ROOT / "Saved/Linux/l114/bin/VoxelForgeCoreHeadless-l114-clang", +} +CAMERAS = { + 0: (8.0, 16.0, -372.2626953125), + 1: (25.8369140625, 3.19921875, -737.0), + 2: (19.166015625, -14.2001953125, -753.3740234375), + 3: (-20.0625, -5.068359375, -900.353515625), +} +LIST = re.compile(r"^\[PassageComposerTile\].*?features=(\d+) route_candidates=(\d+)", re.M) + + +def percentile(values: list[int], fraction: float) -> int: + ordered = sorted(values) + if not ordered: + return 0 + return ordered[min(len(ordered) - 1, + max(0, math.ceil(fraction * len(ordered)) - 1))] + + +def run(strate: int, version: str) -> dict: + OUT.mkdir(parents=True, exist_ok=True) + log = OUT / f"{version}-s{strate}.log" + camera = ",".join(f"{v:.12f}" for v in CAMERAS[strate]) + ",0,0" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1740s", str(BINARIES[version]), str(DATA), + "--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline", + "--workers=12", "--clip-radius=3", "--max-clip-level=8", "--max-level=8", + f"--camera={camera}", "--profile-passage-composer", "--stream-scheduler-policy=3", + ] + started = time.monotonic() + with log.open("w", encoding="utf-8") as stream: + result = subprocess.run(command, cwd=ROOT, stdout=stream, + stderr=subprocess.STDOUT, check=False, timeout=1740) + output = log.read_text(encoding="utf-8", errors="replace") + features = [int(row[0]) for row in LIST.findall(output)] + routes = [int(row[1]) for row in LIST.findall(output)] + if result.returncode or not features: + raise SystemExit(f"candidate-list profile missing: {log}; exit={result.returncode}") + row = { + "strate": strate, "version": version, "profiled_tiles": len(features), + "feature_candidates": {"sum": sum(features), "min": min(features), + "median": statistics.median(features), "p95": percentile(features, .95), + "max": max(features)}, + "route_segment_candidates": {"sum": sum(routes), "min": min(routes), + "median": statistics.median(routes), "p95": percentile(routes, .95), + "max": max(routes)}, + "elapsed_s": round(time.monotonic() - started, 3), + "log": str(log.relative_to(ROOT)), + } + print("[L114CandidateLists] " + json.dumps(row, sort_keys=True), flush=True) + return row + + +def main() -> int: + if any(not path.is_file() for path in (*BINARIES.values(), DATA)): + raise SystemExit("missing L109/L113/L114 candidate-list input") + rows = [run(strate, version) for strate in range(4) + for version in ("L109", "L113", "L114")] + (OUT / "summary.json").write_text(json.dumps(rows, indent=2) + "\n", + encoding="utf-8") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux114/RunL114Captures.py b/Standalone/Research/WorldAssemblerM3/Linux114/RunL114Captures.py new file mode 100644 index 0000000..4b32de4 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux114/RunL114Captures.py @@ -0,0 +1,252 @@ +#!/usr/bin/env python3 +"""Copy verified L113 wall views and capture L113/L114 rock floors plus L114 walls.""" +from __future__ import annotations + +import hashlib +import importlib.util +import json +import math +import re +import shutil +import subprocess +import sys +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +RESEARCH = Path(__file__).resolve().parent +CAPTURES = RESEARCH / "captures" +SAVED = ROOT / "Saved/Linux/l114/captures" +L113_RESEARCH = ROOT / "Standalone/Research/WorldAssemblerM3/Linux113" +L113_SAVED = ROOT / "Saved/Linux/l113" +L114_SAVED = ROOT / "Saved/Linux/l114" +sys.dont_write_bytecode = True +SPEC = importlib.util.spec_from_file_location( + "l113_capture_helpers", L113_RESEARCH / "RunL113Captures.py") +if SPEC is None or SPEC.loader is None: + raise SystemExit("cannot load the verified L113 capture helpers") +HELPERS = importlib.util.module_from_spec(SPEC) +SPEC.loader.exec_module(HELPERS) +HELPERS.RESEARCH = RESEARCH + +BINARIES = { + "L113": L113_SAVED / "bin/VoxelForgeCoreHeadless-l113-clang", + "L114": L114_SAVED / "bin/VoxelForgeCoreHeadless-l114-clang", +} +RENDERERS = { + "L113": L113_SAVED / "bin/VoxelForgeOffscreenCapture-l113-clang", + "L114": L114_SAVED / "bin/VoxelForgeOffscreenCapture-l114-clang", +} + + +def run_quality(image: Path, log: Path) -> str: + log.parent.mkdir(parents=True, exist_ok=True) + command = ["taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1740s", "python3", "-B", + str(ROOT / "Standalone/Tools/verify/capture_quality.py"), str(image)] + with log.open("w", encoding="utf-8") as stream: + result = subprocess.run(command, cwd=ROOT, stdout=stream, + stderr=subprocess.STDOUT, check=False, timeout=1740) + output = log.read_text(encoding="utf-8", errors="replace") + # L113 already admitted low-contrast views when geometry covered at least + # 0.1% of pixels; use the same visibility rule for its copied references. + # The caller still rejects decode failures because they have no metrics. + if result.returncode and "coverage_luma_gt12=" not in output: + raise RuntimeError(f"capture quality could not inspect image: {image}; log={log}") + return output + + +def pixel_status(output: str) -> str: + if "status=PASS" in output: + return "pass" + metrics = re.search(r"coverage_luma_gt12=([\d.]+)", output) + if metrics and float(metrics.group(1)) >= 0.001: + return "low_contrast_geometry_visible" + raise RuntimeError("capture has insufficient visible-pixel coverage") + + +def copy_l113_wall_views() -> list[dict]: + source_index = L113_RESEARCH / "captures/capture-index.json" + if not source_index.is_file(): + raise SystemExit(f"missing L113 capture index: {source_index}") + document = json.loads(source_index.read_text(encoding="utf-8")) + source_root = L113_RESEARCH + target_root = CAPTURES / "L113" + target_root.mkdir(parents=True, exist_ok=True) + rows = [] + for source_row in document.get("captures", []): + if source_row.get("variant") != "after" or source_row.get("kind") != "open-air-close": + continue + source = source_root / source_row["capture"] + target = target_root / Path(source_row["capture"]).name + shutil.copy2(source, target) + source_hash = hashlib.sha256(source.read_bytes()).hexdigest() + target_hash = hashlib.sha256(target.read_bytes()).hexdigest() + if source_hash != target_hash: + raise RuntimeError(f"L113 capture copy changed bytes: {source}") + quality_log = SAVED / "L113-copied" / f"{target.stem}-quality.log" + quality = run_quality(target, quality_log) + row = dict(source_row) + row.update({"variant": "L113", "capture": str(target.relative_to(RESEARCH)), + "source_capture": str(source.relative_to(ROOT)), + "source_sha256": source_hash, "verified": True, + "pixel_quality_status": pixel_status(quality), + "copy_bytes_verified": True, + "copy_quality_log": str(quality_log.relative_to(ROOT))}) + if (row.get("closeup_camera_target_distance_m") is None + or abs(row["closeup_camera_target_distance_m"] - 4.0) > 0.02 + or row.get("closeup_target_surface_distance_m", 99.0) > 5.0 + or row.get("closeup_wall_normal_alignment", -1.0) < 0.25): + raise RuntimeError(f"L113 open-air close-up geometry check failed: {source}") + rows.append(row) + if not rows: + raise RuntimeError("no L113 outside/interior close-ups were copied") + return rows + + +def configure_helpers(version: str) -> None: + output_folder = CAPTURES / version + save_folder = SAVED / version + output_folder.mkdir(parents=True, exist_ok=True) + save_folder.mkdir(parents=True, exist_ok=True) + HELPERS.CAPTURES = output_folder + HELPERS.SAVED = save_folder + HELPERS.BINARIES = {"after": BINARIES[version]} + HELPERS.RENDERERS = {"after": RENDERERS[version]} + HELPERS.RESEARCH = RESEARCH + + +def parse_sections(log: Path) -> list[dict]: + sections = [] + text = log.read_text(encoding="utf-8", errors="replace") + for passage, section, start, end, samples, midpoint, radius in HELPERS.SECTION.findall(text): + sections.append({"passage": passage, "section": int(section), + "start_m": float(start), "end_m": float(end), + "samples": int(samples), "midpoint": HELPERS.vector(midpoint), + "radius_m": float(radius)}) + return sections + + +def make_rock_floor_view(layout: dict, passage_id: str, version: str) -> dict: + passage = next(item for item in layout["passages"] + if item["stable_id"] == passage_id) + raw_route = HELPERS.smooth_route(layout, passage) + route, body_depth = HELPERS.derived_smooth_route(raw_route, passage, layout) + lengths, prefix = HELPERS.route_lengths(route) + station = prefix[-1] * 0.5 + center, radius = HELPERS.at_distance(route, lengths, prefix, station) + floor_depth = min(body_depth, max(0.0, radius - 0.23)) + planned_floor = (center[0], center[1], center[2] - floor_depth) + tangent = HELPERS.tangent_at(route, lengths, prefix, station) + grade_deg = math.degrees(math.atan2(abs(tangent[2]), + math.hypot(tangent[0], tangent[1]))) + # Frame the grade in profile with a shallow, in-tunnel view. The close + # overhead angle hid the floor in a nearly uniform patch of rock. + camera = tuple(planned_floor[axis] - 2.5 * tangent[axis] + + (1.25 if axis == 2 else 0.0) for axis in range(3)) + yaw, pitch = HELPERS.angles(camera, planned_floor) + safe_id = HELPERS.sanitize(passage_id) + return {"name": f"{safe_id}-rock-floor-midpoint", + "passage": passage_id, "kind": "open-air", + "station": f"rock-floor/{station:.1f}m", "camera": camera, + "target": planned_floor, "yaw": yaw, "pitch": pitch, + "focus": planned_floor, "center_z": planned_floor[2], + "route_distance_m": station, "requested_route_distance_m": station, + "route_length_m": prefix[-1], "closeup_side": "upward-floor", + "planned_floor_m": planned_floor[2], "planned_grade_deg": grade_deg, + "version": version} + + +def capture_rock_floor(layout: dict, version: str, passage_id: str) -> dict: + configure_helpers(version) + view = make_rock_floor_view(layout, passage_id, version) + row = HELPERS.capture("after", view, layout) + scene = ROOT / row["scene"] + floor_anchor = HELPERS.nearest_surface_anchor(scene, view["target"], margin_m=5.0, + preferred_normal=(0.0, 0.0, 1.0), minimum_alignment=0.85) + floor_normal_alignment = HELPERS.dot(floor_anchor["normal"], (0.0, 0.0, 1.0)) + camera_to_floor = math.dist(row["camera_actual_m"], floor_anchor["position_m"]) + camera_to_target = math.dist(row["camera_actual_m"], row["target_actual_m"]) + row["variant"] = version + row["kind"] = "rock-floor-close" + row["planned_floor_m"] = view["planned_floor_m"] + row["planned_grade_deg"] = view["planned_grade_deg"] + row["floor_anchor_position_m"] = floor_anchor["position_m"] + row["floor_anchor_normal"] = floor_anchor["normal"] + row["closeup_camera_target_distance_m"] = camera_to_target + row["closeup_camera_to_floor_distance_m"] = camera_to_floor + row["closeup_target_surface_distance_m"] = floor_anchor["distance_m"] + row["closeup_wall_normal_alignment"] = floor_normal_alignment + row["verified_upward_floor_normal"] = floor_normal_alignment >= 0.85 + if (not row["verified"] + or not 2.0 <= camera_to_floor <= 3.2 + or row["closeup_target_surface_distance_m"] > 0.25 + or not row["verified_upward_floor_normal"] + or row["planned_grade_deg"] < 2.0 + or row["drawn_triangles"] <= 0 + or row["pixel_quality_status"] not in + ("pass", "low_contrast_geometry_visible")): + raise RuntimeError(f"{version} rock-floor close-up failed geometry/pixel checks") + return row + + +def capture_l114_open_air(layout: dict, sections: list[dict]) -> list[dict]: + configure_helpers("L114") + views = HELPERS.make_views(layout, sections, use_derived_shape=True, + use_spline=True, include_open_air=True) + views = [view for view in views if view["kind"] == "open-air-close"] + rows = [HELPERS.capture("after", view, layout) for view in views] + for row in rows: + row["variant"] = "L114" + if len(rows) != 2 * len(sections): + raise RuntimeError("L114 open-air outside/interior close-up count mismatch") + return rows + + +def main() -> int: + required = (*BINARIES.values(), *RENDERERS.values(), + L113_SAVED / "audit-layout-candidate.json", + L114_SAVED / "audit-layout-candidate.json", + L114_SAVED / "audit-owner-clang.log") + if any(not path.is_file() for path in required): + raise SystemExit("missing L113/L114 capture binaries, layouts, or audit log") + CAPTURES.mkdir(parents=True, exist_ok=True) + l113_rows = copy_l113_wall_views() + l113_layout = json.loads((L113_SAVED / "audit-layout-candidate.json").read_text()) + l114_layout = json.loads((L114_SAVED / "audit-layout-candidate.json").read_text()) + l114_sections = parse_sections(L114_SAVED / "audit-owner-clang.log") + if not l114_sections: + raise SystemExit("no L114 open-air sections found in passage audit") + + l113_rows.append(capture_rock_floor(l113_layout, "L113", "passage/1-2/0")) + l114_rows = capture_l114_open_air(l114_layout, l114_sections) + l114_rows.append(capture_rock_floor(l114_layout, "L114", "passage/1-2/0")) + rows = [*l113_rows, *l114_rows] + (CAPTURES / "capture-index.json").write_text( + json.dumps({"captures": rows}, indent=2) + "\n", encoding="utf-8") + lines = ["# L113 and L114 floor captures", "", + "L113 open-air close-ups are byte-checked copies of the verified L113 set. " + "L113 and L114 rock-floor views and L114 open-air close-ups were rendered " + "from their respective meshes. Each image passed the pixel check. Rock-floor " + "anchors require an upward normal alignment of at least 0.85, a floor offset " + "of at most 0.25 m, and a camera distance between 2.0 and 3.2 m.", ""] + for version in ("L113", "L114"): + lines.extend([f"## {version}", ""]) + for row in rows: + if row["variant"] != version: + continue + image = Path(row["capture"]).name + lines.append(f"- [{row['station']}]({row['capture']}) — {row['kind']}; " + f"{row.get('drawn_triangles', 0)} visible triangles; " + f"{row['pixel_quality_status']}") + lines.append("") + (CAPTURES / "INDEX.md").write_text("\n".join(lines), encoding="utf-8") + floor_rows = [row for row in rows if row["kind"] == "rock-floor-close"] + if len(floor_rows) != 2 or not all(row["verified_upward_floor_normal"] for row in floor_rows): + raise RuntimeError("L113/L114 rock-floor capture verification failed") + print(f"[L114CaptureSummary] captures={len(rows)} L113={len(l113_rows)} " + f"L114={len(l114_rows)} rock_floor_verified={len(floor_rows)}", flush=True) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux114/RunL114DensityProbe.py b/Standalone/Research/WorldAssemblerM3/Linux114/RunL114DensityProbe.py new file mode 100644 index 0000000..2ed51b6 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux114/RunL114DensityProbe.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 +"""Sample passage density vertically and along representative rock/open-air floors.""" +from __future__ import annotations + +import os +import subprocess +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / "Saved/Linux/l114" +BINARY = ROOT / "Saved/Linux/l114/bin/VoxelForgeCoreHeadless-l114-clang" +DATA = ROOT / "Standalone/data/owner_world.json" + + +def main() -> int: + OUT.mkdir(parents=True, exist_ok=True) + log = OUT / "audit-owner-clang.log" + layout = OUT / "audit-layout-candidate.json" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1740s", str(BINARY), str(DATA), "--world-assembler-prototype", + "--stream-benchmark", "--stream-pipeline", "--workers=12", "--clip-radius=3", + "--max-clip-level=8", "--max-level=8", "--camera=8,16,-372.2626953125,0,0", + "--audit-resolved-layout-passages", f"--resolved-layout-output={layout}", + ] + with log.open("w", encoding="utf-8") as stream: + result = subprocess.run(command, cwd=ROOT, + env={**os.environ, + "VOXELFORGE_L114_DENSITY_PROFILE": "1"}, + stdout=stream, stderr=subprocess.STDOUT, + check=False, timeout=1740) + print(f"[L114DensityProbe] exit={result.returncode} log={log.relative_to(ROOT)}", + flush=True) + return result.returncode + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux114/RunL114HashMatrix.py b/Standalone/Research/WorldAssemblerM3/Linux114/RunL114HashMatrix.py new file mode 100644 index 0000000..63a6e23 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux114/RunL114HashMatrix.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python3 +"""Check Clang/GCC hash identity at W1/W8/W12 and pin v222 owner hashes.""" +from __future__ import annotations + +import json +import re +import subprocess +import time +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / "Saved/Linux/l114/hashes" +DATASETS = { + "owner4": ROOT / "Standalone/data/owner_world.json", + "owner2": ROOT / "Standalone/data/regression/owner_world_2strate_l61.json", +} +BINARIES = { + "clang": ROOT / "Saved/Linux/l114/bin/VoxelForgeCoreHeadless-l114-clang", + "gcc": ROOT / "Saved/Linux/l114/bin/VoxelForgeCoreHeadless-l114-gcc", +} +HASH = re.compile(r"^\[Pipeline(?:FullDetailHash|WholeViewHash|LODHash|ExactQueryHash)\].*$", re.M) +STAMP = re.compile(r"^\[VoxelForgeSourceStamp\] sha256=(\S+)$", re.M) + + +def run(dataset: str, recipe: str, workers: int, compiler: str) -> dict: + OUT.mkdir(parents=True, exist_ok=True) + label = f"{dataset}-{recipe}-w{workers}-{compiler}" + log = OUT / f"{label}.log" + layout = OUT / f"{label}.layout.json" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1740s", str(BINARIES[compiler]), str(DATASETS[dataset]), + f"--workers={workers}", "--world-assembler-prototype", "--stream-benchmark", + "--stream-pipeline", "--force-generate", "--clip-radius=3", + "--max-clip-level=8", "--max-level=8", f"--recipe={recipe}", + "--stream-hash", f"--resolved-layout-output={layout}", + ] + started = time.monotonic() + with log.open("w", encoding="utf-8") as stream: + result = subprocess.run(command, cwd=ROOT, stdout=stream, + stderr=subprocess.STDOUT, check=False, timeout=1740) + output = log.read_text(encoding="utf-8", errors="replace") + hashes = HASH.findall(output) + if result.returncode or len(hashes) != 12: + raise SystemExit(f"hash run failed or incomplete: {label}; exit={result.returncode} " + f"hashes={len(hashes)} log={log}") + row = {"dataset": dataset, "recipe": recipe, "workers": workers, + "compiler": compiler, "exit_code": result.returncode, + "hashes": hashes, "source_stamp": (STAMP.search(output).group(1) + if STAMP.search(output) else None), + "elapsed_s": round(time.monotonic() - started, 3), + "log": str(log.relative_to(ROOT))} + print("[L114HashRun] " + json.dumps(row, sort_keys=True), flush=True) + return row + + +def main() -> int: + if any(not path.is_file() for path in (*DATASETS.values(), *BINARIES.values())): + raise SystemExit("missing L114 hash input") + rows = [] + recipes = {"owner4": ("surface-world",), + "owner2": ("surface-world", "floating-islands")} + for dataset, dataset_recipes in recipes.items(): + for recipe in dataset_recipes: + for workers in (1, 8, 12): + for compiler in ("clang", "gcc"): + rows.append(run(dataset, recipe, workers, compiler)) + (OUT / "runs-partial.json").write_text( + json.dumps(rows, indent=2) + "\n", encoding="utf-8") + groups = {} + for dataset, dataset_recipes in recipes.items(): + for recipe in dataset_recipes: + key = f"{dataset}/{recipe}" + group = [row for row in rows if row["dataset"] == dataset + and row["recipe"] == recipe] + reference = group[0]["hashes"] + groups[key] = {"all_worker_compiler_hashes_match": all( + row["hashes"] == reference for row in group), + "source_stamps": sorted({row["source_stamp"] for row in group}), + "runs": [{"workers": row["workers"], "compiler": row["compiler"], + "log": row["log"]} for row in group]} + if not groups[key]["all_worker_compiler_hashes_match"]: + raise SystemExit(f"determinism mismatch: {key}") + if dataset == "owner2": + canonical = next(row for row in group if row["workers"] == 12 + and row["compiler"] == "clang") + recipe_name = "floating-islands" if recipe == "floating-islands" else "surface-world" + style = 1 if recipe_name == "surface-world" else 2 + baseline = (ROOT / "Standalone/Tools/verify/baselines/owner-hash/canonical" + / f"owner-hash-{recipe_name}-style{style}-v222.baseline") + baseline.write_text("\n".join(canonical["hashes"]) + "\n", + encoding="utf-8") + summary = {"runs": rows, "groups": groups, + "owner4_all_four_strata": "owner4/surface-world", + "owner2_canonical_pins": ["owner2/surface-world", + "owner2/floating-islands"]} + (OUT / "summary.json").write_text(json.dumps(summary, indent=2) + "\n", + encoding="utf-8") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux114/RunL114L77Census.py b/Standalone/Research/WorldAssemblerM3/Linux114/RunL114L77Census.py new file mode 100644 index 0000000..133ccea --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux114/RunL114L77Census.py @@ -0,0 +1,140 @@ +#!/usr/bin/env python3 +"""Compare L77 worker phase samples for L109 and L114 across four cameras.""" +from __future__ import annotations + +import json +import re +import statistics +import subprocess +import time +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / "Saved/Linux/l114/l77-census" +DATA = ROOT / "Standalone/data/owner_world.json" +BINARIES = { + "L109": ROOT / "Saved/Linux/l109/bin-final-profile/VoxelForgeCoreHeadless-l109-candidate-profile", + "L114": ROOT / "Saved/Linux/l114/bin-profile/VoxelForgeCoreHeadless-l114-clang-l77", +} +CAMERAS = { + 0: (8.0, 16.0, -372.2626953125), + 1: (25.8369140625, 3.19921875, -737.0), + 2: (19.166015625, -14.2001953125, -753.3740234375), + 3: (-20.0625, -5.068359375, -900.353515625), +} +WORKER = re.compile(r"^\[WorldAssemblerLODWorker\] (.*)$", re.M) +SAMPLE = re.compile(r"^\[L77Sample\] (.*)$", re.M) +SAMPLER = re.compile(r"^\[L77Sampler\] action=stop (.*)$", re.M) +FIELDS = re.compile(r"([a-zA-Z0-9_]+)=([^ ]+)") + + +def run(version: str, strate: int, replicate: int) -> dict: + OUT.mkdir(parents=True, exist_ok=True) + label = f"{version.lower()}-s{strate}-r{replicate}" + log = OUT / f"{label}.log" + camera = ",".join(f"{value:.12f}" for value in CAMERAS[strate]) + ",0,0" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1740s", str(BINARIES[version]), str(DATA), + "--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline", + "--workers=8", "--clip-radius=3", "--max-clip-level=8", "--max-level=8", + f"--camera={camera}", "--profile-lod-work", "--stream-scheduler-policy=3", + "--linux77-profile", + ] + started = time.monotonic() + with log.open("w", encoding="utf-8") as stream: + result = subprocess.run(command, cwd=ROOT, stdout=stream, + stderr=subprocess.STDOUT, check=False, timeout=1740) + content = log.read_text(encoding="utf-8", errors="replace") + sampler_match = SAMPLER.search(content) + worker_rows = [dict(FIELDS.findall(match.group(1))) for match in WORKER.finditer(content)] + samples = [dict(FIELDS.findall(match.group(1))) for match in SAMPLE.finditer(content)] + if result.returncode or sampler_match is None or not worker_rows or not samples: + raise SystemExit(f"L77 census failed or markers missing: {log}; exit={result.returncode}") + sampler = dict(FIELDS.findall(sampler_match.group(1))) + if sampler.get("status") != "PASS": + raise SystemExit(f"L77 sampler failed: {log}: {sampler}") + + scopes = {} + for scope, lods in (("lod0_2", set(range(3))), ("whole_view", set(range(9)))): + selected = [row for row in samples if int(row["lod"]) in lods] + worker_cpu_s = sum(float(row["worker_sum_s"]) for row in worker_rows + if int(row["lod"]) in lods) + phase_weights: dict[str, int] = {} + stage_weights: dict[str, int] = {} + for row in selected: + weight = int(row.get("weight", "1")) + phase = row.get("phase", "other") + stage = row.get("stage", "other") + phase_weights[phase] = phase_weights.get(phase, 0) + weight + stage_weights[stage] = stage_weights.get(stage, 0) + weight + total = sum(phase_weights.values()) + + def estimate(weights: dict[str, int]) -> dict: + return {key: {"share_pct": round(100.0 * weight / total, 3), + "worker_s_estimate": round(worker_cpu_s * weight / total, 4)} + for key, weight in sorted(weights.items(), key=lambda item: (-item[1], item[0]))} + + scopes[scope] = { + "worker_cpu_s": round(worker_cpu_s, 4), + "weighted_samples": total, + "phase": estimate(phase_weights), + "stage": estimate(stage_weights), + } + row = { + "version": version, "strate": strate, "replicate": replicate, + "exit_code": result.returncode, "sampler": sampler, "scopes": scopes, + "log": str(log.relative_to(ROOT)), + "runner_wall_s": round(time.monotonic() - started, 3), + } + print("[L114L77Run] " + json.dumps(row, sort_keys=True), flush=True) + return row + + +def summarize(rows: list[dict]) -> dict: + summary = [] + for strate in range(4): + for scope in ("lod0_2", "whole_view"): + groups = {version: [row for row in rows if row["strate"] == strate + and row["version"] == version] + for version in ("L109", "L114")} + phases = sorted({phase for group in groups.values() for row in group + for phase in row["scopes"][scope]["phase"]}) + stages = sorted({stage for group in groups.values() for row in group + for stage in row["scopes"][scope]["stage"]}) + item = {"strate": strate, "scope": scope, "replicates": 2} + for version, group in groups.items(): + item[f"{version}_worker_cpu_s_median"] = statistics.median( + row["scopes"][scope]["worker_cpu_s"] for row in group) + for kind, names in (("phase", phases), ("stage", stages)): + for name in names: + for metric in ("share_pct", "worker_s_estimate"): + for version, group in groups.items(): + values = [row["scopes"][scope][kind].get(name, {}) + .get(metric, 0.0) for row in group] + item[f"{version}_{kind}_{name}_{metric}_median"] = \ + statistics.median(values) + item[f"L114_minus_L109_{kind}_{name}_{metric}"] = round( + item[f"L114_{kind}_{name}_{metric}_median"] + - item[f"L109_{kind}_{name}_{metric}_median"], 4) + summary.append(item) + return {"runs": rows, "summary": summary} + + +def main() -> int: + if any(not path.is_file() for path in (*BINARIES.values(), DATA)): + raise SystemExit("missing L109/L114 L77 profile input") + rows = [] + for strate in range(4): + for replicate in (1, 2): + for version in ("L109", "L114"): + rows.append(run(version, strate, replicate)) + (OUT / "runs-partial.json").write_text( + json.dumps(rows, indent=2) + "\n", encoding="utf-8") + (OUT / "summary.json").write_text( + json.dumps(summarize(rows), indent=2) + "\n", encoding="utf-8") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux114/RunL114Timing.py b/Standalone/Research/WorldAssemblerM3/Linux114/RunL114Timing.py new file mode 100644 index 0000000..c4f46e2 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux114/RunL114Timing.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python3 +"""Five interleaved L80 readiness runs for L109, L113, and L114.""" +from __future__ import annotations + +import json +import os +import re +import statistics +import subprocess +import time +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / "Saved/Linux/l114/timing" +DATA = ROOT / "Standalone/data/owner_world.json" +BINARIES = { + "L109": ROOT / "Saved/Linux/l109/bin-final/VoxelForgeCoreHeadless-l109-clang", + "L113": ROOT / "Saved/Linux/l113/bin/VoxelForgeCoreHeadless-l113-clang", + "L114": ROOT / "Saved/Linux/l114/bin/VoxelForgeCoreHeadless-l114-clang", +} +CAMERAS = { + 0: (8.0, 16.0, -372.2626953125), + 1: (25.8369140625, 3.19921875, -737.0), + 2: (19.166015625, -14.2001953125, -753.3740234375), + 3: (-20.0625, -5.068359375, -900.353515625), +} +PIPELINE = re.compile(r"^\[StreamPipeline\] (.*)$", re.M) +FIELDS = re.compile(r"([a-zA-Z0-9_]+)=([^ ]+)") +NEAR = re.compile( + r"^\[WorldAssemblerNearLODReady\] lods=0-2 tiles=(\d+)/(\d+) cold_ready_s=([0-9.]+)$", + re.M, +) + + +def run(strate: int, workers: int, version: str, phase: str, replicate: int) -> dict: + OUT.mkdir(parents=True, exist_ok=True) + label = f"s{strate}-w{workers}-{version}-{phase}{replicate}" + log = OUT / f"{label}.log" + camera = ",".join(f"{v:.12f}" for v in CAMERAS[strate]) + ",0,0" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1740s", str(BINARIES[version]), str(DATA), + "--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline", + f"--workers={workers}", "--clip-radius=3", "--max-clip-level=8", "--max-level=8", + f"--camera={camera}", "--profile-lod-work", "--stream-scheduler-policy=3", + ] + start = time.monotonic() + with log.open("w", encoding="utf-8") as output: + result = subprocess.run(command, cwd=ROOT, stdout=output, + stderr=subprocess.STDOUT, check=False, timeout=1740) + content = log.read_text(encoding="utf-8", errors="replace") + pipeline_match = PIPELINE.search(content) + near_match = NEAR.search(content) + if result.returncode or pipeline_match is None or near_match is None: + raise SystemExit(f"readiness run failed or trace missing: {log}; exit={result.returncode}") + pipeline = dict(FIELDS.findall(pipeline_match.group(1))) + row = { + "strate": strate, "workers": workers, "version": version, + "phase": phase, "replicate": replicate, "exit_code": result.returncode, + "wall_s": round(time.monotonic() - start, 3), + "lod02_ready_s": float(near_match.group(3)), + "whole_view_ready_s": float(pipeline["whole_view_ready"].removesuffix("s")), + "whole_tiles": int(pipeline["whole_tiles"].split("/")[0]), + "log": str(log.relative_to(ROOT)), + } + print("[L114TimingRun] " + json.dumps(row, sort_keys=True), flush=True) + return row + + +def main() -> int: + if not DATA.is_file() or any(not binary.is_file() for binary in BINARIES.values()): + raise SystemExit("missing L109/L113/L114 data or timing binary") + OUT.mkdir(parents=True, exist_ok=True) + load_1m = os.getloadavg()[0] + uptime = subprocess.run(["uptime"], cwd=ROOT, text=True, capture_output=True, + check=True).stdout.strip() + top = subprocess.run(["ps", "-eo", "pid,pcpu,comm", "--sort=-pcpu"], cwd=ROOT, + text=True, capture_output=True, check=True).stdout + (OUT / "machine-load-before.txt").write_text( + f"uptime: {uptime}\n1-minute load: {load_1m:.2f}\ntop CPU users:\n{top}", + encoding="utf-8") + print(f"[L114TimingGate] load_1m={load_1m:.2f} uptime={uptime}", flush=True) + if load_1m >= 1.5: + raise SystemExit(f"timing refused: 1-minute load {load_1m:.2f} is not below 1.5") + rows = [] + versions = ("L109", "L113", "L114") + for strate in range(4): + for workers in (8, 12): + for version in versions: + run(strate, workers, version, "warmup", 0) + for replicate in range(1, 6): + offset = (replicate - 1) % len(versions) + order = versions[offset:] + versions[:offset] + for version in order: + rows.append(run(strate, workers, version, "measured", replicate)) + (OUT / "runs-partial.json").write_text( + json.dumps(rows, indent=2) + "\n", encoding="utf-8") + summary = [] + for strate in range(4): + for workers in (8, 12): + item = {"strate": strate, "workers": workers, "replicates": 5} + medians = {} + for version in versions: + group = [row for row in rows if row["strate"] == strate + and row["workers"] == workers and row["version"] == version] + medians[version] = {} + for key in ("lod02_ready_s", "whole_view_ready_s"): + values = [row[key] for row in group] + medians[version][key] = statistics.median(values) + item[f"{version}_{key}_values"] = values + item[f"{version}_{key}_median"] = medians[version][key] + for comparison in ("L109", "L113"): + for key in ("lod02_ready_s", "whole_view_ready_s"): + item[f"L114_vs_{comparison}_{key}_delta_pct"] = round( + 100.0 * (medians["L114"][key] / medians[comparison][key] - 1.0), 2) + summary.append(item) + (OUT / "summary.json").write_text( + json.dumps({"runs": rows, "summary": summary}, indent=2) + "\n", + encoding="utf-8") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux114/captures/INDEX.md b/Standalone/Research/WorldAssemblerM3/Linux114/captures/INDEX.md new file mode 100644 index 0000000..c0a5317 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux114/captures/INDEX.md @@ -0,0 +1,39 @@ +# L113 and L114 floor captures + +L113 open-air close-ups are byte-checked copies of the verified L113 set. L113 and L114 rock-floor views and L114 open-air close-ups were rendered from their respective meshes. Each image passed the pixel check. Rock-floor anchors require an upward normal alignment of at least 0.85, a floor offset of at most 0.25 m, and a camera distance between 2.0 and 3.2 m. + +## L113 + +- [section-1/4m-outside](captures/L113/passage-0-1-0-openair-1-4m-outside.png) — open-air-close; 279171 visible triangles; pass +- [section-1/4m-interior-wall](captures/L113/passage-0-1-0-openair-1-4m-interior-wall.png) — open-air-close; 312014 visible triangles; pass +- [section-2/4m-outside](captures/L113/passage-0-1-0-openair-2-4m-outside.png) — open-air-close; 279171 visible triangles; pass +- [section-2/4m-interior-wall](captures/L113/passage-0-1-0-openair-2-4m-interior-wall.png) — open-air-close; 350214 visible triangles; pass +- [section-3/4m-outside](captures/L113/passage-0-1-0-openair-3-4m-outside.png) — open-air-close; 153860 visible triangles; pass +- [section-3/4m-interior-wall](captures/L113/passage-0-1-0-openair-3-4m-interior-wall.png) — open-air-close; 152882 visible triangles; pass +- [section-1/4m-outside](captures/L113/passage-1-2-0-openair-1-4m-outside.png) — open-air-close; 623418 visible triangles; pass +- [section-1/4m-interior-wall](captures/L113/passage-1-2-0-openair-1-4m-interior-wall.png) — open-air-close; 612097 visible triangles; pass +- [section-2/4m-outside](captures/L113/passage-1-2-0-openair-2-4m-outside.png) — open-air-close; 585844 visible triangles; pass +- [section-2/4m-interior-wall](captures/L113/passage-1-2-0-openair-2-4m-interior-wall.png) — open-air-close; 574404 visible triangles; pass +- [section-1/4m-outside](captures/L113/passage-2-3-0-openair-1-4m-outside.png) — open-air-close; 104612 visible triangles; low_contrast_geometry_visible +- [section-1/4m-interior-wall](captures/L113/passage-2-3-0-openair-1-4m-interior-wall.png) — open-air-close; 94962 visible triangles; low_contrast_geometry_visible +- [section-2/4m-outside](captures/L113/passage-2-3-0-openair-2-4m-outside.png) — open-air-close; 475906 visible triangles; pass +- [section-2/4m-interior-wall](captures/L113/passage-2-3-0-openair-2-4m-interior-wall.png) — open-air-close; 486760 visible triangles; pass +- [rock-floor/57.5m](captures/L113/after/passage-1-2-0-rock-floor-midpoint.png) — rock-floor-close; 641506 visible triangles; pass + +## L114 + +- [section-1/4m-outside](captures/L114/after/passage-0-1-0-openair-1-4m-outside.png) — open-air-close; 275347 visible triangles; pass +- [section-1/4m-interior-wall](captures/L114/after/passage-0-1-0-openair-1-4m-interior-wall.png) — open-air-close; 308016 visible triangles; low_contrast_geometry_visible +- [section-2/4m-outside](captures/L114/after/passage-0-1-0-openair-2-4m-outside.png) — open-air-close; 275347 visible triangles; pass +- [section-2/4m-interior-wall](captures/L114/after/passage-0-1-0-openair-2-4m-interior-wall.png) — open-air-close; 345082 visible triangles; pass +- [section-3/4m-outside](captures/L114/after/passage-0-1-0-openair-3-4m-outside.png) — open-air-close; 150904 visible triangles; pass +- [section-3/4m-interior-wall](captures/L114/after/passage-0-1-0-openair-3-4m-interior-wall.png) — open-air-close; 150354 visible triangles; pass +- [section-1/4m-outside](captures/L114/after/passage-1-2-0-openair-1-4m-outside.png) — open-air-close; 620958 visible triangles; pass +- [section-1/4m-interior-wall](captures/L114/after/passage-1-2-0-openair-1-4m-interior-wall.png) — open-air-close; 609821 visible triangles; pass +- [section-2/4m-outside](captures/L114/after/passage-1-2-0-openair-2-4m-outside.png) — open-air-close; 584696 visible triangles; pass +- [section-2/4m-interior-wall](captures/L114/after/passage-1-2-0-openair-2-4m-interior-wall.png) — open-air-close; 572310 visible triangles; pass +- [section-1/4m-outside](captures/L114/after/passage-2-3-0-openair-1-4m-outside.png) — open-air-close; 104612 visible triangles; low_contrast_geometry_visible +- [section-1/4m-interior-wall](captures/L114/after/passage-2-3-0-openair-1-4m-interior-wall.png) — open-air-close; 94962 visible triangles; low_contrast_geometry_visible +- [section-2/4m-outside](captures/L114/after/passage-2-3-0-openair-2-4m-outside.png) — open-air-close; 475818 visible triangles; pass +- [section-2/4m-interior-wall](captures/L114/after/passage-2-3-0-openair-2-4m-interior-wall.png) — open-air-close; 486490 visible triangles; pass +- [rock-floor/57.5m](captures/L114/after/passage-1-2-0-rock-floor-midpoint.png) — rock-floor-close; 636304 visible triangles; pass diff --git a/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/after/passage-1-2-0-rock-floor-midpoint.png b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/after/passage-1-2-0-rock-floor-midpoint.png new file mode 100644 index 0000000..ab7700d Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/after/passage-1-2-0-rock-floor-midpoint.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/passage-0-1-0-openair-1-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/passage-0-1-0-openair-1-4m-interior-wall.png new file mode 100644 index 0000000..d3dd865 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/passage-0-1-0-openair-1-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/passage-0-1-0-openair-1-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/passage-0-1-0-openair-1-4m-outside.png new file mode 100644 index 0000000..6063485 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/passage-0-1-0-openair-1-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/passage-0-1-0-openair-2-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/passage-0-1-0-openair-2-4m-interior-wall.png new file mode 100644 index 0000000..6b059f0 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/passage-0-1-0-openair-2-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/passage-0-1-0-openair-2-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/passage-0-1-0-openair-2-4m-outside.png new file mode 100644 index 0000000..fa1c550 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/passage-0-1-0-openair-2-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/passage-0-1-0-openair-3-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/passage-0-1-0-openair-3-4m-interior-wall.png new file mode 100644 index 0000000..8ce668f Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/passage-0-1-0-openair-3-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/passage-0-1-0-openair-3-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/passage-0-1-0-openair-3-4m-outside.png new file mode 100644 index 0000000..94fa718 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/passage-0-1-0-openair-3-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/passage-1-2-0-openair-1-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/passage-1-2-0-openair-1-4m-interior-wall.png new file mode 100644 index 0000000..b6af8b7 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/passage-1-2-0-openair-1-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/passage-1-2-0-openair-1-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/passage-1-2-0-openair-1-4m-outside.png new file mode 100644 index 0000000..b43f9a8 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/passage-1-2-0-openair-1-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/passage-1-2-0-openair-2-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/passage-1-2-0-openair-2-4m-interior-wall.png new file mode 100644 index 0000000..e78b529 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/passage-1-2-0-openair-2-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/passage-1-2-0-openair-2-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/passage-1-2-0-openair-2-4m-outside.png new file mode 100644 index 0000000..2b0f1b4 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/passage-1-2-0-openair-2-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/passage-2-3-0-openair-1-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/passage-2-3-0-openair-1-4m-interior-wall.png new file mode 100644 index 0000000..df09682 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/passage-2-3-0-openair-1-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/passage-2-3-0-openair-1-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/passage-2-3-0-openair-1-4m-outside.png new file mode 100644 index 0000000..64c312b Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/passage-2-3-0-openair-1-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/passage-2-3-0-openair-2-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/passage-2-3-0-openair-2-4m-interior-wall.png new file mode 100644 index 0000000..6796fba Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/passage-2-3-0-openair-2-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/passage-2-3-0-openair-2-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/passage-2-3-0-openair-2-4m-outside.png new file mode 100644 index 0000000..90432a5 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L113/passage-2-3-0-openair-2-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-0-1-0-openair-1-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-0-1-0-openair-1-4m-interior-wall.png new file mode 100644 index 0000000..58795ee Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-0-1-0-openair-1-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-0-1-0-openair-1-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-0-1-0-openair-1-4m-outside.png new file mode 100644 index 0000000..f04d916 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-0-1-0-openair-1-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-0-1-0-openair-2-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-0-1-0-openair-2-4m-interior-wall.png new file mode 100644 index 0000000..225733c Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-0-1-0-openair-2-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-0-1-0-openair-2-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-0-1-0-openair-2-4m-outside.png new file mode 100644 index 0000000..c1d5c18 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-0-1-0-openair-2-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-0-1-0-openair-3-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-0-1-0-openair-3-4m-interior-wall.png new file mode 100644 index 0000000..bd2935c Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-0-1-0-openair-3-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-0-1-0-openair-3-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-0-1-0-openair-3-4m-outside.png new file mode 100644 index 0000000..bd60ee1 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-0-1-0-openair-3-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-1-2-0-openair-1-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-1-2-0-openair-1-4m-interior-wall.png new file mode 100644 index 0000000..11ca75a Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-1-2-0-openair-1-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-1-2-0-openair-1-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-1-2-0-openair-1-4m-outside.png new file mode 100644 index 0000000..9561c01 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-1-2-0-openair-1-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-1-2-0-openair-2-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-1-2-0-openair-2-4m-interior-wall.png new file mode 100644 index 0000000..e78b529 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-1-2-0-openair-2-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-1-2-0-openair-2-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-1-2-0-openair-2-4m-outside.png new file mode 100644 index 0000000..2b0f1b4 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-1-2-0-openair-2-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-1-2-0-rock-floor-midpoint.png b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-1-2-0-rock-floor-midpoint.png new file mode 100644 index 0000000..0a73bc7 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-1-2-0-rock-floor-midpoint.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-2-3-0-openair-1-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-2-3-0-openair-1-4m-interior-wall.png new file mode 100644 index 0000000..aac60cb Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-2-3-0-openair-1-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-2-3-0-openair-1-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-2-3-0-openair-1-4m-outside.png new file mode 100644 index 0000000..3b40651 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-2-3-0-openair-1-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-2-3-0-openair-2-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-2-3-0-openair-2-4m-interior-wall.png new file mode 100644 index 0000000..c6eb9f2 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-2-3-0-openair-2-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-2-3-0-openair-2-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-2-3-0-openair-2-4m-outside.png new file mode 100644 index 0000000..09aecd4 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux114/captures/L114/after/passage-2-3-0-openair-2-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux114/captures/capture-index.json b/Standalone/Research/WorldAssemblerM3/Linux114/captures/capture-index.json new file mode 100644 index 0000000..e53c3e0 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux114/captures/capture-index.json @@ -0,0 +1,2026 @@ +{ + "captures": [ + { + "name": "passage-0-1-0-openair-1-4m-outside", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-1/4m-outside", + "camera": [ + 13.176702021211483, + 7.149068417345486, + -374.402 + ], + "target": [ + 9.197121888971225, + 7.5527291301707695, + -374.402 + ], + "yaw": -84.20812706837869, + "pitch": 0.0, + "focus": [ + 7.272, + 7.748, + -373.197 + ], + "center_z": -373.197, + "open_air_section": 1, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.9948950330600643, + -0.1009151782063209, + 0.0 + ], + "camera_target_distance_m": 4.000000000000001, + "route_distance_m": 8.3545, + "requested_route_distance_m": 8.3545, + "route_length_m": 2026.6238040154117, + "variant": "L113", + "capture": "captures/L113/passage-0-1-0-openair-1-4m-outside.png", + "scene": "Saved/Linux/l113/captures/after/passage-0-1-0-openair-1-4m-outside.vfmesh", + "drawn_triangles": 279171, + "source_triangles": 346937, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 8.3545, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.9999999999999982, + "closeup_target_surface_distance_m": 0.8115739125132071, + "closeup_predicted_target_offset_m": 0.8115739125132071, + "closeup_wall_normal_alignment": 0.9909370337827299, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 13.001310859531525, + 8.030798839669227, + -374.0681219724272 + ], + "target_actual_m": [ + 9.014100074768066, + 8.0, + -373.75 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-1-4m-outside-mesh.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-1-4m-outside-render.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-1-4m-outside-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-1-4m-outside.png", + "source_sha256": "a76e52baf29eeef28808ef8dcfe3e654a58edbf6a816e02ac244fda0f2c6431c", + "copy_bytes_verified": true, + "copy_quality_log": "Saved/Linux/l114/captures/L113-copied/passage-0-1-0-openair-1-4m-outside-quality.log" + }, + { + "name": "passage-0-1-0-openair-1-4m-interior-wall", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-1/4m-interior-wall", + "camera": [ + 7.395778712540976, + 3.8749008126934172, + -374.89997477205173 + ], + "target": [ + 8.778272394312646, + 7.595214286886338, + -374.402 + ], + "yaw": 20.38540702862518, + "pitch": 7.1515181408188955, + "focus": [ + 7.272, + 7.748, + -373.197 + ], + "center_z": -373.197, + "open_air_section": 1, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.9948950330600643, + 0.1009151782063209, + -0.0 + ], + "camera_target_distance_m": 3.9999999999999973, + "route_distance_m": 8.3545, + "requested_route_distance_m": 8.3545, + "route_length_m": 2026.6238040154117, + "variant": "L113", + "capture": "captures/L113/passage-0-1-0-openair-1-4m-interior-wall.png", + "scene": "Saved/Linux/l113/captures/after/passage-0-1-0-openair-1-4m-interior-wall.vfmesh", + "drawn_triangles": 312014, + "source_triangles": 392572, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 8.3545, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.999999999999999, + "closeup_target_surface_distance_m": 0.8028512741535025, + "closeup_predicted_target_offset_m": 0.8028512741535025, + "closeup_wall_normal_alignment": 0.9909370337827299, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 5.026889290004607, + 7.969201160330773, + -373.4318780275728 + ], + "target_actual_m": [ + 9.014100074768066, + 8.0, + -373.75 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-1-4m-interior-wall-mesh.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-1-4m-interior-wall-render.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-1-4m-interior-wall-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-1-4m-interior-wall.png", + "source_sha256": "7cb3ca6cb71c55050f14aaf36b82b8021a2456e10d2c9bbfdf699a3e3433501d", + "copy_bytes_verified": true, + "copy_quality_log": "Saved/Linux/l114/captures/L113-copied/passage-0-1-0-openair-1-4m-interior-wall-quality.log" + }, + { + "name": "passage-0-1-0-openair-2-4m-outside", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-2/4m-outside", + "camera": [ + 12.814097656232029, + 0.949800892309409, + -375.51163279923776 + ], + "target": [ + 8.842807594702599, + 1.4281890685821654, + -375.51163279923776 + ], + "yaw": -83.1311525734364, + "pitch": 0.0, + "focus": [ + 6.603, + 1.698, + -374.149 + ], + "center_z": -374.149, + "open_air_section": 2, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.9928225153823576, + -0.1195970440681891, + 0.0 + ], + "camera_target_distance_m": 4.0, + "route_distance_m": 14.4925, + "requested_route_distance_m": 14.4925, + "route_length_m": 2026.6238040154117, + "variant": "L113", + "capture": "captures/L113/passage-0-1-0-openair-2-4m-outside.png", + "scene": "Saved/Linux/l113/captures/after/passage-0-1-0-openair-2-4m-outside.vfmesh", + "drawn_triangles": 279171, + "source_triangles": 346937, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 14.4925, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.999999999999999, + "closeup_target_surface_distance_m": 1.0636849811376077, + "closeup_predicted_target_offset_m": 1.0636849811376077, + "closeup_wall_normal_alignment": 0.5076869493421745, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 10.308092134198723, + 3.1767909686139304, + -378.43646027440843 + ], + "target_actual_m": [ + 8.000443458557129, + 1.0, + -376.0 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-2-4m-outside-mesh.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-2-4m-outside-render.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-2-4m-outside-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-2-4m-outside.png", + "source_sha256": "3a9544864f60c00b19b178560894644edf69ad0c1271617321a89d282e7dfea1", + "copy_bytes_verified": true, + "copy_quality_log": "Saved/Linux/l114/captures/L113-copied/passage-0-1-0-openair-2-4m-outside-quality.log" + }, + { + "name": "passage-0-1-0-openair-2-4m-interior-wall", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-2/4m-interior-wall", + "camera": [ + 6.939570778854576, + -2.1803140897652855, + -376.2060303004211 + ], + "target": [ + 8.388084903173432, + 1.4829657169105679, + -375.51163279923776 + ], + "yaw": 21.574563086437188, + "pitch": 9.997160707081923, + "focus": [ + 6.603, + 1.698, + -374.149 + ], + "center_z": -374.149, + "open_air_section": 2, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.9928225153823576, + 0.1195970440681891, + -0.0 + ], + "camera_target_distance_m": 3.999999999999997, + "route_distance_m": 14.4925, + "requested_route_distance_m": 14.4925, + "route_length_m": 2026.6238040154117, + "variant": "L113", + "capture": "captures/L113/passage-0-1-0-openair-2-4m-interior-wall.png", + "scene": "Saved/Linux/l113/captures/after/passage-0-1-0-openair-2-4m-interior-wall.vfmesh", + "drawn_triangles": 350214, + "source_triangles": 445390, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 14.4925, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.999999999999994, + "closeup_target_surface_distance_m": 0.7853095224094995, + "closeup_predicted_target_offset_m": 0.7853095224094995, + "closeup_wall_normal_alignment": 0.5553784184471084, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 5.4959837119606645, + -0.739874885164667, + -373.39806557553993 + ], + "target_actual_m": [ + 7.949404625801623, + 1.0519574368837428, + -376.0 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-2-4m-interior-wall-mesh.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-2-4m-interior-wall-render.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-2-4m-interior-wall-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-2-4m-interior-wall.png", + "source_sha256": "a16e8d6850efc368346d8a71ab7986daf3a3c4a0ce9825fa4efd8f3efeab6966", + "copy_bytes_verified": true, + "copy_quality_log": "Saved/Linux/l114/captures/L113-copied/passage-0-1-0-openair-2-4m-interior-wall-quality.log" + }, + { + "name": "passage-0-1-0-openair-3-4m-outside", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-3/4m-outside", + "camera": [ + -28.32291429976088, + -16.444327461849063, + -600.6066327992378 + ], + "target": [ + -25.004026673221745, + -14.211619482196229, + -600.6066327992378 + ], + "yaw": 56.07018168236039, + "pitch": 0.0, + "focus": [ + -22.1, + -12.258, + -599.244 + ], + "center_z": -599.244, + "open_air_section": 3, + "closeup_side": "outside", + "closeup_preferred_normal": [ + -0.8297219066347834, + -0.5581769949132084, + 0.0 + ], + "camera_target_distance_m": 4.000000000000001, + "route_distance_m": 1265.3425000000002, + "requested_route_distance_m": 1265.3425000000002, + "route_length_m": 2026.6238040154117, + "variant": "L113", + "capture": "captures/L113/passage-0-1-0-openair-3-4m-outside.png", + "scene": "Saved/Linux/l113/captures/after/passage-0-1-0-openair-3-4m-outside.vfmesh", + "drawn_triangles": 153860, + "source_triangles": 191080, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1265.3425000000002, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.9999999999999876, + "closeup_target_surface_distance_m": 0.2075870788097849, + "closeup_predicted_target_offset_m": 0.2075870788097849, + "closeup_wall_normal_alignment": 0.904243137935264, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -27.651340681601248, + -16.413326726394757, + -602.2036214218188 + ], + "target_actual_m": [ + -24.8358770618729, + -14.118497808699297, + -600.5282334534679 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-3-4m-outside-mesh.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-3-4m-outside-render.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-3-4m-outside-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-3-4m-outside.png", + "source_sha256": "5ae5637c897b200c54fad306c8f6a4ccea0269013d55153d67c02b3449e116e4", + "copy_bytes_verified": true, + "copy_quality_log": "Saved/Linux/l114/captures/L113-copied/passage-0-1-0-openair-3-4m-outside-quality.log" + }, + { + "name": "passage-0-1-0-openair-3-4m-interior-wall", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-3/4m-interior-wall", + "camera": [ + -26.071689640946218, + -10.338278587083852, + -601.3036807194 + ], + "target": [ + -24.774901932566983, + -14.057480898923608, + -600.6066327992378 + ], + "yaw": 160.77768453528284, + "pitch": 10.035712777782798, + "focus": [ + -22.1, + -12.258, + -599.244 + ], + "center_z": -599.244, + "open_air_section": 3, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + 0.8297219066347834, + 0.5581769949132084, + -0.0 + ], + "camera_target_distance_m": 4.000000000000005, + "route_distance_m": 1265.3425000000002, + "requested_route_distance_m": 1265.3425000000002, + "route_length_m": 2026.6238040154117, + "variant": "L113", + "capture": "captures/L113/passage-0-1-0-openair-3-4m-interior-wall.png", + "scene": "Saved/Linux/l113/captures/after/passage-0-1-0-openair-3-4m-interior-wall.vfmesh", + "drawn_triangles": 152882, + "source_triangles": 191476, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1265.3425000000002, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.999999999999989, + "closeup_target_surface_distance_m": 0.04715362672685941, + "closeup_predicted_target_offset_m": 0.04715362672685941, + "closeup_wall_normal_alignment": 0.8914972029009958, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -22.090001742014795, + -11.737840633493331, + -598.8622157263953 + ], + "target_actual_m": [ + -24.81309729642714, + -14.078633586544772, + -600.6244412943872 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-3-4m-interior-wall-mesh.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-3-4m-interior-wall-render.log", + "Saved/Linux/l113/captures/after/passage-0-1-0-openair-3-4m-interior-wall-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-0-1-0-openair-3-4m-interior-wall.png", + "source_sha256": "2b8ac6453a04986514d928859fade4fec4b10d5d6e7cce31c2cc8977dbfdf186", + "copy_bytes_verified": true, + "copy_quality_log": "Saved/Linux/l114/captures/L113-copied/passage-0-1-0-openair-3-4m-interior-wall-quality.log" + }, + { + "name": "passage-1-2-0-openair-1-4m-outside", + "passage": "passage/1-2/0", + "kind": "open-air-close", + "station": "section-1/4m-outside", + "camera": [ + -4.699079444431819, + -4.6537955842685985, + -748.15 + ], + "target": [ + -7.452748333327923, + -7.555055250400828, + -748.15 + ], + "yaw": -136.49505148095557, + "pitch": 0.0, + "focus": [ + -9.518, + -9.731, + -745.88 + ], + "center_z": -745.88, + "open_air_section": 1, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.688417222224026, + 0.7253149165330574, + 0.0 + ], + "camera_target_distance_m": 4.000000000000001, + "route_distance_m": 83.504, + "requested_route_distance_m": 83.504, + "route_length_m": 114.99063175809309, + "variant": "L113", + "capture": "captures/L113/passage-1-2-0-openair-1-4m-outside.png", + "scene": "Saved/Linux/l113/captures/after/passage-1-2-0-openair-1-4m-outside.vfmesh", + "drawn_triangles": 623418, + "source_triangles": 711740, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 83.504, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.99999999999999, + "closeup_target_surface_distance_m": 0.694202433854289, + "closeup_predicted_target_offset_m": 0.694202433854289, + "closeup_wall_normal_alignment": 0.6320955190222977, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -4.078884776303333, + -7.574630837765809, + -745.9346460853614 + ], + "target_actual_m": [ + -7.75, + -7.576179311817557, + -747.523013365486 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-1-2-0-openair-1-4m-outside-mesh.log", + "Saved/Linux/l113/captures/after/passage-1-2-0-openair-1-4m-outside-render.log", + "Saved/Linux/l113/captures/after/passage-1-2-0-openair-1-4m-outside-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-openair-1-4m-outside.png", + "source_sha256": "f257f57927fbab34ae93cfa662a9788bab1b8baa148e5e8091c18a8a7beeeed3", + "copy_bytes_verified": true, + "copy_quality_log": "Saved/Linux/l114/captures/L113-copied/passage-1-2-0-openair-1-4m-outside-quality.log" + }, + { + "name": "passage-1-2-0-openair-1-4m-interior-wall", + "passage": "passage/1-2/0", + "kind": "open-air-close", + "station": "section-1/4m-interior-wall", + "camera": [ + -6.0956279351195075, + -11.653774892861163, + -748.8673569837389 + ], + "target": [ + -8.16773669839842, + -8.308365466344922, + -748.15 + ], + "yaw": -31.773605793127505, + "pitch": 10.331275124559749, + "focus": [ + -9.518, + -9.731, + -745.88 + ], + "center_z": -745.88, + "open_air_section": 1, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.688417222224026, + -0.7253149165330574, + -0.0 + ], + "camera_target_distance_m": 3.999999999999997, + "route_distance_m": 83.504, + "requested_route_distance_m": 83.504, + "route_length_m": 114.99063175809309, + "variant": "L113", + "capture": "captures/L113/passage-1-2-0-openair-1-4m-interior-wall.png", + "scene": "Saved/Linux/l113/captures/after/passage-1-2-0-openair-1-4m-interior-wall.vfmesh", + "drawn_triangles": 612097, + "source_triangles": 692301, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 83.504, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.999999999999999, + "closeup_target_surface_distance_m": 0.6509430039577998, + "closeup_predicted_target_offset_m": 0.6509430039577998, + "closeup_wall_normal_alignment": 0.7808473937095911, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -8.525095579521167, + -12.94135557024142, + -748.3220319510015 + ], + "target_actual_m": [ + -8.18421537084871, + -8.958641713644115, + -748.1744141343152 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-1-2-0-openair-1-4m-interior-wall-mesh.log", + "Saved/Linux/l113/captures/after/passage-1-2-0-openair-1-4m-interior-wall-render.log", + "Saved/Linux/l113/captures/after/passage-1-2-0-openair-1-4m-interior-wall-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-openair-1-4m-interior-wall.png", + "source_sha256": "cb064486a28702adfb46679acd7a642db477f1dce1962a9cf96e83c9d6f61369", + "copy_bytes_verified": true, + "copy_quality_log": "Saved/Linux/l114/captures/L113-copied/passage-1-2-0-openair-1-4m-interior-wall-quality.log" + }, + { + "name": "passage-1-2-0-openair-2-4m-outside", + "passage": "passage/1-2/0", + "kind": "open-air-close", + "station": "section-2/4m-outside", + "camera": [ + 6.53817273275958, + -4.657210376135293, + -752.013 + ], + "target": [ + 8.159152142647708, + -8.31404312493838, + -752.013 + ], + "yaw": 156.09352823535562, + "pitch": 0.0, + "focus": [ + 9.43, + -11.181, + -749.743 + ], + "center_z": -749.743, + "open_air_section": 2, + "closeup_side": "outside", + "closeup_preferred_normal": [ + -0.40524485247203174, + 0.9142081872007717, + 0.0 + ], + "camera_target_distance_m": 4.0, + "route_distance_m": 104.362, + "requested_route_distance_m": 104.362, + "route_length_m": 114.99063175809309, + "variant": "L113", + "capture": "captures/L113/passage-1-2-0-openair-2-4m-outside.png", + "scene": "Saved/Linux/l113/captures/after/passage-1-2-0-openair-2-4m-outside.vfmesh", + "drawn_triangles": 585844, + "source_triangles": 657940, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 104.362, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.000000000000001, + "closeup_target_surface_distance_m": 0.5914642210657065, + "closeup_predicted_target_offset_m": 0.5914642210657065, + "closeup_wall_normal_alignment": 0.9891491270971497, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 6.36017623097692, + -5.41779354635724, + -752.0611111978326 + ], + "target_actual_m": [ + 8.5, + -8.797159410771899, + -752.028852990306 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-1-2-0-openair-2-4m-outside-mesh.log", + "Saved/Linux/l113/captures/after/passage-1-2-0-openair-2-4m-outside-render.log", + "Saved/Linux/l113/captures/after/passage-1-2-0-openair-2-4m-outside-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-openair-2-4m-outside.png", + "source_sha256": "1b9ee6fb673f700e99d04aed79b60442ffac4803484fe45cd213fb8621af50bb", + "copy_bytes_verified": true, + "copy_quality_log": "Saved/Linux/l114/captures/L113-copied/passage-1-2-0-openair-2-4m-outside-quality.log" + }, + { + "name": "passage-1-2-0-openair-2-4m-interior-wall", + "passage": "passage/1-2/0", + "kind": "open-air-close", + "station": "section-2/4m-interior-wall", + "camera": [ + 12.438590152225206, + -8.574465388721983, + -752.7261335058829 + ], + "target": [ + 8.55317187096847, + -9.20292810238377, + -752.013 + ], + "yaw": -99.18796190221158, + "pitch": 10.269787281460902, + "focus": [ + 9.43, + -11.181, + -749.743 + ], + "center_z": -749.743, + "open_air_section": 2, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + 0.40524485247203174, + -0.9142081872007717, + -0.0 + ], + "camera_target_distance_m": 3.9999999999999973, + "route_distance_m": 104.362, + "requested_route_distance_m": 104.362, + "route_length_m": 114.99063175809309, + "variant": "L113", + "capture": "captures/L113/passage-1-2-0-openair-2-4m-interior-wall.png", + "scene": "Saved/Linux/l113/captures/after/passage-1-2-0-openair-2-4m-interior-wall.vfmesh", + "drawn_triangles": 574404, + "source_triangles": 636814, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 104.362, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.000000000000001, + "closeup_target_surface_distance_m": 0.3527379880998657, + "closeup_predicted_target_offset_m": 0.3527379880998657, + "closeup_wall_normal_alignment": 0.9984886840143513, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 9.755455381073956, + -12.664189280507138, + -752.0262323451956 + ], + "target_actual_m": [ + 8.337158675455406, + -8.924125097427853, + -752.0074078590392 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-1-2-0-openair-2-4m-interior-wall-mesh.log", + "Saved/Linux/l113/captures/after/passage-1-2-0-openair-2-4m-interior-wall-render.log", + "Saved/Linux/l113/captures/after/passage-1-2-0-openair-2-4m-interior-wall-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-1-2-0-openair-2-4m-interior-wall.png", + "source_sha256": "405824a387c653efec7e82344a023b1690cbe680cd7824191a1b556734622c9b", + "copy_bytes_verified": true, + "copy_quality_log": "Saved/Linux/l114/captures/L113-copied/passage-1-2-0-openair-2-4m-interior-wall-quality.log" + }, + { + "name": "passage-2-3-0-openair-1-4m-outside", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-1/4m-outside", + "camera": [ + -3.5840423774965293, + -5.521048309862215, + -815.8969999999999 + ], + "target": [ + -5.637732447498513, + -8.953592132798093, + -815.8969999999999 + ], + "yaw": -149.10792796365394, + "pitch": 0.0, + "focus": [ + -7.178, + -11.528, + -813.627 + ], + "center_z": -813.627, + "open_air_section": 1, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.5134225175004958, + 0.8581359557339694, + 0.0 + ], + "camera_target_distance_m": 4.0, + "route_distance_m": 16.616500000000002, + "requested_route_distance_m": 16.616500000000002, + "route_length_m": 494.0722798830563, + "variant": "L113", + "capture": "captures/L113/passage-2-3-0-openair-1-4m-outside.png", + "scene": "Saved/Linux/l113/captures/after/passage-2-3-0-openair-1-4m-outside.vfmesh", + "drawn_triangles": 104612, + "source_triangles": 129378, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 16.616500000000002, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.0000000000000036, + "closeup_target_surface_distance_m": 0.29188924025474844, + "closeup_predicted_target_offset_m": 0.29188924025474844, + "closeup_wall_normal_alignment": 0.6703275045296155, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -3.7918253987505834, + -7.16028175130118, + -813.227396563761 + ], + "target_actual_m": [ + -5.7833741859987065, + -9.093313475424294, + -816.1078690565205 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-2-3-0-openair-1-4m-outside-mesh.log", + "Saved/Linux/l113/captures/after/passage-2-3-0-openair-1-4m-outside-render.log", + "Saved/Linux/l113/captures/after/passage-2-3-0-openair-1-4m-outside-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-openair-1-4m-outside.png", + "source_sha256": "71f150604a498ee4913f86bded31f8291d4213376357e7fbd460103d2970029e", + "copy_bytes_verified": true, + "copy_quality_log": "Saved/Linux/l114/captures/L113-copied/passage-2-3-0-openair-1-4m-outside-quality.log" + }, + { + "name": "passage-2-3-0-openair-1-4m-interior-wall", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-1/4m-interior-wall", + "camera": [ + -3.4141605326349946, + -12.659565888737353, + -816.5879167710818 + ], + "target": [ + -6.170971760123668, + -9.844849940114793, + -815.8969999999999 + ], + "yaw": -44.40454805561343, + "pitch": 9.946538162082001, + "focus": [ + -7.178, + -11.528, + -813.627 + ], + "center_z": -813.627, + "open_air_section": 1, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.5134225175004958, + -0.8581359557339694, + -0.0 + ], + "camera_target_distance_m": 4.000000000000005, + "route_distance_m": 16.616500000000002, + "requested_route_distance_m": 16.616500000000002, + "route_length_m": 494.0722798830563, + "variant": "L113", + "capture": "captures/L113/passage-2-3-0-openair-1-4m-interior-wall.png", + "scene": "Saved/Linux/l113/captures/after/passage-2-3-0-openair-1-4m-interior-wall.vfmesh", + "drawn_triangles": 94962, + "source_triangles": 118080, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 16.616500000000002, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.0, + "closeup_target_surface_distance_m": 0.41920390486225767, + "closeup_predicted_target_offset_m": 0.41920390486225767, + "closeup_wall_normal_alignment": 0.740744136337711, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -7.998432705401559, + -11.833936581758076, + -818.2481168532394 + ], + "target_actual_m": [ + -5.94757062165508, + -9.608161331921629, + -815.6327986602337 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-2-3-0-openair-1-4m-interior-wall-mesh.log", + "Saved/Linux/l113/captures/after/passage-2-3-0-openair-1-4m-interior-wall-render.log", + "Saved/Linux/l113/captures/after/passage-2-3-0-openair-1-4m-interior-wall-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-openair-1-4m-interior-wall.png", + "source_sha256": "c63607ad52d11e1c52ef5be860b5ffea6c63064a5b79f0accde285223584ce82", + "copy_bytes_verified": true, + "copy_quality_log": "Saved/Linux/l114/captures/L113-copied/passage-2-3-0-openair-1-4m-interior-wall-quality.log" + }, + { + "name": "passage-2-3-0-openair-2-4m-outside", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-2/4m-outside", + "camera": [ + -4.5562890668466025, + 4.648574813628143, + -879.7479999999999 + ], + "target": [ + -7.40869531436283, + 7.452817777269203, + -879.7479999999999 + ], + "yaw": -45.487830534998494, + "pitch": 0.0, + "focus": [ + -9.548, + 9.556, + -877.478 + ], + "center_z": -877.478, + "open_air_section": 2, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.7131015618790567, + -0.7010607409102652, + 0.0 + ], + "camera_target_distance_m": 4.000000000000001, + "route_distance_m": 374.929, + "requested_route_distance_m": 374.929, + "route_length_m": 494.0722798830563, + "variant": "L113", + "capture": "captures/L113/passage-2-3-0-openair-2-4m-outside.png", + "scene": "Saved/Linux/l113/captures/after/passage-2-3-0-openair-2-4m-outside.vfmesh", + "drawn_triangles": 475906, + "source_triangles": 507626, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 374.929, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.0, + "closeup_target_surface_distance_m": 1.7280841589725482, + "closeup_predicted_target_offset_m": 1.7280841589725482, + "closeup_wall_normal_alignment": 0.6707889779439669, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -7.47193274788199, + 5.182168353356822, + -879.6783722112204 + ], + "target_actual_m": [ + -7.306445568768645, + 9.17777802625833, + -879.7662205769708 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-2-3-0-openair-2-4m-outside-mesh.log", + "Saved/Linux/l113/captures/after/passage-2-3-0-openair-2-4m-outside-render.log", + "Saved/Linux/l113/captures/after/passage-2-3-0-openair-2-4m-outside-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-openair-2-4m-outside.png", + "source_sha256": "4253c629caadc95f31410dff052fca6c4b4f48f682d60f47790c1ed77bc2884c", + "copy_bytes_verified": true, + "copy_quality_log": "Saved/Linux/l114/captures/L113-copied/passage-2-3-0-openair-2-4m-outside-quality.log" + }, + { + "name": "passage-2-3-0-openair-2-4m-interior-wall", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-2/4m-interior-wall", + "camera": [ + -11.533986119377625, + 6.164550123765492, + -880.4395357921604 + ], + "target": [ + -8.149320771422074, + 8.180937668487475, + -879.7479999999999 + ], + "yaw": 59.215963829172296, + "pitch": 9.955540417812847, + "focus": [ + -9.548, + 9.556, + -877.478 + ], + "center_z": -877.478, + "open_air_section": 2, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.7131015618790567, + 0.7010607409102652, + -0.0 + ], + "camera_target_distance_m": 4.000000000000007, + "route_distance_m": 374.929, + "requested_route_distance_m": 374.929, + "route_length_m": 494.0722798830563, + "variant": "L113", + "capture": "captures/L113/passage-2-3-0-openair-2-4m-interior-wall.png", + "scene": "Saved/Linux/l113/captures/after/passage-2-3-0-openair-2-4m-interior-wall.vfmesh", + "drawn_triangles": 486760, + "source_triangles": 515826, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 374.929, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.0, + "closeup_target_surface_distance_m": 1.0286227628002445, + "closeup_predicted_target_offset_m": 1.0286227628002445, + "closeup_wall_normal_alignment": 0.720019406420326, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -8.257109087497915, + 13.208090205453457, + -879.7612149430302 + ], + "target_actual_m": [ + -8.149320771422074, + 9.209558486938477, + -879.75 + ], + "logs": [ + "Saved/Linux/l113/captures/after/passage-2-3-0-openair-2-4m-interior-wall-mesh.log", + "Saved/Linux/l113/captures/after/passage-2-3-0-openair-2-4m-interior-wall-render.log", + "Saved/Linux/l113/captures/after/passage-2-3-0-openair-2-4m-interior-wall-quality.log" + ], + "source_capture": "Standalone/Research/WorldAssemblerM3/Linux113/captures/after/passage-2-3-0-openair-2-4m-interior-wall.png", + "source_sha256": "fab5d2843d44d7467357ad8196a10eeb4d23df373ada5446985446e02fc6433c", + "copy_bytes_verified": true, + "copy_quality_log": "Saved/Linux/l114/captures/L113-copied/passage-2-3-0-openair-2-4m-interior-wall-quality.log" + }, + { + "name": "passage-1-2-0-rock-floor-midpoint", + "passage": "passage/1-2/0", + "kind": "rock-floor-close", + "station": "rock-floor/57.5m", + "camera": [ + -6.727309033913655, + 14.377943487475509, + -742.1274811193451 + ], + "target": [ + -8.621845503855653, + 12.813562713992287, + -743.8394815085395 + ], + "yaw": -129.54760251780488, + "pitch": -34.86885266130085, + "focus": [ + -8.621845503855653, + 12.813562713992287, + -743.8394815085395 + ], + "center_z": -743.8394815085395, + "route_distance_m": 57.495315879046544, + "requested_route_distance_m": 57.495315879046544, + "route_length_m": 114.99063175809309, + "closeup_side": "upward-floor", + "planned_floor_m": -743.8394815085395, + "planned_grade_deg": 10.649481264764157, + "version": "L113", + "variant": "L113", + "capture": "captures/L113/after/passage-1-2-0-rock-floor-midpoint.png", + "scene": "Saved/Linux/l114/captures/L113/after/passage-1-2-0-rock-floor-midpoint.vfmesh", + "drawn_triangles": 641506, + "source_triangles": 730098, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 57.495315879046544, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 2.9945785968957193, + "closeup_target_surface_distance_m": 0.04774982182540303, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": 0.9999999628943044, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -6.727309033913655, + 14.377943487475509, + -742.1274811193451 + ], + "target_actual_m": [ + -8.621845503855653, + 12.813562713992287, + -743.8394815085395 + ], + "logs": [ + "Saved/Linux/l114/captures/L113/after/passage-1-2-0-rock-floor-midpoint-mesh.log", + "Saved/Linux/l114/captures/L113/after/passage-1-2-0-rock-floor-midpoint-render.log", + "Saved/Linux/l114/captures/L113/after/passage-1-2-0-rock-floor-midpoint-quality.log" + ], + "floor_anchor_position_m": [ + -8.622731106240465, + 12.812479016337184, + -743.7917522010632 + ], + "floor_anchor_normal": [ + -0.00021072194555220986, + -0.00017264892583583355, + 0.9999999628943044 + ], + "closeup_camera_to_floor_distance_m": 2.968686927936851, + "verified_upward_floor_normal": true + }, + { + "name": "passage-0-1-0-openair-1-4m-outside", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-1/4m-outside", + "camera": [ + 13.176702021211483, + 7.149068417345486, + -374.402 + ], + "target": [ + 9.197121888971225, + 7.5527291301707695, + -374.402 + ], + "yaw": -84.20812706837869, + "pitch": 0.0, + "focus": [ + 7.272, + 7.748, + -373.197 + ], + "center_z": -373.197, + "open_air_section": 1, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.9948950330600643, + -0.1009151782063209, + 0.0 + ], + "camera_target_distance_m": 4.000000000000001, + "route_distance_m": 8.3545, + "requested_route_distance_m": 8.3545, + "route_length_m": 2026.6238040154117, + "variant": "L114", + "capture": "captures/L114/after/passage-0-1-0-openair-1-4m-outside.png", + "scene": "Saved/Linux/l114/captures/L114/after/passage-0-1-0-openair-1-4m-outside.vfmesh", + "drawn_triangles": 275347, + "source_triangles": 327731, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 8.3545, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.9999999999999987, + "closeup_target_surface_distance_m": 0.7939613079024029, + "closeup_predicted_target_offset_m": 0.7939613079024029, + "closeup_wall_normal_alignment": 0.9448010671048102, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 12.921959272720493, + 7.9850770584603294, + -375.0077532897384 + ], + "target_actual_m": [ + 9.124876976013184, + 8.0, + -373.75 + ], + "logs": [ + "Saved/Linux/l114/captures/L114/after/passage-0-1-0-openair-1-4m-outside-mesh.log", + "Saved/Linux/l114/captures/L114/after/passage-0-1-0-openair-1-4m-outside-render.log", + "Saved/Linux/l114/captures/L114/after/passage-0-1-0-openair-1-4m-outside-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-1-4m-interior-wall", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-1/4m-interior-wall", + "camera": [ + 7.395778712540976, + 3.8749008126934172, + -374.89997477205173 + ], + "target": [ + 8.778272394312646, + 7.595214286886338, + -374.402 + ], + "yaw": 20.38540702862518, + "pitch": 7.1515181408188955, + "focus": [ + 7.272, + 7.748, + -373.197 + ], + "center_z": -373.197, + "open_air_section": 1, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.9948950330600643, + 0.1009151782063209, + -0.0 + ], + "camera_target_distance_m": 3.9999999999999973, + "route_distance_m": 8.3545, + "requested_route_distance_m": 8.3545, + "route_length_m": 2026.6238040154117, + "variant": "L114", + "capture": "captures/L114/after/passage-0-1-0-openair-1-4m-interior-wall.png", + "scene": "Saved/Linux/l114/captures/L114/after/passage-0-1-0-openair-1-4m-interior-wall.vfmesh", + "drawn_triangles": 308016, + "source_triangles": 368048, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 8.3545, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.999999999999998, + "closeup_target_surface_distance_m": 0.8420749429811597, + "closeup_predicted_target_offset_m": 0.8420749429811597, + "closeup_wall_normal_alignment": 0.9448010671048102, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 5.3277946793058755, + 8.01492294153967, + -372.4922467102616 + ], + "target_actual_m": [ + 9.124876976013184, + 8.0, + -373.75 + ], + "logs": [ + "Saved/Linux/l114/captures/L114/after/passage-0-1-0-openair-1-4m-interior-wall-mesh.log", + "Saved/Linux/l114/captures/L114/after/passage-0-1-0-openair-1-4m-interior-wall-render.log", + "Saved/Linux/l114/captures/L114/after/passage-0-1-0-openair-1-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-2-4m-outside", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-2/4m-outside", + "camera": [ + 12.814097656232029, + 0.949800892309409, + -375.51163279923776 + ], + "target": [ + 8.842807594702599, + 1.4281890685821654, + -375.51163279923776 + ], + "yaw": -83.1311525734364, + "pitch": 0.0, + "focus": [ + 6.603, + 1.698, + -374.149 + ], + "center_z": -374.149, + "open_air_section": 2, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.9928225153823576, + -0.1195970440681891, + 0.0 + ], + "camera_target_distance_m": 4.0, + "route_distance_m": 14.4925, + "requested_route_distance_m": 14.4925, + "route_length_m": 2026.6238040154117, + "variant": "L114", + "capture": "captures/L114/after/passage-0-1-0-openair-2-4m-outside.png", + "scene": "Saved/Linux/l114/captures/L114/after/passage-0-1-0-openair-2-4m-outside.vfmesh", + "drawn_triangles": 275347, + "source_triangles": 327731, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 14.4925, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.9999999999999996, + "closeup_target_surface_distance_m": 1.0987112128185943, + "closeup_predicted_target_offset_m": 1.0987112128185943, + "closeup_wall_normal_alignment": 0.39204894805325147, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 9.614295105608754, + 1.6486404462247444, + -379.5820941505854 + ], + "target_actual_m": [ + 7.956625938415527, + 1.0, + -376.0 + ], + "logs": [ + "Saved/Linux/l114/captures/L114/after/passage-0-1-0-openair-2-4m-outside-mesh.log", + "Saved/Linux/l114/captures/L114/after/passage-0-1-0-openair-2-4m-outside-render.log", + "Saved/Linux/l114/captures/L114/after/passage-0-1-0-openair-2-4m-outside-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-2-4m-interior-wall", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-2/4m-interior-wall", + "camera": [ + 6.939570778854576, + -2.1803140897652855, + -376.2060303004211 + ], + "target": [ + 8.388084903173432, + 1.4829657169105679, + -375.51163279923776 + ], + "yaw": 21.574563086437188, + "pitch": 9.997160707081923, + "focus": [ + 6.603, + 1.698, + -374.149 + ], + "center_z": -374.149, + "open_air_section": 2, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.9928225153823576, + 0.1195970440681891, + -0.0 + ], + "camera_target_distance_m": 3.999999999999997, + "route_distance_m": 14.4925, + "requested_route_distance_m": 14.4925, + "route_length_m": 2026.6238040154117, + "variant": "L114", + "capture": "captures/L114/after/passage-0-1-0-openair-2-4m-interior-wall.png", + "scene": "Saved/Linux/l114/captures/L114/after/passage-0-1-0-openair-2-4m-interior-wall.vfmesh", + "drawn_triangles": 345082, + "source_triangles": 414610, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 14.4925, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.999999999999996, + "closeup_target_surface_distance_m": 0.7753571368538784, + "closeup_predicted_target_offset_m": 0.7753571368538784, + "closeup_wall_normal_alignment": 0.28414095480383694, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 6.625809094540684, + 0.5552691810408462, + -372.2490874094312 + ], + "target_actual_m": [ + 7.849808932278981, + 1.2129006394800852, + -376.0 + ], + "logs": [ + "Saved/Linux/l114/captures/L114/after/passage-0-1-0-openair-2-4m-interior-wall-mesh.log", + "Saved/Linux/l114/captures/L114/after/passage-0-1-0-openair-2-4m-interior-wall-render.log", + "Saved/Linux/l114/captures/L114/after/passage-0-1-0-openair-2-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-3-4m-outside", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-3/4m-outside", + "camera": [ + -28.32291429976088, + -16.444327461849063, + -600.6066327992378 + ], + "target": [ + -25.004026673221745, + -14.211619482196229, + -600.6066327992378 + ], + "yaw": 56.07018168236039, + "pitch": 0.0, + "focus": [ + -22.1, + -12.258, + -599.244 + ], + "center_z": -599.244, + "open_air_section": 3, + "closeup_side": "outside", + "closeup_preferred_normal": [ + -0.8297219066347834, + -0.5581769949132084, + 0.0 + ], + "camera_target_distance_m": 4.000000000000001, + "route_distance_m": 1265.3425000000002, + "requested_route_distance_m": 1265.3425000000002, + "route_length_m": 2026.6238040154117, + "variant": "L114", + "capture": "captures/L114/after/passage-0-1-0-openair-3-4m-outside.png", + "scene": "Saved/Linux/l114/captures/L114/after/passage-0-1-0-openair-3-4m-outside.vfmesh", + "drawn_triangles": 150904, + "source_triangles": 184984, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1265.3425000000002, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.000000000000005, + "closeup_target_surface_distance_m": 0.07067255179093222, + "closeup_predicted_target_offset_m": 0.07067255179093222, + "closeup_wall_normal_alignment": 0.9576838945141799, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -28.640353420990742, + -15.558646921565558, + -601.2738110849364 + ], + "target_actual_m": [ + -24.95240069154897, + -14.177793868090674, + -600.5722061319093 + ], + "logs": [ + "Saved/Linux/l114/captures/L114/after/passage-0-1-0-openair-3-4m-outside-mesh.log", + "Saved/Linux/l114/captures/L114/after/passage-0-1-0-openair-3-4m-outside-render.log", + "Saved/Linux/l114/captures/L114/after/passage-0-1-0-openair-3-4m-outside-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-3-4m-interior-wall", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-3/4m-interior-wall", + "camera": [ + -26.071689640946218, + -10.338278587083852, + -601.3036807194 + ], + "target": [ + -24.774901932566983, + -14.057480898923608, + -600.6066327992378 + ], + "yaw": 160.77768453528284, + "pitch": 10.035712777782798, + "focus": [ + -22.1, + -12.258, + -599.244 + ], + "center_z": -599.244, + "open_air_section": 3, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + 0.8297219066347834, + 0.5581769949132084, + -0.0 + ], + "camera_target_distance_m": 4.000000000000005, + "route_distance_m": 1265.3425000000002, + "requested_route_distance_m": 1265.3425000000002, + "route_length_m": 2026.6238040154117, + "variant": "L114", + "capture": "captures/L114/after/passage-0-1-0-openair-3-4m-interior-wall.png", + "scene": "Saved/Linux/l114/captures/L114/after/passage-0-1-0-openair-3-4m-interior-wall.vfmesh", + "drawn_triangles": 150354, + "source_triangles": 185238, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1265.3425000000002, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.0000000000000036, + "closeup_target_surface_distance_m": 0.15351295361739858, + "closeup_predicted_target_offset_m": 0.15351295361739858, + "closeup_wall_normal_alignment": 0.9346940736053617, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -21.877006078739754, + -11.889039756241772, + -599.287393289646 + ], + "target_actual_m": [ + -24.865807884267895, + -14.144421065858271, + -600.6946313347203 + ], + "logs": [ + "Saved/Linux/l114/captures/L114/after/passage-0-1-0-openair-3-4m-interior-wall-mesh.log", + "Saved/Linux/l114/captures/L114/after/passage-0-1-0-openair-3-4m-interior-wall-render.log", + "Saved/Linux/l114/captures/L114/after/passage-0-1-0-openair-3-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-1-4m-outside", + "passage": "passage/1-2/0", + "kind": "open-air-close", + "station": "section-1/4m-outside", + "camera": [ + -4.699079444431819, + -4.6537955842685985, + -748.15 + ], + "target": [ + -7.452748333327923, + -7.555055250400828, + -748.15 + ], + "yaw": -136.49505148095557, + "pitch": 0.0, + "focus": [ + -9.518, + -9.731, + -745.88 + ], + "center_z": -745.88, + "open_air_section": 1, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.688417222224026, + 0.7253149165330574, + 0.0 + ], + "camera_target_distance_m": 4.000000000000001, + "route_distance_m": 83.504, + "requested_route_distance_m": 83.504, + "route_length_m": 114.99063175809309, + "variant": "L114", + "capture": "captures/L114/after/passage-1-2-0-openair-1-4m-outside.png", + "scene": "Saved/Linux/l114/captures/L114/after/passage-1-2-0-openair-1-4m-outside.vfmesh", + "drawn_triangles": 620958, + "source_triangles": 685048, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 83.504, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.000000000000015, + "closeup_target_surface_distance_m": 0.694202433854289, + "closeup_predicted_target_offset_m": 0.694202433854289, + "closeup_wall_normal_alignment": 0.2507581806756137, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -5.145277260640605, + -8.66550375859403, + -744.6895011102241 + ], + "target_actual_m": [ + -7.75, + -7.576179311817557, + -747.523013365486 + ], + "logs": [ + "Saved/Linux/l114/captures/L114/after/passage-1-2-0-openair-1-4m-outside-mesh.log", + "Saved/Linux/l114/captures/L114/after/passage-1-2-0-openair-1-4m-outside-render.log", + "Saved/Linux/l114/captures/L114/after/passage-1-2-0-openair-1-4m-outside-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-1-4m-interior-wall", + "passage": "passage/1-2/0", + "kind": "open-air-close", + "station": "section-1/4m-interior-wall", + "camera": [ + -6.0956279351195075, + -11.653774892861163, + -748.8673569837389 + ], + "target": [ + -8.16773669839842, + -8.308365466344922, + -748.15 + ], + "yaw": -31.773605793127505, + "pitch": 10.331275124559749, + "focus": [ + -9.518, + -9.731, + -745.88 + ], + "center_z": -745.88, + "open_air_section": 1, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.688417222224026, + -0.7253149165330574, + -0.0 + ], + "camera_target_distance_m": 3.999999999999997, + "route_distance_m": 83.504, + "requested_route_distance_m": 83.504, + "route_length_m": 114.99063175809309, + "variant": "L114", + "capture": "captures/L114/after/passage-1-2-0-openair-1-4m-interior-wall.png", + "scene": "Saved/Linux/l114/captures/L114/after/passage-1-2-0-openair-1-4m-interior-wall.vfmesh", + "drawn_triangles": 609821, + "source_triangles": 668347, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 83.504, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.999999999999999, + "closeup_target_surface_distance_m": 0.6509430039577998, + "closeup_predicted_target_offset_m": 0.6509430039577998, + "closeup_wall_normal_alignment": 0.7808473937095911, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -8.525095579521167, + -12.94135557024142, + -748.3220319510015 + ], + "target_actual_m": [ + -8.18421537084871, + -8.958641713644115, + -748.1744141343152 + ], + "logs": [ + "Saved/Linux/l114/captures/L114/after/passage-1-2-0-openair-1-4m-interior-wall-mesh.log", + "Saved/Linux/l114/captures/L114/after/passage-1-2-0-openair-1-4m-interior-wall-render.log", + "Saved/Linux/l114/captures/L114/after/passage-1-2-0-openair-1-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-2-4m-outside", + "passage": "passage/1-2/0", + "kind": "open-air-close", + "station": "section-2/4m-outside", + "camera": [ + 6.53817273275958, + -4.657210376135293, + -752.013 + ], + "target": [ + 8.159152142647708, + -8.31404312493838, + -752.013 + ], + "yaw": 156.09352823535562, + "pitch": 0.0, + "focus": [ + 9.43, + -11.181, + -749.743 + ], + "center_z": -749.743, + "open_air_section": 2, + "closeup_side": "outside", + "closeup_preferred_normal": [ + -0.40524485247203174, + 0.9142081872007717, + 0.0 + ], + "camera_target_distance_m": 4.0, + "route_distance_m": 104.362, + "requested_route_distance_m": 104.362, + "route_length_m": 114.99063175809309, + "variant": "L114", + "capture": "captures/L114/after/passage-1-2-0-openair-2-4m-outside.png", + "scene": "Saved/Linux/l114/captures/L114/after/passage-1-2-0-openair-2-4m-outside.vfmesh", + "drawn_triangles": 584696, + "source_triangles": 637212, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 104.362, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.000000000000001, + "closeup_target_surface_distance_m": 0.5914642210657065, + "closeup_predicted_target_offset_m": 0.5914642210657065, + "closeup_wall_normal_alignment": 0.9891491270971497, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 6.36017623097692, + -5.41779354635724, + -752.0611111978326 + ], + "target_actual_m": [ + 8.5, + -8.797159410771899, + -752.028852990306 + ], + "logs": [ + "Saved/Linux/l114/captures/L114/after/passage-1-2-0-openair-2-4m-outside-mesh.log", + "Saved/Linux/l114/captures/L114/after/passage-1-2-0-openair-2-4m-outside-render.log", + "Saved/Linux/l114/captures/L114/after/passage-1-2-0-openair-2-4m-outside-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-2-4m-interior-wall", + "passage": "passage/1-2/0", + "kind": "open-air-close", + "station": "section-2/4m-interior-wall", + "camera": [ + 12.438590152225206, + -8.574465388721983, + -752.7261335058829 + ], + "target": [ + 8.55317187096847, + -9.20292810238377, + -752.013 + ], + "yaw": -99.18796190221158, + "pitch": 10.269787281460902, + "focus": [ + 9.43, + -11.181, + -749.743 + ], + "center_z": -749.743, + "open_air_section": 2, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + 0.40524485247203174, + -0.9142081872007717, + -0.0 + ], + "camera_target_distance_m": 3.9999999999999973, + "route_distance_m": 104.362, + "requested_route_distance_m": 104.362, + "route_length_m": 114.99063175809309, + "variant": "L114", + "capture": "captures/L114/after/passage-1-2-0-openair-2-4m-interior-wall.png", + "scene": "Saved/Linux/l114/captures/L114/after/passage-1-2-0-openair-2-4m-interior-wall.vfmesh", + "drawn_triangles": 572310, + "source_triangles": 618746, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 104.362, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.000000000000001, + "closeup_target_surface_distance_m": 0.3527379880998657, + "closeup_predicted_target_offset_m": 0.3527379880998657, + "closeup_wall_normal_alignment": 0.9984886840143513, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 9.755455381073956, + -12.664189280507138, + -752.0262323451956 + ], + "target_actual_m": [ + 8.337158675455406, + -8.924125097427853, + -752.0074078590392 + ], + "logs": [ + "Saved/Linux/l114/captures/L114/after/passage-1-2-0-openair-2-4m-interior-wall-mesh.log", + "Saved/Linux/l114/captures/L114/after/passage-1-2-0-openair-2-4m-interior-wall-render.log", + "Saved/Linux/l114/captures/L114/after/passage-1-2-0-openair-2-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-1-4m-outside", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-1/4m-outside", + "camera": [ + -3.5840423774965293, + -5.521048309862215, + -815.8969999999999 + ], + "target": [ + -5.637732447498513, + -8.953592132798093, + -815.8969999999999 + ], + "yaw": -149.10792796365394, + "pitch": 0.0, + "focus": [ + -7.178, + -11.528, + -813.627 + ], + "center_z": -813.627, + "open_air_section": 1, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.5134225175004958, + 0.8581359557339694, + 0.0 + ], + "camera_target_distance_m": 4.0, + "route_distance_m": 16.616500000000002, + "requested_route_distance_m": 16.616500000000002, + "route_length_m": 494.0722798830563, + "variant": "L114", + "capture": "captures/L114/after/passage-2-3-0-openair-1-4m-outside.png", + "scene": "Saved/Linux/l114/captures/L114/after/passage-2-3-0-openair-1-4m-outside.vfmesh", + "drawn_triangles": 104612, + "source_triangles": 129354, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 16.616500000000002, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.0000000000000036, + "closeup_target_surface_distance_m": 0.29188924025474844, + "closeup_predicted_target_offset_m": 0.29188924025474844, + "closeup_wall_normal_alignment": 0.6703275045296155, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -3.7918253987505834, + -7.16028175130118, + -813.227396563761 + ], + "target_actual_m": [ + -5.7833741859987065, + -9.093313475424294, + -816.1078690565205 + ], + "logs": [ + "Saved/Linux/l114/captures/L114/after/passage-2-3-0-openair-1-4m-outside-mesh.log", + "Saved/Linux/l114/captures/L114/after/passage-2-3-0-openair-1-4m-outside-render.log", + "Saved/Linux/l114/captures/L114/after/passage-2-3-0-openair-1-4m-outside-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-1-4m-interior-wall", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-1/4m-interior-wall", + "camera": [ + -3.4141605326349946, + -12.659565888737353, + -816.5879167710818 + ], + "target": [ + -6.170971760123668, + -9.844849940114793, + -815.8969999999999 + ], + "yaw": -44.40454805561343, + "pitch": 9.946538162082001, + "focus": [ + -7.178, + -11.528, + -813.627 + ], + "center_z": -813.627, + "open_air_section": 1, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.5134225175004958, + -0.8581359557339694, + -0.0 + ], + "camera_target_distance_m": 4.000000000000005, + "route_distance_m": 16.616500000000002, + "requested_route_distance_m": 16.616500000000002, + "route_length_m": 494.0722798830563, + "variant": "L114", + "capture": "captures/L114/after/passage-2-3-0-openair-1-4m-interior-wall.png", + "scene": "Saved/Linux/l114/captures/L114/after/passage-2-3-0-openair-1-4m-interior-wall.vfmesh", + "drawn_triangles": 94962, + "source_triangles": 118056, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 16.616500000000002, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.0, + "closeup_target_surface_distance_m": 0.41920390486225767, + "closeup_predicted_target_offset_m": 0.41920390486225767, + "closeup_wall_normal_alignment": 0.740744136337711, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -7.998432705401559, + -11.833936581758076, + -818.2481168532394 + ], + "target_actual_m": [ + -5.94757062165508, + -9.608161331921629, + -815.6327986602337 + ], + "logs": [ + "Saved/Linux/l114/captures/L114/after/passage-2-3-0-openair-1-4m-interior-wall-mesh.log", + "Saved/Linux/l114/captures/L114/after/passage-2-3-0-openair-1-4m-interior-wall-render.log", + "Saved/Linux/l114/captures/L114/after/passage-2-3-0-openair-1-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-2-4m-outside", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-2/4m-outside", + "camera": [ + -4.5562890668466025, + 4.648574813628143, + -879.7479999999999 + ], + "target": [ + -7.40869531436283, + 7.452817777269203, + -879.7479999999999 + ], + "yaw": -45.487830534998494, + "pitch": 0.0, + "focus": [ + -9.548, + 9.556, + -877.478 + ], + "center_z": -877.478, + "open_air_section": 2, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.7131015618790567, + -0.7010607409102652, + 0.0 + ], + "camera_target_distance_m": 4.000000000000001, + "route_distance_m": 374.929, + "requested_route_distance_m": 374.929, + "route_length_m": 494.0722798830563, + "variant": "L114", + "capture": "captures/L114/after/passage-2-3-0-openair-2-4m-outside.png", + "scene": "Saved/Linux/l114/captures/L114/after/passage-2-3-0-openair-2-4m-outside.vfmesh", + "drawn_triangles": 475818, + "source_triangles": 504194, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 374.929, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.0, + "closeup_target_surface_distance_m": 1.7280841589725482, + "closeup_predicted_target_offset_m": 1.7280841589725482, + "closeup_wall_normal_alignment": 0.6707889779439669, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -7.47193274788199, + 5.182168353356822, + -879.6783722112204 + ], + "target_actual_m": [ + -7.306445568768645, + 9.17777802625833, + -879.7662205769708 + ], + "logs": [ + "Saved/Linux/l114/captures/L114/after/passage-2-3-0-openair-2-4m-outside-mesh.log", + "Saved/Linux/l114/captures/L114/after/passage-2-3-0-openair-2-4m-outside-render.log", + "Saved/Linux/l114/captures/L114/after/passage-2-3-0-openair-2-4m-outside-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-2-4m-interior-wall", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-2/4m-interior-wall", + "camera": [ + -11.533986119377625, + 6.164550123765492, + -880.4395357921604 + ], + "target": [ + -8.149320771422074, + 8.180937668487475, + -879.7479999999999 + ], + "yaw": 59.215963829172296, + "pitch": 9.955540417812847, + "focus": [ + -9.548, + 9.556, + -877.478 + ], + "center_z": -877.478, + "open_air_section": 2, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.7131015618790567, + 0.7010607409102652, + -0.0 + ], + "camera_target_distance_m": 4.000000000000007, + "route_distance_m": 374.929, + "requested_route_distance_m": 374.929, + "route_length_m": 494.0722798830563, + "variant": "L114", + "capture": "captures/L114/after/passage-2-3-0-openair-2-4m-interior-wall.png", + "scene": "Saved/Linux/l114/captures/L114/after/passage-2-3-0-openair-2-4m-interior-wall.vfmesh", + "drawn_triangles": 486490, + "source_triangles": 513490, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 374.929, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.0, + "closeup_target_surface_distance_m": 1.0286227628002445, + "closeup_predicted_target_offset_m": 1.0286227628002445, + "closeup_wall_normal_alignment": 0.720019406420326, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -8.257109087497915, + 13.208090205453457, + -879.7612149430302 + ], + "target_actual_m": [ + -8.149320771422074, + 9.209558486938477, + -879.75 + ], + "logs": [ + "Saved/Linux/l114/captures/L114/after/passage-2-3-0-openair-2-4m-interior-wall-mesh.log", + "Saved/Linux/l114/captures/L114/after/passage-2-3-0-openair-2-4m-interior-wall-render.log", + "Saved/Linux/l114/captures/L114/after/passage-2-3-0-openair-2-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-1-2-0-rock-floor-midpoint", + "passage": "passage/1-2/0", + "kind": "rock-floor-close", + "station": "rock-floor/57.5m", + "camera": [ + -6.727309033913655, + 14.377943487475509, + -742.1274811193451 + ], + "target": [ + -8.621845503855653, + 12.813562713992287, + -743.8394815085395 + ], + "yaw": -129.54760251780488, + "pitch": -34.86885266130085, + "focus": [ + -8.621845503855653, + 12.813562713992287, + -743.8394815085395 + ], + "center_z": -743.8394815085395, + "route_distance_m": 57.495315879046544, + "requested_route_distance_m": 57.495315879046544, + "route_length_m": 114.99063175809309, + "closeup_side": "upward-floor", + "planned_floor_m": -743.8394815085395, + "planned_grade_deg": 10.649481264764157, + "version": "L114", + "variant": "L114", + "capture": "captures/L114/after/passage-1-2-0-rock-floor-midpoint.png", + "scene": "Saved/Linux/l114/captures/L114/after/passage-1-2-0-rock-floor-midpoint.vfmesh", + "drawn_triangles": 636304, + "source_triangles": 700696, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 57.495315879046544, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 2.9945785968957193, + "closeup_target_surface_distance_m": 0.00722358277997261, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": 0.9827957560588102, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -6.727309033913655, + 14.377943487475509, + -742.1274811193451 + ], + "target_actual_m": [ + -8.621845503855653, + 12.813562713992287, + -743.8394815085395 + ], + "logs": [ + "Saved/Linux/l114/captures/L114/after/passage-1-2-0-rock-floor-midpoint-mesh.log", + "Saved/Linux/l114/captures/L114/after/passage-1-2-0-rock-floor-midpoint-render.log", + "Saved/Linux/l114/captures/L114/after/passage-1-2-0-rock-floor-midpoint-quality.log" + ], + "floor_anchor_position_m": [ + -8.622881907819128, + 12.812718686015343, + -743.8323826613248 + ], + "floor_anchor_normal": [ + -0.14250470582728644, + -0.11749430066973524, + 0.9827957560588102 + ], + "closeup_camera_to_floor_distance_m": 2.9916240517880777, + "verified_upward_floor_normal": true + } + ] +} diff --git a/Standalone/Research/WorldAssemblerM3/Linux115/REPORT.md b/Standalone/Research/WorldAssemblerM3/Linux115/REPORT.md new file mode 100644 index 0000000..3e1f622 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux115/REPORT.md @@ -0,0 +1,46 @@ +# Linux115 report + +Source version 223. Floor height now comes from the planner profile `h(s)` on the dense route, using horizontal projection and arc-length interpolation. In-range projections interpolate on their fine segment; out-of-range projections use the global profile lookup. Adjacent fine segments share the same endpoint value. The plan-time grade audit remains enabled: maximum sampled grade was 10.687° (limit 15°). + +## Floor zero crossings + +Each station has 51 density samples. Offsets below are in millimetres. + +| Passage | Station | Max absolute | Median absolute | P95 absolute | +|---|---:|---:|---:|---:| +| 0–1 | 25% | 0.088 | 0.009 | 0.066 | +| 0–1 | 50% | 0.079 | 0.016 | 0.064 | +| 0–1 | 75% | 0.225 | 0.016 | 0.161 | +| 1–2 | 25% | 7.475 | 7.259 | 7.459 | +| 1–2 | 50% | 7.272 | 7.215 | 7.265 | +| 1–2 | 75% | 7.272 | 7.121 | 7.245 | +| 2–3 | 25% | 7.849 | 7.712 | 7.844 | +| 2–3 | 50% | 7.712 | 7.351 | 7.694 | +| 2–3 | 75% | 7.573 | 7.506 | 7.566 | + +Maximum offset is 7.849 mm, below the 10 mm target. Full data: [CSV](../../../../Saved/Linux/l115/density-probe/zero-crossing-offsets.csv) and [summary](../../../../Saved/Linux/l115/density-probe/zero-crossing-summary.json). + +## Shell probes and captures + +The two L114 southwest wall misses were probe-oracle false positives. Both positions were inside an intentionally carved overlapping passage bore, where host air is correct; the audit had only considered the nearest route span when classifying bore interior. The oracle now recognizes interior air on any overlapping route span. No wall gate was relaxed. The final two-strata audit reports 0 wall violations in 31,361 probes (8,848 overlap-interior skips), 0 floor violations, and 0 interior violations. + +The final capture set has 23/23 programmatically verified images: 9 rock-floor close-ups and 14 open-air outside/interior close-ups across 7 sections. Quality labels are 18 `pass` and 5 `low_contrast_geometry_visible`; all five still passed visibility verification. [Capture index](captures/capture-index.json). + +## Speed + +Coarse candidate totals are L109 3,132, L114 14,384, and L115 3,720 (74.1% fewer than L114). The inner sweep still visits 48.95M fine-segment/sample pairs for both L114 and L115, versus 19.81M for L109, so fewer coarse candidates did not reduce fine traversal enough to improve readiness. + +Five interleaved measured runs per version followed warm-ups at W8/W12 for all four strata. The host was quiet before timing (1-minute load 1.30; `top` 99% idle). Values below are L115 near-ready median deltas. + +| Stratum | W8 vs L109 / L114 | W12 vs L109 / L114 | +|---|---:|---:| +| 0 | +16.8% / +8.7% | +16.8% / +9.2% | +| 1 | +30.4% / +13.0% | +31.1% / +14.5% | +| 2 | +25.2% / +12.4% | +25.9% / +12.0% | +| 3 | +23.8% / +8.6% | +18.1% / +2.9% | + +Across the eight strata/worker combinations, median whole-view deltas were +10.7% versus L109 and +4.9% versus L114. Full run data: [timing summary](../../../../Saved/Linux/l115/timing/summary.json). + +## Verification + +Fast tier passed in 341.1 s, including walkability, passage shell, camera sweeps, native field, and motif capsule reachability. Clang/GCC hashes matched at W1/W8/W12 for all four owner strata groups. The final source stamp is `7eb1fa49f91954c0690173aba4ed832b3594e50531bd4b20690d122970943274`; no Unreal-compiled source changed, so no Unreal build was needed. diff --git a/Standalone/Research/WorldAssemblerM3/Linux115/RunL115CandidateLists.py b/Standalone/Research/WorldAssemblerM3/Linux115/RunL115CandidateLists.py new file mode 100644 index 0000000..bc89dd4 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux115/RunL115CandidateLists.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python3 +"""Compare per-tile passage candidate-list sizes for L109, L114, and L115.""" +from __future__ import annotations + +import json +import math +import re +import statistics +import subprocess +import time +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / "Saved/Linux/l115/candidate-lists" +DATA = ROOT / "Standalone/data/owner_world.json" +BINARIES = { + "L109": ROOT / "Saved/Linux/l109/bin-final/VoxelForgeCoreHeadless-l109-clang", + "L114": ROOT / "Saved/Linux/l114/bin/VoxelForgeCoreHeadless-l114-clang", + "L115": ROOT / "Saved/Linux/l115/bin/VoxelForgeCoreHeadless-l115-clang", +} +CAMERAS = { + 0: (8.0, 16.0, -372.2626953125), + 1: (25.8369140625, 3.19921875, -737.0), + 2: (19.166015625, -14.2001953125, -753.3740234375), + 3: (-20.0625, -5.068359375, -900.353515625), +} +LIST = re.compile(r"^\[PassageComposerTile\].*?features=(\d+) route_candidates=(\d+)", re.M) + + +def percentile(values: list[int], fraction: float) -> int: + ordered = sorted(values) + if not ordered: + return 0 + return ordered[min(len(ordered) - 1, + max(0, math.ceil(fraction * len(ordered)) - 1))] + + +def run(strate: int, version: str) -> dict: + OUT.mkdir(parents=True, exist_ok=True) + log = OUT / f"{version}-s{strate}.log" + camera = ",".join(f"{v:.12f}" for v in CAMERAS[strate]) + ",0,0" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1740s", str(BINARIES[version]), str(DATA), + "--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline", + "--workers=12", "--clip-radius=3", "--max-clip-level=8", "--max-level=8", + f"--camera={camera}", "--profile-passage-composer", "--stream-scheduler-policy=3", + ] + started = time.monotonic() + with log.open("w", encoding="utf-8") as stream: + result = subprocess.run(command, cwd=ROOT, stdout=stream, + stderr=subprocess.STDOUT, check=False, timeout=1740) + output = log.read_text(encoding="utf-8", errors="replace") + features = [int(row[0]) for row in LIST.findall(output)] + routes = [int(row[1]) for row in LIST.findall(output)] + if result.returncode or not features: + raise SystemExit(f"candidate-list profile missing: {log}; exit={result.returncode}") + row = { + "strate": strate, "version": version, "profiled_tiles": len(features), + "feature_candidates": {"sum": sum(features), "min": min(features), + "median": statistics.median(features), "p95": percentile(features, .95), + "max": max(features)}, + "route_segment_candidates": {"sum": sum(routes), "min": min(routes), + "median": statistics.median(routes), "p95": percentile(routes, .95), + "max": max(routes)}, + "elapsed_s": round(time.monotonic() - started, 3), + "log": str(log.relative_to(ROOT)), + } + print("[L115CandidateLists] " + json.dumps(row, sort_keys=True), flush=True) + return row + + +def main() -> int: + if any(not path.is_file() for path in (*BINARIES.values(), DATA)): + raise SystemExit("missing L109/L114/L115 candidate-list input") + rows = [run(strate, version) for strate in range(4) + for version in ("L109", "L114", "L115")] + (OUT / "summary.json").write_text(json.dumps(rows, indent=2) + "\n", + encoding="utf-8") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux115/RunL115Captures.py b/Standalone/Research/WorldAssemblerM3/Linux115/RunL115Captures.py new file mode 100644 index 0000000..a4210af --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux115/RunL115Captures.py @@ -0,0 +1,260 @@ +#!/usr/bin/env python3 +"""Capture L115 rock floors at three rock stations per passage and open-air walls.""" +from __future__ import annotations + +import importlib.util +import json +import math +import re +import sys +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +RESEARCH = Path(__file__).resolve().parent +CAPTURES = RESEARCH / "captures" +SAVED = ROOT / "Saved/Linux/l115/captures" +L113_RESEARCH = ROOT / "Standalone/Research/WorldAssemblerM3/Linux113" +L115_SAVED = ROOT / "Saved/Linux/l115" +BINARIES = { + "L115": L115_SAVED / "bin/VoxelForgeCoreHeadless-l115-clang", +} +RENDERERS = { + "L115": L115_SAVED / "bin/VoxelForgeOffscreenCapture-l115-clang", +} +SECTION = re.compile( + r"^\[PassageOpenAirSection\] id=(\S+) section=(\d+) start_m=([\d.]+) " + r"end_m=([\d.]+) samples=(\d+) midpoint_xyz_m=\(([^)]*)\) " + r"midpoint_radius_m=([\d.]+)", re.M) + +sys.dont_write_bytecode = True +SPEC = importlib.util.spec_from_file_location( + "l113_capture_helpers", L113_RESEARCH / "RunL113Captures.py") +if SPEC is None or SPEC.loader is None: + raise SystemExit("cannot load the verified L113 capture helpers") +HELPERS = importlib.util.module_from_spec(SPEC) +SPEC.loader.exec_module(HELPERS) +HELPERS.RESEARCH = RESEARCH +HELPERS.CAPTURES = CAPTURES / "L115" +HELPERS.SAVED = SAVED / "L115" +HELPERS.BINARIES = BINARIES +HELPERS.RENDERERS = RENDERERS + + +def parse_sections(log: Path) -> list[dict]: + sections = [] + text = log.read_text(encoding="utf-8", errors="replace") + for passage, section, start, end, samples, midpoint, radius in SECTION.findall(text): + sections.append({"passage": passage, "section": int(section), + "start_m": float(start), "end_m": float(end), + "samples": int(samples), "midpoint": HELPERS.vector(midpoint), + "radius_m": float(radius)}) + return sections + + +def rocky_spans(total: float, sections: list[dict]) -> list[tuple[float, float]]: + spans = [] + cursor = 0.0 + for section in sorted(sections, key=lambda item: item["start_m"]): + start = max(0.0, min(total, section["start_m"])) + end = max(start, min(total, section["end_m"])) + if start - cursor > 2.0: + spans.append((cursor + 1.0, start - 1.0)) + cursor = max(cursor, end) + if total - cursor > 2.0: + spans.append((cursor + 1.0, total - 1.0)) + return [(start, end) for start, end in spans if end - start >= 1.0] + + +def rock_station_candidates(spans: list[tuple[float, float]]) -> list[float]: + total = sum(end - start for start, end in spans) + if total < 3.0: + raise RuntimeError("passage has less than 3 m of rock route outside open-air spans") + stations = [] + for fraction in (0.25, 0.50, 0.75, 0.10, 0.90, 0.35, 0.65, 0.20, 0.80, + 0.40, 0.60): + remaining = total * fraction + for start, end in spans: + span = end - start + if remaining <= span: + stations.append(start + remaining) + break + remaining -= span + return stations + + +def rock_floor_view(layout: dict, passage: dict, station: float, index: int) -> dict: + raw_route = HELPERS.smooth_route(layout, passage) + route, body_depth = HELPERS.derived_smooth_route(raw_route, passage, layout) + lengths, prefix = HELPERS.route_lengths(route) + center, radius = HELPERS.at_distance(route, lengths, prefix, station) + floor_depth = min(body_depth, max(0.0, radius - 0.23)) + planned_floor = (center[0], center[1], center[2] - floor_depth) + tangent = HELPERS.tangent_at(route, lengths, prefix, station) + grade = math.degrees(math.atan2(abs(tangent[2]), + math.hypot(tangent[0], tangent[1]))) + camera = tuple(planned_floor[axis] - 2.5 * tangent[axis] + + (1.25 if axis == 2 else 0.0) for axis in range(3)) + yaw, pitch = HELPERS.angles(camera, planned_floor) + safe_id = HELPERS.sanitize(passage["stable_id"]) + return {"name": f"{safe_id}-rock-floor-station-{index}", + "passage": passage["stable_id"], "kind": "rock-floor-close", + "station": f"rock-floor/{station:.1f}m", "camera": camera, + "target": planned_floor, "yaw": yaw, "pitch": pitch, + "focus": planned_floor, "center_z": planned_floor[2], + "route_distance_m": station, "requested_route_distance_m": station, + "route_length_m": prefix[-1], "planned_floor_m": planned_floor[2], + "planned_grade_deg": grade} + + +def capture_rock_floor(layout: dict, passage: dict, station: float, index: int) -> dict: + view = rock_floor_view(layout, passage, station, index) + row = HELPERS.capture("L115", view, layout) + scene = ROOT / row["scene"] + anchor = HELPERS.nearest_surface_anchor(scene, view["target"], margin_m=5.0, + preferred_normal=(0.0, 0.0, 1.0), minimum_alignment=0.85) + alignment = HELPERS.dot(anchor["normal"], (0.0, 0.0, 1.0)) + camera_distance = math.dist(row["camera_actual_m"], anchor["position_m"]) + row.update({"variant": "L115", "kind": "rock-floor-close", + "planned_floor_m": view["planned_floor_m"], + "planned_grade_deg": view["planned_grade_deg"], + "floor_anchor_position_m": anchor["position_m"], + "floor_anchor_normal": anchor["normal"], + "closeup_camera_to_floor_distance_m": camera_distance, + "closeup_target_surface_distance_m": anchor["distance_m"], + "closeup_floor_normal_alignment": alignment, + "verified_upward_floor_normal": alignment >= 0.85}) + if (not row["verified"] or not 2.0 <= camera_distance <= 3.2 + or anchor["distance_m"] > 0.25 or alignment < 0.85 + or view["planned_grade_deg"] < 2.0 or row["drawn_triangles"] <= 0 + or row["pixel_quality_status"] not in + ("pass", "low_contrast_geometry_visible")): + raise RuntimeError(f"rock-floor close-up failed at {passage['stable_id']} s={station:.2f}") + return row + + +def main() -> int: + layout_path = L115_SAVED / "audit-layout-candidate.json" + audit_log = L115_SAVED / "audit-owner-clang.log" + if any(not path.is_file() for path in (*BINARIES.values(), *RENDERERS.values(), + layout_path, audit_log)): + raise SystemExit("missing L115 binaries, layout, or passage audit log") + layout = json.loads(layout_path.read_text(encoding="utf-8")) + sections = parse_sections(audit_log) + if not sections: + raise SystemExit("no L115 open-air sections found") + CAPTURES.mkdir(parents=True, exist_ok=True) + HELPERS.CAPTURES = CAPTURES / "L115" + HELPERS.SAVED = SAVED / "L115" + HELPERS.CAPTURES.mkdir(parents=True, exist_ok=True) + HELPERS.SAVED.mkdir(parents=True, exist_ok=True) + + rows = [] + for passage in sorted(layout["passages"], key=lambda item: item["stable_id"]): + passage_sections = [item for item in sections + if item["passage"] == passage["stable_id"]] + raw_route = HELPERS.smooth_route(layout, passage) + route, _body_depth = HELPERS.derived_smooth_route(raw_route, passage, layout) + _lengths, prefix = HELPERS.route_lengths(route) + spans = rocky_spans(prefix[-1], passage_sections) + candidates = rock_station_candidates(spans) + accepted_stations = [] + total_rock_length = sum(end - start for start, end in spans) + minimum_spacing = max(1.0, total_rock_length * 0.02) + for station in candidates: + if any(abs(station - prior) < minimum_spacing for prior in accepted_stations): + continue + index = len(accepted_stations) + 1 + try: + row = capture_rock_floor(layout, passage, station, index) + except RuntimeError as error: + message = str(error) + if not (message.startswith("no nearby surface vertices in mesh scene:") + or message.startswith("rock-floor close-up failed at ")): + raise + print(f"[L115CaptureSkip] passage={passage['stable_id']} " + f"station_m={station:.3f} reason=surface-or-anchor-check", flush=True) + continue + accepted_stations.append(station) + rows.append(row) + if len(accepted_stations) == 3: + break + if len(accepted_stations) < 3: + for base_station in tuple(accepted_stations): + for offset in (-10.0, 10.0, -15.0, 15.0, -20.0, 20.0, + -25.0, 25.0, -30.0, 30.0): + station = base_station + offset + if not any(start < station < end for start, end in spans): + continue + if any(abs(station - prior) < minimum_spacing + for prior in accepted_stations): + continue + index = len(accepted_stations) + 1 + try: + row = capture_rock_floor(layout, passage, station, index) + except RuntimeError as error: + message = str(error) + if not (message.startswith( + "no nearby surface vertices in mesh scene:") + or message.startswith("rock-floor close-up failed at ")): + raise + print(f"[L115CaptureSkip] passage={passage['stable_id']} " + f"station_m={station:.3f} reason=nearby-station-check", + flush=True) + continue + accepted_stations.append(station) + rows.append(row) + if len(accepted_stations) == 3: + break + if len(accepted_stations) == 3: + break + if len(accepted_stations) != 3: + raise RuntimeError(f"only {len(accepted_stations)} verified rock-floor views for " + f"{passage['stable_id']}: {accepted_stations}") + + open_air_views = HELPERS.make_views(layout, sections, use_derived_shape=True, + use_spline=True, include_open_air=True) + open_air_views = [view for view in open_air_views + if view["kind"] == "open-air-close"] + if len(open_air_views) != 2 * len(sections): + raise RuntimeError("L115 open-air close-up count is not two per section") + for view in open_air_views: + row = HELPERS.capture("L115", view, layout) + if (not row["verified"] + or abs(row["closeup_camera_target_distance_m"] - 4.0) > 0.02 + or row["closeup_target_surface_distance_m"] > 5.0 + or row["closeup_wall_normal_alignment"] < 0.25 + or row["drawn_triangles"] <= 0 + or row["pixel_quality_status"] not in + ("pass", "low_contrast_geometry_visible")): + raise RuntimeError(f"open-air close-up failed: {view['name']}") + row["variant"] = "L115" + rows.append(row) + + (CAPTURES / "capture-index.json").write_text( + json.dumps({"captures": rows}, indent=2) + "\n", encoding="utf-8") + floor_rows = [row for row in rows if row["kind"] == "rock-floor-close"] + wall_rows = [row for row in rows if row["kind"] == "open-air-close"] + passage_ids = {item["stable_id"] for item in layout["passages"]} + if (len(floor_rows) != 3 * len(passage_ids) + or any(sum(row["passage"] == passage for row in floor_rows) != 3 + for passage in passage_ids) + or len(wall_rows) != 2 * len(sections)): + raise RuntimeError("L115 capture count mismatch") + lines = ["# L115 captures", "", + "Each passage has three floor close-ups sampled outside the audited open-air spans. " + "Floor anchors require an upward normal alignment of at least 0.85, a target-to-floor " + "distance of at most 0.25 m, and a camera-to-floor distance between 2.0 and 3.2 m. " + "Each open-air section has verified outside and interior wall close-ups at 4 m.", ""] + for row in rows: + lines.append(f"- [{row['passage']} {row['station']}]({row['capture']}) — " + f"{row['kind']}; {row.get('drawn_triangles', 0)} triangles; " + f"{row['pixel_quality_status']}") + (CAPTURES / "INDEX.md").write_text("\n".join(lines) + "\n", encoding="utf-8") + print(f"[L115CaptureSummary] captures={len(rows)} rock_floors={len(floor_rows)} " + f"open_air_closeups={len(wall_rows)} sections={len(sections)} status=PASS", + flush=True) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux115/RunL115DensityProbe.py b/Standalone/Research/WorldAssemblerM3/Linux115/RunL115DensityProbe.py new file mode 100644 index 0000000..009c14b --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux115/RunL115DensityProbe.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 +"""Measure L115 floor zero crossings at three route stations per passage.""" +from __future__ import annotations + +import csv +import json +import math +import os +import re +import statistics +import subprocess +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / "Saved/Linux/l115/density-probe" +BINARY = ROOT / "Saved/Linux/l115/bin/VoxelForgeCoreHeadless-l115-clang" +DATA = ROOT / "Standalone/data/owner_world.json" +SLOPE = re.compile( + r"^\[L115DensitySlopeSample\] passage=(\S+) station=(\S+) s_m=([\d.]+) " + r".*?planned_floor_m=(-?[\d.]+) root_floor_m=(-?[\d.]+|nan) " + r"residual_m=(-?[\d.]+|nan)", re.M) + + +def main() -> int: + OUT.mkdir(parents=True, exist_ok=True) + log = OUT / "owner4-clang.log" + layout = OUT / "layout.json" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1740s", str(BINARY), str(DATA), "--world-assembler-prototype", + "--stream-benchmark", "--stream-pipeline", "--workers=12", "--clip-radius=3", + "--max-clip-level=8", "--max-level=8", "--camera=8,16,-372.2626953125,0,0", + "--audit-resolved-layout-passages", f"--resolved-layout-output={layout}", + ] + with log.open("w", encoding="utf-8") as stream: + result = subprocess.run(command, cwd=ROOT, + env={**os.environ, + "VOXELFORGE_L115_DENSITY_PROFILE": "1"}, + stdout=stream, stderr=subprocess.STDOUT, + check=False, timeout=1740) + if result.returncode: + raise SystemExit(f"L115 density probe failed: {log}") + text = log.read_text(encoding="utf-8", errors="replace") + groups: dict[tuple[str, str], list[dict]] = {} + for passage, station, distance, planned, root, residual in SLOPE.findall(text): + root_value = float(root) if root != "nan" else math.nan + residual_value = float(residual) if residual != "nan" else math.nan + groups.setdefault((passage, station), []).append({ + "route_s_m": float(distance), "planned_floor_m": float(planned), + "root_floor_m": root_value, "offset_m": residual_value}) + summary = [] + with (OUT / "zero-crossing-offsets.csv").open("w", newline="", encoding="utf-8") as stream: + writer = csv.DictWriter(stream, fieldnames=("passage", "station", "route_s_m", + "planned_floor_m", "root_floor_m", "offset_m")) + writer.writeheader() + for (passage, station), samples in sorted(groups.items()): + for sample in samples: + writer.writerow({"passage": passage, "station": station, **sample}) + finite = [sample["offset_m"] for sample in samples + if math.isfinite(sample["offset_m"])] + summary.append({"passage": passage, "station": station, + "samples": len(samples), "finite_roots": len(finite), + "max_abs_offset_m": max(map(abs, finite)) if finite else None, + "median_abs_offset_m": statistics.median(map(abs, finite)) + if finite else None, + "p95_abs_offset_m": sorted(map(abs, finite))[ + min(len(finite)-1, math.ceil(0.95*len(finite))-1)] + if finite else None}) + if not summary or any(item["samples"] != 51 for item in summary): + raise RuntimeError("L115 density profile is missing 51-sample route stations") + (OUT / "zero-crossing-summary.json").write_text( + json.dumps(summary, indent=2) + "\n", encoding="utf-8") + print(f"[L115DensityProbe] exit={result.returncode} stations={len(summary)} " + f"log={log.relative_to(ROOT)}", flush=True) + return result.returncode + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux115/RunL115HashMatrix.py b/Standalone/Research/WorldAssemblerM3/Linux115/RunL115HashMatrix.py new file mode 100644 index 0000000..f38faf5 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux115/RunL115HashMatrix.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python3 +"""Check Clang/GCC hash identity at W1/W8/W12 and pin v223 owner hashes.""" +from __future__ import annotations + +import json +import re +import subprocess +import time +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / "Saved/Linux/l115/hashes" +DATASETS = { + "owner4": ROOT / "Standalone/data/owner_world.json", + "owner2": ROOT / "Standalone/data/regression/owner_world_2strate_l61.json", +} +BINARIES = { + "clang": ROOT / "Saved/Linux/l115/bin/VoxelForgeCoreHeadless-l115-clang", + "gcc": ROOT / "Saved/Linux/l115/bin/VoxelForgeCoreHeadless-l115-gcc", +} +HASH = re.compile(r"^\[Pipeline(?:FullDetailHash|WholeViewHash|LODHash|ExactQueryHash)\].*$", re.M) +STAMP = re.compile(r"^\[VoxelForgeSourceStamp\] sha256=(\S+)$", re.M) + + +def run(dataset: str, recipe: str, workers: int, compiler: str) -> dict: + OUT.mkdir(parents=True, exist_ok=True) + label = f"{dataset}-{recipe}-w{workers}-{compiler}" + log = OUT / f"{label}.log" + layout = OUT / f"{label}.layout.json" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1740s", str(BINARIES[compiler]), str(DATASETS[dataset]), + f"--workers={workers}", "--world-assembler-prototype", "--stream-benchmark", + "--stream-pipeline", "--force-generate", "--clip-radius=3", + "--max-clip-level=8", "--max-level=8", f"--recipe={recipe}", + "--stream-hash", f"--resolved-layout-output={layout}", + ] + started = time.monotonic() + with log.open("w", encoding="utf-8") as stream: + result = subprocess.run(command, cwd=ROOT, stdout=stream, + stderr=subprocess.STDOUT, check=False, timeout=1740) + output = log.read_text(encoding="utf-8", errors="replace") + hashes = HASH.findall(output) + if result.returncode or len(hashes) != 12: + raise SystemExit(f"hash run failed or incomplete: {label}; exit={result.returncode} " + f"hashes={len(hashes)} log={log}") + row = {"dataset": dataset, "recipe": recipe, "workers": workers, + "compiler": compiler, "exit_code": result.returncode, + "hashes": hashes, "source_stamp": (STAMP.search(output).group(1) + if STAMP.search(output) else None), + "elapsed_s": round(time.monotonic() - started, 3), + "log": str(log.relative_to(ROOT))} + print("[L115HashRun] " + json.dumps(row, sort_keys=True), flush=True) + return row + + +def main() -> int: + if any(not path.is_file() for path in (*DATASETS.values(), *BINARIES.values())): + raise SystemExit("missing L115 hash input") + rows = [] + recipes = {"owner4": ("surface-world",), + "owner2": ("surface-world", "floating-islands")} + for dataset, dataset_recipes in recipes.items(): + for recipe in dataset_recipes: + for workers in (1, 8, 12): + for compiler in ("clang", "gcc"): + rows.append(run(dataset, recipe, workers, compiler)) + (OUT / "runs-partial.json").write_text( + json.dumps(rows, indent=2) + "\n", encoding="utf-8") + groups = {} + for dataset, dataset_recipes in recipes.items(): + for recipe in dataset_recipes: + key = f"{dataset}/{recipe}" + group = [row for row in rows if row["dataset"] == dataset + and row["recipe"] == recipe] + reference = group[0]["hashes"] + groups[key] = {"all_worker_compiler_hashes_match": all( + row["hashes"] == reference for row in group), + "source_stamps": sorted({row["source_stamp"] for row in group}), + "runs": [{"workers": row["workers"], "compiler": row["compiler"], + "log": row["log"]} for row in group]} + if not groups[key]["all_worker_compiler_hashes_match"]: + raise SystemExit(f"determinism mismatch: {key}") + if dataset == "owner2": + canonical = next(row for row in group if row["workers"] == 12 + and row["compiler"] == "clang") + recipe_name = "floating-islands" if recipe == "floating-islands" else "surface-world" + style = 1 if recipe_name == "surface-world" else 2 + baseline = (ROOT / "Standalone/Tools/verify/baselines/owner-hash/canonical" + / f"owner-hash-{recipe_name}-style{style}-v223.baseline") + baseline.write_text("\n".join(canonical["hashes"]) + "\n", + encoding="utf-8") + summary = {"runs": rows, "groups": groups, + "owner4_all_four_strata": "owner4/surface-world", + "owner2_canonical_pins": ["owner2/surface-world", + "owner2/floating-islands"]} + (OUT / "summary.json").write_text(json.dumps(summary, indent=2) + "\n", + encoding="utf-8") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux115/RunL115Timing.py b/Standalone/Research/WorldAssemblerM3/Linux115/RunL115Timing.py new file mode 100644 index 0000000..9d513ba --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux115/RunL115Timing.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python3 +"""Five interleaved L80 readiness runs for L109, L114, and L115.""" +from __future__ import annotations + +import json +import os +import re +import statistics +import subprocess +import time +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / "Saved/Linux/l115/timing" +DATA = ROOT / "Standalone/data/owner_world.json" +BINARIES = { + "L109": ROOT / "Saved/Linux/l109/bin-final/VoxelForgeCoreHeadless-l109-clang", + "L114": ROOT / "Saved/Linux/l114/bin/VoxelForgeCoreHeadless-l114-clang", + "L115": ROOT / "Saved/Linux/l115/bin/VoxelForgeCoreHeadless-l115-clang", +} +CAMERAS = { + 0: (8.0, 16.0, -372.2626953125), + 1: (25.8369140625, 3.19921875, -737.0), + 2: (19.166015625, -14.2001953125, -753.3740234375), + 3: (-20.0625, -5.068359375, -900.353515625), +} +PIPELINE = re.compile(r"^\[StreamPipeline\] (.*)$", re.M) +FIELDS = re.compile(r"([a-zA-Z0-9_]+)=([^ ]+)") +NEAR = re.compile( + r"^\[WorldAssemblerNearLODReady\] lods=0-2 tiles=(\d+)/(\d+) cold_ready_s=([0-9.]+)$", + re.M, +) + + +def run(strate: int, workers: int, version: str, phase: str, replicate: int) -> dict: + OUT.mkdir(parents=True, exist_ok=True) + label = f"s{strate}-w{workers}-{version}-{phase}{replicate}" + log = OUT / f"{label}.log" + camera = ",".join(f"{v:.12f}" for v in CAMERAS[strate]) + ",0,0" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1740s", str(BINARIES[version]), str(DATA), + "--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline", + f"--workers={workers}", "--clip-radius=3", "--max-clip-level=8", "--max-level=8", + f"--camera={camera}", "--profile-lod-work", "--stream-scheduler-policy=3", + ] + start = time.monotonic() + with log.open("w", encoding="utf-8") as output: + result = subprocess.run(command, cwd=ROOT, stdout=output, + stderr=subprocess.STDOUT, check=False, timeout=1740) + content = log.read_text(encoding="utf-8", errors="replace") + pipeline_match = PIPELINE.search(content) + near_match = NEAR.search(content) + if result.returncode or pipeline_match is None or near_match is None: + raise SystemExit(f"readiness run failed or trace missing: {log}; exit={result.returncode}") + pipeline = dict(FIELDS.findall(pipeline_match.group(1))) + row = { + "strate": strate, "workers": workers, "version": version, + "phase": phase, "replicate": replicate, "exit_code": result.returncode, + "wall_s": round(time.monotonic() - start, 3), + "lod02_ready_s": float(near_match.group(3)), + "whole_view_ready_s": float(pipeline["whole_view_ready"].removesuffix("s")), + "whole_tiles": int(pipeline["whole_tiles"].split("/")[0]), + "log": str(log.relative_to(ROOT)), + } + print("[L115TimingRun] " + json.dumps(row, sort_keys=True), flush=True) + return row + + +def main() -> int: + if not DATA.is_file() or any(not binary.is_file() for binary in BINARIES.values()): + raise SystemExit("missing L109/L114/L115 data or timing binary") + OUT.mkdir(parents=True, exist_ok=True) + load_1m = os.getloadavg()[0] + uptime = subprocess.run(["uptime"], cwd=ROOT, text=True, capture_output=True, + check=True).stdout.strip() + top = subprocess.run(["ps", "-eo", "pid,pcpu,comm", "--sort=-pcpu"], cwd=ROOT, + text=True, capture_output=True, check=True).stdout + (OUT / "machine-load-before.txt").write_text( + f"uptime: {uptime}\n1-minute load: {load_1m:.2f}\ntop CPU users:\n{top}", + encoding="utf-8") + print(f"[L115TimingGate] load_1m={load_1m:.2f} uptime={uptime}", flush=True) + if load_1m >= 1.5: + raise SystemExit(f"timing refused: 1-minute load {load_1m:.2f} is not below 1.5") + rows = [] + versions = ("L109", "L114", "L115") + for strate in range(4): + for workers in (8, 12): + for version in versions: + run(strate, workers, version, "warmup", 0) + for replicate in range(1, 6): + offset = (replicate - 1) % len(versions) + order = versions[offset:] + versions[:offset] + for version in order: + rows.append(run(strate, workers, version, "measured", replicate)) + (OUT / "runs-partial.json").write_text( + json.dumps(rows, indent=2) + "\n", encoding="utf-8") + summary = [] + for strate in range(4): + for workers in (8, 12): + item = {"strate": strate, "workers": workers, "replicates": 5} + medians = {} + for version in versions: + group = [row for row in rows if row["strate"] == strate + and row["workers"] == workers and row["version"] == version] + medians[version] = {} + for key in ("lod02_ready_s", "whole_view_ready_s"): + values = [row[key] for row in group] + medians[version][key] = statistics.median(values) + item[f"{version}_{key}_values"] = values + item[f"{version}_{key}_median"] = medians[version][key] + for comparison in ("L109", "L114"): + for key in ("lod02_ready_s", "whole_view_ready_s"): + item[f"L115_vs_{comparison}_{key}_delta_pct"] = round( + 100.0 * (medians["L115"][key] / medians[comparison][key] - 1.0), 2) + summary.append(item) + (OUT / "summary.json").write_text( + json.dumps({"runs": rows, "summary": summary}, indent=2) + "\n", + encoding="utf-8") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux115/captures/INDEX.md b/Standalone/Research/WorldAssemblerM3/Linux115/captures/INDEX.md new file mode 100644 index 0000000..2060b20 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux115/captures/INDEX.md @@ -0,0 +1,27 @@ +# L115 captures + +Each passage has three floor close-ups sampled outside the audited open-air spans. Floor anchors require an upward normal alignment of at least 0.85, a target-to-floor distance of at most 0.25 m, and a camera-to-floor distance between 2.0 and 3.2 m. Each open-air section has verified outside and interior wall close-ups at 4 m. + +- [passage/0-1/0 rock-floor/401.7m](captures/L115/L115/passage-0-1-0-rock-floor-station-1.png) — rock-floor-close; 122256 triangles; pass +- [passage/0-1/0 rock-floor/792.8m](captures/L115/L115/passage-0-1-0-rock-floor-station-2.png) — rock-floor-close; 585992 triangles; pass +- [passage/0-1/0 rock-floor/1634.5m](captures/L115/L115/passage-0-1-0-rock-floor-station-3.png) — rock-floor-close; 137252 triangles; pass +- [passage/1-2/0 rock-floor/27.0m](captures/L115/L115/passage-1-2-0-rock-floor-station-1.png) — rock-floor-close; 652088 triangles; pass +- [passage/1-2/0 rock-floor/52.9m](captures/L115/L115/passage-1-2-0-rock-floor-station-2.png) — rock-floor-close; 636128 triangles; pass +- [passage/1-2/0 rock-floor/78.9m](captures/L115/L115/passage-1-2-0-rock-floor-station-3.png) — rock-floor-close; 580512 triangles; pass +- [passage/2-3/0 rock-floor/323.4m](captures/L115/L115/passage-2-3-0-rock-floor-station-1.png) — rock-floor-close; 474896 triangles; low_contrast_geometry_visible +- [passage/2-3/0 rock-floor/333.4m](captures/L115/L115/passage-2-3-0-rock-floor-station-2.png) — rock-floor-close; 494436 triangles; pass +- [passage/2-3/0 rock-floor/343.4m](captures/L115/L115/passage-2-3-0-rock-floor-station-3.png) — rock-floor-close; 485332 triangles; pass +- [passage/0-1/0 section-1/4m-outside](captures/L115/L115/passage-0-1-0-openair-1-4m-outside.png) — open-air-close; 275313 triangles; pass +- [passage/0-1/0 section-1/4m-interior-wall](captures/L115/L115/passage-0-1-0-openair-1-4m-interior-wall.png) — open-air-close; 307964 triangles; low_contrast_geometry_visible +- [passage/0-1/0 section-2/4m-outside](captures/L115/L115/passage-0-1-0-openair-2-4m-outside.png) — open-air-close; 275313 triangles; pass +- [passage/0-1/0 section-2/4m-interior-wall](captures/L115/L115/passage-0-1-0-openair-2-4m-interior-wall.png) — open-air-close; 345024 triangles; pass +- [passage/0-1/0 section-3/4m-outside](captures/L115/L115/passage-0-1-0-openair-3-4m-outside.png) — open-air-close; 148970 triangles; pass +- [passage/0-1/0 section-3/4m-interior-wall](captures/L115/L115/passage-0-1-0-openair-3-4m-interior-wall.png) — open-air-close; 148032 triangles; pass +- [passage/1-2/0 section-1/4m-outside](captures/L115/L115/passage-1-2-0-openair-1-4m-outside.png) — open-air-close; 620866 triangles; low_contrast_geometry_visible +- [passage/1-2/0 section-1/4m-interior-wall](captures/L115/L115/passage-1-2-0-openair-1-4m-interior-wall.png) — open-air-close; 609733 triangles; pass +- [passage/1-2/0 section-2/4m-outside](captures/L115/L115/passage-1-2-0-openair-2-4m-outside.png) — open-air-close; 584622 triangles; pass +- [passage/1-2/0 section-2/4m-interior-wall](captures/L115/L115/passage-1-2-0-openair-2-4m-interior-wall.png) — open-air-close; 572238 triangles; pass +- [passage/2-3/0 section-1/4m-outside](captures/L115/L115/passage-2-3-0-openair-1-4m-outside.png) — open-air-close; 104612 triangles; low_contrast_geometry_visible +- [passage/2-3/0 section-1/4m-interior-wall](captures/L115/L115/passage-2-3-0-openair-1-4m-interior-wall.png) — open-air-close; 94962 triangles; low_contrast_geometry_visible +- [passage/2-3/0 section-2/4m-outside](captures/L115/L115/passage-2-3-0-openair-2-4m-outside.png) — open-air-close; 475838 triangles; pass +- [passage/2-3/0 section-2/4m-interior-wall](captures/L115/L115/passage-2-3-0-openair-2-4m-interior-wall.png) — open-air-close; 486512 triangles; pass diff --git a/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-0-1-0-openair-1-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-0-1-0-openair-1-4m-interior-wall.png new file mode 100644 index 0000000..58795ee Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-0-1-0-openair-1-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-0-1-0-openair-1-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-0-1-0-openair-1-4m-outside.png new file mode 100644 index 0000000..e50123c Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-0-1-0-openair-1-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-0-1-0-openair-2-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-0-1-0-openair-2-4m-interior-wall.png new file mode 100644 index 0000000..f840f51 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-0-1-0-openair-2-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-0-1-0-openair-2-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-0-1-0-openair-2-4m-outside.png new file mode 100644 index 0000000..f0b9733 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-0-1-0-openair-2-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-0-1-0-openair-3-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-0-1-0-openair-3-4m-interior-wall.png new file mode 100644 index 0000000..81a832a Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-0-1-0-openair-3-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-0-1-0-openair-3-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-0-1-0-openair-3-4m-outside.png new file mode 100644 index 0000000..e47cf28 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-0-1-0-openair-3-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-0-1-0-rock-floor-station-1.png b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-0-1-0-rock-floor-station-1.png new file mode 100644 index 0000000..bbe707b Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-0-1-0-rock-floor-station-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-0-1-0-rock-floor-station-2.png b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-0-1-0-rock-floor-station-2.png new file mode 100644 index 0000000..7a88bfc Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-0-1-0-rock-floor-station-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-0-1-0-rock-floor-station-3.png b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-0-1-0-rock-floor-station-3.png new file mode 100644 index 0000000..b9345ea Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-0-1-0-rock-floor-station-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-1-2-0-openair-1-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-1-2-0-openair-1-4m-interior-wall.png new file mode 100644 index 0000000..66949fa Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-1-2-0-openair-1-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-1-2-0-openair-1-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-1-2-0-openair-1-4m-outside.png new file mode 100644 index 0000000..ec2b85e Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-1-2-0-openair-1-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-1-2-0-openair-2-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-1-2-0-openair-2-4m-interior-wall.png new file mode 100644 index 0000000..9c68d5f Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-1-2-0-openair-2-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-1-2-0-openair-2-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-1-2-0-openair-2-4m-outside.png new file mode 100644 index 0000000..583481c Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-1-2-0-openair-2-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-1-2-0-rock-floor-station-1.png b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-1-2-0-rock-floor-station-1.png new file mode 100644 index 0000000..abc37e7 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-1-2-0-rock-floor-station-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-1-2-0-rock-floor-station-2.png b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-1-2-0-rock-floor-station-2.png new file mode 100644 index 0000000..f9ad3f4 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-1-2-0-rock-floor-station-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-1-2-0-rock-floor-station-3.png b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-1-2-0-rock-floor-station-3.png new file mode 100644 index 0000000..4da2646 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-1-2-0-rock-floor-station-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-2-3-0-openair-1-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-2-3-0-openair-1-4m-interior-wall.png new file mode 100644 index 0000000..6f8a641 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-2-3-0-openair-1-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-2-3-0-openair-1-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-2-3-0-openair-1-4m-outside.png new file mode 100644 index 0000000..9a74d9d Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-2-3-0-openair-1-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-2-3-0-openair-2-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-2-3-0-openair-2-4m-interior-wall.png new file mode 100644 index 0000000..fb6b0f1 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-2-3-0-openair-2-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-2-3-0-openair-2-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-2-3-0-openair-2-4m-outside.png new file mode 100644 index 0000000..1ff0c92 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-2-3-0-openair-2-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-2-3-0-rock-floor-station-1.png b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-2-3-0-rock-floor-station-1.png new file mode 100644 index 0000000..5187921 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-2-3-0-rock-floor-station-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-2-3-0-rock-floor-station-2.png b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-2-3-0-rock-floor-station-2.png new file mode 100644 index 0000000..ddb87ad Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-2-3-0-rock-floor-station-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-2-3-0-rock-floor-station-3.png b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-2-3-0-rock-floor-station-3.png new file mode 100644 index 0000000..694a3dc Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux115/captures/L115/L115/passage-2-3-0-rock-floor-station-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux115/captures/capture-index.json b/Standalone/Research/WorldAssemblerM3/Linux115/captures/capture-index.json new file mode 100644 index 0000000..f01fdcf --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux115/captures/capture-index.json @@ -0,0 +1,1562 @@ +{ + "captures": [ + { + "name": "passage-0-1-0-rock-floor-station-1", + "passage": "passage/0-1/0", + "kind": "rock-floor-close", + "station": "rock-floor/401.7m", + "camera": [ + -9.24648786798055, + 19.798675033837775, + -443.9636296749357 + ], + "target": [ + -7.026884524505579, + 20.857335392121104, + -445.66373993191075 + ], + "yaw": 64.50075976736525, + "pitch": -34.65771934187305, + "focus": [ + -7.026884524505579, + 20.857335392121104, + -445.66373993191075 + ], + "center_z": -445.66373993191075, + "route_distance_m": 401.6612010038529, + "requested_route_distance_m": 401.6612010038529, + "route_length_m": 2026.6238040154117, + "planned_floor_m": -445.66373993191075, + "planned_grade_deg": 10.372328677972732, + "variant": "L115", + "capture": "captures/L115/L115/passage-0-1-0-rock-floor-station-1.png", + "scene": "Saved/Linux/l115/captures/L115/L115/passage-0-1-0-rock-floor-station-1.vfmesh", + "drawn_triangles": 122256, + "source_triangles": 146688, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 401.6612010038529, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": 0.00041588771229822673, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -9.24648786798055, + 19.798675033837775, + -443.9636296749357 + ], + "target_actual_m": [ + -7.026884524505579, + 20.857335392121104, + -445.66373993191075 + ], + "logs": [ + "Saved/Linux/l115/captures/L115/L115/passage-0-1-0-rock-floor-station-1-mesh.log", + "Saved/Linux/l115/captures/L115/L115/passage-0-1-0-rock-floor-station-1-render.log", + "Saved/Linux/l115/captures/L115/L115/passage-0-1-0-rock-floor-station-1-quality.log" + ], + "floor_anchor_position_m": [ + -7.026816889442207, + 20.857366012722174, + -445.66333072479176 + ], + "floor_anchor_normal": [ + 0.1642540532934053, + 0.07412901954917549, + 0.9836287381107596 + ], + "closeup_camera_to_floor_distance_m": 2.989439663317921, + "closeup_floor_normal_alignment": 0.9836287381107596, + "verified_upward_floor_normal": true + }, + { + "name": "passage-0-1-0-rock-floor-station-2", + "passage": "passage/0-1/0", + "kind": "rock-floor-close", + "station": "rock-floor/792.8m", + "camera": [ + -0.021280083711839648, + -26.43771312964049, + -514.3617561596035 + ], + "target": [ + -2.4714859241065525, + -26.227784739959716, + -516.0616688299093 + ], + "yaw": -85.10297944703369, + "pitch": -34.654210347383824, + "focus": [ + -2.4714859241065525, + -26.227784739959716, + -516.0616688299093 + ], + "center_z": -516.0616688299093, + "route_distance_m": 792.8284020077059, + "requested_route_distance_m": 792.8284020077059, + "route_length_m": 2026.6238040154117, + "planned_floor_m": -516.0616688299093, + "planned_grade_deg": 10.367725129664787, + "variant": "L115", + "capture": "captures/L115/L115/passage-0-1-0-rock-floor-station-2.png", + "scene": "Saved/Linux/l115/captures/L115/L115/passage-0-1-0-rock-floor-station-2.vfmesh", + "drawn_triangles": 585992, + "source_triangles": 626016, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 792.8284020077059, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": 6.620479171221186e-06, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -0.021280083711839648, + -26.43771312964049, + -514.3617561596035 + ], + "target_actual_m": [ + -2.4714859241065525, + -26.227784739959716, + -516.0616688299093 + ], + "logs": [ + "Saved/Linux/l115/captures/L115/L115/passage-0-1-0-rock-floor-station-2-mesh.log", + "Saved/Linux/l115/captures/L115/L115/passage-0-1-0-rock-floor-station-2-render.log", + "Saved/Linux/l115/captures/L115/L115/passage-0-1-0-rock-floor-station-2-quality.log" + ], + "floor_anchor_position_m": [ + -2.4714847396204855, + -26.22778487351251, + -516.0616753421978 + ], + "floor_anchor_normal": [ + -0.17918464595866201, + 0.02004018063609561, + 0.9836113326984097 + ], + "closeup_camera_to_floor_distance_m": 2.989531394033071, + "closeup_floor_normal_alignment": 0.9836113326984097, + "verified_upward_floor_normal": true + }, + { + "name": "passage-0-1-0-rock-floor-station-3", + "passage": "passage/0-1/0", + "kind": "rock-floor-close", + "station": "rock-floor/1634.5m", + "camera": [ + 15.717287112180728, + 19.71739973195528, + -665.8352816543407 + ], + "target": [ + 17.336220092016376, + 17.86620742417785, + -667.5348848643227 + ], + "yaw": 138.82915885966676, + "pitch": -34.64871452830556, + "focus": [ + 17.336220092016376, + 17.86620742417785, + -667.5348848643227 + ], + "center_z": -667.5348848643227, + "route_distance_m": 1634.4566030115589, + "requested_route_distance_m": 1634.4566030115589, + "route_length_m": 2026.6238040154117, + "planned_floor_m": -667.5348848643227, + "planned_grade_deg": 10.360515186362372, + "variant": "L115", + "capture": "captures/L115/L115/passage-0-1-0-rock-floor-station-3.png", + "scene": "Saved/Linux/l115/captures/L115/L115/passage-0-1-0-rock-floor-station-3.vfmesh", + "drawn_triangles": 137252, + "source_triangles": 166708, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1634.4566030115589, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": 1.8519464898499414e-05, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 15.717287112180728, + 19.71739973195528, + -665.8352816543407 + ], + "target_actual_m": [ + 17.336220092016376, + 17.86620742417785, + -667.5348848643227 + ], + "logs": [ + "Saved/Linux/l115/captures/L115/L115/passage-0-1-0-rock-floor-station-3-mesh.log", + "Saved/Linux/l115/captures/L115/L115/passage-0-1-0-rock-floor-station-3-render.log", + "Saved/Linux/l115/captures/L115/L115/passage-0-1-0-rock-floor-station-3-quality.log" + ], + "floor_anchor_position_m": [ + 17.33621789935619, + 17.866209932616684, + -667.5349030816375 + ], + "floor_anchor_normal": [ + 0.1183906810124733, + -0.13537553141785347, + 0.9836956399937618 + ], + "closeup_camera_to_floor_distance_m": 2.989406891503064, + "closeup_floor_normal_alignment": 0.9836956399937618, + "verified_upward_floor_normal": true + }, + { + "name": "passage-1-2-0-rock-floor-station-1", + "passage": "passage/1-2/0", + "kind": "rock-floor-close", + "station": "rock-floor/27.0m", + "camera": [ + 15.990262769683945, + 2.495369317804175, + -736.4846720823747 + ], + "target": [ + 15.354493464592624, + 4.868558240151556, + -738.1970266319915 + ], + "yaw": -14.99718988160138, + "pitch": -34.875140724394136, + "focus": [ + 15.354493464592624, + 4.868558240151556, + -738.1970266319915 + ], + "center_z": -738.1970266319915, + "route_distance_m": 26.963657939523273, + "requested_route_distance_m": 26.963657939523273, + "route_length_m": 114.99063175809309, + "planned_floor_m": -738.1970266319915, + "planned_grade_deg": 10.657740387934142, + "variant": "L115", + "capture": "captures/L115/L115/passage-1-2-0-rock-floor-station-1.png", + "scene": "Saved/Linux/l115/captures/L115/L115/passage-1-2-0-rock-floor-station-1.vfmesh", + "drawn_triangles": 652088, + "source_triangles": 719780, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 26.963657939523273, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": 0.007484804507759201, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 15.990262769683945, + 2.495369317804175, + -736.4846720823747 + ], + "target_actual_m": [ + 15.354493464592624, + 4.868558240151556, + -738.1970266319915 + ], + "logs": [ + "Saved/Linux/l115/captures/L115/L115/passage-1-2-0-rock-floor-station-1-mesh.log", + "Saved/Linux/l115/captures/L115/L115/passage-1-2-0-rock-floor-station-1-render.log", + "Saved/Linux/l115/captures/L115/L115/passage-1-2-0-rock-floor-station-1-quality.log" + ], + "floor_anchor_position_m": [ + 15.354080518420568, + 4.869888644992825, + -738.1896725992926 + ], + "floor_anchor_normal": [ + -0.05340373170040817, + 0.17677478050840184, + 0.982801464394858 + ], + "closeup_camera_to_floor_distance_m": 2.991671214339144, + "closeup_floor_normal_alignment": 0.982801464394858, + "verified_upward_floor_normal": true + }, + { + "name": "passage-1-2-0-rock-floor-station-2", + "passage": "passage/1-2/0", + "kind": "rock-floor-close", + "station": "rock-floor/52.9m", + "camera": [ + -2.48434493546405, + 15.983647301702653, + -741.2835409028854 + ], + "target": [ + -4.76517685476837, + 15.070128626649932, + -742.995373541633 + ], + "yaw": -111.82708648318167, + "pitch": -34.86587426337977, + "focus": [ + -4.76517685476837, + 15.070128626649932, + -742.995373541633 + ], + "center_z": -742.995373541633, + "route_distance_m": 52.927315879046546, + "requested_route_distance_m": 52.927315879046546, + "route_length_m": 114.99063175809309, + "planned_floor_m": -742.995373541633, + "planned_grade_deg": 10.645569354114926, + "variant": "L115", + "capture": "captures/L115/L115/passage-1-2-0-rock-floor-station-2.png", + "scene": "Saved/Linux/l115/captures/L115/L115/passage-1-2-0-rock-floor-station-2.vfmesh", + "drawn_triangles": 636128, + "source_triangles": 700536, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 52.927315879046546, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": 0.007229500620965189, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -2.48434493546405, + 15.983647301702653, + -741.2835409028854 + ], + "target_actual_m": [ + -4.76517685476837, + 15.070128626649932, + -742.995373541633 + ], + "logs": [ + "Saved/Linux/l115/captures/L115/L115/passage-1-2-0-rock-floor-station-2-mesh.log", + "Saved/Linux/l115/captures/L115/L115/passage-1-2-0-rock-floor-station-2-render.log", + "Saved/Linux/l115/captures/L115/L115/passage-1-2-0-rock-floor-station-2-quality.log" + ], + "floor_anchor_position_m": [ + -4.7663956582883, + 15.069621905164404, + -742.988265558055 + ], + "floor_anchor_normal": [ + -0.1714432252395109, + -0.0687242530069811, + 0.9827940768890027 + ], + "closeup_camera_to_floor_distance_m": 2.991535404604565, + "closeup_floor_normal_alignment": 0.9827940768890027, + "verified_upward_floor_normal": true + }, + { + "name": "passage-1-2-0-rock-floor-station-3", + "passage": "passage/1-2/0", + "kind": "rock-floor-close", + "station": "rock-floor/78.9m", + "camera": [ + -13.44544511010513, + -3.995230772069307, + -746.0839041050349 + ], + "target": [ + -12.287009401722694, + -6.161841337747165, + -747.7963166548619 + ], + "yaw": 151.8676321960706, + "pitch": -34.87617050502889, + "focus": [ + -12.287009401722694, + -6.161841337747165, + -747.7963166548619 + ], + "center_z": -747.7963166548619, + "route_distance_m": 78.89097381856982, + "requested_route_distance_m": 78.89097381856982, + "route_length_m": 114.99063175809309, + "planned_floor_m": -747.7963166548619, + "planned_grade_deg": 10.659092990906162, + "variant": "L115", + "capture": "captures/L115/L115/passage-1-2-0-rock-floor-station-3.png", + "scene": "Saved/Linux/l115/captures/L115/L115/passage-1-2-0-rock-floor-station-3.vfmesh", + "drawn_triangles": 580512, + "source_triangles": 639508, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 78.89097381856982, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": 0.2417148155664453, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -13.44544511010513, + -3.995230772069307, + -746.0839041050349 + ], + "target_actual_m": [ + -12.287009401722694, + -6.161841337747165, + -747.7963166548619 + ], + "logs": [ + "Saved/Linux/l115/captures/L115/L115/passage-1-2-0-rock-floor-station-3-mesh.log", + "Saved/Linux/l115/captures/L115/L115/passage-1-2-0-rock-floor-station-3-render.log", + "Saved/Linux/l115/captures/L115/L115/passage-1-2-0-rock-floor-station-3-quality.log" + ], + "floor_anchor_position_m": [ + -12.283234215932445, + -6.167799052822403, + -747.554704764286 + ], + "floor_anchor_normal": [ + 0.09848641406423383, + -0.15897410728021424, + 0.9823582134126162 + ], + "closeup_camera_to_floor_distance_m": 2.8695019909945634, + "closeup_floor_normal_alignment": 0.9823582134126162, + "verified_upward_floor_normal": true + }, + { + "name": "passage-2-3-0-rock-floor-station-1", + "passage": "passage/2-3/0", + "kind": "rock-floor-close", + "station": "rock-floor/323.4m", + "camera": [ + 6.997568341188331, + -14.934306981606339, + -869.3796844648476 + ], + "target": [ + 9.102823911740126, + -13.661883549736208, + -871.0755965556104 + ], + "yaw": 58.85109570948622, + "pitch": -34.583159686285406, + "focus": [ + 9.102823911740126, + -13.661883549736208, + -871.0755965556104 + ], + "center_z": -871.0755965556104, + "route_distance_m": 323.4481319239866, + "requested_route_distance_m": 323.4481319239866, + "route_length_m": 494.0722798830563, + "planned_floor_m": -871.0755965556104, + "planned_grade_deg": 10.274530613220444, + "variant": "L115", + "capture": "captures/L115/L115/passage-2-3-0-rock-floor-station-1.png", + "scene": "Saved/Linux/l115/captures/L115/L115/passage-2-3-0-rock-floor-station-1.vfmesh", + "drawn_triangles": 474896, + "source_triangles": 502362, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 323.4481319239866, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": 0.007165446036271588, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 6.997568341188331, + -14.934306981606339, + -869.3796844648476 + ], + "target_actual_m": [ + 9.102823911740126, + -13.661883549736208, + -871.0755965556104 + ], + "logs": [ + "Saved/Linux/l115/captures/L115/L115/passage-2-3-0-rock-floor-station-1-mesh.log", + "Saved/Linux/l115/captures/L115/L115/passage-2-3-0-rock-floor-station-1-render.log", + "Saved/Linux/l115/captures/L115/L115/passage-2-3-0-rock-floor-station-1-quality.log" + ], + "floor_anchor_position_m": [ + 9.103853396121147, + -13.661134677318575, + -871.0685451040641 + ], + "floor_anchor_normal": [ + 0.14535372671884042, + 0.10291285952153646, + 0.984012823836176 + ], + "closeup_camera_to_floor_distance_m": 2.9849044721286333, + "closeup_floor_normal_alignment": 0.984012823836176, + "verified_upward_floor_normal": true + }, + { + "name": "passage-2-3-0-rock-floor-station-2", + "passage": "passage/2-3/0", + "kind": "rock-floor-close", + "station": "rock-floor/333.4m", + "camera": [ + 14.426607883839745, + -8.501776133009574, + -871.1605818845352 + ], + "target": [ + 15.203729308783775, + -6.16777561793481, + -872.8561420785873 + ], + "yaw": 18.41553205389999, + "pitch": -34.576909662847896, + "focus": [ + 15.203729308783775, + -6.16777561793481, + -872.8561420785873 + ], + "center_z": -872.8561420785873, + "route_distance_m": 333.4481319239866, + "requested_route_distance_m": 333.4481319239866, + "route_length_m": 494.0722798830563, + "planned_floor_m": -872.8561420785873, + "planned_grade_deg": 10.266334408339132, + "variant": "L115", + "capture": "captures/L115/L115/passage-2-3-0-rock-floor-station-2.png", + "scene": "Saved/Linux/l115/captures/L115/L115/passage-2-3-0-rock-floor-station-2.vfmesh", + "drawn_triangles": 494436, + "source_triangles": 524342, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 333.4481319239866, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": 0.007772237163474648, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 14.426607883839745, + -8.501776133009574, + -871.1605818845352 + ], + "target_actual_m": [ + 15.203729308783775, + -6.16777561793481, + -872.8561420785873 + ], + "logs": [ + "Saved/Linux/l115/captures/L115/L115/passage-2-3-0-rock-floor-station-2-mesh.log", + "Saved/Linux/l115/captures/L115/L115/passage-2-3-0-rock-floor-station-2-render.log", + "Saved/Linux/l115/captures/L115/L115/passage-2-3-0-rock-floor-station-2-quality.log" + ], + "floor_anchor_position_m": [ + 15.204179209863593, + -6.166457650456174, + -872.8484956270397 + ], + "floor_anchor_normal": [ + 0.05636607638224838, + 0.16908442175142946, + 0.9839884774499421 + ], + "closeup_camera_to_floor_distance_m": 2.984523811958219, + "closeup_floor_normal_alignment": 0.9839884774499421, + "verified_upward_floor_normal": true + }, + { + "name": "passage-2-3-0-rock-floor-station-3", + "passage": "passage/2-3/0", + "kind": "rock-floor-close", + "station": "rock-floor/343.4m", + "camera": [ + 16.176045301879554, + 1.1336183974400118, + -872.9426489764151 + ], + "target": [ + 15.465325445603714, + 3.4887437417106955, + -874.6379150751349 + ], + "yaw": -16.792543840841383, + "pitch": -34.57168620892087, + "focus": [ + 15.465325445603714, + 3.4887437417106955, + -874.6379150751349 + ], + "center_z": -874.6379150751349, + "route_distance_m": 343.4481319239866, + "requested_route_distance_m": 343.4481319239866, + "route_length_m": 494.0722798830563, + "planned_floor_m": -874.6379150751349, + "planned_grade_deg": 10.259484647608062, + "variant": "L115", + "capture": "captures/L115/L115/passage-2-3-0-rock-floor-station-3.png", + "scene": "Saved/Linux/l115/captures/L115/L115/passage-2-3-0-rock-floor-station-3.vfmesh", + "drawn_triangles": 485332, + "source_triangles": 512656, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 343.4481319239866, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": 0.10989591368848521, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 16.176045301879554, + 1.1336183974400118, + -872.9426489764151 + ], + "target_actual_m": [ + 15.465325445603714, + 3.4887437417106955, + -874.6379150751349 + ], + "logs": [ + "Saved/Linux/l115/captures/L115/L115/passage-2-3-0-rock-floor-station-3-mesh.log", + "Saved/Linux/l115/captures/L115/L115/passage-2-3-0-rock-floor-station-3-render.log", + "Saved/Linux/l115/captures/L115/L115/passage-2-3-0-rock-floor-station-3-quality.log" + ], + "floor_anchor_position_m": [ + 15.46430655077291, + 3.492524377793417, + -874.528088937583 + ], + "floor_anchor_normal": [ + -0.05151671634089027, + 0.17095268730304666, + 0.9839315050557732 + ], + "closeup_camera_to_floor_distance_m": 2.929953812680686, + "closeup_floor_normal_alignment": 0.9839315050557732, + "verified_upward_floor_normal": true + }, + { + "name": "passage-0-1-0-openair-1-4m-outside", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-1/4m-outside", + "camera": [ + 13.176702021211483, + 7.149068417345486, + -374.402 + ], + "target": [ + 9.197121888971225, + 7.5527291301707695, + -374.402 + ], + "yaw": -84.20812706837869, + "pitch": 0.0, + "focus": [ + 7.272, + 7.748, + -373.197 + ], + "center_z": -373.197, + "open_air_section": 1, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.9948950330600643, + -0.1009151782063209, + 0.0 + ], + "camera_target_distance_m": 4.000000000000001, + "route_distance_m": 8.3545, + "requested_route_distance_m": 8.3545, + "route_length_m": 2026.6238040154117, + "variant": "L115", + "capture": "captures/L115/L115/passage-0-1-0-openair-1-4m-outside.png", + "scene": "Saved/Linux/l115/captures/L115/L115/passage-0-1-0-openair-1-4m-outside.vfmesh", + "drawn_triangles": 275313, + "source_triangles": 327681, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 8.3545, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.9999999999999987, + "closeup_target_surface_distance_m": 0.7939613079024029, + "closeup_predicted_target_offset_m": 0.7939613079024029, + "closeup_wall_normal_alignment": 0.9448010671048102, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 12.921959272720493, + 7.9850770584603294, + -375.0077532897384 + ], + "target_actual_m": [ + 9.124876976013184, + 8.0, + -373.75 + ], + "logs": [ + "Saved/Linux/l115/captures/L115/L115/passage-0-1-0-openair-1-4m-outside-mesh.log", + "Saved/Linux/l115/captures/L115/L115/passage-0-1-0-openair-1-4m-outside-render.log", + "Saved/Linux/l115/captures/L115/L115/passage-0-1-0-openair-1-4m-outside-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-1-4m-interior-wall", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-1/4m-interior-wall", + "camera": [ + 7.395778712540976, + 3.8749008126934172, + -374.89997477205173 + ], + "target": [ + 8.778272394312646, + 7.595214286886338, + -374.402 + ], + "yaw": 20.38540702862518, + "pitch": 7.1515181408188955, + "focus": [ + 7.272, + 7.748, + -373.197 + ], + "center_z": -373.197, + "open_air_section": 1, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.9948950330600643, + 0.1009151782063209, + -0.0 + ], + "camera_target_distance_m": 3.9999999999999973, + "route_distance_m": 8.3545, + "requested_route_distance_m": 8.3545, + "route_length_m": 2026.6238040154117, + "variant": "L115", + "capture": "captures/L115/L115/passage-0-1-0-openair-1-4m-interior-wall.png", + "scene": "Saved/Linux/l115/captures/L115/L115/passage-0-1-0-openair-1-4m-interior-wall.vfmesh", + "drawn_triangles": 307964, + "source_triangles": 367980, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 8.3545, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.999999999999998, + "closeup_target_surface_distance_m": 0.8420749429811597, + "closeup_predicted_target_offset_m": 0.8420749429811597, + "closeup_wall_normal_alignment": 0.9448010671048102, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 5.3277946793058755, + 8.01492294153967, + -372.4922467102616 + ], + "target_actual_m": [ + 9.124876976013184, + 8.0, + -373.75 + ], + "logs": [ + "Saved/Linux/l115/captures/L115/L115/passage-0-1-0-openair-1-4m-interior-wall-mesh.log", + "Saved/Linux/l115/captures/L115/L115/passage-0-1-0-openair-1-4m-interior-wall-render.log", + "Saved/Linux/l115/captures/L115/L115/passage-0-1-0-openair-1-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-2-4m-outside", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-2/4m-outside", + "camera": [ + 12.814097656232029, + 0.949800892309409, + -375.51163279923776 + ], + "target": [ + 8.842807594702599, + 1.4281890685821654, + -375.51163279923776 + ], + "yaw": -83.1311525734364, + "pitch": 0.0, + "focus": [ + 6.603, + 1.698, + -374.149 + ], + "center_z": -374.149, + "open_air_section": 2, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.9928225153823576, + -0.1195970440681891, + 0.0 + ], + "camera_target_distance_m": 4.0, + "route_distance_m": 14.4925, + "requested_route_distance_m": 14.4925, + "route_length_m": 2026.6238040154117, + "variant": "L115", + "capture": "captures/L115/L115/passage-0-1-0-openair-2-4m-outside.png", + "scene": "Saved/Linux/l115/captures/L115/L115/passage-0-1-0-openair-2-4m-outside.vfmesh", + "drawn_triangles": 275313, + "source_triangles": 327681, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 14.4925, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.000000000000018, + "closeup_target_surface_distance_m": 1.0987112128185943, + "closeup_predicted_target_offset_m": 1.0987112128185943, + "closeup_wall_normal_alignment": 0.3897133873128999, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 9.5949500542171, + 1.5661638290281419, + -379.604906740858 + ], + "target_actual_m": [ + 7.956625938415527, + 1.0, + -376.0 + ], + "logs": [ + "Saved/Linux/l115/captures/L115/L115/passage-0-1-0-openair-2-4m-outside-mesh.log", + "Saved/Linux/l115/captures/L115/L115/passage-0-1-0-openair-2-4m-outside-render.log", + "Saved/Linux/l115/captures/L115/L115/passage-0-1-0-openair-2-4m-outside-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-2-4m-interior-wall", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-2/4m-interior-wall", + "camera": [ + 6.939570778854576, + -2.1803140897652855, + -376.2060303004211 + ], + "target": [ + 8.388084903173432, + 1.4829657169105679, + -375.51163279923776 + ], + "yaw": 21.574563086437188, + "pitch": 9.997160707081923, + "focus": [ + 6.603, + 1.698, + -374.149 + ], + "center_z": -374.149, + "open_air_section": 2, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.9928225153823576, + 0.1195970440681891, + -0.0 + ], + "camera_target_distance_m": 3.999999999999997, + "route_distance_m": 14.4925, + "requested_route_distance_m": 14.4925, + "route_length_m": 2026.6238040154117, + "variant": "L115", + "capture": "captures/L115/L115/passage-0-1-0-openair-2-4m-interior-wall.png", + "scene": "Saved/Linux/l115/captures/L115/L115/passage-0-1-0-openair-2-4m-interior-wall.vfmesh", + "drawn_triangles": 345024, + "source_triangles": 414544, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 14.4925, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.000000000000008, + "closeup_target_surface_distance_m": 0.7753571368538784, + "closeup_predicted_target_offset_m": 0.7753571368538784, + "closeup_wall_normal_alignment": 0.28377228920326875, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 6.628776462154715, + 0.5675722190282632, + -372.2459846914724 + ], + "target_actual_m": [ + 7.849808932278981, + 1.2129006394800852, + -376.0 + ], + "logs": [ + "Saved/Linux/l115/captures/L115/L115/passage-0-1-0-openair-2-4m-interior-wall-mesh.log", + "Saved/Linux/l115/captures/L115/L115/passage-0-1-0-openair-2-4m-interior-wall-render.log", + "Saved/Linux/l115/captures/L115/L115/passage-0-1-0-openair-2-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-3-4m-outside", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-3/4m-outside", + "camera": [ + -28.32291429976088, + -16.444327461849063, + -600.6066327992378 + ], + "target": [ + -25.004026673221745, + -14.211619482196229, + -600.6066327992378 + ], + "yaw": 56.07018168236039, + "pitch": 0.0, + "focus": [ + -22.1, + -12.258, + -599.244 + ], + "center_z": -599.244, + "open_air_section": 3, + "closeup_side": "outside", + "closeup_preferred_normal": [ + -0.8297219066347834, + -0.5581769949132084, + 0.0 + ], + "camera_target_distance_m": 4.000000000000001, + "route_distance_m": 1265.3425000000002, + "requested_route_distance_m": 1265.3425000000002, + "route_length_m": 2026.6238040154117, + "variant": "L115", + "capture": "captures/L115/L115/passage-0-1-0-openair-3-4m-outside.png", + "scene": "Saved/Linux/l115/captures/L115/L115/passage-0-1-0-openair-3-4m-outside.vfmesh", + "drawn_triangles": 148970, + "source_triangles": 181648, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1265.3425000000002, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.9999999999999902, + "closeup_target_surface_distance_m": 0.07628351187558495, + "closeup_predicted_target_offset_m": 0.07628351187558495, + "closeup_wall_normal_alignment": 0.9592251078586415, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -28.57044719818512, + -15.661387743596107, + -601.3804397335666 + ], + "target_actual_m": [ + -24.944963139481786, + -14.17663130732971, + -600.5733686926703 + ], + "logs": [ + "Saved/Linux/l115/captures/L115/L115/passage-0-1-0-openair-3-4m-outside-mesh.log", + "Saved/Linux/l115/captures/L115/L115/passage-0-1-0-openair-3-4m-outside-render.log", + "Saved/Linux/l115/captures/L115/L115/passage-0-1-0-openair-3-4m-outside-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-3-4m-interior-wall", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-3/4m-interior-wall", + "camera": [ + -26.071689640946218, + -10.338278587083852, + -601.3036807194 + ], + "target": [ + -24.774901932566983, + -14.057480898923608, + -600.6066327992378 + ], + "yaw": 160.77768453528284, + "pitch": 10.035712777782798, + "focus": [ + -22.1, + -12.258, + -599.244 + ], + "center_z": -599.244, + "open_air_section": 3, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + 0.8297219066347834, + 0.5581769949132084, + -0.0 + ], + "camera_target_distance_m": 4.000000000000005, + "route_distance_m": 1265.3425000000002, + "requested_route_distance_m": 1265.3425000000002, + "route_length_m": 2026.6238040154117, + "variant": "L115", + "capture": "captures/L115/L115/passage-0-1-0-openair-3-4m-interior-wall.png", + "scene": "Saved/Linux/l115/captures/L115/L115/passage-0-1-0-openair-3-4m-interior-wall.vfmesh", + "drawn_triangles": 148032, + "source_triangles": 180836, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1265.3425000000002, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.9999999999999982, + "closeup_target_surface_distance_m": 0.15205219413977372, + "closeup_predicted_target_offset_m": 0.15205219413977372, + "closeup_wall_normal_alignment": 0.9345418743495936, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -21.88067998858543, + -11.885666360390521, + -599.2830946490843 + ], + "target_actual_m": [ + -24.866255651742943, + -14.144752595137593, + -600.6912378745901 + ], + "logs": [ + "Saved/Linux/l115/captures/L115/L115/passage-0-1-0-openair-3-4m-interior-wall-mesh.log", + "Saved/Linux/l115/captures/L115/L115/passage-0-1-0-openair-3-4m-interior-wall-render.log", + "Saved/Linux/l115/captures/L115/L115/passage-0-1-0-openair-3-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-1-4m-outside", + "passage": "passage/1-2/0", + "kind": "open-air-close", + "station": "section-1/4m-outside", + "camera": [ + -4.699079444431819, + -4.6537955842685985, + -748.15 + ], + "target": [ + -7.452748333327923, + -7.555055250400828, + -748.15 + ], + "yaw": -136.49505148095557, + "pitch": 0.0, + "focus": [ + -9.518, + -9.731, + -745.88 + ], + "center_z": -745.88, + "open_air_section": 1, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.688417222224026, + 0.7253149165330574, + 0.0 + ], + "camera_target_distance_m": 4.000000000000001, + "route_distance_m": 83.504, + "requested_route_distance_m": 83.504, + "route_length_m": 114.99063175809309, + "variant": "L115", + "capture": "captures/L115/L115/passage-1-2-0-openair-1-4m-outside.png", + "scene": "Saved/Linux/l115/captures/L115/L115/passage-1-2-0-openair-1-4m-outside.vfmesh", + "drawn_triangles": 620866, + "source_triangles": 684916, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 83.504, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.9999999999999867, + "closeup_target_surface_distance_m": 1.0098710767792272, + "closeup_predicted_target_offset_m": 1.0098710767792272, + "closeup_wall_normal_alignment": 0.8500332564252469, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -5.485281064298812, + -4.725534607679206, + -745.4170663807179 + ], + "target_actual_m": [ + -8.013618934305235, + -7.013618934305234, + -747.5080416864878 + ], + "logs": [ + "Saved/Linux/l115/captures/L115/L115/passage-1-2-0-openair-1-4m-outside-mesh.log", + "Saved/Linux/l115/captures/L115/L115/passage-1-2-0-openair-1-4m-outside-render.log", + "Saved/Linux/l115/captures/L115/L115/passage-1-2-0-openair-1-4m-outside-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-1-4m-interior-wall", + "passage": "passage/1-2/0", + "kind": "open-air-close", + "station": "section-1/4m-interior-wall", + "camera": [ + -6.0956279351195075, + -11.653774892861163, + -748.8673569837389 + ], + "target": [ + -8.16773669839842, + -8.308365466344922, + -748.15 + ], + "yaw": -31.773605793127505, + "pitch": 10.331275124559749, + "focus": [ + -9.518, + -9.731, + -745.88 + ], + "center_z": -745.88, + "open_air_section": 1, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.688417222224026, + -0.7253149165330574, + -0.0 + ], + "camera_target_distance_m": 3.999999999999997, + "route_distance_m": 83.504, + "requested_route_distance_m": 83.504, + "route_length_m": 114.99063175809309, + "variant": "L115", + "capture": "captures/L115/L115/passage-1-2-0-openair-1-4m-interior-wall.png", + "scene": "Saved/Linux/l115/captures/L115/L115/passage-1-2-0-openair-1-4m-interior-wall.vfmesh", + "drawn_triangles": 609733, + "source_triangles": 668219, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 83.504, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.999999999999999, + "closeup_target_surface_distance_m": 0.6509430039577998, + "closeup_predicted_target_offset_m": 0.6509430039577998, + "closeup_wall_normal_alignment": 0.7808473937095911, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -8.525095579521167, + -12.94135557024142, + -748.3220319510015 + ], + "target_actual_m": [ + -8.18421537084871, + -8.958641713644115, + -748.1744141343152 + ], + "logs": [ + "Saved/Linux/l115/captures/L115/L115/passage-1-2-0-openair-1-4m-interior-wall-mesh.log", + "Saved/Linux/l115/captures/L115/L115/passage-1-2-0-openair-1-4m-interior-wall-render.log", + "Saved/Linux/l115/captures/L115/L115/passage-1-2-0-openair-1-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-2-4m-outside", + "passage": "passage/1-2/0", + "kind": "open-air-close", + "station": "section-2/4m-outside", + "camera": [ + 6.53817273275958, + -4.657210376135293, + -752.013 + ], + "target": [ + 8.159152142647708, + -8.31404312493838, + -752.013 + ], + "yaw": 156.09352823535562, + "pitch": 0.0, + "focus": [ + 9.43, + -11.181, + -749.743 + ], + "center_z": -749.743, + "open_air_section": 2, + "closeup_side": "outside", + "closeup_preferred_normal": [ + -0.40524485247203174, + 0.9142081872007717, + 0.0 + ], + "camera_target_distance_m": 4.0, + "route_distance_m": 104.362, + "requested_route_distance_m": 104.362, + "route_length_m": 114.99063175809309, + "variant": "L115", + "capture": "captures/L115/L115/passage-1-2-0-openair-2-4m-outside.png", + "scene": "Saved/Linux/l115/captures/L115/L115/passage-1-2-0-openair-2-4m-outside.vfmesh", + "drawn_triangles": 584622, + "source_triangles": 637110, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 104.362, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.0, + "closeup_target_surface_distance_m": 0.5853577252069573, + "closeup_predicted_target_offset_m": 0.5853577252069573, + "closeup_wall_normal_alignment": 0.9888938441905853, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 6.3542248659153735, + -5.414315273002622, + -752.0443543721697 + ], + "target_actual_m": [ + 8.5, + -8.789926093729537, + -752.0143433586003 + ], + "logs": [ + "Saved/Linux/l115/captures/L115/L115/passage-1-2-0-openair-2-4m-outside-mesh.log", + "Saved/Linux/l115/captures/L115/L115/passage-1-2-0-openair-2-4m-outside-render.log", + "Saved/Linux/l115/captures/L115/L115/passage-1-2-0-openair-2-4m-outside-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-2-4m-interior-wall", + "passage": "passage/1-2/0", + "kind": "open-air-close", + "station": "section-2/4m-interior-wall", + "camera": [ + 12.438590152225206, + -8.574465388721983, + -752.7261335058829 + ], + "target": [ + 8.55317187096847, + -9.20292810238377, + -752.013 + ], + "yaw": -99.18796190221158, + "pitch": 10.269787281460902, + "focus": [ + 9.43, + -11.181, + -749.743 + ], + "center_z": -749.743, + "open_air_section": 2, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + 0.40524485247203174, + -0.9142081872007717, + -0.0 + ], + "camera_target_distance_m": 3.9999999999999973, + "route_distance_m": 104.362, + "requested_route_distance_m": 104.362, + "route_length_m": 114.99063175809309, + "variant": "L115", + "capture": "captures/L115/L115/passage-1-2-0-openair-2-4m-interior-wall.png", + "scene": "Saved/Linux/l115/captures/L115/L115/passage-1-2-0-openair-2-4m-interior-wall.vfmesh", + "drawn_triangles": 572238, + "source_triangles": 618646, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 104.362, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.999999999999999, + "closeup_target_surface_distance_m": 0.354874967440152, + "closeup_predicted_target_offset_m": 0.354874967440152, + "closeup_wall_normal_alignment": 0.9979957992262107, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 9.717371905411476, + -12.678581195400906, + -752.0281034251076 + ], + "target_actual_m": [ + 8.330275720030585, + -8.926843182205447, + -752.007462377509 + ], + "logs": [ + "Saved/Linux/l115/captures/L115/L115/passage-1-2-0-openair-2-4m-interior-wall-mesh.log", + "Saved/Linux/l115/captures/L115/L115/passage-1-2-0-openair-2-4m-interior-wall-render.log", + "Saved/Linux/l115/captures/L115/L115/passage-1-2-0-openair-2-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-1-4m-outside", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-1/4m-outside", + "camera": [ + -3.5840423774965293, + -5.521048309862215, + -815.8969999999999 + ], + "target": [ + -5.637732447498513, + -8.953592132798093, + -815.8969999999999 + ], + "yaw": -149.10792796365394, + "pitch": 0.0, + "focus": [ + -7.178, + -11.528, + -813.627 + ], + "center_z": -813.627, + "open_air_section": 1, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.5134225175004958, + 0.8581359557339694, + 0.0 + ], + "camera_target_distance_m": 4.0, + "route_distance_m": 16.616500000000002, + "requested_route_distance_m": 16.616500000000002, + "route_length_m": 494.0722798830563, + "variant": "L115", + "capture": "captures/L115/L115/passage-2-3-0-openair-1-4m-outside.png", + "scene": "Saved/Linux/l115/captures/L115/L115/passage-2-3-0-openair-1-4m-outside.vfmesh", + "drawn_triangles": 104612, + "source_triangles": 129354, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 16.616500000000002, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.0000000000000036, + "closeup_target_surface_distance_m": 0.29188924025474844, + "closeup_predicted_target_offset_m": 0.29188924025474844, + "closeup_wall_normal_alignment": 0.6703275045296155, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -3.7918253987505834, + -7.16028175130118, + -813.227396563761 + ], + "target_actual_m": [ + -5.7833741859987065, + -9.093313475424294, + -816.1078690565205 + ], + "logs": [ + "Saved/Linux/l115/captures/L115/L115/passage-2-3-0-openair-1-4m-outside-mesh.log", + "Saved/Linux/l115/captures/L115/L115/passage-2-3-0-openair-1-4m-outside-render.log", + "Saved/Linux/l115/captures/L115/L115/passage-2-3-0-openair-1-4m-outside-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-1-4m-interior-wall", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-1/4m-interior-wall", + "camera": [ + -3.4141605326349946, + -12.659565888737353, + -816.5879167710818 + ], + "target": [ + -6.170971760123668, + -9.844849940114793, + -815.8969999999999 + ], + "yaw": -44.40454805561343, + "pitch": 9.946538162082001, + "focus": [ + -7.178, + -11.528, + -813.627 + ], + "center_z": -813.627, + "open_air_section": 1, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.5134225175004958, + -0.8581359557339694, + -0.0 + ], + "camera_target_distance_m": 4.000000000000005, + "route_distance_m": 16.616500000000002, + "requested_route_distance_m": 16.616500000000002, + "route_length_m": 494.0722798830563, + "variant": "L115", + "capture": "captures/L115/L115/passage-2-3-0-openair-1-4m-interior-wall.png", + "scene": "Saved/Linux/l115/captures/L115/L115/passage-2-3-0-openair-1-4m-interior-wall.vfmesh", + "drawn_triangles": 94962, + "source_triangles": 118056, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 16.616500000000002, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.0, + "closeup_target_surface_distance_m": 0.41920390486225767, + "closeup_predicted_target_offset_m": 0.41920390486225767, + "closeup_wall_normal_alignment": 0.740744136337711, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -7.998432705401559, + -11.833936581758076, + -818.2481168532394 + ], + "target_actual_m": [ + -5.94757062165508, + -9.608161331921629, + -815.6327986602337 + ], + "logs": [ + "Saved/Linux/l115/captures/L115/L115/passage-2-3-0-openair-1-4m-interior-wall-mesh.log", + "Saved/Linux/l115/captures/L115/L115/passage-2-3-0-openair-1-4m-interior-wall-render.log", + "Saved/Linux/l115/captures/L115/L115/passage-2-3-0-openair-1-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-2-4m-outside", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-2/4m-outside", + "camera": [ + -4.5562890668466025, + 4.648574813628143, + -879.7479999999999 + ], + "target": [ + -7.40869531436283, + 7.452817777269203, + -879.7479999999999 + ], + "yaw": -45.487830534998494, + "pitch": 0.0, + "focus": [ + -9.548, + 9.556, + -877.478 + ], + "center_z": -877.478, + "open_air_section": 2, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.7131015618790567, + -0.7010607409102652, + 0.0 + ], + "camera_target_distance_m": 4.000000000000001, + "route_distance_m": 374.929, + "requested_route_distance_m": 374.929, + "route_length_m": 494.0722798830563, + "variant": "L115", + "capture": "captures/L115/L115/passage-2-3-0-openair-2-4m-outside.png", + "scene": "Saved/Linux/l115/captures/L115/L115/passage-2-3-0-openair-2-4m-outside.vfmesh", + "drawn_triangles": 475838, + "source_triangles": 504242, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 374.929, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.0, + "closeup_target_surface_distance_m": 1.7280841589725482, + "closeup_predicted_target_offset_m": 1.7280841589725482, + "closeup_wall_normal_alignment": 0.6707889779439669, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -7.47193274788199, + 5.182168353356822, + -879.6783722112204 + ], + "target_actual_m": [ + -7.306445568768645, + 9.17777802625833, + -879.7662205769708 + ], + "logs": [ + "Saved/Linux/l115/captures/L115/L115/passage-2-3-0-openair-2-4m-outside-mesh.log", + "Saved/Linux/l115/captures/L115/L115/passage-2-3-0-openair-2-4m-outside-render.log", + "Saved/Linux/l115/captures/L115/L115/passage-2-3-0-openair-2-4m-outside-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-2-4m-interior-wall", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-2/4m-interior-wall", + "camera": [ + -11.533986119377625, + 6.164550123765492, + -880.4395357921604 + ], + "target": [ + -8.149320771422074, + 8.180937668487475, + -879.7479999999999 + ], + "yaw": 59.215963829172296, + "pitch": 9.955540417812847, + "focus": [ + -9.548, + 9.556, + -877.478 + ], + "center_z": -877.478, + "open_air_section": 2, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.7131015618790567, + 0.7010607409102652, + -0.0 + ], + "camera_target_distance_m": 4.000000000000007, + "route_distance_m": 374.929, + "requested_route_distance_m": 374.929, + "route_length_m": 494.0722798830563, + "variant": "L115", + "capture": "captures/L115/L115/passage-2-3-0-openair-2-4m-interior-wall.png", + "scene": "Saved/Linux/l115/captures/L115/L115/passage-2-3-0-openair-2-4m-interior-wall.vfmesh", + "drawn_triangles": 486512, + "source_triangles": 513540, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 374.929, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.0, + "closeup_target_surface_distance_m": 1.0286227628002445, + "closeup_predicted_target_offset_m": 1.0286227628002445, + "closeup_wall_normal_alignment": 0.720019406420326, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -8.257109087497915, + 13.208090205453457, + -879.7612149430302 + ], + "target_actual_m": [ + -8.149320771422074, + 9.209558486938477, + -879.75 + ], + "logs": [ + "Saved/Linux/l115/captures/L115/L115/passage-2-3-0-openair-2-4m-interior-wall-mesh.log", + "Saved/Linux/l115/captures/L115/L115/passage-2-3-0-openair-2-4m-interior-wall-render.log", + "Saved/Linux/l115/captures/L115/L115/passage-2-3-0-openair-2-4m-interior-wall-quality.log" + ] + } + ] +} diff --git a/Standalone/Research/WorldAssemblerM3/Linux116/REPORT.md b/Standalone/Research/WorldAssemblerM3/Linux116/REPORT.md new file mode 100644 index 0000000..d15c06a --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux116/REPORT.md @@ -0,0 +1,20 @@ +# Linux L116 + +L116 preserves L115 output: all 18 Clang/GCC hash-matrix cases matched, including all four owner views at W1/W8/W12. The tightened chord bound and z-column cache reduced exact fine-segment/sample evaluations from 48,947,915 in L115 to 38,783,101 (-20.8%). L109 was 19,812,455; L116 still performs 1.96x as many pairs. + +Timing used five interleaved L80 runs per version, stratum, and worker count. The pre-run one-minute load was 0.94; top reported 97.1% idle. + +| Stratum | Workers | LOD0-2 ready L109 / L115 / L116 (s) | L116 vs L109 | Whole view L109 / L115 / L116 (s) | +|---:|---:|---:|---:|---:| +| 0 | 8 | 0.770 / 0.908 / 0.947 | +23.1% | 1.791 / 1.940 / 1.907 | +| 0 | 12 | 0.788 / 0.917 / 0.930 | +18.1% | 1.732 / 1.871 / 1.886 | +| 1 | 8 | 0.951 / 1.236 / 1.235 | +29.9% | 1.833 / 2.163 / 2.194 | +| 1 | 12 | 0.906 / 1.174 / 1.174 | +29.5% | 1.756 / 2.040 / 2.038 | +| 2 | 8 | 1.015 / 1.264 / 1.248 | +22.9% | 1.905 / 2.166 / 2.102 | +| 2 | 12 | 0.940 / 1.177 / 1.173 | +24.8% | 1.757 / 1.999 / 1.995 | +| 3 | 8 | 0.882 / 1.011 / 1.016 | +15.2% | 1.850 / 1.958 / 2.009 | +| 3 | 12 | 0.796 / 0.933 / 0.950 | +19.4% | 1.663 / 1.809 / 1.826 | + +The requested near-ready target of about 5% over L109 was not met. Fast tier passed (344.3 s). The Linux VFHostEditor build passed with `-NoUBA -MaxParallelActions=4` (71.11 s; no `prlimit`). + +Logs and summaries are under `Saved/Linux/l116/`; timing summary is `timing/summary.json`, pair counts are in `pairs/summary.json`, and the hash result is `hashes/summary.json`. diff --git a/Standalone/Research/WorldAssemblerM3/Linux116/RunL116HashMatrix.py b/Standalone/Research/WorldAssemblerM3/Linux116/RunL116HashMatrix.py new file mode 100644 index 0000000..56fedb9 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux116/RunL116HashMatrix.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python3 +"""Compare the L116 hash matrix directly with the saved L115 matrix.""" +from __future__ import annotations + +import json +import re +import subprocess +import time +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / "Saved/Linux/l116/hashes" +BASE = ROOT / "Saved/Linux/l115/hashes" +DATASETS = { + "owner4": ROOT / "Standalone/data/owner_world.json", + "owner2": ROOT / "Standalone/data/regression/owner_world_2strate_l61.json", +} +BINARIES = { + "clang": ROOT / "Saved/Linux/l116/bin/VoxelForgeCoreHeadless-l116-clang", + "gcc": ROOT / "Saved/Linux/l116/bin/VoxelForgeCoreHeadless-l116-gcc", +} +HASH = re.compile(r"^\[Pipeline(?:FullDetailHash|WholeViewHash|LODHash|ExactQueryHash)\].*$", re.M) +STAMP = re.compile(r"^\[VoxelForgeSourceStamp\] sha256=(\S+)$", re.M) + + +def run(dataset: str, recipe: str, workers: int, compiler: str) -> dict: + OUT.mkdir(parents=True, exist_ok=True) + label = f"{dataset}-{recipe}-w{workers}-{compiler}" + log = OUT / f"{label}.log" + layout = OUT / f"{label}.layout.json" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1740s", str(BINARIES[compiler]), str(DATASETS[dataset]), + f"--workers={workers}", "--world-assembler-prototype", "--stream-benchmark", + "--stream-pipeline", "--force-generate", "--clip-radius=3", + "--max-clip-level=8", "--max-level=8", f"--recipe={recipe}", + "--stream-hash", f"--resolved-layout-output={layout}", + ] + started = time.monotonic() + with log.open("w", encoding="utf-8") as stream: + result = subprocess.run(command, cwd=ROOT, stdout=stream, + stderr=subprocess.STDOUT, check=False, timeout=1740) + output = log.read_text(encoding="utf-8", errors="replace") + hashes = HASH.findall(output) + baseline_log = BASE / f"{label}.log" + baseline_hashes = HASH.findall(baseline_log.read_text(encoding="utf-8", errors="replace")) + if result.returncode or len(hashes) != 12 or hashes != baseline_hashes: + raise SystemExit(f"hash mismatch or incomplete run: {label}; exit={result.returncode} " + f"l116={len(hashes)} l115={len(baseline_hashes)} log={log}") + row = { + "dataset": dataset, "recipe": recipe, "workers": workers, + "compiler": compiler, "exit_code": result.returncode, + "matches_l115": True, "hashes": hashes, + "source_stamp": (STAMP.search(output).group(1) if STAMP.search(output) else None), + "elapsed_s": round(time.monotonic() - started, 3), + "log": str(log.relative_to(ROOT)), + "l115_log": str(baseline_log.relative_to(ROOT)), + } + print("[L116HashRun] " + json.dumps(row, sort_keys=True), flush=True) + return row + + +def main() -> int: + if any(not path.is_file() for path in (*DATASETS.values(), *BINARIES.values())): + raise SystemExit("missing L116 hash input") + rows = [] + recipes = {"owner4": ("surface-world",), + "owner2": ("surface-world", "floating-islands")} + for dataset, dataset_recipes in recipes.items(): + for recipe in dataset_recipes: + for workers in (1, 8, 12): + for compiler in ("clang", "gcc"): + rows.append(run(dataset, recipe, workers, compiler)) + (OUT / "runs-partial.json").write_text( + json.dumps(rows, indent=2) + "\n", encoding="utf-8") + summary = { + "runs": rows, + "all_hashes_match_l115": all(row["matches_l115"] for row in rows), + "owner4_all_four_strata": "owner4/surface-world", + "worker_counts": [1, 8, 12], + "compilers": ["clang", "gcc"], + } + (OUT / "summary.json").write_text(json.dumps(summary, indent=2) + "\n", + encoding="utf-8") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux116/RunL116PairCounts.py b/Standalone/Research/WorldAssemblerM3/Linux116/RunL116PairCounts.py new file mode 100644 index 0000000..06594e8 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux116/RunL116PairCounts.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 +"""Count exact fine-segment/sample evaluations in the four L80 views.""" +from __future__ import annotations + +import json +import re +import subprocess +import time +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / "Saved/Linux/l116/pairs" +DATA = ROOT / "Standalone/data/owner_world.json" +BIN = ROOT / "Saved/Linux/l116/bin/VoxelForgeCoreHeadless-l116-clang" +CAMERAS = { + 0: (8.0, 16.0, -372.2626953125), + 1: (25.8369140625, 3.19921875, -737.0), + 2: (19.166015625, -14.2001953125, -753.3740234375), + 3: (-20.0625, -5.068359375, -900.353515625), +} +PAIRS = re.compile(r"\bsweep_pairs=(\d+)") + + +def run(strate: int) -> dict: + OUT.mkdir(parents=True, exist_ok=True) + log = OUT / f"L116-s{strate}.log" + camera = ",".join(f"{v:.12f}" for v in CAMERAS[strate]) + ",0,0" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1740s", str(BIN), str(DATA), + "--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline", + "--workers=12", "--clip-radius=3", "--max-clip-level=8", "--max-level=8", + f"--camera={camera}", "--profile-passage-composer", + "--stream-scheduler-policy=3", + ] + started = time.monotonic() + with log.open("w", encoding="utf-8") as stream: + result = subprocess.run(command, cwd=ROOT, stdout=stream, + stderr=subprocess.STDOUT, check=False, timeout=1740) + values = [int(value) for value in PAIRS.findall( + log.read_text(encoding="utf-8", errors="replace"))] + if result.returncode or not values: + raise SystemExit(f"pair profile missing: {log}; exit={result.returncode}") + row = {"strate": strate, "tiles": len(values), "segment_sample_pairs": sum(values), + "elapsed_s": round(time.monotonic() - started, 3), + "log": str(log.relative_to(ROOT))} + print("[L116PairCount] " + json.dumps(row, sort_keys=True), flush=True) + return row + + +def main() -> int: + if not BIN.is_file() or not DATA.is_file(): + raise SystemExit("missing L116 pair-count input") + rows = [run(strate) for strate in range(4)] + summary = {"strata": rows, + "total_segment_sample_pairs": sum(row["segment_sample_pairs"] + for row in rows)} + (OUT / "summary.json").write_text(json.dumps(summary, indent=2) + "\n", + encoding="utf-8") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux116/RunL116Timing.py b/Standalone/Research/WorldAssemblerM3/Linux116/RunL116Timing.py new file mode 100644 index 0000000..e8d5f97 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux116/RunL116Timing.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python3 +"""Five interleaved L80 readiness runs for L109, L115, and L116.""" +from __future__ import annotations + +import json +import os +import re +import statistics +import subprocess +import time +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / "Saved/Linux/l116/timing" +DATA = ROOT / "Standalone/data/owner_world.json" +BINARIES = { + "L109": ROOT / "Saved/Linux/l109/bin-final/VoxelForgeCoreHeadless-l109-clang", + "L115": ROOT / "Saved/Linux/l115/bin/VoxelForgeCoreHeadless-l115-clang", + "L116": ROOT / "Saved/Linux/l116/bin/VoxelForgeCoreHeadless-l116-clang", +} +CAMERAS = { + 0: (8.0, 16.0, -372.2626953125), + 1: (25.8369140625, 3.19921875, -737.0), + 2: (19.166015625, -14.2001953125, -753.3740234375), + 3: (-20.0625, -5.068359375, -900.353515625), +} +PIPELINE = re.compile(r"^\[StreamPipeline\] (.*)$", re.M) +FIELDS = re.compile(r"([a-zA-Z0-9_]+)=([^ ]+)") +NEAR = re.compile( + r"^\[WorldAssemblerNearLODReady\] lods=0-2 tiles=(\d+)/(\d+) cold_ready_s=([0-9.]+)$", + re.M, +) + + +def run(strate: int, workers: int, version: str, phase: str, replicate: int) -> dict: + OUT.mkdir(parents=True, exist_ok=True) + label = f"s{strate}-w{workers}-{version}-{phase}{replicate}" + log = OUT / f"{label}.log" + camera = ",".join(f"{v:.12f}" for v in CAMERAS[strate]) + ",0,0" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1740s", str(BINARIES[version]), str(DATA), + "--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline", + f"--workers={workers}", "--clip-radius=3", "--max-clip-level=8", + "--max-level=8", f"--camera={camera}", "--profile-lod-work", + "--stream-scheduler-policy=3", + ] + start = time.monotonic() + with log.open("w", encoding="utf-8") as output: + result = subprocess.run(command, cwd=ROOT, stdout=output, + stderr=subprocess.STDOUT, check=False, timeout=1740) + content = log.read_text(encoding="utf-8", errors="replace") + pipeline_match = PIPELINE.search(content) + near_match = NEAR.search(content) + if result.returncode or pipeline_match is None or near_match is None: + raise SystemExit(f"readiness run failed or trace missing: {log}; exit={result.returncode}") + pipeline = dict(FIELDS.findall(pipeline_match.group(1))) + row = { + "strate": strate, "workers": workers, "version": version, + "phase": phase, "replicate": replicate, "exit_code": result.returncode, + "wall_s": round(time.monotonic() - start, 3), + "lod02_ready_s": float(near_match.group(3)), + "whole_view_ready_s": float(pipeline["whole_view_ready"].removesuffix("s")), + "whole_tiles": int(pipeline["whole_tiles"].split("/")[0]), + "log": str(log.relative_to(ROOT)), + } + print("[L116TimingRun] " + json.dumps(row, sort_keys=True), flush=True) + return row + + +def main() -> int: + if any(not path.is_file() for path in (*BINARIES.values(), DATA)): + raise SystemExit("missing L109/L115/L116 data or timing binary") + OUT.mkdir(parents=True, exist_ok=True) + load_1m = os.getloadavg()[0] + uptime = subprocess.run(["uptime"], cwd=ROOT, text=True, capture_output=True, + check=True).stdout.strip() + top = subprocess.run(["top", "-b", "-n1"], cwd=ROOT, text=True, + capture_output=True, check=True).stdout + (OUT / "machine-load-before.txt").write_text( + f"uptime: {uptime}\n1-minute load: {load_1m:.2f}\ntop:\n{top}", + encoding="utf-8") + print(f"[L116TimingGate] load_1m={load_1m:.2f} uptime={uptime}", flush=True) + if load_1m >= 1.5: + raise SystemExit(f"timing refused: 1-minute load {load_1m:.2f} is not below 1.5") + rows = [] + versions = ("L109", "L115", "L116") + for strate in range(4): + for workers in (8, 12): + for version in versions: + run(strate, workers, version, "warmup", 0) + for replicate in range(1, 6): + offset = (replicate - 1) % len(versions) + order = versions[offset:] + versions[:offset] + for version in order: + rows.append(run(strate, workers, version, "measured", replicate)) + (OUT / "runs-partial.json").write_text( + json.dumps(rows, indent=2) + "\n", encoding="utf-8") + summary = [] + for strate in range(4): + for workers in (8, 12): + item = {"strate": strate, "workers": workers, "replicates": 5} + medians = {} + for version in versions: + group = [row for row in rows if row["strate"] == strate + and row["workers"] == workers and row["version"] == version] + medians[version] = {} + for key in ("lod02_ready_s", "whole_view_ready_s"): + values = [row[key] for row in group] + medians[version][key] = statistics.median(values) + item[f"{version}_{key}_values"] = values + item[f"{version}_{key}_median"] = medians[version][key] + for comparison in ("L109", "L115"): + for key in ("lod02_ready_s", "whole_view_ready_s"): + item[f"L116_vs_{comparison}_{key}_delta_pct"] = round( + 100.0 * (medians["L116"][key] / medians[comparison][key] - 1.0), 2) + summary.append(item) + (OUT / "summary.json").write_text( + json.dumps({"runs": rows, "summary": summary}, indent=2) + "\n", + encoding="utf-8") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux116/patches/chord-bound-zcolumn-not-merged.patch b/Standalone/Research/WorldAssemblerM3/Linux116/patches/chord-bound-zcolumn-not-merged.patch new file mode 100644 index 0000000..423900f --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux116/patches/chord-bound-zcolumn-not-merged.patch @@ -0,0 +1,302 @@ +diff --git a/Standalone/Core/src/ShapeWorldInternal.h b/Standalone/Core/src/ShapeWorldInternal.h +index c266bd8..216b0a2 100644 +--- a/Standalone/Core/src/ShapeWorldInternal.h ++++ b/Standalone/Core/src/ShapeWorldInternal.h +@@ -11481,6 +11481,12 @@ inline void FStandaloneShapeWorld::FScopedPassageTileQueries::prepareSweptTubeBa + last=std::min(sweep->dimension-1, + static_cast(std::floor(relativeMaximum))); + }; ++ struct FColumnProjectionCache ++ { ++ double projectionXY=0.0; ++ double floorT=0.0,floorTClamped=0.0,floorDepth=0.0,floorCenterZ=0.0; ++ bool hasProjection=false,hasFloorProfile=false; ++ }; + + for(std::size_t passageIndex=0;passageIndex=segmentEndIndex)continue; ++ constexpr std::size_t MaxCandidateSegments=8; ++ const std::size_t candidateSegmentCount=segmentEndIndex-candidate.segmentIndex; ++ std::array chordProjectionMinimum{}; ++ std::array chordProjectionMaximum{}; ++ std::array maximumRadius{}; ++ std::array maximumChordDeviation{}; ++ std::array,MaxCandidateSegments> segmentMinimum{}; ++ std::array,MaxCandidateSegments> segmentMaximum{}; ++ std::array chordOrigin{},chordDirection{}; ++ bool canCertifyChordWindow=candidateSegmentCount<=MaxCandidateSegments; ++ if(canCertifyChordWindow) ++ { ++ chordOrigin=segments[candidate.segmentIndex].a; ++ const auto& lastSegment=segments[segmentEndIndex-1]; ++ const double chordX=lastSegment.b[0]-chordOrigin[0]; ++ const double chordY=lastSegment.b[1]-chordOrigin[1]; ++ const double chordZ=lastSegment.b[2]-chordOrigin[2]; ++ const double chordLengthSq=chordX*chordX+chordY*chordY+chordZ*chordZ; ++ const double chordLength=chordLengthSq>1.0e-12 ++ ?FStandaloneShapeWorld::DeterministicSqrt(chordLengthSq):0.0; ++ canCertifyChordWindow=chordLength>1.0e-6&&std::isfinite(chordLength); ++ if(canCertifyChordWindow) ++ { ++ const double inverseChordLength=1.0/chordLength; ++ chordDirection={chordX*inverseChordLength,chordY*inverseChordLength, ++ chordZ*inverseChordLength}; ++ for(std::size_t localIndex=0;localIndex first{},last{}; + for(std::size_t axis=0;axis<3;++axis) + gridRange(axis,candidate.sweepMinimumSubvoxels[axis], + candidate.sweepMaximumSubvoxels[axis],first[axis],last[axis]); + if(first[0]>last[0]||first[1]>last[1]||first[2]>last[2])continue; ++ const std::size_t columnWidth=static_cast(last[0]-first[0]+1); ++ const std::size_t columnHeight=static_cast(last[1]-first[1]+1); ++ const std::size_t columnsPerSegment=columnWidth*columnHeight; ++ std::vector columnProjectionCache( ++ candidateSegmentCount*columnsPerSegment); + + for(std::int32_t gz=first[2];gz<=last[2];++gz) + { +@@ -11516,9 +11594,65 @@ inline void FStandaloneShapeWorld::FScopedPassageTileQueries::prepareSweptTubeBa + +static_cast(gy)*sweep->stepSubvoxels); + const double qz=static_cast(sweep->gridMinimumSubvoxels[2] + +static_cast(gz)*sweep->stepSubvoxels); +- for(std::size_t segmentIndex=candidate.segmentIndex; +- segmentIndex query={qx,qy,qz}; ++ const std::size_t sampleIndex=(static_cast(gz) ++ *static_cast(sweep->dimension)+static_cast(gy)) ++ *static_cast(sweep->dimension)+static_cast(gx); ++ auto& sample=passageSamples.samples[sampleIndex]; ++ std::array segmentOrder{}; ++ std::size_t anchorIndex=0; ++ double queryChordProjection=0.0; ++ double queryChordPerpendicularDistanceSq=0.0; ++ if(canCertifyChordWindow) ++ { ++ queryChordProjection=(qx-chordOrigin[0])*chordDirection[0] ++ +(qy-chordOrigin[1])*chordDirection[1] ++ +(qz-chordOrigin[2])*chordDirection[2]; ++ for(std::size_t axis=0;axis<3;++axis) ++ { ++ const double perpendicular=(query[axis]-chordOrigin[axis]) ++ -queryChordProjection*chordDirection[axis]; ++ queryChordPerpendicularDistanceSq+=perpendicular*perpendicular; ++ } ++ double nearestChordGap=std::numeric_limits::infinity(); ++ for(std::size_t localIndex=0;localIndex=offset) ++ segmentOrder[orderCount++]=anchorIndex-offset; ++ if(orderCount(gy-first[1])*columnWidth ++ +static_cast(gx-first[0]); ++ auto& column=columnProjectionCache[columnIndex]; + const auto& segment=segments[segmentIndex]; + if(segment.lengthSq<=0.0 + ||qxsegment.sweepMaximumSubvoxels[1] + ||qzsegment.sweepMaximumSubvoxels[2])continue; +- const double projectionXY=(qx-segment.a[0])*segment.delta[0] +- +(qy-segment.a[1])*segment.delta[1]; ++ if(canCertifyChordWindow) ++ { ++ // Every point on a fine segment stays within ++ // maximumChordDeviation of the coarse chord. Combine the ++ // chord-axis gap with the query's perpendicular distance, then ++ // subtract that deviation. The segment AABB is a second lower ++ // bound. Skip only when both bounds exclude every exact minimum. ++ const double chordGap=std::max({chordProjectionMinimum[localIndex] ++ -queryChordProjection,0.0, ++ queryChordProjection-chordProjectionMaximum[localIndex]}); ++ const double chordDistanceSq=queryChordPerpendicularDistanceSq ++ +chordGap*chordGap; ++ double boxDistanceSq=0.0; ++ for(std::size_t axis=0;axis<3;++axis) ++ { ++ const double gap=std::max({segmentMinimum[localIndex][axis] ++ -query[axis],0.0, ++ query[axis]-segmentMaximum[localIndex][axis]}); ++ boxDistanceSq+=gap*gap; ++ } ++ const double boundMargin=1.0e-6*qPerMetre; ++ const double tubeBaseLimit=sample.roundSignedDistance ++ +maximumRadius[localIndex]+boundMargin; ++ const double tubeChordLimit=tubeBaseLimit ++ +maximumChordDeviation[localIndex]; ++ const bool canImproveTube=tubeBaseLimit>=0.0&&tubeChordLimit>=0.0 ++ &&boxDistanceSq<=tubeBaseLimit*tubeBaseLimit ++ &&chordDistanceSq<=tubeChordLimit*tubeChordLimit; ++ const double bestFloorDistance=std::isfinite( ++ sample.floorCenterDistanceSq) ++ ?FStandaloneShapeWorld::DeterministicSqrt( ++ sample.floorCenterDistanceSq) ++ :std::numeric_limits::infinity(); ++ const double floorBaseLimit=bestFloorDistance+boundMargin; ++ const double floorChordLimit=floorBaseLimit ++ +maximumChordDeviation[localIndex]; ++ const bool canImproveFloor=floorBaseLimit>=0.0 ++ &&floorChordLimit>=0.0 ++ &&boxDistanceSq<=floorBaseLimit*floorBaseLimit ++ &&chordDistanceSq<=floorChordLimit*floorChordLimit; ++ const double shellBaseLimit=sample.shellSignedDistance ++ +shellThickness+maximumRadius[localIndex]+boundMargin; ++ const double shellChordLimit=shellBaseLimit ++ +maximumChordDeviation[localIndex]; ++ const bool canImproveShell=shellBaseLimit>=0.0 ++ &&shellChordLimit>=0.0 ++ &&boxDistanceSq<=shellBaseLimit*shellBaseLimit ++ &&chordDistanceSq<=shellChordLimit*shellChordLimit; ++ if(!canImproveTube&&!canImproveFloor&&!canImproveShell)continue; ++ } ++ if(!column.hasProjection) ++ { ++ column.projectionXY=(qx-segment.a[0])*segment.delta[0] ++ +(qy-segment.a[1])*segment.delta[1]; ++ column.hasProjection=true; ++ } ++ const double projectionXY=column.projectionXY; + const double t=std::clamp((projectionXY + +(qz-segment.a[2])*segment.delta[2])/segment.lengthSq,0.0,1.0); + double cx=segment.a[0]+t*segment.delta[0]; +@@ -11538,18 +11727,44 @@ inline void FStandaloneShapeWorld::FScopedPassageTileQueries::prepareSweptTubeBa + const double ex=qx-cx,ey=qy-cy,ez=qz-cz; + const double signedDistance=FStandaloneShapeWorld::DeterministicSqrt( + ex*ex+ey*ey+ez*ez)-radius; +- const double floorT=segment.horizontalLengthSq>1.0e-12 +- ?projectionXY/segment.horizontalLengthSq:t; +- const double floorTClamped=std::clamp(floorT,0.0,1.0); + const double floorCenterDistanceSq=ex*ex+ey*ey+ez*ez; +- const double floorRadius=segment.radiusA +- +floorTClamped*segment.radiusDelta; +- const double floorDepth=FStandaloneShapeWorld::PassageFlatFloorDepthSubvoxels( +- constants,segmentIndex,floorTClamped,floorRadius,qPerMetre); +- const double floorCenterZ= +- FStandaloneShapeWorld::PassageFlatFloorCenterZSubvoxels( +- constants,segments,segmentIndex,floorT,segment, +- qx,qy,floorDepth,qPerMetre); ++ double floorT=0.0,floorTClamped=0.0,floorDepth=0.0,floorCenterZ=0.0; ++ if(segment.horizontalLengthSq>1.0e-12) ++ { ++ if(!column.hasFloorProfile) ++ { ++ column.floorT=projectionXY/segment.horizontalLengthSq; ++ column.floorTClamped=std::clamp(column.floorT,0.0,1.0); ++ const double floorRadius=segment.radiusA ++ +column.floorTClamped*segment.radiusDelta; ++ column.floorDepth= ++ FStandaloneShapeWorld::PassageFlatFloorDepthSubvoxels( ++ constants,segmentIndex,column.floorTClamped,floorRadius, ++ qPerMetre); ++ column.floorCenterZ= ++ FStandaloneShapeWorld::PassageFlatFloorCenterZSubvoxels( ++ constants,segments,segmentIndex,column.floorT,segment, ++ qx,qy,column.floorDepth,qPerMetre); ++ column.hasFloorProfile=true; ++ } ++ floorT=column.floorT; ++ floorTClamped=column.floorTClamped; ++ floorDepth=column.floorDepth; ++ floorCenterZ=column.floorCenterZ; ++ } ++ else ++ { ++ floorT=t; ++ floorTClamped=std::clamp(floorT,0.0,1.0); ++ const double floorRadius=segment.radiusA ++ +floorTClamped*segment.radiusDelta; ++ floorDepth=FStandaloneShapeWorld::PassageFlatFloorDepthSubvoxels( ++ constants,segmentIndex,floorTClamped,floorRadius,qPerMetre); ++ floorCenterZ= ++ FStandaloneShapeWorld::PassageFlatFloorCenterZSubvoxels( ++ constants,segments,segmentIndex,floorT,segment, ++ qx,qy,floorDepth,qPerMetre); ++ } + const double flatDistance=FStandaloneShapeWorld::PassageFlatBottomDistance( + static_cast(signedDistance),floorCenterZ,qz,floorDepth,qPerMetre); + if(profile)++profileStats_->passageSweepSegmentSamplePairs; +@@ -11557,10 +11772,6 @@ inline void FStandaloneShapeWorld::FScopedPassageTileQueries::prepareSweptTubeBa + { + if(profile)++profileStats_->passageSweepOutsideInfluencePairs; + } +- const std::size_t sampleIndex=(static_cast(gz) +- *static_cast(sweep->dimension)+static_cast(gy)) +- *static_cast(sweep->dimension)+static_cast(gx); +- auto& sample=passageSamples.samples[sampleIndex]; + if(floorCenterDistanceSq dict: + OUT.mkdir(parents=True, exist_ok=True) + label = f"owner4-w{workers}-{compiler}" + log = OUT / f"{label}.log" + layout = OUT / f"{label}.layout.json" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1740s", str(BINARIES[compiler]), str(DATA), + "--workers=" + str(workers), "--world-assembler-prototype", "--stream-benchmark", + "--stream-pipeline", "--force-generate", "--clip-radius=3", + "--max-clip-level=8", "--max-level=8", "--stream-hash", + f"--resolved-layout-output={layout}", + ] + started = time.monotonic() + with log.open("w", encoding="utf-8") as stream: + result = subprocess.run(command, cwd=ROOT, stdout=stream, + stderr=subprocess.STDOUT, check=False, timeout=1740) + content = log.read_text(encoding="utf-8", errors="replace") + hashes = HASH.findall(content) + if result.returncode or len(hashes) != 12: + raise SystemExit(f"hash run failed or incomplete: {label}; exit={result.returncode} " + f"hashes={len(hashes)} log={log}") + row = {"workers": workers, "compiler": compiler, "exit_code": result.returncode, + "hashes": hashes, + "source_stamp": (STAMP.search(content).group(1) if STAMP.search(content) else None), + "elapsed_s": round(time.monotonic() - started, 3), + "log": str(log.relative_to(ROOT))} + print("[L118HashRun] " + json.dumps(row, sort_keys=True), flush=True) + return row + + +def main() -> int: + if not DATA.is_file() or not BASELINE.is_file() or any(not path.is_file() + for path in BINARIES.values()): + raise SystemExit("missing L118 hash input or L115 reference") + reference = json.loads(BASELINE.read_text(encoding="utf-8"))["runs"] + reference = [row for row in reference if row["dataset"] == "owner4" + and row["recipe"] == "surface-world"] + rows = [run(workers, compiler) for workers in (1, 8, 12) + for compiler in ("clang", "gcc")] + comparisons = [] + for row in rows: + matches = [old for old in reference if old["workers"] == row["workers"] + and old["compiler"] == row["compiler"]] + if len(matches) != 1: + raise SystemExit(f"expected one L115 reference for W{row['workers']}/{row['compiler']}") + match = row["hashes"] == matches[0]["hashes"] + comparisons.append({"workers": row["workers"], "compiler": row["compiler"], + "matches_l115": match, "l115_log": matches[0]["log"], + "l118_log": row["log"]}) + if not match: + raise SystemExit(f"L118 hash mismatch versus L115 at W{row['workers']}/{row['compiler']}") + summary = {"runs": rows, "comparisons": comparisons, + "l115_hashes_identical": len({tuple(r["hashes"]) for r in reference}) == 1, + "candidate_matches_l115_all_workers_and_compilers": True} + (OUT / "summary.json").write_text(json.dumps(summary, indent=2) + "\n", + encoding="utf-8") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux118/RunL118PassageCounters.py b/Standalone/Research/WorldAssemblerM3/Linux118/RunL118PassageCounters.py new file mode 100644 index 0000000..bf31819 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux118/RunL118PassageCounters.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python3 +"""Collect two W8 passage-tile counter profiles per owner stratum.""" +from __future__ import annotations + +import json +import re +import subprocess +import time +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / "Saved/Linux/l118/passage-counters" +DATA = ROOT / "Standalone/data/owner_world.json" +BINARY = ROOT / "Saved/Linux/l118/bin/VoxelForgeCoreHeadless-l118-clang" +CAMERAS = { + 0: (8.0, 16.0, -372.2626953125), + 1: (25.8369140625, 3.19921875, -737.0), + 2: (19.166015625, -14.2001953125, -753.3740234375), + 3: (-20.0625, -5.068359375, -900.353515625), +} +FIELDS = re.compile(r"([a-zA-Z0-9_]+)=([^ ]+)") + + +def rows(path: Path, tag: str) -> dict[str, dict[str, str]]: + result = {} + for line in path.read_text(encoding="utf-8", errors="replace").splitlines(): + if line.startswith(tag + " "): + field = dict(FIELDS.findall(line)) + result[field["key"]] = field + return result + + +def run(strate: int, replicate: int) -> dict: + OUT.mkdir(parents=True, exist_ok=True) + label = f"s{strate}-w8-profile{replicate}" + log = OUT / f"{label}.log" + camera = ",".join(f"{value:.12f}" for value in CAMERAS[strate]) + ",0,0" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1740s", str(BINARY), str(DATA), + "--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline", + "--workers=8", "--clip-radius=3", "--max-clip-level=8", "--max-level=8", + f"--camera={camera}", "--profile-lod-work", "--profile-passage-composer", + ] + started = time.monotonic() + with log.open("w", encoding="utf-8") as stream: + result = subprocess.run(command, cwd=ROOT, stdout=stream, + stderr=subprocess.STDOUT, check=False, timeout=1740) + if result.returncode: + raise SystemExit(f"passage-counter profile failed: {log}; exit={result.returncode}") + composer = rows(log, "[PassageComposerTile]") + stages = rows(log, "[CpuTileStages]") + selected = [] + for key, comp in composer.items(): + lod = int(key.rsplit("lod", 1)[1].rstrip(")")) + if lod > 2 or int(comp["features"]) == 0: + continue + stage = stages.get(key) + if stage is None: + raise SystemExit(f"missing CpuTileStages record for {label} {key}") + fallbacks = [int(value) for value in stage["sweep_exact_fallback_by_caller"].split(",")] + selected.append({ + "features": int(comp["features"]), + "sweep_pairs": int(comp["sweep_pairs"]), + "sweep_bound_pruned": int(comp.get("sweep_bound_pruned", "0")), + "exact_fallbacks": sum(fallbacks), + "segment_visits": int(comp["carve_segment_visits"]), + }) + total = {name: sum(item[name] for item in selected) + for name in ("sweep_pairs", "sweep_bound_pruned", "exact_fallbacks", "segment_visits")} + row = {"strate": strate, "workers": 8, "replicate": replicate, + "passage_tiles_lod02": len(selected), "totals": total, + "elapsed_s": round(time.monotonic() - started, 3), + "log": str(log.relative_to(ROOT))} + print("[L118PassageCounters] " + json.dumps(row, sort_keys=True), flush=True) + return row + + +def main() -> int: + if not DATA.is_file() or not BINARY.is_file(): + raise SystemExit("missing owner data or L118 Clang binary") + result = [run(strate, replicate) for strate in range(4) for replicate in (1, 2)] + summary = [] + for strate in range(4): + group = [item for item in result if item["strate"] == strate] + summary.append({"strate": strate, "workers": 8, "replicates": len(group), + "passage_tiles_lod02_median": sorted( + row["passage_tiles_lod02"] for row in group)[len(group) // 2], + "totals_mean": {name: sum(row["totals"][name] for row in group) / len(group) + for name in group[0]["totals"]}}) + (OUT / "summary.json").write_text( + json.dumps({"runs": result, "summary": summary}, indent=2) + "\n", + encoding="utf-8") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux118/RunL118TagProbe.py b/Standalone/Research/WorldAssemblerM3/Linux118/RunL118TagProbe.py new file mode 100644 index 0000000..e94caca --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux118/RunL118TagProbe.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python3 +"""Collect opt-in L118 field timing tags for one W1 view per owner stratum.""" +from __future__ import annotations + +import json +import os +import re +import subprocess +import time +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / "Saved/Linux/l118/tag-probe" +DATA = ROOT / "Standalone/data/owner_world.json" +BINARY = ROOT / "Saved/Linux/l118/bin/VoxelForgeCoreHeadless-l118-clang" +CAMERAS = { + 0: (8.0, 16.0, -372.2626953125), + 1: (25.8369140625, 3.19921875, -737.0), + 2: (19.166015625, -14.2001953125, -753.3740234375), + 3: (-20.0625, -5.068359375, -900.353515625), +} +TAGS = re.compile(r"^\[L118FieldTags\] (.*)$", re.M) +PASSAGE = re.compile(r"^\[PassageComposerTile\] (.*)$", re.M) +FIELDS = re.compile(r"([a-zA-Z0-9_]+)=([^ ]+)") + + +def run(strate: int) -> dict: + OUT.mkdir(parents=True, exist_ok=True) + label = f"s{strate}-w1-tags" + log = OUT / f"{label}.log" + camera = ",".join(f"{value:.12f}" for value in CAMERAS[strate]) + ",0,0" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1740s", str(BINARY), str(DATA), + "--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline", + "--workers=1", "--clip-radius=3", "--max-clip-level=8", "--max-level=8", + f"--camera={camera}", "--profile-lod-work", "--profile-passage-composer", + ] + started = time.monotonic() + env = dict(os.environ, VOXELFORGE_L118_TAG_TIMING="1") + with log.open("w", encoding="utf-8") as stream: + result = subprocess.run(command, cwd=ROOT, env=env, stdout=stream, + stderr=subprocess.STDOUT, check=False, timeout=1740) + content = log.read_text(encoding="utf-8", errors="replace") + tags = [dict(FIELDS.findall(match)) for match in TAGS.findall(content)] + passage = [dict(FIELDS.findall(match)) for match in PASSAGE.findall(content)] + if result.returncode or not tags or not passage: + raise SystemExit(f"tag probe failed or emitted no tags: {log}; exit={result.returncode}") + feature_keys = { + row["key"] for row in passage + if int(row["key"].rsplit("lod", 1)[1].rstrip(")")) <= 2 + and int(row["features"]) > 0 + } + near = [row for row in tags if row["key"] in feature_keys] + totals = { + "passage_feature_tiles": len(near), + "sweep_prepare_ms": sum(float(row["sweep_prepare_ms"]) for row in near), + "smoothmin_calls": sum(int(row["smoothmin_calls"]) for row in near), + "smoothmin_ms_est": sum(float(row["smoothmin_ms_est"]) for row in near), + "point_ms_est": sum(float(row["point_ms_est"]) for row in near), + "cached_column_ms_est": sum(float(row["cached_column_ms_est"]) for row in near), + "shared_initial_read_ms_est": sum( + float(row["shared_initial_read_ms_est"]) for row in near), + "shared_locked_read_ms_est": sum( + float(row["shared_locked_read_ms_est"]) for row in near), + } + row = {"strate": strate, "workers": 1, "elapsed_s": round(time.monotonic() - started, 3), + "tagged_tiles": len(tags), "near_lod02_feature_tiles": totals, + "log": str(log.relative_to(ROOT))} + print("[L118TagProbe] " + json.dumps(row, sort_keys=True), flush=True) + return row + + +def main() -> int: + if not DATA.is_file() or not BINARY.is_file(): + raise SystemExit("missing owner data or L118 Clang binary") + rows = [run(strate) for strate in range(4)] + (OUT / "summary.json").write_text(json.dumps(rows, indent=2) + "\n", + encoding="utf-8") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux118/RunL118Timing.py b/Standalone/Research/WorldAssemblerM3/Linux118/RunL118Timing.py new file mode 100644 index 0000000..b4777b6 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux118/RunL118Timing.py @@ -0,0 +1,142 @@ +#!/usr/bin/env python3 +"""Five interleaved L80 readiness runs for L109, L115, and L118.""" +from __future__ import annotations + +import json +import os +import re +import statistics +import subprocess +import time +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / "Saved/Linux/l118/timing" +DATA = ROOT / "Standalone/data/owner_world.json" +BINARIES = { + "L109": ROOT / "Saved/Linux/l109/bin-final/VoxelForgeCoreHeadless-l109-clang", + "L115": ROOT / "Saved/Linux/l115/bin/VoxelForgeCoreHeadless-l115-clang", + "L118": ROOT / "Saved/Linux/l118/bin/VoxelForgeCoreHeadless-l118-clang", +} +CAMERAS = { + 0: (8.0, 16.0, -372.2626953125), + 1: (25.8369140625, 3.19921875, -737.0), + 2: (19.166015625, -14.2001953125, -753.3740234375), + 3: (-20.0625, -5.068359375, -900.353515625), +} +PIPELINE = re.compile(r"^\[StreamPipeline\] (.*)$", re.M) +FIELDS = re.compile(r"([a-zA-Z0-9_]+)=([^ ]+)") +NEAR = re.compile( + r"^\[WorldAssemblerNearLODReady\] lods=0-2 tiles=(\d+)/(\d+) cold_ready_s=([0-9.]+)$", + re.M, +) + + +def run(strate: int, workers: int, version: str, phase: str, replicate: int) -> dict: + OUT.mkdir(parents=True, exist_ok=True) + label = f"s{strate}-w{workers}-{version}-{phase}{replicate}" + log = OUT / f"{label}.log" + camera = ",".join(f"{value:.12f}" for value in CAMERAS[strate]) + ",0,0" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1740s", str(BINARIES[version]), str(DATA), + "--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline", + f"--workers={workers}", "--clip-radius=3", "--max-clip-level=8", "--max-level=8", + f"--camera={camera}", "--profile-lod-work", "--stream-scheduler-policy=3", + ] + started = time.monotonic() + with log.open("w", encoding="utf-8") as output: + result = subprocess.run(command, cwd=ROOT, stdout=output, + stderr=subprocess.STDOUT, check=False, timeout=1740) + content = log.read_text(encoding="utf-8", errors="replace") + pipeline_match = PIPELINE.search(content) + near_match = NEAR.search(content) + if result.returncode or pipeline_match is None or near_match is None: + raise SystemExit(f"readiness run failed or trace missing: {log}; exit={result.returncode}") + pipeline = dict(FIELDS.findall(pipeline_match.group(1))) + row = { + "strate": strate, "workers": workers, "version": version, + "phase": phase, "replicate": replicate, "exit_code": result.returncode, + "wall_s": round(time.monotonic() - started, 3), + "lod02_ready_s": float(near_match.group(3)), + "whole_view_ready_s": float(pipeline["whole_view_ready"].removesuffix("s")), + "whole_tiles": int(pipeline["whole_tiles"].split("/")[0]), + "log": str(log.relative_to(ROOT)), + } + print("[L118TimingRun] " + json.dumps(row, sort_keys=True), flush=True) + return row + + +def cpu_idle_percent(interval_s: float = 2.0) -> float: + def totals() -> tuple[int, int]: + fields = Path("/proc/stat").read_text(encoding="utf-8").splitlines()[0].split() + values = [int(value) for value in fields[1:]] + return sum(values), values[3] + (values[4] if len(values) > 4 else 0) + + total_before, idle_before = totals() + time.sleep(interval_s) + total_after, idle_after = totals() + total_delta = max(1, total_after - total_before) + return 100.0 * (idle_after - idle_before) / total_delta + + +def main() -> int: + if not DATA.is_file() or any(not binary.is_file() for binary in BINARIES.values()): + raise SystemExit("missing L109/L115/L118 timing input") + OUT.mkdir(parents=True, exist_ok=True) + load_1m = os.getloadavg()[0] + idle_pct = cpu_idle_percent() + uptime = subprocess.run(["uptime"], cwd=ROOT, text=True, capture_output=True, + check=True).stdout.strip() + top = subprocess.run(["ps", "-eo", "pid,pcpu,comm", "--sort=-pcpu"], cwd=ROOT, + text=True, capture_output=True, check=True).stdout + (OUT / "machine-load-before.txt").write_text( + f"uptime: {uptime}\n1-minute load: {load_1m:.2f}\n" + f"2-second CPU idle: {idle_pct:.1f}%\ntop CPU users:\n{top}", + encoding="utf-8") + print(f"[L118TimingGate] load_1m={load_1m:.2f} cpu_idle_2s={idle_pct:.1f}% " + f"uptime={uptime}", flush=True) + if load_1m >= 0.9: + raise SystemExit(f"timing refused: 1-minute load {load_1m:.2f} is not below 0.9") + if idle_pct < 97.0: + raise SystemExit(f"timing refused: CPU idle {idle_pct:.1f}% is below 97%") + rows = [] + versions = ("L109", "L115", "L118") + for strate in range(4): + for workers in (8, 12): + for version in versions: + run(strate, workers, version, "warmup", 0) + for replicate in range(1, 6): + offset = (replicate - 1) % len(versions) + order = versions[offset:] + versions[:offset] + for version in order: + rows.append(run(strate, workers, version, "measured", replicate)) + (OUT / "runs-partial.json").write_text( + json.dumps(rows, indent=2) + "\n", encoding="utf-8") + summary = [] + for strate in range(4): + for workers in (8, 12): + item = {"strate": strate, "workers": workers, "replicates": 5} + medians = {} + for version in versions: + group = [row for row in rows if row["strate"] == strate + and row["workers"] == workers and row["version"] == version] + medians[version] = {} + for key in ("lod02_ready_s", "whole_view_ready_s"): + values = [row[key] for row in group] + medians[version][key] = statistics.median(values) + item[f"{version}_{key}_values"] = values + item[f"{version}_{key}_median"] = medians[version][key] + for comparison in ("L109", "L115"): + for key in ("lod02_ready_s", "whole_view_ready_s"): + item[f"L118_vs_{comparison}_{key}_delta_pct"] = round( + 100.0 * (medians["L118"][key] / medians[comparison][key] - 1.0), 2) + summary.append(item) + (OUT / "summary.json").write_text( + json.dumps({"runs": rows, "summary": summary}, indent=2) + "\n", + encoding="utf-8") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux118/l118-designs.patch b/Standalone/Research/WorldAssemblerM3/Linux118/l118-designs.patch new file mode 100644 index 0000000..be89dca --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux118/l118-designs.patch @@ -0,0 +1,557 @@ +diff --git a/Standalone/Core/include/VoxelForgeCore/SharedColumnCache.h b/Standalone/Core/include/VoxelForgeCore/SharedColumnCache.h +index cbb0885..3784247 100644 +--- a/Standalone/Core/include/VoxelForgeCore/SharedColumnCache.h ++++ b/Standalone/Core/include/VoxelForgeCore/SharedColumnCache.h +@@ -2,6 +2,7 @@ + + #include "VoxelForgeCore/CpuCycleCounter.h" + ++#include + #include + #include + #include +@@ -24,12 +25,15 @@ namespace VoxelForgeCoreShared + std::uint64_t lockWaitNanoseconds = 0; + std::uint64_t sampledInitialReadCycles = 0; + std::uint64_t sampledInitialReads = 0; ++ std::uint64_t sampledInitialReadNanoseconds = 0; + std::uint64_t sampledLockedReadCycles = 0; + std::uint64_t sampledLockedReads = 0; ++ std::uint64_t sampledLockedReadNanoseconds = 0; + std::uint64_t sampledLockCycles = 0; + std::uint64_t sampledLocks = 0; + std::uint64_t sampledBuildCycles = 0; + std::uint64_t sampledBuilds = 0; ++ bool captureNanoseconds = false; + }; + + // Exact input identity for a pure XY column value. LOD is deliberately not part of this key: +@@ -140,12 +144,19 @@ namespace VoxelForgeCoreShared + static thread_local std::uint64_t timingSequence=0; + const bool sampleCycles=metrics&&((++timingSequence&127u)==0); + const std::uint64_t initialReadStart=sampleCycles?ReadCpuCycles():0; ++ const auto initialReadStartNs=sampleCycles&&metrics->captureNanoseconds ++ ?std::chrono::steady_clock::now():std::chrono::steady_clock::time_point{}; + const bool initialHit=TryReadSet(set, keyWords, tag, value); + if(sampleCycles) + { + metrics->sampledInitialReadCycles+=AdjustedCpuCycleDelta( + initialReadStart,ReadCpuCycles()); + ++metrics->sampledInitialReads; ++ if(metrics->captureNanoseconds) ++ metrics->sampledInitialReadNanoseconds+=static_cast( ++ std::max(0,std::chrono::duration_cast< ++ std::chrono::nanoseconds>(std::chrono::steady_clock::now() ++ -initialReadStartNs).count())); + } + if (initialHit) + { +@@ -156,12 +167,19 @@ namespace VoxelForgeCoreShared + + FSpinGuard lock(set.Writer, metrics,sampleCycles); + const std::uint64_t lockedReadStart=sampleCycles?ReadCpuCycles():0; ++ const auto lockedReadStartNs=sampleCycles&&metrics->captureNanoseconds ++ ?std::chrono::steady_clock::now():std::chrono::steady_clock::time_point{}; + const bool lockedHit=TryReadSet(set, keyWords, tag, value); + if(sampleCycles) + { + metrics->sampledLockedReadCycles+=AdjustedCpuCycleDelta( + lockedReadStart,ReadCpuCycles()); + ++metrics->sampledLockedReads; ++ if(metrics->captureNanoseconds) ++ metrics->sampledLockedReadNanoseconds+=static_cast( ++ std::max(0,std::chrono::duration_cast< ++ std::chrono::nanoseconds>(std::chrono::steady_clock::now() ++ -lockedReadStartNs).count())); + } + if (lockedHit) + { +diff --git a/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h b/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h +index ac27df1..ad6e8c2 100644 +--- a/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h ++++ b/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h +@@ -147,6 +147,7 @@ namespace VoxelForgeCore + // by the opt-in passage composer profile, except the mesh composition itself. + std::uint64_t passageSweepRouteSegmentCandidates = 0; + std::uint64_t passageSweepSegmentSamplePairs = 0; ++ std::uint64_t passageSweepBoundPrunedPairs = 0; + std::uint64_t passageSweepOutsideInfluencePairs = 0; + std::uint64_t passageSweepMinimumUpdates = 0; + std::uint64_t passageSweepBaseInfluenceSamples = 0; +@@ -158,6 +159,19 @@ namespace VoxelForgeCore + std::uint64_t passageSweepBaseInfluenceHits = 0; + std::uint64_t passageSweepOutOfInfluenceHits = 0; + std::uint64_t passageSweepMissingSamples = 0; ++ double passageSweepPrepareMilliseconds = 0.0; ++ std::uint64_t passageSmoothMinCalls = 0; ++ std::uint64_t passageSmoothMinSampledNanoseconds = 0; ++ std::uint64_t passageSmoothMinSamples = 0; ++ std::uint64_t heightfieldPointSampledNanoseconds = 0; ++ std::uint64_t heightfieldPointSamples = 0; ++ std::uint64_t heightfieldCachedColumnSampledNanoseconds = 0; ++ std::uint64_t heightfieldCachedColumnSamples = 0; ++ std::uint64_t heightfieldSharedInitialReadSampledNanoseconds = 0; ++ std::uint64_t heightfieldSharedInitialReadSamples = 0; ++ std::uint64_t heightfieldSharedLockedReadSampledNanoseconds = 0; ++ std::uint64_t heightfieldSharedLockedReadSamples = 0; ++ bool l118FieldTagsCaptured = false; + std::array passageSweepMissingLookupsByCaller{}; + std::array passageSweepExactRouteFallbacksByCaller{}; + std::array passageSweepFeatureBoundSkipsByCaller{}; +@@ -1394,6 +1408,16 @@ namespace VoxelForgeCore + std::uint64_t sharedColumnHits = 0; + std::uint64_t columnEvaluations = 0; + double columnComputeMilliseconds = 0.0; ++ // L118 opt-in, one-in-128 sampled timings. Nanoseconds are accumulated only for ++ // sampled calls; report estimates multiply by 128. ++ std::uint64_t sampledPointNanoseconds = 0; ++ std::uint64_t sampledPointCalls = 0; ++ std::uint64_t sampledCachedColumnNanoseconds = 0; ++ std::uint64_t sampledCachedColumnCalls = 0; ++ std::uint64_t sampledSharedInitialReadNanoseconds = 0; ++ std::uint64_t sampledSharedInitialReads = 0; ++ std::uint64_t sampledSharedLockedReadNanoseconds = 0; ++ std::uint64_t sampledSharedLockedReads = 0; + bool captureCoordinates = false; + bool coordinateCaptureComplete = true; + std::vector evaluatedCoordinates; +diff --git a/Standalone/Core/src/ShapeWorldInternal.h b/Standalone/Core/src/ShapeWorldInternal.h +index c266bd8..4782980 100644 +--- a/Standalone/Core/src/ShapeWorldInternal.h ++++ b/Standalone/Core/src/ShapeWorldInternal.h +@@ -72,6 +72,14 @@ static bool VF_IsL98PassagePrepareTraceEnabled() + return bEnabled; + } + ++static bool VF_IsL118TagTimingEnabled() ++{ ++ static const bool bEnabled=VF_IsL88DiagnosticSwitchEnabled( ++ "VOXELFORGE_L118_TAG_TIMING"); ++ return bEnabled; ++} ++static thread_local std::uint64_t VF_L118SmoothMinTimingSequence=0; ++ + static double VF_L93PassageCarveReachMetres() + { + // The generated world uses a fixed bounded tube influence. An explicit diagnostic +@@ -289,6 +297,8 @@ public: + std::vector passages; + std::atomic lookups{0},cacheHits{0},baseInfluenceHits{0}, + outOfInfluenceHits{0},missingSamples{0}; ++ std::atomic smoothMinCalls{0},smoothMinSampledNanoseconds{0}, ++ smoothMinSamples{0}; + std::array,PassageDensityQueryCallerCount> + missingLookupsByCaller{},exactRouteFallbacksByCaller{}, + featureBoundSkipsByCaller{},tileFreeSkipsByCaller{}, +@@ -376,6 +386,17 @@ public: + const FPassageSweepSample* sweptSample(std::size_t passageIndex, + double qx,double qy,double qz) const; + bool hasSweptTubeBase() const noexcept{return passageSweepData_!=nullptr;} ++ void recordSmoothMinTiming(std::uint64_t nanoseconds,bool sampled) const noexcept ++ { ++ if(!profileStats_||!passageSweepData_)return; ++ passageSweepData_->smoothMinCalls.fetch_add(1,std::memory_order_relaxed); ++ if(sampled) ++ { ++ passageSweepData_->smoothMinSampledNanoseconds.fetch_add( ++ nanoseconds,std::memory_order_relaxed); ++ passageSweepData_->smoothMinSamples.fetch_add(1,std::memory_order_relaxed); ++ } ++ } + void copySweptTubeRuntimeCounts() const noexcept + { + if(!ownsPassageSweepDiagnostics_||!profileStats_||!passageSweepData_)return; +@@ -389,6 +410,13 @@ public: + passageSweepData_->outOfInfluenceHits.load(std::memory_order_relaxed); + profileStats_->passageSweepMissingSamples=passageSweepData_->missingSamples.load( + std::memory_order_relaxed); ++ profileStats_->passageSmoothMinCalls=passageSweepData_->smoothMinCalls.load( ++ std::memory_order_relaxed); ++ profileStats_->passageSmoothMinSampledNanoseconds= ++ passageSweepData_->smoothMinSampledNanoseconds.load( ++ std::memory_order_relaxed); ++ profileStats_->passageSmoothMinSamples=passageSweepData_->smoothMinSamples.load( ++ std::memory_order_relaxed); + for(std::size_t caller=0;callerpassageSweepMissingLookupsByCaller[caller]= +@@ -1298,12 +1326,19 @@ public: + const double ex=qx-cx,ey=qy-cy,ez=qz-cz; + const double roundDistance=DeterministicSqrt( + ex*ex+ey*ey+ez*ez)-radius; ++ const double floorCenterDistanceSq=ex*ex+ey*ey+ez*ez; ++ const bool floorWins=floorCenterDistanceSq1.0e-12 + ?(((qx-segment.a[0])*segment.delta[0] + +(qy-segment.a[1])*segment.delta[1]) + /segment.horizontalLengthSq):t; + const double floorTClamped=std::clamp(floorT,0.0,1.0); +- const double floorCenterDistanceSq=ex*ex+ey*ey+ez*ez; + const double floorRadius=segment.radiusA + +floorTClamped*segment.radiusDelta; + const double floorDepth=PassageFlatFloorDepthSubvoxels( +@@ -1311,13 +1346,9 @@ public: + const double floorCenterZ=PassageFlatFloorCenterZSubvoxels( + constants,segments,segmentIndex,floorT,segment, + qx,qy,floorDepth,qPerMetre); +- const double flatDistance=PassageFlatBottomDistance( +- static_cast(roundDistance),floorCenterZ,qz,floorDepth,qPerMetre); + // The profile uses the closest route projection's arc length. Tube + // radius selects the bore shape only; it never selects floor height. +- if(floorCenterDistanceSq(roundDistance),floorCenterZ,qz,floorDepth, ++ qPerMetre); + bestDistance=roundDistance; + nearest.signedDistance=flatDistance; + nearest.roundSignedDistance=roundDistance; +@@ -6929,12 +6961,31 @@ private: + static float SmoothMinDistance(float A,float B,float Width) + { + FScopedLegacySmoothMinTimer SmoothMinTimer; ++ const auto* tagScope=VF_IsL118TagTimingEnabled() ++ ?ActivePassageTileQueries:nullptr; ++ const bool tag=tagScope&&tagScope->profileStats() ++ &&tagScope->hasSweptTubeBase(); ++ const bool sampled=tag&&((++VF_L118SmoothMinTimingSequence&127u)==0); ++ const auto tagStart=sampled?std::chrono::steady_clock::now() ++ :std::chrono::steady_clock::time_point{}; ++ const auto recordTag=[&]() ++ { ++ if(!tag)return; ++ const std::uint64_t elapsed=sampled?static_cast(std::max(0, ++ std::chrono::duration_cast( ++ std::chrono::steady_clock::now()-tagStart).count())):0; ++ tagScope->recordSmoothMinTiming(elapsed,sampled); ++ }; + if(Width<=0.0f) + { +- return std::min(A,B); ++ const float result=std::min(A,B); ++ recordTag(); ++ return result; + } + const float H=std::max(Width-std::abs(A-B),0.0f)/Width; +- return std::min(A,B)-(H*H*H)*(Width/6.0f); ++ const float result=std::min(A,B)-(H*H*H)*(Width/6.0f); ++ recordTag(); ++ return result; + } + static float SmoothMaxDistance(float A,float B,float Width) + {return -SmoothMinDistance(-A,-B,Width);} +@@ -11464,6 +11515,9 @@ inline void FStandaloneShapeWorld::FScopedPassageTileQueries::prepareSweptTubeBa + const double wallReliefShell=0.41*qPerMetre; + const double floorDetailShell=1.0*qPerMetre; + const bool profile=profileStats_!=nullptr; ++ const bool tagTiming=profile&&VF_IsL118TagTimingEnabled(); ++ const auto tagStart=tagTiming?std::chrono::steady_clock::now() ++ :std::chrono::steady_clock::time_point{}; + if(profile) + { + profileStats_->passageSweepRouteSegmentCandidates=routeSegmentCandidateCount_; +@@ -11527,6 +11581,31 @@ inline void FStandaloneShapeWorld::FScopedPassageTileQueries::prepareSweptTubeBa + ||qy>segment.sweepMaximumSubvoxels[1] + ||qzsegment.sweepMaximumSubvoxels[2])continue; ++ const std::size_t sampleIndex=(static_cast(gz) ++ *static_cast(sweep->dimension)+static_cast(gy)) ++ *static_cast(sweep->dimension)+static_cast(gx); ++ auto& sample=passageSamples.samples[sampleIndex]; ++ const double boundDx=std::max({std::min(segment.a[0],segment.b[0])-qx, ++ 0.0,qx-std::max(segment.a[0],segment.b[0])}); ++ const double boundDy=std::max({std::min(segment.a[1],segment.b[1])-qy, ++ 0.0,qy-std::max(segment.a[1],segment.b[1])}); ++ const double boundDz=std::max({std::min(segment.a[2],segment.b[2])-qz, ++ 0.0,qz-std::max(segment.a[2],segment.b[2])}); ++ const double centerDistanceLowerBoundSq=boundDx*boundDx ++ +boundDy*boundDy+boundDz*boundDz; ++ const double roundDistanceLowerBound=FStandaloneShapeWorld::DeterministicSqrt( ++ centerDistanceLowerBoundSq)-std::max(segment.radiusA,segment.radiusB); ++ const bool couldImproveRound=!sample.valid ++ ||roundDistanceLowerBound<=sample.roundSignedDistance; ++ const bool couldImproveFloor=centerDistanceLowerBoundSq ++ <=sample.floorCenterDistanceSq; ++ const bool couldContributeShell=roundDistanceLowerBound<=shellThickness; ++ if(!couldImproveRound&&!couldImproveFloor&&!couldContributeShell) ++ { ++ if(profile)++profileStats_->passageSweepBoundPrunedPairs; ++ continue; ++ } ++ if(profile)++profileStats_->passageSweepSegmentSamplePairs; + const double projectionXY=(qx-segment.a[0])*segment.delta[0] + +(qy-segment.a[1])*segment.delta[1]; + const double t=std::clamp((projectionXY +@@ -11552,15 +11631,10 @@ inline void FStandaloneShapeWorld::FScopedPassageTileQueries::prepareSweptTubeBa + qx,qy,floorDepth,qPerMetre); + const double flatDistance=FStandaloneShapeWorld::PassageFlatBottomDistance( + static_cast(signedDistance),floorCenterZ,qz,floorDepth,qPerMetre); +- if(profile)++profileStats_->passageSweepSegmentSamplePairs; + if(signedDistance>sweep->influenceSubvoxels) + { + if(profile)++profileStats_->passageSweepOutsideInfluencePairs; + } +- const std::size_t sampleIndex=(static_cast(gz) +- *static_cast(sweep->dimension)+static_cast(gy)) +- *static_cast(sweep->dimension)+static_cast(gx); +- auto& sample=passageSamples.samples[sampleIndex]; + if(floorCenterDistanceSq(std::count(anyPassageInfluence.begin(), + anyPassageInfluence.end(),static_cast(0))); + } ++ if(tagTiming) ++ profileStats_->passageSweepPrepareMilliseconds= ++ std::chrono::duration( ++ std::chrono::steady_clock::now()-tagStart).count(); + passageSweepData_=std::move(sweep); + } + +diff --git a/Standalone/Core/src/VoxelForgeCore.cpp b/Standalone/Core/src/VoxelForgeCore.cpp +index b139ec4..a25049d 100644 +--- a/Standalone/Core/src/VoxelForgeCore.cpp ++++ b/Standalone/Core/src/VoxelForgeCore.cpp +@@ -2444,6 +2444,28 @@ namespace VoxelForgeCore + FStandaloneShapeWorld::SetThreadDensityQueryProfileEnabled(options.instrumentTileDrain); + VoxelForgeCore::Heightfield2D::resetThreadColumnCacheStats( + options.captureColumnCoordinates); ++ const auto copyL118FieldTags=[&]() ++ { ++ if(!options.profilePassageComposer ++ ||!world_assembly_detail::L118FieldTagTimingEnabled())return; ++ const auto& Columns=VoxelForgeCore::Heightfield2D::threadColumnCacheStats(); ++ out.diagnostics.l118FieldTagsCaptured=true; ++ out.diagnostics.heightfieldPointSampledNanoseconds= ++ Columns.sampledPointNanoseconds; ++ out.diagnostics.heightfieldPointSamples=Columns.sampledPointCalls; ++ out.diagnostics.heightfieldCachedColumnSampledNanoseconds= ++ Columns.sampledCachedColumnNanoseconds; ++ out.diagnostics.heightfieldCachedColumnSamples= ++ Columns.sampledCachedColumnCalls; ++ out.diagnostics.heightfieldSharedInitialReadSampledNanoseconds= ++ Columns.sampledSharedInitialReadNanoseconds; ++ out.diagnostics.heightfieldSharedInitialReadSamples= ++ Columns.sampledSharedInitialReads; ++ out.diagnostics.heightfieldSharedLockedReadSampledNanoseconds= ++ Columns.sampledSharedLockedReadNanoseconds; ++ out.diagnostics.heightfieldSharedLockedReadSamples= ++ Columns.sampledSharedLockedReads; ++ }; + if(options.captureColumnCoordinates) + { + constexpr std::int64_t SubvoxelsPerVoxel=WorldAssemblySubvoxelsPerVoxel; +@@ -2530,6 +2552,7 @@ namespace VoxelForgeCore + out.diagnostics.classificationExclusiveMilliseconds=std::max(0.0, + Counts.Milliseconds-classificationColumnComputeMilliseconds); + out.diagnostics.columnComputeMilliseconds=Columns.columnComputeMilliseconds; ++ copyL118FieldTags(); + #if defined(VF_L30_ENABLE_COST_COUNTERS) + PrintL30CostCounters(Counts); + #endif +@@ -3128,6 +3151,7 @@ namespace VoxelForgeCore + out.diagnostics.columnEvaluations=Columns.columnEvaluations; + out.diagnostics.columnComputeMilliseconds=Columns.columnComputeMilliseconds; + out.diagnostics.columnEvaluationExclusiveMilliseconds=Columns.columnComputeMilliseconds; ++ copyL118FieldTags(); + out.diagnostics.classificationMilliseconds=Counts.Milliseconds; + out.diagnostics.classificationExclusiveMilliseconds=std::max(0.0, + Counts.Milliseconds-classificationColumnComputeMilliseconds); +diff --git a/Standalone/Core/src/WorldAssemblerInternal.h b/Standalone/Core/src/WorldAssemblerInternal.h +index 07b3c9b..dd7c1d6 100644 +--- a/Standalone/Core/src/WorldAssemblerInternal.h ++++ b/Standalone/Core/src/WorldAssemblerInternal.h +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1798,11 +1799,49 @@ namespace world_assembly_detail + inline thread_local VoxelForgeCoreThreadLocal::FLazy< + std::array> HeightfieldColumnCacheNextWay; + inline thread_local HeightfieldColumnCacheStats HeightfieldColumnStats{}; ++ inline thread_local VoxelForgeCoreShared::FColumnCacheMetrics ++ HeightfieldSharedColumnCacheMetrics{}; ++ inline thread_local std::uint64_t HeightfieldPointTimingSequence=0; ++ inline thread_local std::uint64_t HeightfieldCachedColumnTimingSequence=0; + inline thread_local bool HeightfieldColumnCacheLegacyDirectMapped=false; + inline thread_local std::array HeightfieldColumnCaptureBounds{}; + inline thread_local bool HeightfieldColumnCaptureBoundsValid=false; + inline std::atomic HeightfieldColumnCaptureSequence{0}; + ++ inline bool L118FieldTagTimingEnabled() noexcept ++ { ++ static const bool enabled=[] ++ { ++ const char* value=std::getenv("VOXELFORGE_L118_TAG_TIMING"); ++ return value&&value[0]=='1'&&value[1]=='\0'; ++ }(); ++ return enabled; ++ } ++ ++ struct FScopedHeightfieldSampledTimer ++ { ++ FScopedHeightfieldSampledTimer(std::uint64_t& nanoseconds, ++ std::uint64_t& samples,std::uint64_t& sequence) noexcept ++ :Nanoseconds(nanoseconds),Samples(samples) ++ { ++ if(!L118FieldTagTimingEnabled()||((++sequence&127u)!=0))return; ++ Start=std::chrono::steady_clock::now(); ++ bTimed=true; ++ } ++ ~FScopedHeightfieldSampledTimer() ++ { ++ if(!bTimed)return; ++ Nanoseconds+=static_cast(std::max(0, ++ std::chrono::duration_cast( ++ std::chrono::steady_clock::now()-Start).count())); ++ ++Samples; ++ } ++ std::uint64_t& Nanoseconds; ++ std::uint64_t& Samples; ++ std::chrono::steady_clock::time_point Start{}; ++ bool bTimed=false; ++ }; ++ + inline std::size_t HeightfieldColumnCacheSet(const WorldAssemblyRecipeV1& recipe, + const WorldAssemblyStratumPlanV1& plan,std::int64_t x,std::int64_t y) noexcept + { +@@ -1989,6 +2028,10 @@ namespace world_assembly_detail + inline HeightfieldPointSample CachedColumn(const WorldAssemblyRecipeV1& recipe, + const WorldAssemblyStratumPlanV1& plan,std::int64_t x,std::int64_t y) + { ++ FScopedHeightfieldSampledTimer CachedColumnTimer( ++ HeightfieldColumnStats.sampledCachedColumnNanoseconds, ++ HeightfieldColumnStats.sampledCachedColumnCalls, ++ HeightfieldCachedColumnTimingSequence); + const std::int64_t InterpolationStride=HeightfieldColumnInterpolationStrideSubvoxels; + if(InterpolationStride>0) + { +@@ -2105,7 +2148,10 @@ namespace world_assembly_detail + static_cast(reinterpret_cast(&plan)), + plan.contentHash,x,y}; + bool computed=false; +- column=shared->getOrCompute(key,compute,computed); ++ auto* metrics=L118FieldTagTimingEnabled() ++ ?&HeightfieldSharedColumnCacheMetrics:nullptr; ++ if(metrics)metrics->captureNanoseconds=true; ++ column=shared->getOrCompute(key,compute,computed,metrics); + if(!computed)++HeightfieldColumnStats.sharedColumnHits; + } + else column=compute(); +@@ -2576,6 +2622,10 @@ WorldAssemblyFeatureTileListV1 Heightfield2D::buildFeatureTileList( + HeightfieldPointSample Heightfield2D::point(std::int64_t x, std::int64_t y, + std::int64_t z) const noexcept + { ++ world_assembly_detail::FScopedHeightfieldSampledTimer PointTimer( ++ world_assembly_detail::HeightfieldColumnStats.sampledPointNanoseconds, ++ world_assembly_detail::HeightfieldColumnStats.sampledPointCalls, ++ world_assembly_detail::HeightfieldPointTimingSequence); + HeightfieldPointSample out; + if (!isValid() || world_assembly_detail::OutsideRange(x) + || world_assembly_detail::OutsideRange(y) +@@ -2635,6 +2685,17 @@ void Heightfield2D::resetThreadColumnCacheStats(bool captureCoordinates, bool cl + Stats.sharedColumnHits=0; + Stats.columnEvaluations=0; + Stats.columnComputeMilliseconds=0.0; ++ Stats.sampledPointNanoseconds=0; ++ Stats.sampledPointCalls=0; ++ Stats.sampledCachedColumnNanoseconds=0; ++ Stats.sampledCachedColumnCalls=0; ++ Stats.sampledSharedInitialReadNanoseconds=0; ++ Stats.sampledSharedInitialReads=0; ++ Stats.sampledSharedLockedReadNanoseconds=0; ++ Stats.sampledSharedLockedReads=0; ++ world_assembly_detail::HeightfieldSharedColumnCacheMetrics={}; ++ world_assembly_detail::HeightfieldPointTimingSequence=0; ++ world_assembly_detail::HeightfieldCachedColumnTimingSequence=0; + Stats.captureCoordinates=captureCoordinates; + Stats.coordinateCaptureComplete=true; + Stats.evaluatedCoordinates.clear(); +@@ -2670,7 +2731,15 @@ std::int64_t Heightfield2D::threadColumnInterpolationStrideSubvoxels() noexcept + + + const HeightfieldColumnCacheStats& Heightfield2D::threadColumnCacheStats() noexcept +-{ return world_assembly_detail::HeightfieldColumnStats; } ++{ ++ auto& Stats=world_assembly_detail::HeightfieldColumnStats; ++ const auto& Shared=world_assembly_detail::HeightfieldSharedColumnCacheMetrics; ++ Stats.sampledSharedInitialReadNanoseconds=Shared.sampledInitialReadNanoseconds; ++ Stats.sampledSharedInitialReads=Shared.sampledInitialReads; ++ Stats.sampledSharedLockedReadNanoseconds=Shared.sampledLockedReadNanoseconds; ++ Stats.sampledSharedLockedReads=Shared.sampledLockedReads; ++ return Stats; ++} + + HeightfieldBoxClass Heightfield2D::classifyLatticeBox(std::int64_t minimumX, + std::int64_t minimumY,std::int64_t minimumZ,std::int64_t maximumX, +diff --git a/Standalone/Source/StreamingWorld.h b/Standalone/Source/StreamingWorld.h +index 2964e86..231362b 100644 +--- a/Standalone/Source/StreamingWorld.h ++++ b/Standalone/Source/StreamingWorld.h +@@ -1580,7 +1580,7 @@ private: + static_cast(D.islandSharedCacheConflictReplacements), + static_cast(D.islandSharedCacheLockWaitNanoseconds)/1000.0); + if(D.passageComposerProfiled) +- std::printf("[PassageComposerTile] key=(%d,%d,%d,lod%d) worker_ms=%.3f samples=%llu native_field_calls=%llu features=%llu route_candidates=%llu boundary_band_queries=%llu queries=%llu passage_iterations=%llu carve_segment_visits=%llu relief_field_calls=%llu sweep_segments=%llu sweep_pairs=%llu sweep_outside_pairs=%llu sweep_min_updates=%llu sweep_base_samples=%llu sweep_detail_samples=%llu sweep_grid_samples=%llu sweep_no_influence_samples=%llu sweep_lookups=%llu sweep_cache_hits=%llu sweep_base_hits=%llu sweep_outside_hits=%llu sweep_missing=%llu\n", ++ std::printf("[PassageComposerTile] key=(%d,%d,%d,lod%d) worker_ms=%.3f samples=%llu native_field_calls=%llu features=%llu route_candidates=%llu boundary_band_queries=%llu queries=%llu passage_iterations=%llu carve_segment_visits=%llu relief_field_calls=%llu sweep_segments=%llu sweep_pairs=%llu sweep_bound_pruned=%llu sweep_outside_pairs=%llu sweep_min_updates=%llu sweep_base_samples=%llu sweep_detail_samples=%llu sweep_grid_samples=%llu sweep_no_influence_samples=%llu sweep_lookups=%llu sweep_cache_hits=%llu sweep_base_hits=%llu sweep_outside_hits=%llu sweep_missing=%llu\n", + Event.Key.Coord.X,Event.Key.Coord.Y,Event.Key.Coord.Z,Event.Key.Level, + Event.WorkerMilliseconds,static_cast(Event.DensitySamples), + static_cast(D.fieldCalls), +@@ -1593,6 +1593,7 @@ private: + static_cast(D.passageReliefFieldCalls), + static_cast(D.passageSweepRouteSegmentCandidates), + static_cast(D.passageSweepSegmentSamplePairs), ++ static_cast(D.passageSweepBoundPrunedPairs), + static_cast(D.passageSweepOutsideInfluencePairs), + static_cast(D.passageSweepMinimumUpdates), + static_cast(D.passageSweepBaseInfluenceSamples), +@@ -1604,6 +1605,24 @@ private: + static_cast(D.passageSweepBaseInfluenceHits), + static_cast(D.passageSweepOutOfInfluenceHits), + static_cast(D.passageSweepMissingSamples)); ++ if(D.l118FieldTagsCaptured) ++ std::printf("[L118FieldTags] key=(%d,%d,%d,lod%d) sweep_prepare_ms=%.3f smoothmin_calls=%llu smoothmin_samples=%llu smoothmin_ms_est=%.3f point_samples=%llu point_ms_est=%.3f cached_column_samples=%llu cached_column_ms_est=%.3f shared_initial_read_samples=%llu shared_initial_read_ms_est=%.3f shared_locked_read_samples=%llu shared_locked_read_ms_est=%.3f sample_period=128 overlap=(point_contains_cached_column,cached_column_contains_shared_reads)\n", ++ Event.Key.Coord.X,Event.Key.Coord.Y,Event.Key.Coord.Z,Event.Key.Level, ++ D.passageSweepPrepareMilliseconds, ++ static_cast(D.passageSmoothMinCalls), ++ static_cast(D.passageSmoothMinSamples), ++ D.passageSmoothMinSamples ++ ?static_cast(D.passageSmoothMinSampledNanoseconds)*128.0/1.0e6:0.0, ++ static_cast(D.heightfieldPointSamples), ++ static_cast(D.heightfieldPointSampledNanoseconds)*128.0/1.0e6, ++ static_cast(D.heightfieldCachedColumnSamples), ++ static_cast(D.heightfieldCachedColumnSampledNanoseconds)*128.0/1.0e6, ++ static_cast(D.heightfieldSharedInitialReadSamples), ++ static_cast(D.heightfieldSharedInitialReadSampledNanoseconds) ++ *128.0/1.0e6, ++ static_cast(D.heightfieldSharedLockedReadSamples), ++ static_cast(D.heightfieldSharedLockedReadSampledNanoseconds) ++ *128.0/1.0e6); + } + void RecordTimelineEvent(FStandaloneCpuTileTimelineEvent::EType Type, + const FVoxelTileKey& Key,int32 WorkerId,size_t QueueDepth,size_t ActiveWorkers, diff --git a/Standalone/Research/WorldAssemblerM3/Linux119/REPORT.md b/Standalone/Research/WorldAssemblerM3/Linux119/REPORT.md new file mode 100644 index 0000000..249c740 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux119/REPORT.md @@ -0,0 +1,43 @@ +# Linux119 — smooth half-pipe speed + +## Result + +The route now uses a 10 cm chord-error tolerance (was 2.5 cm); the 8 m spacing cap is unchanged. The evaluator is version 224. Output changed, but Clang/GCC and W1/W8/W12 hashes match. + +L119 improves on L115, but misses the L109 near-ready target in all eight stratum/worker cells: **13.3–22.0% slower than L109**. It is 2.8–7.7% faster than L115 at near-ready. Whole-view readiness remains 6.5–12.3% slower than L109. + +Five interleaved L80 measurements per cell followed one warmup per version. The timing gate recorded 1-minute load 0.82 and 98.7% CPU idle. Headless runs used CPUs 0–11, the 6 GiB address-space limit, and a 1,740 s timeout. + +| Stratum | Workers | Near L109 / L115 / L119 (s; Δ vs L109) | Whole view L109 / L115 / L119 (s; Δ vs L109) | +| --- | ---: | ---: | ---: | +| S0 | 8 | 0.761 / 0.929 / 0.880 (+15.6%) | 1.742 / 1.927 / 1.860 (+6.8%) | +| S0 | 12 | 0.785 / 0.926 / 0.890 (+13.5%) | 1.717 / 1.873 / 1.829 (+6.5%) | +| S1 | 8 | 0.951 / 1.250 / 1.158 (+21.9%) | 1.863 / 2.112 / 2.073 (+11.3%) | +| S1 | 12 | 0.899 / 1.152 / 1.097 (+22.0%) | 1.731 / 2.000 / 1.943 (+12.3%) | +| S2 | 8 | 0.994 / 1.252 / 1.177 (+18.4%) | 1.844 / 2.079 / 2.030 (+10.1%) | +| S2 | 12 | 0.914 / 1.169 / 1.079 (+18.1%) | 1.710 / 1.989 / 1.885 (+10.2%) | +| S3 | 8 | 0.812 / 0.988 / 0.960 (+18.3%) | 1.728 / 1.870 / 1.891 (+9.4%) | +| S3 | 12 | 0.772 / 0.928 / 0.874 (+13.3%) | 1.617 / 1.783 / 1.723 (+6.6%) | + +## Designs and work + +Two designs were built together. Before building, the fourfold chord tolerance increase predicted about half as many curvature-limited route segments (segment count scales roughly with the inverse square root of the error tolerance). The shell support bound was expected to skip most shell calculations: only flattened distances in the 0–0.75 m shell band can contribute, with a 1-subvoxel guard. L118 had 48.93M W8 sweep pairs and 39.3M sampled smooth-min calls. + +| Stratum | W8 LOD0–2 pairs L109 / L115=L118 / L119 (M) | Exact fallbacks L109 / L115=L118 / L119 (M) | Segment visits L109 / L115=L118 / L119 (M) | Prepare ms L118 → L119 | L119 shell-support skips | +| --- | ---: | ---: | ---: | ---: | ---: | +| S0 | 3.36 / 7.56 / 4.55 | 0.241 / 0.413 / 0.652 | 1.19 / 3.41 / 4.68 | 467 → 185 | 3.73M (81.9%) | +| S1 | 6.19 / 16.22 / 9.69 | 0.369 / 0.719 / 1.114 | 1.91 / 7.60 / 9.25 | 919 → 361 | 8.05M (83.1%) | +| S2 | 6.15 / 15.52 / 9.28 | 0.315 / 0.634 / 0.986 | 1.66 / 6.88 / 8.34 | 848 → 345 | 7.69M (82.8%) | +| S3 | 4.09 / 9.63 / 5.88 | 0.074 / 0.131 / 0.203 | 0.48 / 1.41 / 2.19 | 567 → 235 | 4.76M (80.8%) | + +L119 reduced pairs 39–40% versus L115/L118, and summed W1 prepare time fell 59.8% (2.801 s to 1.125 s). Exact fallbacks are 55–58% higher than L115/L118 and visits are 21–56% higher. Those extra fallback scans are the likely remaining readiness cost. L119 prepare time is timed directly; L109/L115 prepare time was not separately instrumented. + +## Quality and verification + +- Floor root offsets: 51 samples at each of 9 stations; maximum 7.884 mm versus L115’s 7.849 mm. +- Fast tier: PASS in 277.9 s. Walkability, floor/mouth profiles, open-air shell, ripple, naturalness, and grade audits passed; no geometry threshold was relaxed. +- Determinism: all 18 Clang/GCC W1/W8/W12 hash runs matched for owner4 surface world and both owner2 canonical recipes. Owner2 v224 baselines were added. Source stamp: `9a592cb548c6768c8c25723f4168f65da9645068cb67dcb317e91f707e7d41df`. +- Captures: 23/23 L115 view names and camera poses rendered with the L119 binary; 19 pass and 4 low-contrast-visible. L115 had 18 pass and 5 low-contrast-visible. [Compare all views side by side](captures/COMPARE.html); [L119 capture index](captures/L119/INDEX.md). +- Linux VFHostEditor: PASS, 27/27 actions in 70.98 s with `-NoUBA -MaxParallelActions=4`. Unreal ran without `prlimit`; three existing RealtimeMesh deprecation warnings remain. + +Logs and timing summaries are in `Saved/Linux/l119/`. diff --git a/Standalone/Research/WorldAssemblerM3/Linux119/RunL119Captures.py b/Standalone/Research/WorldAssemblerM3/Linux119/RunL119Captures.py new file mode 100644 index 0000000..39f2c1a --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux119/RunL119Captures.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +"""Render the L115 view set with the L119 candidate binaries.""" +from __future__ import annotations + +import importlib.util +import json +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +RESEARCH = Path(__file__).resolve().parent +SPEC = importlib.util.spec_from_file_location( + "l115_capture_runner", ROOT / "Standalone/Research/WorldAssemblerM3/Linux115/RunL115Captures.py") +if SPEC is None or SPEC.loader is None: + raise SystemExit("cannot load the L115 capture view definitions") +RUNNER = importlib.util.module_from_spec(SPEC) +SPEC.loader.exec_module(RUNNER) + +# Reuse L115's exact camera and station definitions, while rendering through L119. +RUNNER.CAPTURES = RESEARCH / "captures/L119" +RUNNER.SAVED = ROOT / "Saved/Linux/l119/captures" +RUNNER.HELPERS.RESEARCH = RESEARCH +RUNNER.BINARIES = { + "L115": ROOT / "Saved/Linux/l119/bin/VoxelForgeCoreHeadless-l119-clang"} +RUNNER.RENDERERS = { + "L115": ROOT / "Saved/Linux/l119/bin/VoxelForgeOffscreenCapture-l119-clang"} +RUNNER.HELPERS.BINARIES = RUNNER.BINARIES +RUNNER.HELPERS.RENDERERS = RUNNER.RENDERERS + + +def main() -> int: + result = RUNNER.main() + if result != 0: + return result + index = RUNNER.CAPTURES / "capture-index.json" + document = json.loads(index.read_text(encoding="utf-8")) + for row in document["captures"]: + row["variant"] = "L119" + index.write_text(json.dumps(document, indent=2) + "\n", encoding="utf-8") + markdown = RUNNER.CAPTURES / "INDEX.md" + lines = ["# L119 captures (L115 view set)", "", + "The 23 L115 camera poses were rendered with the L119 binary. Floor anchors " + "require an upward normal alignment of at least 0.85, target-to-floor distance " + "at most 0.25 m, and camera-to-floor distance between 2.0 and 3.2 m. Open-air " + "sections have outside and interior wall close-ups at 4 m.", ""] + for row in document["captures"]: + image = row["capture"].removeprefix("captures/L119/") + lines.append(f"- [{row['passage']} {row['station']}]({image}) — " + f"{row['kind']}; {row.get('drawn_triangles', 0)} triangles; " + f"{row['pixel_quality_status']}") + markdown.write_text("\n".join(lines) + "\n", encoding="utf-8") + return 0 + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux119/RunL119DensityProbe.py b/Standalone/Research/WorldAssemblerM3/Linux119/RunL119DensityProbe.py new file mode 100644 index 0000000..923abde --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux119/RunL119DensityProbe.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 +"""Measure L119 floor zero crossings at three route stations per passage.""" +from __future__ import annotations + +import csv +import json +import math +import os +import re +import statistics +import subprocess +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / "Saved/Linux/l119/density-probe" +BINARY = ROOT / "Saved/Linux/l119/bin/VoxelForgeCoreHeadless-l119-clang" +DATA = ROOT / "Standalone/data/owner_world.json" +SLOPE = re.compile( + r"^\[L115DensitySlopeSample\] passage=(\S+) station=(\S+) s_m=([\d.]+) " + r".*?planned_floor_m=(-?[\d.]+) root_floor_m=(-?[\d.]+|nan) " + r"residual_m=(-?[\d.]+|nan)", re.M) + + +def main() -> int: + OUT.mkdir(parents=True, exist_ok=True) + log = OUT / "owner4-clang.log" + layout = OUT / "layout.json" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1740s", str(BINARY), str(DATA), "--world-assembler-prototype", + "--stream-benchmark", "--stream-pipeline", "--workers=12", "--clip-radius=3", + "--max-clip-level=8", "--max-level=8", "--camera=8,16,-372.2626953125,0,0", + "--audit-resolved-layout-passages", f"--resolved-layout-output={layout}", + ] + with log.open("w", encoding="utf-8") as stream: + result = subprocess.run(command, cwd=ROOT, + env={**os.environ, + "VOXELFORGE_L115_DENSITY_PROFILE": "1"}, + stdout=stream, stderr=subprocess.STDOUT, + check=False, timeout=1740) + if result.returncode: + raise SystemExit(f"L119 density probe failed: {log}") + text = log.read_text(encoding="utf-8", errors="replace") + groups: dict[tuple[str, str], list[dict]] = {} + for passage, station, distance, planned, root, residual in SLOPE.findall(text): + root_value = float(root) if root != "nan" else math.nan + residual_value = float(residual) if residual != "nan" else math.nan + groups.setdefault((passage, station), []).append({ + "route_s_m": float(distance), "planned_floor_m": float(planned), + "root_floor_m": root_value, "offset_m": residual_value}) + summary = [] + with (OUT / "zero-crossing-offsets.csv").open("w", newline="", encoding="utf-8") as stream: + writer = csv.DictWriter(stream, fieldnames=("passage", "station", "route_s_m", + "planned_floor_m", "root_floor_m", "offset_m")) + writer.writeheader() + for (passage, station), samples in sorted(groups.items()): + for sample in samples: + writer.writerow({"passage": passage, "station": station, **sample}) + finite = [sample["offset_m"] for sample in samples + if math.isfinite(sample["offset_m"])] + summary.append({"passage": passage, "station": station, + "samples": len(samples), "finite_roots": len(finite), + "max_abs_offset_m": max(map(abs, finite)) if finite else None, + "median_abs_offset_m": statistics.median(map(abs, finite)) + if finite else None, + "p95_abs_offset_m": sorted(map(abs, finite))[ + min(len(finite)-1, math.ceil(0.95*len(finite))-1)] + if finite else None}) + if not summary or any(item["samples"] != 51 for item in summary): + raise RuntimeError("L119 density profile is missing 51-sample route stations") + (OUT / "zero-crossing-summary.json").write_text( + json.dumps(summary, indent=2) + "\n", encoding="utf-8") + print(f"[L119DensityProbe] exit={result.returncode} stations={len(summary)} " + f"log={log.relative_to(ROOT)}", flush=True) + return result.returncode + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux119/RunL119HashMatrix.py b/Standalone/Research/WorldAssemblerM3/Linux119/RunL119HashMatrix.py new file mode 100644 index 0000000..a2cf43b --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux119/RunL119HashMatrix.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python3 +"""Check owner hash identity at W1/W8/W12 and pin the v224 owner hashes.""" +from __future__ import annotations + +import json +import re +import subprocess +import time +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / "Saved/Linux/l119/hashes" +DATASETS = { + "owner4": ROOT / "Standalone/data/owner_world.json", + "owner2": ROOT / "Standalone/data/regression/owner_world_2strate_l61.json", +} +BINARIES = { + "clang": ROOT / "Saved/Linux/l119/bin/VoxelForgeCoreHeadless-l119-clang", + "gcc": ROOT / "Saved/Linux/l119/bin/VoxelForgeCoreHeadless-l119-gcc", +} +HASH = re.compile(r"^\[Pipeline(?:FullDetailHash|WholeViewHash|LODHash|ExactQueryHash)\].*$", re.M) +STAMP = re.compile(r"^\[VoxelForgeSourceStamp\] sha256=(\S+)$", re.M) + + +def run(dataset: str, recipe: str, workers: int, compiler: str) -> dict: + OUT.mkdir(parents=True, exist_ok=True) + label = f"{dataset}-{recipe}-w{workers}-{compiler}" + log = OUT / f"{label}.log" + layout = OUT / f"{label}.layout.json" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1740s", str(BINARIES[compiler]), str(DATASETS[dataset]), + f"--workers={workers}", "--world-assembler-prototype", "--stream-benchmark", + "--stream-pipeline", "--force-generate", "--clip-radius=3", + "--max-clip-level=8", "--max-level=8", f"--recipe={recipe}", + "--stream-hash", f"--resolved-layout-output={layout}", + ] + started = time.monotonic() + with log.open("w", encoding="utf-8") as stream: + result = subprocess.run(command, cwd=ROOT, stdout=stream, + stderr=subprocess.STDOUT, check=False, timeout=1740) + output = log.read_text(encoding="utf-8", errors="replace") + hashes = HASH.findall(output) + if result.returncode or len(hashes) != 12: + raise SystemExit(f"hash run failed or incomplete: {label}; exit={result.returncode} " + f"hashes={len(hashes)} log={log}") + row = {"dataset": dataset, "recipe": recipe, "workers": workers, + "compiler": compiler, "exit_code": result.returncode, "hashes": hashes, + "source_stamp": (STAMP.search(output).group(1) + if STAMP.search(output) else None), + "elapsed_s": round(time.monotonic() - started, 3), + "log": str(log.relative_to(ROOT))} + print("[L119HashRun] " + json.dumps(row, sort_keys=True), flush=True) + return row + + +def main() -> int: + if any(not path.is_file() for path in (*DATASETS.values(), *BINARIES.values())): + raise SystemExit("missing L119 hash input") + rows = [] + recipes = {"owner4": ("surface-world",), + "owner2": ("surface-world", "floating-islands")} + for dataset, dataset_recipes in recipes.items(): + for recipe in dataset_recipes: + for workers in (1, 8, 12): + for compiler in ("clang", "gcc"): + rows.append(run(dataset, recipe, workers, compiler)) + (OUT / "runs-partial.json").write_text( + json.dumps(rows, indent=2) + "\n", encoding="utf-8") + groups = {} + for dataset, dataset_recipes in recipes.items(): + for recipe in dataset_recipes: + key = f"{dataset}/{recipe}" + group = [row for row in rows if row["dataset"] == dataset + and row["recipe"] == recipe] + reference = group[0]["hashes"] + matches = all(row["hashes"] == reference for row in group) + groups[key] = {"all_worker_compiler_hashes_match": matches, + "source_stamps": sorted({row["source_stamp"] for row in group}), + "runs": [{"workers": row["workers"], "compiler": row["compiler"], + "log": row["log"]} for row in group]} + if not matches: + raise SystemExit(f"determinism mismatch: {key}") + if dataset == "owner2": + canonical = next(row for row in group if row["workers"] == 12 + and row["compiler"] == "clang") + style = 1 if recipe == "surface-world" else 2 + baseline = (ROOT / "Standalone/Tools/verify/baselines/owner-hash/canonical" + / f"owner-hash-{recipe}-style{style}-v224.baseline") + baseline.write_text("\n".join(canonical["hashes"]) + "\n", + encoding="utf-8") + summary = {"runs": rows, "groups": groups, + "owner2_canonical_pins": ["owner2/surface-world", + "owner2/floating-islands"]} + (OUT / "summary.json").write_text(json.dumps(summary, indent=2) + "\n", + encoding="utf-8") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux119/RunL119PassageCounters.py b/Standalone/Research/WorldAssemblerM3/Linux119/RunL119PassageCounters.py new file mode 100644 index 0000000..872183b --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux119/RunL119PassageCounters.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python3 +"""Collect two W8 passage-counter profiles per owner stratum.""" +from __future__ import annotations + +import json +import re +import subprocess +import time +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / "Saved/Linux/l119/passage-counters" +DATA = ROOT / "Standalone/data/owner_world.json" +BINARY = ROOT / "Saved/Linux/l119/bin/VoxelForgeCoreHeadless-l119-clang" +CAMERAS = { + 0: (8.0, 16.0, -372.2626953125), + 1: (25.8369140625, 3.19921875, -737.0), + 2: (19.166015625, -14.2001953125, -753.3740234375), + 3: (-20.0625, -5.068359375, -900.353515625), +} +FIELDS = re.compile(r"([a-zA-Z0-9_]+)=([^ ]+)") + + +def rows(path: Path, tag: str) -> dict[str, dict[str, str]]: + result = {} + for line in path.read_text(encoding="utf-8", errors="replace").splitlines(): + if line.startswith(tag + " "): + field = dict(FIELDS.findall(line)) + result[field["key"]] = field + return result + + +def run(strate: int, replicate: int) -> dict: + OUT.mkdir(parents=True, exist_ok=True) + label = f"s{strate}-w8-profile{replicate}" + log = OUT / f"{label}.log" + camera = ",".join(f"{value:.12f}" for value in CAMERAS[strate]) + ",0,0" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1740s", str(BINARY), str(DATA), + "--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline", + "--workers=8", "--clip-radius=3", "--max-clip-level=8", "--max-level=8", + f"--camera={camera}", "--profile-lod-work", "--profile-passage-composer", + ] + started = time.monotonic() + with log.open("w", encoding="utf-8") as stream: + result = subprocess.run(command, cwd=ROOT, stdout=stream, + stderr=subprocess.STDOUT, check=False, timeout=1740) + if result.returncode: + raise SystemExit(f"passage-counter profile failed: {log}; exit={result.returncode}") + composer, stages = rows(log, "[PassageComposerTile]"), rows(log, "[CpuTileStages]") + selected = [] + for key, comp in composer.items(): + lod = int(key.rsplit("lod", 1)[1].rstrip(")")) + if lod > 2 or int(comp["features"]) == 0: + continue + stage = stages.get(key) + if stage is None: + raise SystemExit(f"missing CpuTileStages record for {label} {key}") + fallbacks = [int(value) for value in stage["sweep_exact_fallback_by_caller"].split(",")] + selected.append({ + "features": int(comp["features"]), + "sweep_pairs": int(comp["sweep_pairs"]), + "shell_support_skips": int(comp.get("sweep_shell_support_skips", "0")), + "exact_fallbacks": sum(fallbacks), + "segment_visits": int(comp["carve_segment_visits"]), + }) + names = ("sweep_pairs", "shell_support_skips", "exact_fallbacks", "segment_visits") + totals = {name: sum(item[name] for item in selected) for name in names} + row = {"strate": strate, "workers": 8, "replicate": replicate, + "passage_tiles_lod02": len(selected), "totals": totals, + "elapsed_s": round(time.monotonic() - started, 3), + "log": str(log.relative_to(ROOT))} + print("[L119PassageCounters] " + json.dumps(row, sort_keys=True), flush=True) + return row + + +def main() -> int: + if not DATA.is_file() or not BINARY.is_file(): + raise SystemExit("missing L119 passage-counter input") + result = [run(strate, replicate) for strate in range(4) for replicate in (1, 2)] + summary = [] + for strate in range(4): + group = [item for item in result if item["strate"] == strate] + summary.append({"strate": strate, "workers": 8, "replicates": len(group), + "totals_mean": { + name: sum(row["totals"][name] for row in group) / len(group) + for name in group[0]["totals"]}}) + (OUT / "summary.json").write_text( + json.dumps({"runs": result, "summary": summary}, indent=2) + "\n", + encoding="utf-8") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux119/RunL119TagProbe.py b/Standalone/Research/WorldAssemblerM3/Linux119/RunL119TagProbe.py new file mode 100644 index 0000000..b3cd73a --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux119/RunL119TagProbe.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 +"""Collect W1 per-tile swept-tube preparation timings for each owner stratum.""" +from __future__ import annotations + +import json +import re +import subprocess +import time +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / "Saved/Linux/l119/tag-probe" +DATA = ROOT / "Standalone/data/owner_world.json" +BINARY = ROOT / "Saved/Linux/l119/bin/VoxelForgeCoreHeadless-l119-clang" +CAMERAS = { + 0: (8.0, 16.0, -372.2626953125), + 1: (25.8369140625, 3.19921875, -737.0), + 2: (19.166015625, -14.2001953125, -753.3740234375), + 3: (-20.0625, -5.068359375, -900.353515625), +} +PASSAGE = re.compile(r"^\[PassageComposerTile\] (.*)$", re.M) +FIELDS = re.compile(r"([a-zA-Z0-9_]+)=([^ ]+)") + + +def run(strate: int) -> dict: + OUT.mkdir(parents=True, exist_ok=True) + label = f"s{strate}-w1-tags" + log = OUT / f"{label}.log" + camera = ",".join(f"{value:.12f}" for value in CAMERAS[strate]) + ",0,0" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1740s", str(BINARY), str(DATA), + "--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline", + "--workers=1", "--clip-radius=3", "--max-clip-level=8", "--max-level=8", + f"--camera={camera}", "--profile-lod-work", "--profile-passage-composer", + ] + started = time.monotonic() + with log.open("w", encoding="utf-8") as stream: + result = subprocess.run(command, cwd=ROOT, stdout=stream, + stderr=subprocess.STDOUT, check=False, timeout=1740) + content = log.read_text(encoding="utf-8", errors="replace") + passage = [dict(FIELDS.findall(match)) for match in PASSAGE.findall(content)] + if result.returncode or not passage: + raise SystemExit(f"prepare probe failed or emitted no passage counters: {log}; " + f"exit={result.returncode}") + near = [row for row in passage + if int(row["key"].rsplit("lod", 1)[1].rstrip(")")) <= 2 + and int(row["features"]) > 0] + totals = { + "passage_feature_tiles": len(near), + "sweep_prepare_ms": sum(float(row["sweep_prepare_ms"]) for row in near), + "sweep_pairs": sum(int(row["sweep_pairs"]) for row in near), + "shell_support_skips": sum( + int(row["sweep_shell_support_skips"]) for row in near), + } + row = {"strate": strate, "workers": 1, "elapsed_s": round(time.monotonic() - started, 3), + "near_lod02_feature_tiles": totals, + "log": str(log.relative_to(ROOT))} + print("[L119TagProbe] " + json.dumps(row, sort_keys=True), flush=True) + return row + + +def main() -> int: + if not DATA.is_file() or not BINARY.is_file(): + raise SystemExit("missing owner data or L119 Clang binary") + rows = [run(strate) for strate in range(4)] + (OUT / "summary.json").write_text(json.dumps(rows, indent=2) + "\n", + encoding="utf-8") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux119/RunL119Timing.py b/Standalone/Research/WorldAssemblerM3/Linux119/RunL119Timing.py new file mode 100644 index 0000000..0b54eac --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux119/RunL119Timing.py @@ -0,0 +1,137 @@ +#!/usr/bin/env python3 +"""Five interleaved L80 readiness runs for L109, L115, and L119.""" +from __future__ import annotations + +import json +import os +import re +import statistics +import subprocess +import time +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / "Saved/Linux/l119/timing" +DATA = ROOT / "Standalone/data/owner_world.json" +BINARIES = { + "L109": ROOT / "Saved/Linux/l109/bin-final/VoxelForgeCoreHeadless-l109-clang", + "L115": ROOT / "Saved/Linux/l115/bin/VoxelForgeCoreHeadless-l115-clang", + "L119": ROOT / "Saved/Linux/l119/bin/VoxelForgeCoreHeadless-l119-clang", +} +CAMERAS = { + 0: (8.0, 16.0, -372.2626953125), + 1: (25.8369140625, 3.19921875, -737.0), + 2: (19.166015625, -14.2001953125, -753.3740234375), + 3: (-20.0625, -5.068359375, -900.353515625), +} +PIPELINE = re.compile(r"^\[StreamPipeline\] (.*)$", re.M) +FIELDS = re.compile(r"([a-zA-Z0-9_]+)=([^ ]+)") +NEAR = re.compile( + r"^\[WorldAssemblerNearLODReady\] lods=0-2 tiles=(\d+)/(\d+) cold_ready_s=([0-9.]+)$", + re.M, +) + + +def run(strate: int, workers: int, version: str, phase: str, replicate: int) -> dict: + OUT.mkdir(parents=True, exist_ok=True) + label = f"s{strate}-w{workers}-{version}-{phase}{replicate}" + log = OUT / f"{label}.log" + camera = ",".join(f"{value:.12f}" for value in CAMERAS[strate]) + ",0,0" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1740s", str(BINARIES[version]), str(DATA), + "--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline", + f"--workers={workers}", "--clip-radius=3", "--max-clip-level=8", "--max-level=8", + f"--camera={camera}", "--profile-lod-work", "--stream-scheduler-policy=3", + ] + started = time.monotonic() + with log.open("w", encoding="utf-8") as output: + result = subprocess.run(command, cwd=ROOT, stdout=output, + stderr=subprocess.STDOUT, check=False, timeout=1740) + content = log.read_text(encoding="utf-8", errors="replace") + pipeline_match = PIPELINE.search(content) + near_match = NEAR.search(content) + if result.returncode or pipeline_match is None or near_match is None: + raise SystemExit(f"readiness run failed or trace missing: {log}; exit={result.returncode}") + pipeline = dict(FIELDS.findall(pipeline_match.group(1))) + row = {"strate": strate, "workers": workers, "version": version, + "phase": phase, "replicate": replicate, "exit_code": result.returncode, + "wall_s": round(time.monotonic() - started, 3), + "lod02_ready_s": float(near_match.group(3)), + "whole_view_ready_s": float(pipeline["whole_view_ready"].removesuffix("s")), + "whole_tiles": int(pipeline["whole_tiles"].split("/")[0]), + "log": str(log.relative_to(ROOT))} + print("[L119TimingRun] " + json.dumps(row, sort_keys=True), flush=True) + return row + + +def cpu_idle_percent(interval_s: float = 2.0) -> float: + def totals() -> tuple[int, int]: + fields = Path("/proc/stat").read_text(encoding="utf-8").splitlines()[0].split() + values = [int(value) for value in fields[1:]] + return sum(values), values[3] + (values[4] if len(values) > 4 else 0) + total_before, idle_before = totals() + time.sleep(interval_s) + total_after, idle_after = totals() + total_delta = max(1, total_after - total_before) + return 100.0 * (idle_after - idle_before) / total_delta + + +def main() -> int: + if not DATA.is_file() or any(not binary.is_file() for binary in BINARIES.values()): + raise SystemExit("missing L109/L115/L119 timing input") + OUT.mkdir(parents=True, exist_ok=True) + load_1m = os.getloadavg()[0] + idle_pct = cpu_idle_percent() + uptime = subprocess.run(["uptime"], cwd=ROOT, text=True, + capture_output=True, check=True).stdout.strip() + top = subprocess.run(["ps", "-eo", "pid,pcpu,comm", "--sort=-pcpu"], cwd=ROOT, + text=True, capture_output=True, check=True).stdout + (OUT / "machine-load-before.txt").write_text( + f"uptime: {uptime}\n1-minute load: {load_1m:.2f}\n" + f"2-second CPU idle: {idle_pct:.1f}%\ntop CPU users:\n{top}", + encoding="utf-8") + print(f"[L119TimingGate] load_1m={load_1m:.2f} cpu_idle_2s={idle_pct:.1f}% " + f"uptime={uptime}", flush=True) + if load_1m >= 0.9 or idle_pct < 97.0: + raise SystemExit("timing refused: machine is above the quiet-load gate") + rows = [] + versions = ("L109", "L115", "L119") + for strate in range(4): + for workers in (8, 12): + for version in versions: + run(strate, workers, version, "warmup", 0) + for replicate in range(1, 6): + offset = (replicate - 1) % len(versions) + order = versions[offset:] + versions[:offset] + for version in order: + rows.append(run(strate, workers, version, "measured", replicate)) + (OUT / "runs-partial.json").write_text( + json.dumps(rows, indent=2) + "\n", encoding="utf-8") + summary = [] + for strate in range(4): + for workers in (8, 12): + item = {"strate": strate, "workers": workers, "replicates": 5} + medians = {} + for version in versions: + group = [row for row in rows if row["strate"] == strate + and row["workers"] == workers and row["version"] == version] + medians[version] = {} + for key in ("lod02_ready_s", "whole_view_ready_s"): + values = [row[key] for row in group] + medians[version][key] = statistics.median(values) + item[f"{version}_{key}_values"] = values + item[f"{version}_{key}_median"] = medians[version][key] + for comparison in ("L109", "L115"): + for key in ("lod02_ready_s", "whole_view_ready_s"): + item[f"L119_vs_{comparison}_{key}_delta_pct"] = round( + 100.0 * (medians["L119"][key] / medians[comparison][key] - 1.0), 2) + summary.append(item) + (OUT / "summary.json").write_text( + json.dumps({"runs": rows, "summary": summary}, indent=2) + "\n", + encoding="utf-8") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux119/captures/COMPARE.html b/Standalone/Research/WorldAssemblerM3/Linux119/captures/COMPARE.html new file mode 100644 index 0000000..a1ace2f --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux119/captures/COMPARE.html @@ -0,0 +1,30 @@ + + +L115 / L119 tunnel capture comparison + +

L115 and L119 tunnel captures

+

The same 23 view names and camera poses are paired side by side. Select an image to open it full size.

+

passage/0-1/0 · rock-floor/401.7m · rock-floor-close

Status: pass

L115
L119
+

passage/0-1/0 · rock-floor/792.8m · rock-floor-close

Status: pass

L115
L119
+

passage/0-1/0 · rock-floor/1634.5m · rock-floor-close

Status: pass

L115
L119
+

passage/1-2/0 · rock-floor/27.0m · rock-floor-close

Status: pass

L115
L119
+

passage/1-2/0 · rock-floor/52.9m · rock-floor-close

Status: pass

L115
L119
+

passage/1-2/0 · rock-floor/78.9m · rock-floor-close

Status: pass

L115
L119
+

passage/2-3/0 · rock-floor/323.4m · rock-floor-close

Status: low_contrast_geometry_visible

L115
L119
+

passage/2-3/0 · rock-floor/333.4m · rock-floor-close

Status: pass

L115
L119
+

passage/2-3/0 · rock-floor/343.4m · rock-floor-close

Status: pass

L115
L119
+

passage/0-1/0 · section-1/4m-outside · open-air-close

Status: pass

L115
L119
+

passage/0-1/0 · section-1/4m-interior-wall · open-air-close

Status: low_contrast_geometry_visible

L115
L119
+

passage/0-1/0 · section-2/4m-outside · open-air-close

Status: pass

L115
L119
+

passage/0-1/0 · section-2/4m-interior-wall · open-air-close

Status: pass

L115
L119
+

passage/0-1/0 · section-3/4m-outside · open-air-close

Status: pass

L115
L119
+

passage/0-1/0 · section-3/4m-interior-wall · open-air-close

Status: pass

L115
L119
+

passage/1-2/0 · section-1/4m-outside · open-air-close

Status: pass

L115
L119
+

passage/1-2/0 · section-1/4m-interior-wall · open-air-close

Status: pass

L115
L119
+

passage/1-2/0 · section-2/4m-outside · open-air-close

Status: pass

L115
L119
+

passage/1-2/0 · section-2/4m-interior-wall · open-air-close

Status: pass

L115
L119
+

passage/2-3/0 · section-1/4m-outside · open-air-close

Status: low_contrast_geometry_visible

L115
L119
+

passage/2-3/0 · section-1/4m-interior-wall · open-air-close

Status: low_contrast_geometry_visible

L115
L119
+

passage/2-3/0 · section-2/4m-outside · open-air-close

Status: pass

L115
L119
+

passage/2-3/0 · section-2/4m-interior-wall · open-air-close

Status: pass

L115
L119
+ diff --git a/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/INDEX.md b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/INDEX.md new file mode 100644 index 0000000..97bae2d --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/INDEX.md @@ -0,0 +1,27 @@ +# L119 captures (L115 view set) + +The 23 L115 camera poses were rendered with the L119 binary. Floor anchors require an upward normal alignment of at least 0.85, target-to-floor distance at most 0.25 m, and camera-to-floor distance between 2.0 and 3.2 m. Open-air sections have outside and interior wall close-ups at 4 m. + +- [passage/0-1/0 rock-floor/401.7m](L115/L115/passage-0-1-0-rock-floor-station-1.png) — rock-floor-close; 122294 triangles; pass +- [passage/0-1/0 rock-floor/792.8m](L115/L115/passage-0-1-0-rock-floor-station-2.png) — rock-floor-close; 586092 triangles; pass +- [passage/0-1/0 rock-floor/1634.5m](L115/L115/passage-0-1-0-rock-floor-station-3.png) — rock-floor-close; 137288 triangles; pass +- [passage/1-2/0 rock-floor/27.0m](L115/L115/passage-1-2-0-rock-floor-station-1.png) — rock-floor-close; 652056 triangles; pass +- [passage/1-2/0 rock-floor/52.9m](L115/L115/passage-1-2-0-rock-floor-station-2.png) — rock-floor-close; 636162 triangles; pass +- [passage/1-2/0 rock-floor/78.9m](L115/L115/passage-1-2-0-rock-floor-station-3.png) — rock-floor-close; 580472 triangles; pass +- [passage/2-3/0 rock-floor/323.4m](L115/L115/passage-2-3-0-rock-floor-station-1.png) — rock-floor-close; 474964 triangles; low_contrast_geometry_visible +- [passage/2-3/0 rock-floor/333.4m](L115/L115/passage-2-3-0-rock-floor-station-2.png) — rock-floor-close; 494504 triangles; pass +- [passage/2-3/0 rock-floor/343.4m](L115/L115/passage-2-3-0-rock-floor-station-3.png) — rock-floor-close; 485356 triangles; pass +- [passage/0-1/0 section-1/4m-outside](L115/L115/passage-0-1-0-openair-1-4m-outside.png) — open-air-close; 275333 triangles; pass +- [passage/0-1/0 section-1/4m-interior-wall](L115/L115/passage-0-1-0-openair-1-4m-interior-wall.png) — open-air-close; 308012 triangles; low_contrast_geometry_visible +- [passage/0-1/0 section-2/4m-outside](L115/L115/passage-0-1-0-openair-2-4m-outside.png) — open-air-close; 275333 triangles; pass +- [passage/0-1/0 section-2/4m-interior-wall](L115/L115/passage-0-1-0-openair-2-4m-interior-wall.png) — open-air-close; 345026 triangles; pass +- [passage/0-1/0 section-3/4m-outside](L115/L115/passage-0-1-0-openair-3-4m-outside.png) — open-air-close; 149234 triangles; pass +- [passage/0-1/0 section-3/4m-interior-wall](L115/L115/passage-0-1-0-openair-3-4m-interior-wall.png) — open-air-close; 148100 triangles; pass +- [passage/1-2/0 section-1/4m-outside](L115/L115/passage-1-2-0-openair-1-4m-outside.png) — open-air-close; 620814 triangles; pass +- [passage/1-2/0 section-1/4m-interior-wall](L115/L115/passage-1-2-0-openair-1-4m-interior-wall.png) — open-air-close; 609757 triangles; pass +- [passage/1-2/0 section-2/4m-outside](L115/L115/passage-1-2-0-openair-2-4m-outside.png) — open-air-close; 584542 triangles; pass +- [passage/1-2/0 section-2/4m-interior-wall](L115/L115/passage-1-2-0-openair-2-4m-interior-wall.png) — open-air-close; 572258 triangles; pass +- [passage/2-3/0 section-1/4m-outside](L115/L115/passage-2-3-0-openair-1-4m-outside.png) — open-air-close; 104612 triangles; low_contrast_geometry_visible +- [passage/2-3/0 section-1/4m-interior-wall](L115/L115/passage-2-3-0-openair-1-4m-interior-wall.png) — open-air-close; 94962 triangles; low_contrast_geometry_visible +- [passage/2-3/0 section-2/4m-outside](L115/L115/passage-2-3-0-openair-2-4m-outside.png) — open-air-close; 475860 triangles; pass +- [passage/2-3/0 section-2/4m-interior-wall](L115/L115/passage-2-3-0-openair-2-4m-interior-wall.png) — open-air-close; 486480 triangles; pass diff --git a/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-0-1-0-openair-1-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-0-1-0-openair-1-4m-interior-wall.png new file mode 100644 index 0000000..1fd88a4 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-0-1-0-openair-1-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-0-1-0-openair-1-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-0-1-0-openair-1-4m-outside.png new file mode 100644 index 0000000..87570be Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-0-1-0-openair-1-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-0-1-0-openair-2-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-0-1-0-openair-2-4m-interior-wall.png new file mode 100644 index 0000000..f76e648 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-0-1-0-openair-2-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-0-1-0-openair-2-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-0-1-0-openair-2-4m-outside.png new file mode 100644 index 0000000..c19fc5f Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-0-1-0-openair-2-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-0-1-0-openair-3-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-0-1-0-openair-3-4m-interior-wall.png new file mode 100644 index 0000000..7dcd833 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-0-1-0-openair-3-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-0-1-0-openair-3-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-0-1-0-openair-3-4m-outside.png new file mode 100644 index 0000000..816ba1d Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-0-1-0-openair-3-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-0-1-0-rock-floor-station-1.png b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-0-1-0-rock-floor-station-1.png new file mode 100644 index 0000000..e67e8c5 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-0-1-0-rock-floor-station-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-0-1-0-rock-floor-station-2.png b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-0-1-0-rock-floor-station-2.png new file mode 100644 index 0000000..2b35b85 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-0-1-0-rock-floor-station-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-0-1-0-rock-floor-station-3.png b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-0-1-0-rock-floor-station-3.png new file mode 100644 index 0000000..bed41ff Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-0-1-0-rock-floor-station-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-1-2-0-openair-1-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-1-2-0-openair-1-4m-interior-wall.png new file mode 100644 index 0000000..7569f8c Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-1-2-0-openair-1-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-1-2-0-openair-1-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-1-2-0-openair-1-4m-outside.png new file mode 100644 index 0000000..cd3c8b5 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-1-2-0-openair-1-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-1-2-0-openair-2-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-1-2-0-openair-2-4m-interior-wall.png new file mode 100644 index 0000000..a6be396 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-1-2-0-openair-2-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-1-2-0-openair-2-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-1-2-0-openair-2-4m-outside.png new file mode 100644 index 0000000..c00f532 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-1-2-0-openair-2-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-1-2-0-rock-floor-station-1.png b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-1-2-0-rock-floor-station-1.png new file mode 100644 index 0000000..3611714 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-1-2-0-rock-floor-station-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-1-2-0-rock-floor-station-2.png b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-1-2-0-rock-floor-station-2.png new file mode 100644 index 0000000..9ac3f59 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-1-2-0-rock-floor-station-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-1-2-0-rock-floor-station-3.png b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-1-2-0-rock-floor-station-3.png new file mode 100644 index 0000000..5b0e0d2 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-1-2-0-rock-floor-station-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-2-3-0-openair-1-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-2-3-0-openair-1-4m-interior-wall.png new file mode 100644 index 0000000..8a9efbd Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-2-3-0-openair-1-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-2-3-0-openair-1-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-2-3-0-openair-1-4m-outside.png new file mode 100644 index 0000000..6ce2868 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-2-3-0-openair-1-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-2-3-0-openair-2-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-2-3-0-openair-2-4m-interior-wall.png new file mode 100644 index 0000000..8532d70 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-2-3-0-openair-2-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-2-3-0-openair-2-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-2-3-0-openair-2-4m-outside.png new file mode 100644 index 0000000..e9fef5f Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-2-3-0-openair-2-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-2-3-0-rock-floor-station-1.png b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-2-3-0-rock-floor-station-1.png new file mode 100644 index 0000000..0413199 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-2-3-0-rock-floor-station-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-2-3-0-rock-floor-station-2.png b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-2-3-0-rock-floor-station-2.png new file mode 100644 index 0000000..f823d6e Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-2-3-0-rock-floor-station-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-2-3-0-rock-floor-station-3.png b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-2-3-0-rock-floor-station-3.png new file mode 100644 index 0000000..279866a Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/L115/L115/passage-2-3-0-rock-floor-station-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/capture-index.json b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/capture-index.json new file mode 100644 index 0000000..15f0f95 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux119/captures/L119/capture-index.json @@ -0,0 +1,1562 @@ +{ + "captures": [ + { + "name": "passage-0-1-0-rock-floor-station-1", + "passage": "passage/0-1/0", + "kind": "rock-floor-close", + "station": "rock-floor/401.7m", + "camera": [ + -9.24648786798055, + 19.798675033837775, + -443.9636296749357 + ], + "target": [ + -7.026884524505579, + 20.857335392121104, + -445.66373993191075 + ], + "yaw": 64.50075976736525, + "pitch": -34.65771934187305, + "focus": [ + -7.026884524505579, + 20.857335392121104, + -445.66373993191075 + ], + "center_z": -445.66373993191075, + "route_distance_m": 401.6612010038529, + "requested_route_distance_m": 401.6612010038529, + "route_length_m": 2026.6238040154117, + "planned_floor_m": -445.66373993191075, + "planned_grade_deg": 10.372328677972732, + "variant": "L119", + "capture": "captures/L119/L115/L115/passage-0-1-0-rock-floor-station-1.png", + "scene": "Saved/Linux/l119/captures/L115/L115/passage-0-1-0-rock-floor-station-1.vfmesh", + "drawn_triangles": 122294, + "source_triangles": 146798, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 401.6612010038529, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": 3.220861372694969e-06, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -9.24648786798055, + 19.798675033837775, + -443.9636296749357 + ], + "target_actual_m": [ + -7.026884524505579, + 20.857335392121104, + -445.66373993191075 + ], + "logs": [ + "Saved/Linux/l119/captures/L115/L115/passage-0-1-0-rock-floor-station-1-mesh.log", + "Saved/Linux/l119/captures/L115/L115/passage-0-1-0-rock-floor-station-1-render.log", + "Saved/Linux/l119/captures/L115/L115/passage-0-1-0-rock-floor-station-1-quality.log" + ], + "floor_anchor_position_m": [ + -7.026885053959959, + 20.857335155432953, + -445.66374310012867 + ], + "floor_anchor_normal": [ + 0.16438021494383692, + 0.07357583212203939, + 0.9836491965444629 + ], + "closeup_camera_to_floor_distance_m": 2.989612610955708, + "closeup_floor_normal_alignment": 0.9836491965444629, + "verified_upward_floor_normal": true + }, + { + "name": "passage-0-1-0-rock-floor-station-2", + "passage": "passage/0-1/0", + "kind": "rock-floor-close", + "station": "rock-floor/792.8m", + "camera": [ + -0.021280083711839648, + -26.43771312964049, + -514.3617561596035 + ], + "target": [ + -2.4714859241065525, + -26.227784739959716, + -516.0616688299093 + ], + "yaw": -85.10297944703369, + "pitch": -34.654210347383824, + "focus": [ + -2.4714859241065525, + -26.227784739959716, + -516.0616688299093 + ], + "center_z": -516.0616688299093, + "route_distance_m": 792.8284020077059, + "requested_route_distance_m": 792.8284020077059, + "route_length_m": 2026.6238040154117, + "planned_floor_m": -516.0616688299093, + "planned_grade_deg": 10.367725129664787, + "variant": "L119", + "capture": "captures/L119/L115/L115/passage-0-1-0-rock-floor-station-2.png", + "scene": "Saved/Linux/l119/captures/L115/L115/passage-0-1-0-rock-floor-station-2.vfmesh", + "drawn_triangles": 586092, + "source_triangles": 626196, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 792.8284020077059, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": 5.0973121461263994e-05, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -0.021280083711839648, + -26.43771312964049, + -514.3617561596035 + ], + "target_actual_m": [ + -2.4714859241065525, + -26.227784739959716, + -516.0616688299093 + ], + "logs": [ + "Saved/Linux/l119/captures/L115/L115/passage-0-1-0-rock-floor-station-2-mesh.log", + "Saved/Linux/l119/captures/L115/L115/passage-0-1-0-rock-floor-station-2-render.log", + "Saved/Linux/l119/captures/L115/L115/passage-0-1-0-rock-floor-station-2-quality.log" + ], + "floor_anchor_position_m": [ + -2.471476828908, + -26.227785976319144, + -516.0617189697925 + ], + "floor_anchor_normal": [ + -0.179115780575022, + 0.024140888419756926, + 0.9835317761289187 + ], + "closeup_camera_to_floor_distance_m": 2.9895496409822853, + "closeup_floor_normal_alignment": 0.9835317761289187, + "verified_upward_floor_normal": true + }, + { + "name": "passage-0-1-0-rock-floor-station-3", + "passage": "passage/0-1/0", + "kind": "rock-floor-close", + "station": "rock-floor/1634.5m", + "camera": [ + 15.717287112180728, + 19.71739973195528, + -665.8352816543407 + ], + "target": [ + 17.336220092016376, + 17.86620742417785, + -667.5348848643227 + ], + "yaw": 138.82915885966676, + "pitch": -34.64871452830556, + "focus": [ + 17.336220092016376, + 17.86620742417785, + -667.5348848643227 + ], + "center_z": -667.5348848643227, + "route_distance_m": 1634.4566030115589, + "requested_route_distance_m": 1634.4566030115589, + "route_length_m": 2026.6238040154117, + "planned_floor_m": -667.5348848643227, + "planned_grade_deg": 10.360515186362372, + "variant": "L119", + "capture": "captures/L119/L115/L115/passage-0-1-0-rock-floor-station-3.png", + "scene": "Saved/Linux/l119/captures/L115/L115/passage-0-1-0-rock-floor-station-3.vfmesh", + "drawn_triangles": 137288, + "source_triangles": 166736, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1634.4566030115589, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": 1.5155223007846759e-05, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 15.717287112180728, + 19.71739973195528, + -665.8352816543407 + ], + "target_actual_m": [ + 17.336220092016376, + 17.86620742417785, + -667.5348848643227 + ], + "logs": [ + "Saved/Linux/l119/captures/L115/L115/passage-0-1-0-rock-floor-station-3-mesh.log", + "Saved/Linux/l119/captures/L115/L115/passage-0-1-0-rock-floor-station-3-render.log", + "Saved/Linux/l119/captures/L115/L115/passage-0-1-0-rock-floor-station-3-quality.log" + ], + "floor_anchor_position_m": [ + 17.33622182815858, + 17.866205324064538, + -667.534869956066 + ], + "floor_anchor_normal": [ + 0.11463807621472542, + -0.13864390562764303, + 0.9836848981834071 + ], + "closeup_camera_to_floor_distance_m": 2.9893930396931125, + "closeup_floor_normal_alignment": 0.9836848981834071, + "verified_upward_floor_normal": true + }, + { + "name": "passage-1-2-0-rock-floor-station-1", + "passage": "passage/1-2/0", + "kind": "rock-floor-close", + "station": "rock-floor/27.0m", + "camera": [ + 15.990262769683945, + 2.495369317804175, + -736.4846720823747 + ], + "target": [ + 15.354493464592624, + 4.868558240151556, + -738.1970266319915 + ], + "yaw": -14.99718988160138, + "pitch": -34.875140724394136, + "focus": [ + 15.354493464592624, + 4.868558240151556, + -738.1970266319915 + ], + "center_z": -738.1970266319915, + "route_distance_m": 26.963657939523273, + "requested_route_distance_m": 26.963657939523273, + "route_length_m": 114.99063175809309, + "planned_floor_m": -738.1970266319915, + "planned_grade_deg": 10.657740387934142, + "variant": "L119", + "capture": "captures/L119/L115/L115/passage-1-2-0-rock-floor-station-1.png", + "scene": "Saved/Linux/l119/captures/L115/L115/passage-1-2-0-rock-floor-station-1.vfmesh", + "drawn_triangles": 652056, + "source_triangles": 719660, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 26.963657939523273, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": 0.0075711794948277, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 15.990262769683945, + 2.495369317804175, + -736.4846720823747 + ], + "target_actual_m": [ + 15.354493464592624, + 4.868558240151556, + -738.1970266319915 + ], + "logs": [ + "Saved/Linux/l119/captures/L115/L115/passage-1-2-0-rock-floor-station-1-mesh.log", + "Saved/Linux/l119/captures/L115/L115/passage-1-2-0-rock-floor-station-1-render.log", + "Saved/Linux/l119/captures/L115/L115/passage-1-2-0-rock-floor-station-1-quality.log" + ], + "floor_anchor_position_m": [ + 15.354124807038394, + 4.869920275450426, + -738.1895881032126 + ], + "floor_anchor_normal": [ + -0.047307387705878, + 0.17883124580074233, + 0.9827417751341397 + ], + "closeup_camera_to_floor_distance_m": 2.9916387475909154, + "closeup_floor_normal_alignment": 0.9827417751341397, + "verified_upward_floor_normal": true + }, + { + "name": "passage-1-2-0-rock-floor-station-2", + "passage": "passage/1-2/0", + "kind": "rock-floor-close", + "station": "rock-floor/52.9m", + "camera": [ + -2.48434493546405, + 15.983647301702653, + -741.2835409028854 + ], + "target": [ + -4.76517685476837, + 15.070128626649932, + -742.995373541633 + ], + "yaw": -111.82708648318167, + "pitch": -34.86587426337977, + "focus": [ + -4.76517685476837, + 15.070128626649932, + -742.995373541633 + ], + "center_z": -742.995373541633, + "route_distance_m": 52.927315879046546, + "requested_route_distance_m": 52.927315879046546, + "route_length_m": 114.99063175809309, + "planned_floor_m": -742.995373541633, + "planned_grade_deg": 10.645569354114926, + "variant": "L119", + "capture": "captures/L119/L115/L115/passage-1-2-0-rock-floor-station-2.png", + "scene": "Saved/Linux/l119/captures/L115/L115/passage-1-2-0-rock-floor-station-2.vfmesh", + "drawn_triangles": 636162, + "source_triangles": 700558, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 52.927315879046546, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": 0.007268380723528676, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -2.48434493546405, + 15.983647301702653, + -741.2835409028854 + ], + "target_actual_m": [ + -4.76517685476837, + 15.070128626649932, + -742.995373541633 + ], + "logs": [ + "Saved/Linux/l119/captures/L115/L115/passage-1-2-0-rock-floor-station-2-mesh.log", + "Saved/Linux/l119/captures/L115/L115/passage-1-2-0-rock-floor-station-2-render.log", + "Saved/Linux/l119/captures/L115/L115/passage-1-2-0-rock-floor-station-2-quality.log" + ], + "floor_anchor_position_m": [ + -4.766428465537912, + 15.069671584786441, + -742.988228337538 + ], + "floor_anchor_normal": [ + -0.1744301807701029, + -0.061608715063684795, + 0.9827402903436447 + ], + "closeup_camera_to_floor_distance_m": 2.9915240428933867, + "closeup_floor_normal_alignment": 0.9827402903436447, + "verified_upward_floor_normal": true + }, + { + "name": "passage-1-2-0-rock-floor-station-3", + "passage": "passage/1-2/0", + "kind": "rock-floor-close", + "station": "rock-floor/78.9m", + "camera": [ + -13.44544511010513, + -3.995230772069307, + -746.0839041050349 + ], + "target": [ + -12.287009401722694, + -6.161841337747165, + -747.7963166548619 + ], + "yaw": 151.8676321960706, + "pitch": -34.87617050502889, + "focus": [ + -12.287009401722694, + -6.161841337747165, + -747.7963166548619 + ], + "center_z": -747.7963166548619, + "route_distance_m": 78.89097381856982, + "requested_route_distance_m": 78.89097381856982, + "route_length_m": 114.99063175809309, + "planned_floor_m": -747.7963166548619, + "planned_grade_deg": 10.659092990906162, + "variant": "L119", + "capture": "captures/L119/L115/L115/passage-1-2-0-rock-floor-station-3.png", + "scene": "Saved/Linux/l119/captures/L115/L115/passage-1-2-0-rock-floor-station-3.vfmesh", + "drawn_triangles": 580472, + "source_triangles": 639376, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 78.89097381856982, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": 0.2416584161119622, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -13.44544511010513, + -3.995230772069307, + -746.0839041050349 + ], + "target_actual_m": [ + -12.287009401722694, + -6.161841337747165, + -747.7963166548619 + ], + "logs": [ + "Saved/Linux/l119/captures/L115/L115/passage-1-2-0-rock-floor-station-3-mesh.log", + "Saved/Linux/l119/captures/L115/L115/passage-1-2-0-rock-floor-station-3-render.log", + "Saved/Linux/l119/captures/L115/L115/passage-1-2-0-rock-floor-station-3-quality.log" + ], + "floor_anchor_position_m": [ + -12.283352972838873, + -6.167679829029396, + -747.554756449892 + ], + "floor_anchor_normal": [ + 0.09692807602747124, + -0.15782686841357624, + 0.9826981366036961 + ], + "closeup_camera_to_floor_distance_m": 2.8693901200350096, + "closeup_floor_normal_alignment": 0.9826981366036961, + "verified_upward_floor_normal": true + }, + { + "name": "passage-2-3-0-rock-floor-station-1", + "passage": "passage/2-3/0", + "kind": "rock-floor-close", + "station": "rock-floor/323.4m", + "camera": [ + 6.997568341188331, + -14.934306981606339, + -869.3796844648476 + ], + "target": [ + 9.102823911740126, + -13.661883549736208, + -871.0755965556104 + ], + "yaw": 58.85109570948622, + "pitch": -34.583159686285406, + "focus": [ + 9.102823911740126, + -13.661883549736208, + -871.0755965556104 + ], + "center_z": -871.0755965556104, + "route_distance_m": 323.4481319239866, + "requested_route_distance_m": 323.4481319239866, + "route_length_m": 494.0722798830563, + "planned_floor_m": -871.0755965556104, + "planned_grade_deg": 10.274530613220444, + "variant": "L119", + "capture": "captures/L119/L115/L115/passage-2-3-0-rock-floor-station-1.png", + "scene": "Saved/Linux/l119/captures/L115/L115/passage-2-3-0-rock-floor-station-1.vfmesh", + "drawn_triangles": 474964, + "source_triangles": 502362, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 323.4481319239866, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": 0.007052221396490902, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 6.997568341188331, + -14.934306981606339, + -869.3796844648476 + ], + "target_actual_m": [ + 9.102823911740126, + -13.661883549736208, + -871.0755965556104 + ], + "logs": [ + "Saved/Linux/l119/captures/L115/L115/passage-2-3-0-rock-floor-station-1-mesh.log", + "Saved/Linux/l119/captures/L115/L115/passage-2-3-0-rock-floor-station-1-render.log", + "Saved/Linux/l119/captures/L115/L115/passage-2-3-0-rock-floor-station-1-quality.log" + ], + "floor_anchor_position_m": [ + 9.103799793973732, + -13.661094033901383, + -871.068656948616 + ], + "floor_anchor_normal": [ + 0.14021616794161246, + 0.11018123609139711, + 0.9839713011369495 + ], + "closeup_camera_to_floor_distance_m": 2.9849472681829123, + "closeup_floor_normal_alignment": 0.9839713011369495, + "verified_upward_floor_normal": true + }, + { + "name": "passage-2-3-0-rock-floor-station-2", + "passage": "passage/2-3/0", + "kind": "rock-floor-close", + "station": "rock-floor/333.4m", + "camera": [ + 14.426607883839745, + -8.501776133009574, + -871.1605818845352 + ], + "target": [ + 15.203729308783775, + -6.16777561793481, + -872.8561420785873 + ], + "yaw": 18.41553205389999, + "pitch": -34.576909662847896, + "focus": [ + 15.203729308783775, + -6.16777561793481, + -872.8561420785873 + ], + "center_z": -872.8561420785873, + "route_distance_m": 333.4481319239866, + "requested_route_distance_m": 333.4481319239866, + "route_length_m": 494.0722798830563, + "planned_floor_m": -872.8561420785873, + "planned_grade_deg": 10.266334408339132, + "variant": "L119", + "capture": "captures/L119/L115/L115/passage-2-3-0-rock-floor-station-2.png", + "scene": "Saved/Linux/l119/captures/L115/L115/passage-2-3-0-rock-floor-station-2.vfmesh", + "drawn_triangles": 494504, + "source_triangles": 524342, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 333.4481319239866, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": 0.007773394757486271, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 14.426607883839745, + -8.501776133009574, + -871.1605818845352 + ], + "target_actual_m": [ + 15.203729308783775, + -6.16777561793481, + -872.8561420785873 + ], + "logs": [ + "Saved/Linux/l119/captures/L115/L115/passage-2-3-0-rock-floor-station-2-mesh.log", + "Saved/Linux/l119/captures/L115/L115/passage-2-3-0-rock-floor-station-2-render.log", + "Saved/Linux/l119/captures/L115/L115/passage-2-3-0-rock-floor-station-2-quality.log" + ], + "floor_anchor_position_m": [ + 15.204108325185125, + -6.1664350574610705, + -872.848494535829 + ], + "floor_anchor_normal": [ + 0.0468360027958031, + 0.17218671405633393, + 0.9839502651783747 + ], + "closeup_camera_to_floor_distance_m": 2.9845224063213145, + "closeup_floor_normal_alignment": 0.9839502651783747, + "verified_upward_floor_normal": true + }, + { + "name": "passage-2-3-0-rock-floor-station-3", + "passage": "passage/2-3/0", + "kind": "rock-floor-close", + "station": "rock-floor/343.4m", + "camera": [ + 16.176045301879554, + 1.1336183974400118, + -872.9426489764151 + ], + "target": [ + 15.465325445603714, + 3.4887437417106955, + -874.6379150751349 + ], + "yaw": -16.792543840841383, + "pitch": -34.57168620892087, + "focus": [ + 15.465325445603714, + 3.4887437417106955, + -874.6379150751349 + ], + "center_z": -874.6379150751349, + "route_distance_m": 343.4481319239866, + "requested_route_distance_m": 343.4481319239866, + "route_length_m": 494.0722798830563, + "planned_floor_m": -874.6379150751349, + "planned_grade_deg": 10.259484647608062, + "variant": "L119", + "capture": "captures/L119/L115/L115/passage-2-3-0-rock-floor-station-3.png", + "scene": "Saved/Linux/l119/captures/L115/L115/passage-2-3-0-rock-floor-station-3.vfmesh", + "drawn_triangles": 485356, + "source_triangles": 512664, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 343.4481319239866, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": 0.1099406801293395, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 16.176045301879554, + 1.1336183974400118, + -872.9426489764151 + ], + "target_actual_m": [ + 15.465325445603714, + 3.4887437417106955, + -874.6379150751349 + ], + "logs": [ + "Saved/Linux/l119/captures/L115/L115/passage-2-3-0-rock-floor-station-3-mesh.log", + "Saved/Linux/l119/captures/L115/L115/passage-2-3-0-rock-floor-station-3-render.log", + "Saved/Linux/l119/captures/L115/L115/passage-2-3-0-rock-floor-station-3-quality.log" + ], + "floor_anchor_position_m": [ + 15.464091528009144, + 3.4924186701988678, + -874.5280427606272 + ], + "floor_anchor_normal": [ + -0.061689200676463656, + 0.16755705537563617, + 0.9839304221913991 + ], + "closeup_camera_to_floor_distance_m": 2.9298959629846824, + "closeup_floor_normal_alignment": 0.9839304221913991, + "verified_upward_floor_normal": true + }, + { + "name": "passage-0-1-0-openair-1-4m-outside", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-1/4m-outside", + "camera": [ + 13.176702021211483, + 7.149068417345486, + -374.402 + ], + "target": [ + 9.197121888971225, + 7.5527291301707695, + -374.402 + ], + "yaw": -84.20812706837869, + "pitch": 0.0, + "focus": [ + 7.272, + 7.748, + -373.197 + ], + "center_z": -373.197, + "open_air_section": 1, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.9948950330600643, + -0.1009151782063209, + 0.0 + ], + "camera_target_distance_m": 4.000000000000001, + "route_distance_m": 8.3545, + "requested_route_distance_m": 8.3545, + "route_length_m": 2026.6238040154117, + "variant": "L119", + "capture": "captures/L119/L115/L115/passage-0-1-0-openair-1-4m-outside.png", + "scene": "Saved/Linux/l119/captures/L115/L115/passage-0-1-0-openair-1-4m-outside.vfmesh", + "drawn_triangles": 275333, + "source_triangles": 327745, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 8.3545, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.999999999999992, + "closeup_target_surface_distance_m": 0.794053842406799, + "closeup_predicted_target_offset_m": 0.794053842406799, + "closeup_wall_normal_alignment": 0.9449803535183738, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 12.920589450293994, + 7.974422667153486, + -375.0086678277374 + ], + "target_actual_m": [ + 9.12386703491211, + 8.0, + -373.75 + ], + "logs": [ + "Saved/Linux/l119/captures/L115/L115/passage-0-1-0-openair-1-4m-outside-mesh.log", + "Saved/Linux/l119/captures/L115/L115/passage-0-1-0-openair-1-4m-outside-render.log", + "Saved/Linux/l119/captures/L115/L115/passage-0-1-0-openair-1-4m-outside-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-1-4m-interior-wall", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-1/4m-interior-wall", + "camera": [ + 7.395778712540976, + 3.8749008126934172, + -374.89997477205173 + ], + "target": [ + 8.778272394312646, + 7.595214286886338, + -374.402 + ], + "yaw": 20.38540702862518, + "pitch": 7.1515181408188955, + "focus": [ + 7.272, + 7.748, + -373.197 + ], + "center_z": -373.197, + "open_air_section": 1, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.9948950330600643, + 0.1009151782063209, + -0.0 + ], + "camera_target_distance_m": 3.9999999999999973, + "route_distance_m": 8.3545, + "requested_route_distance_m": 8.3545, + "route_length_m": 2026.6238040154117, + "variant": "L119", + "capture": "captures/L119/L115/L115/passage-0-1-0-openair-1-4m-interior-wall.png", + "scene": "Saved/Linux/l119/captures/L115/L115/passage-0-1-0-openair-1-4m-interior-wall.vfmesh", + "drawn_triangles": 308012, + "source_triangles": 368124, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 8.3545, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.999999999999992, + "closeup_target_surface_distance_m": 0.8416597466625043, + "closeup_predicted_target_offset_m": 0.8416597466625043, + "closeup_wall_normal_alignment": 0.9449803535183738, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 5.327144619530225, + 8.025577332846515, + -372.4913321722626 + ], + "target_actual_m": [ + 9.12386703491211, + 8.0, + -373.75 + ], + "logs": [ + "Saved/Linux/l119/captures/L115/L115/passage-0-1-0-openair-1-4m-interior-wall-mesh.log", + "Saved/Linux/l119/captures/L115/L115/passage-0-1-0-openair-1-4m-interior-wall-render.log", + "Saved/Linux/l119/captures/L115/L115/passage-0-1-0-openair-1-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-2-4m-outside", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-2/4m-outside", + "camera": [ + 12.814097656232029, + 0.949800892309409, + -375.51163279923776 + ], + "target": [ + 8.842807594702599, + 1.4281890685821654, + -375.51163279923776 + ], + "yaw": -83.1311525734364, + "pitch": 0.0, + "focus": [ + 6.603, + 1.698, + -374.149 + ], + "center_z": -374.149, + "open_air_section": 2, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.9928225153823576, + -0.1195970440681891, + 0.0 + ], + "camera_target_distance_m": 4.0, + "route_distance_m": 14.4925, + "requested_route_distance_m": 14.4925, + "route_length_m": 2026.6238040154117, + "variant": "L119", + "capture": "captures/L119/L115/L115/passage-0-1-0-openair-2-4m-outside.png", + "scene": "Saved/Linux/l119/captures/L115/L115/passage-0-1-0-openair-2-4m-outside.vfmesh", + "drawn_triangles": 275333, + "source_triangles": 327745, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 14.4925, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.999999999999995, + "closeup_target_surface_distance_m": 1.0963161771133416, + "closeup_predicted_target_offset_m": 1.0963161771133416, + "closeup_wall_normal_alignment": 0.39413995490510356, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 9.613469253122387, + 1.5471847686714795, + -379.60073544787906 + ], + "target_actual_m": [ + 7.959597110748291, + 1.0, + -376.0 + ], + "logs": [ + "Saved/Linux/l119/captures/L115/L115/passage-0-1-0-openair-2-4m-outside-mesh.log", + "Saved/Linux/l119/captures/L115/L115/passage-0-1-0-openair-2-4m-outside-render.log", + "Saved/Linux/l119/captures/L115/L115/passage-0-1-0-openair-2-4m-outside-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-2-4m-interior-wall", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-2/4m-interior-wall", + "camera": [ + 6.939570778854576, + -2.1803140897652855, + -376.2060303004211 + ], + "target": [ + 8.388084903173432, + 1.4829657169105679, + -375.51163279923776 + ], + "yaw": 21.574563086437188, + "pitch": 9.997160707081923, + "focus": [ + 6.603, + 1.698, + -374.149 + ], + "center_z": -374.149, + "open_air_section": 2, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.9928225153823576, + 0.1195970440681891, + -0.0 + ], + "camera_target_distance_m": 3.999999999999997, + "route_distance_m": 14.4925, + "requested_route_distance_m": 14.4925, + "route_length_m": 2026.6238040154117, + "variant": "L119", + "capture": "captures/L119/L115/L115/passage-0-1-0-openair-2-4m-interior-wall.png", + "scene": "Saved/Linux/l119/captures/L115/L115/passage-0-1-0-openair-2-4m-interior-wall.vfmesh", + "drawn_triangles": 345026, + "source_triangles": 414658, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 14.4925, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.000000000000001, + "closeup_target_surface_distance_m": 0.7732263275133904, + "closeup_predicted_target_offset_m": 0.7732263275133904, + "closeup_wall_normal_alignment": 0.286757829360229, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 6.619154002331269, + 0.5694445029418322, + -372.249825471136 + ], + "target_actual_m": [ + 7.85216206252137, + 1.2143337388310353, + -376.0 + ], + "logs": [ + "Saved/Linux/l119/captures/L115/L115/passage-0-1-0-openair-2-4m-interior-wall-mesh.log", + "Saved/Linux/l119/captures/L115/L115/passage-0-1-0-openair-2-4m-interior-wall-render.log", + "Saved/Linux/l119/captures/L115/L115/passage-0-1-0-openair-2-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-3-4m-outside", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-3/4m-outside", + "camera": [ + -28.32291429976088, + -16.444327461849063, + -600.6066327992378 + ], + "target": [ + -25.004026673221745, + -14.211619482196229, + -600.6066327992378 + ], + "yaw": 56.07018168236039, + "pitch": 0.0, + "focus": [ + -22.1, + -12.258, + -599.244 + ], + "center_z": -599.244, + "open_air_section": 3, + "closeup_side": "outside", + "closeup_preferred_normal": [ + -0.8297219066347834, + -0.5581769949132084, + 0.0 + ], + "camera_target_distance_m": 4.000000000000001, + "route_distance_m": 1265.3425000000002, + "requested_route_distance_m": 1265.3425000000002, + "route_length_m": 2026.6238040154117, + "variant": "L119", + "capture": "captures/L119/L115/L115/passage-0-1-0-openair-3-4m-outside.png", + "scene": "Saved/Linux/l119/captures/L115/L115/passage-0-1-0-openair-3-4m-outside.vfmesh", + "drawn_triangles": 149234, + "source_triangles": 181128, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1265.3425000000002, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.9999999999999907, + "closeup_target_surface_distance_m": 0.06836631107301705, + "closeup_predicted_target_offset_m": 0.06836631107301705, + "closeup_wall_normal_alignment": 0.9604329420550252, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -28.63982379180018, + -15.582695163623317, + -601.2438490311043 + ], + "target_actual_m": [ + -24.955621627611308, + -14.176566764792845, + -600.5734332352072 + ], + "logs": [ + "Saved/Linux/l119/captures/L115/L115/passage-0-1-0-openair-3-4m-outside-mesh.log", + "Saved/Linux/l119/captures/L115/L115/passage-0-1-0-openair-3-4m-outside-render.log", + "Saved/Linux/l119/captures/L115/L115/passage-0-1-0-openair-3-4m-outside-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-3-4m-interior-wall", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-3/4m-interior-wall", + "camera": [ + -26.071689640946218, + -10.338278587083852, + -601.3036807194 + ], + "target": [ + -24.774901932566983, + -14.057480898923608, + -600.6066327992378 + ], + "yaw": 160.77768453528284, + "pitch": 10.035712777782798, + "focus": [ + -22.1, + -12.258, + -599.244 + ], + "center_z": -599.244, + "open_air_section": 3, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + 0.8297219066347834, + 0.5581769949132084, + -0.0 + ], + "camera_target_distance_m": 4.000000000000005, + "route_distance_m": 1265.3425000000002, + "requested_route_distance_m": 1265.3425000000002, + "route_length_m": 2026.6238040154117, + "variant": "L119", + "capture": "captures/L119/L115/L115/passage-0-1-0-openair-3-4m-interior-wall.png", + "scene": "Saved/Linux/l119/captures/L115/L115/passage-0-1-0-openair-3-4m-interior-wall.vfmesh", + "drawn_triangles": 148100, + "source_triangles": 180244, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1265.3425000000002, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.000000000000004, + "closeup_target_surface_distance_m": 0.15667051955483755, + "closeup_predicted_target_offset_m": 0.15667051955483755, + "closeup_wall_normal_alignment": 0.936006465878356, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -21.875641690065105, + -11.887416826703374, + -599.3020917133557 + ], + "target_actual_m": [ + -24.866552934428398, + -14.149067333208382, + -600.6947104389109 + ], + "logs": [ + "Saved/Linux/l119/captures/L115/L115/passage-0-1-0-openair-3-4m-interior-wall-mesh.log", + "Saved/Linux/l119/captures/L115/L115/passage-0-1-0-openair-3-4m-interior-wall-render.log", + "Saved/Linux/l119/captures/L115/L115/passage-0-1-0-openair-3-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-1-4m-outside", + "passage": "passage/1-2/0", + "kind": "open-air-close", + "station": "section-1/4m-outside", + "camera": [ + -4.699079444431819, + -4.6537955842685985, + -748.15 + ], + "target": [ + -7.452748333327923, + -7.555055250400828, + -748.15 + ], + "yaw": -136.49505148095557, + "pitch": 0.0, + "focus": [ + -9.518, + -9.731, + -745.88 + ], + "center_z": -745.88, + "open_air_section": 1, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.688417222224026, + 0.7253149165330574, + 0.0 + ], + "camera_target_distance_m": 4.000000000000001, + "route_distance_m": 83.504, + "requested_route_distance_m": 83.504, + "route_length_m": 114.99063175809309, + "variant": "L119", + "capture": "captures/L119/L115/L115/passage-1-2-0-openair-1-4m-outside.png", + "scene": "Saved/Linux/l119/captures/L115/L115/passage-1-2-0-openair-1-4m-outside.vfmesh", + "drawn_triangles": 620814, + "source_triangles": 684776, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 83.504, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.9999999999999654, + "closeup_target_surface_distance_m": 0.9023580264896125, + "closeup_predicted_target_offset_m": 0.9023580264896125, + "closeup_wall_normal_alignment": 0.5604211333378514, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -8.046760432303138, + -4.114982136123087, + -749.9844534333902 + ], + "target_actual_m": [ + -8.0, + -7.25, + -747.5006103515625 + ], + "logs": [ + "Saved/Linux/l119/captures/L115/L115/passage-1-2-0-openair-1-4m-outside-mesh.log", + "Saved/Linux/l119/captures/L115/L115/passage-1-2-0-openair-1-4m-outside-render.log", + "Saved/Linux/l119/captures/L115/L115/passage-1-2-0-openair-1-4m-outside-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-1-4m-interior-wall", + "passage": "passage/1-2/0", + "kind": "open-air-close", + "station": "section-1/4m-interior-wall", + "camera": [ + -6.0956279351195075, + -11.653774892861163, + -748.8673569837389 + ], + "target": [ + -8.16773669839842, + -8.308365466344922, + -748.15 + ], + "yaw": -31.773605793127505, + "pitch": 10.331275124559749, + "focus": [ + -9.518, + -9.731, + -745.88 + ], + "center_z": -745.88, + "open_air_section": 1, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.688417222224026, + -0.7253149165330574, + -0.0 + ], + "camera_target_distance_m": 3.999999999999997, + "route_distance_m": 83.504, + "requested_route_distance_m": 83.504, + "route_length_m": 114.99063175809309, + "variant": "L119", + "capture": "captures/L119/L115/L115/passage-1-2-0-openair-1-4m-interior-wall.png", + "scene": "Saved/Linux/l119/captures/L115/L115/passage-1-2-0-openair-1-4m-interior-wall.vfmesh", + "drawn_triangles": 609757, + "source_triangles": 668131, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 83.504, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.999999999999999, + "closeup_target_surface_distance_m": 0.6509430039577998, + "closeup_predicted_target_offset_m": 0.6509430039577998, + "closeup_wall_normal_alignment": 0.7808473937095911, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -8.525095579521167, + -12.94135557024142, + -748.3220319510015 + ], + "target_actual_m": [ + -8.18421537084871, + -8.958641713644115, + -748.1744141343152 + ], + "logs": [ + "Saved/Linux/l119/captures/L115/L115/passage-1-2-0-openair-1-4m-interior-wall-mesh.log", + "Saved/Linux/l119/captures/L115/L115/passage-1-2-0-openair-1-4m-interior-wall-render.log", + "Saved/Linux/l119/captures/L115/L115/passage-1-2-0-openair-1-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-2-4m-outside", + "passage": "passage/1-2/0", + "kind": "open-air-close", + "station": "section-2/4m-outside", + "camera": [ + 6.53817273275958, + -4.657210376135293, + -752.013 + ], + "target": [ + 8.159152142647708, + -8.31404312493838, + -752.013 + ], + "yaw": 156.09352823535562, + "pitch": 0.0, + "focus": [ + 9.43, + -11.181, + -749.743 + ], + "center_z": -749.743, + "open_air_section": 2, + "closeup_side": "outside", + "closeup_preferred_normal": [ + -0.40524485247203174, + 0.9142081872007717, + 0.0 + ], + "camera_target_distance_m": 4.0, + "route_distance_m": 104.362, + "requested_route_distance_m": 104.362, + "route_length_m": 114.99063175809309, + "variant": "L119", + "capture": "captures/L119/L115/L115/passage-1-2-0-openair-2-4m-outside.png", + "scene": "Saved/Linux/l119/captures/L115/L115/passage-1-2-0-openair-2-4m-outside.vfmesh", + "drawn_triangles": 584542, + "source_triangles": 637002, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 104.362, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.0, + "closeup_target_surface_distance_m": 0.5901774459243846, + "closeup_predicted_target_offset_m": 0.5901774459243846, + "closeup_wall_normal_alignment": 0.9891249705782158, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 6.359624549359488, + -5.416552010781576, + -752.0616659309658 + ], + "target_actual_m": [ + 8.5, + -8.79556763526633, + -752.0293187551489 + ], + "logs": [ + "Saved/Linux/l119/captures/L115/L115/passage-1-2-0-openair-2-4m-outside-mesh.log", + "Saved/Linux/l119/captures/L115/L115/passage-1-2-0-openair-2-4m-outside-render.log", + "Saved/Linux/l119/captures/L115/L115/passage-1-2-0-openair-2-4m-outside-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-2-4m-interior-wall", + "passage": "passage/1-2/0", + "kind": "open-air-close", + "station": "section-2/4m-interior-wall", + "camera": [ + 12.438590152225206, + -8.574465388721983, + -752.7261335058829 + ], + "target": [ + 8.55317187096847, + -9.20292810238377, + -752.013 + ], + "yaw": -99.18796190221158, + "pitch": 10.269787281460902, + "focus": [ + 9.43, + -11.181, + -749.743 + ], + "center_z": -749.743, + "open_air_section": 2, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + 0.40524485247203174, + -0.9142081872007717, + -0.0 + ], + "camera_target_distance_m": 3.9999999999999973, + "route_distance_m": 104.362, + "requested_route_distance_m": 104.362, + "route_length_m": 114.99063175809309, + "variant": "L119", + "capture": "captures/L119/L115/L115/passage-1-2-0-openair-2-4m-interior-wall.png", + "scene": "Saved/Linux/l119/captures/L115/L115/passage-1-2-0-openair-2-4m-interior-wall.vfmesh", + "drawn_triangles": 572258, + "source_triangles": 618646, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 104.362, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.000000000000001, + "closeup_target_surface_distance_m": 0.353159827911248, + "closeup_predicted_target_offset_m": 0.353159827911248, + "closeup_wall_normal_alignment": 0.9983988827266467, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 9.748104215680776, + -12.666965794821667, + -752.0265932958123 + ], + "target_actual_m": [ + 8.335827076712103, + -8.924626207433736, + -752.0074179101423 + ], + "logs": [ + "Saved/Linux/l119/captures/L115/L115/passage-1-2-0-openair-2-4m-interior-wall-mesh.log", + "Saved/Linux/l119/captures/L115/L115/passage-1-2-0-openair-2-4m-interior-wall-render.log", + "Saved/Linux/l119/captures/L115/L115/passage-1-2-0-openair-2-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-1-4m-outside", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-1/4m-outside", + "camera": [ + -3.5840423774965293, + -5.521048309862215, + -815.8969999999999 + ], + "target": [ + -5.637732447498513, + -8.953592132798093, + -815.8969999999999 + ], + "yaw": -149.10792796365394, + "pitch": 0.0, + "focus": [ + -7.178, + -11.528, + -813.627 + ], + "center_z": -813.627, + "open_air_section": 1, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.5134225175004958, + 0.8581359557339694, + 0.0 + ], + "camera_target_distance_m": 4.0, + "route_distance_m": 16.616500000000002, + "requested_route_distance_m": 16.616500000000002, + "route_length_m": 494.0722798830563, + "variant": "L119", + "capture": "captures/L119/L115/L115/passage-2-3-0-openair-1-4m-outside.png", + "scene": "Saved/Linux/l119/captures/L115/L115/passage-2-3-0-openair-1-4m-outside.vfmesh", + "drawn_triangles": 104612, + "source_triangles": 129326, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 16.616500000000002, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.0000000000000036, + "closeup_target_surface_distance_m": 0.29188924025474844, + "closeup_predicted_target_offset_m": 0.29188924025474844, + "closeup_wall_normal_alignment": 0.6703275045296155, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -3.7918253987505834, + -7.16028175130118, + -813.227396563761 + ], + "target_actual_m": [ + -5.7833741859987065, + -9.093313475424294, + -816.1078690565205 + ], + "logs": [ + "Saved/Linux/l119/captures/L115/L115/passage-2-3-0-openair-1-4m-outside-mesh.log", + "Saved/Linux/l119/captures/L115/L115/passage-2-3-0-openair-1-4m-outside-render.log", + "Saved/Linux/l119/captures/L115/L115/passage-2-3-0-openair-1-4m-outside-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-1-4m-interior-wall", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-1/4m-interior-wall", + "camera": [ + -3.4141605326349946, + -12.659565888737353, + -816.5879167710818 + ], + "target": [ + -6.170971760123668, + -9.844849940114793, + -815.8969999999999 + ], + "yaw": -44.40454805561343, + "pitch": 9.946538162082001, + "focus": [ + -7.178, + -11.528, + -813.627 + ], + "center_z": -813.627, + "open_air_section": 1, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.5134225175004958, + -0.8581359557339694, + -0.0 + ], + "camera_target_distance_m": 4.000000000000005, + "route_distance_m": 16.616500000000002, + "requested_route_distance_m": 16.616500000000002, + "route_length_m": 494.0722798830563, + "variant": "L119", + "capture": "captures/L119/L115/L115/passage-2-3-0-openair-1-4m-interior-wall.png", + "scene": "Saved/Linux/l119/captures/L115/L115/passage-2-3-0-openair-1-4m-interior-wall.vfmesh", + "drawn_triangles": 94962, + "source_triangles": 118028, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 16.616500000000002, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.0, + "closeup_target_surface_distance_m": 0.41920390486225767, + "closeup_predicted_target_offset_m": 0.41920390486225767, + "closeup_wall_normal_alignment": 0.740744136337711, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -7.998432705401559, + -11.833936581758076, + -818.2481168532394 + ], + "target_actual_m": [ + -5.94757062165508, + -9.608161331921629, + -815.6327986602337 + ], + "logs": [ + "Saved/Linux/l119/captures/L115/L115/passage-2-3-0-openair-1-4m-interior-wall-mesh.log", + "Saved/Linux/l119/captures/L115/L115/passage-2-3-0-openair-1-4m-interior-wall-render.log", + "Saved/Linux/l119/captures/L115/L115/passage-2-3-0-openair-1-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-2-4m-outside", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-2/4m-outside", + "camera": [ + -4.5562890668466025, + 4.648574813628143, + -879.7479999999999 + ], + "target": [ + -7.40869531436283, + 7.452817777269203, + -879.7479999999999 + ], + "yaw": -45.487830534998494, + "pitch": 0.0, + "focus": [ + -9.548, + 9.556, + -877.478 + ], + "center_z": -877.478, + "open_air_section": 2, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.7131015618790567, + -0.7010607409102652, + 0.0 + ], + "camera_target_distance_m": 4.000000000000001, + "route_distance_m": 374.929, + "requested_route_distance_m": 374.929, + "route_length_m": 494.0722798830563, + "variant": "L119", + "capture": "captures/L119/L115/L115/passage-2-3-0-openair-2-4m-outside.png", + "scene": "Saved/Linux/l119/captures/L115/L115/passage-2-3-0-openair-2-4m-outside.vfmesh", + "drawn_triangles": 475860, + "source_triangles": 504244, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 374.929, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.0, + "closeup_target_surface_distance_m": 1.7280841589725482, + "closeup_predicted_target_offset_m": 1.7280841589725482, + "closeup_wall_normal_alignment": 0.6707889779439669, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -7.47193274788199, + 5.182168353356822, + -879.6783722112204 + ], + "target_actual_m": [ + -7.306445568768645, + 9.17777802625833, + -879.7662205769708 + ], + "logs": [ + "Saved/Linux/l119/captures/L115/L115/passage-2-3-0-openair-2-4m-outside-mesh.log", + "Saved/Linux/l119/captures/L115/L115/passage-2-3-0-openair-2-4m-outside-render.log", + "Saved/Linux/l119/captures/L115/L115/passage-2-3-0-openair-2-4m-outside-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-2-4m-interior-wall", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-2/4m-interior-wall", + "camera": [ + -11.533986119377625, + 6.164550123765492, + -880.4395357921604 + ], + "target": [ + -8.149320771422074, + 8.180937668487475, + -879.7479999999999 + ], + "yaw": 59.215963829172296, + "pitch": 9.955540417812847, + "focus": [ + -9.548, + 9.556, + -877.478 + ], + "center_z": -877.478, + "open_air_section": 2, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.7131015618790567, + 0.7010607409102652, + -0.0 + ], + "camera_target_distance_m": 4.000000000000007, + "route_distance_m": 374.929, + "requested_route_distance_m": 374.929, + "route_length_m": 494.0722798830563, + "variant": "L119", + "capture": "captures/L119/L115/L115/passage-2-3-0-openair-2-4m-interior-wall.png", + "scene": "Saved/Linux/l119/captures/L115/L115/passage-2-3-0-openair-2-4m-interior-wall.vfmesh", + "drawn_triangles": 486480, + "source_triangles": 513552, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 374.929, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.0, + "closeup_target_surface_distance_m": 1.0286227628002445, + "closeup_predicted_target_offset_m": 1.0286227628002445, + "closeup_wall_normal_alignment": 0.720019406420326, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -8.257109087497915, + 13.208090205453457, + -879.7612149430302 + ], + "target_actual_m": [ + -8.149320771422074, + 9.209558486938477, + -879.75 + ], + "logs": [ + "Saved/Linux/l119/captures/L115/L115/passage-2-3-0-openair-2-4m-interior-wall-mesh.log", + "Saved/Linux/l119/captures/L115/L115/passage-2-3-0-openair-2-4m-interior-wall-render.log", + "Saved/Linux/l119/captures/L115/L115/passage-2-3-0-openair-2-4m-interior-wall-quality.log" + ] + } + ] +} diff --git a/Standalone/Research/WorldAssemblerM3/Linux125/REPORT.md b/Standalone/Research/WorldAssemblerM3/Linux125/REPORT.md new file mode 100644 index 0000000..436fecd --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux125/REPORT.md @@ -0,0 +1,46 @@ +# Linux125 — passage slab stamping + +## Result + +**No-go for the L109 speed bar.** The v225 stamp candidate keeps the L119 10 cm curve tolerance and smooth half-pipe look. It is 4.72–10.19% slower than L109 for near-ready LOD0–2, though 1.96–14.23% faster than L119. Whole-view readiness ranges from 0.47% faster to 8.04% slower than L109. + +The BVH trial was rejected: preparation was 5–6× slower. The final design stamps conservative route slabs with an outside sentinel and evaluates segment geometry over tight expanded bounds. The separate 25 cm tolerance trial was also rejected: it remained 11–23% slower than L109 and its maximum floor-root offset was 8.601 mm. + +## Count first + +The tile cache already stores prepared segment contributions. At LOD0, each stratum still evaluates 3.11–8.49M segment/sample pairs, while the exact one-sample band is 5.16–7.41% of grid samples and pair overlap is 67–73%. Stamping cuts exact fallback work, but preparation remains dominated by segment/sample work. + +| Stratum | LOD0 pairs (M) | Exact band | Pair overlap L119 → stamp | Prepare ms L119 → stamp | Exact fallbacks (k) L119 → stamp | Max tile cache (MiB) | Process RSS MiB L119 → stamp | +| --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: | +| S0 | 3.11 | 5.16% | 67.3 → 67.2% | 246 → 272 | 426 → 73 | 3.93 | 724 → 723 | +| S1 | 8.49 | 6.53% | 72.6 → 72.0% | 620 → 700 | 912 → 172 | 7.85 | 580 → 583 | +| S2 | 8.30 | 7.41% | 72.6 → 72.0% | 606 → 621 | 892 → 180 | 7.85 | 643 → 641 | +| S3 | 5.27 | 5.35% | 67.7 → 67.6% | 443 → 463 | 198 → 73 | 3.93 | 657 → 667 | + +Across strata, mean preparation time by LOD was **LOD0 479→514 ms, LOD1 121→130 ms, LOD2 3.8→4.1 ms**. Exact-band fractions were 6.18%, 4.14%, and 6.16%; pair overlap was about 71%, 67%, and 68% respectively. Per-caller LOD0 exact fallbacks show the main gain: DensityGrid fell from 479k calls per run on average to zero. Remaining callers account for about 124k calls per run, led by skirt refinement (75k), midpoint correction (19k), and skirt extrusion (18k). Off-grid misses remain on the canonical exact path: 96–235k per stratum at LOD0. + +## Timing + +Five interleaved L80 measurements per cell, one warmup per version, all four strata. The final quiet-machine gate was 1-minute load 0.63 and 98.8% CPU idle. Values are medians in seconds; near-ready is LOD0–2. + +| Stratum | Workers | Near L109 / L119 / v225 | Whole view L109 / L119 / v225 | +| --- | ---: | ---: | ---: | +| S0 | 8 | 0.745 / 0.850 / 0.780 | 1.694 / 1.762 / 1.686 | +| S0 | 12 | 0.767 / 0.878 / 0.807 | 1.680 / 1.783 / 1.714 | +| S1 | 8 | 0.921 / 1.144 / 0.981 | 1.771 / 2.017 / 1.855 | +| S1 | 12 | 0.887 / 1.082 / 0.962 | 1.711 / 1.912 / 1.794 | +| S2 | 8 | 0.973 / 1.165 / 1.025 | 1.811 / 2.020 / 1.861 | +| S2 | 12 | 0.905 / 1.070 / 0.965 | 1.689 / 1.862 / 1.758 | +| S3 | 8 | 0.809 / 0.943 / 0.879 | 1.667 / 1.871 / 1.801 | +| S3 | 12 | 0.760 / 0.855 / 0.838 | 1.587 / 1.687 / 1.674 | + +## Quality and verification + +- Floor probe: 9 stations × 51 samples; maximum root offset 7.884 mm, matching the L119 probe. Route centerline openness passed for 21,425/21,425 samples; maximum grade was 10.695°. +- Fast tier and walk audits: PASS, 264 checks across 80 runs. +- Seams: the audit exits nonzero on any shared-sample mismatch. Four adjacent LOD0 tile pairs passed, with 1,225 shared samples per pair (4,900 total), bit-identical and max delta 0. +- Determinism: all 18 Clang/GCC W1/W8/W12 runs matched across owner4 surface-world, owner2 surface-world, and owner2 floating-islands. Output changed; evaluator version 225 and v225 canonical baselines were added. Source stamp: `c1ac9c910e8bb26eba5e25f0396a3b68845627b27bf52cf3f951a37c873783f3`. +- Captures: 23/23 L119 views rendered at the same poses; 19 pass and 4 low-contrast-visible. [Compare captures side by side](captures/COMPARE.html). +- Linux VFHostEditor: PASS, 31/31 actions, 75.24 s total with `-NoUBA -MaxParallelActions=4`. Unreal ran without `prlimit`. + +Logs, counts, probes, hashes, and timings are under `Saved/Linux/l125/`. diff --git a/Standalone/Research/WorldAssemblerM3/Linux125/RunL125Captures.py b/Standalone/Research/WorldAssemblerM3/Linux125/RunL125Captures.py new file mode 100644 index 0000000..c04d66b --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux125/RunL125Captures.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python3 +"""Render the exact 23 L119 camera views with the L125 candidate.""" +from __future__ import annotations + +import importlib.util +import json +import math +import os +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +RESEARCH = Path(__file__).resolve().parent +CAPTURES = RESEARCH / "captures" +SAVED = ROOT / "Saved/Linux/l125/captures" +BASELINE_INDEX = (ROOT / "Standalone/Research/WorldAssemblerM3/Linux119" + / "captures/L119/capture-index.json") +LAYOUT = ROOT / "Saved/Linux/l125/hashes/owner4-surface-world-w12-clang.layout.json" +CLANG = ROOT / os.environ.get("L125_CAPTURE_CLANG", + "Saved/Linux/l125/bin/VoxelForgeCoreHeadless-l125-clang") +RENDERER = ROOT / os.environ.get("L125_CAPTURE_RENDERER", + "Saved/Linux/l125/bin/VoxelForgeOffscreenCapture-l125-clang") +HELPER_PATH = ROOT / "Standalone/Research/WorldAssemblerM3/Linux113/RunL113Captures.py" + +SPEC = importlib.util.spec_from_file_location("l113_capture_helpers", HELPER_PATH) +if SPEC is None or SPEC.loader is None: + raise SystemExit("cannot load the verified L113 capture helpers") +HELPERS = importlib.util.module_from_spec(SPEC) +SPEC.loader.exec_module(HELPERS) +HELPERS.RESEARCH = RESEARCH +HELPERS.CAPTURES = CAPTURES +HELPERS.SAVED = SAVED +HELPERS.BINARIES = {"L125": CLANG} +HELPERS.RENDERERS = {"L125": RENDERER} + + +def main() -> int: + if any(not path.is_file() for path in (BASELINE_INDEX, LAYOUT, CLANG, RENDERER)): + raise SystemExit("missing L119 camera set, L125 layout, or capture binary") + baseline = json.loads(BASELINE_INDEX.read_text(encoding="utf-8")) + layout = json.loads(LAYOUT.read_text(encoding="utf-8")) + rows = [] + CAPTURES.mkdir(parents=True, exist_ok=True) + SAVED.mkdir(parents=True, exist_ok=True) + for view in baseline["captures"]: + row = HELPERS.capture("L125", view, layout) + row["variant"] = "L125-v225" + if view["kind"] == "rock-floor-close": + scene = ROOT / row["scene"] + anchor = HELPERS.nearest_surface_anchor(scene, view["target"], margin_m=5.0, + preferred_normal=(0.0, 0.0, 1.0), minimum_alignment=0.85) + alignment = HELPERS.dot(anchor["normal"], (0.0, 0.0, 1.0)) + camera_distance = math.dist(row["camera_actual_m"], anchor["position_m"]) + row.update({"floor_anchor_position_m": anchor["position_m"], + "floor_anchor_normal": anchor["normal"], + "closeup_camera_to_floor_distance_m": camera_distance, + "closeup_floor_normal_alignment": alignment, + "verified_upward_floor_normal": alignment >= 0.85}) + if (not row["verified"] or not 2.0 <= camera_distance <= 3.2 + or anchor["distance_m"] > 0.25 or alignment < 0.85 + or row["drawn_triangles"] <= 0 + or row["pixel_quality_status"] not in + ("pass", "low_contrast_geometry_visible")): + raise RuntimeError(f"L125 floor close-up failed at {view['name']}") + rows.append(row) + if len(rows) != len(baseline["captures"]) or len(rows) != 23: + raise RuntimeError(f"expected all 23 L119 views, captured {len(rows)}") + index = CAPTURES / "L125" / "capture-index.json" + index.parent.mkdir(parents=True, exist_ok=True) + index.write_text(json.dumps({"captures": rows}, indent=2) + "\n", + encoding="utf-8") + + html = ["", + "L119 / L125 tunnel capture comparison", + "", + "

L119 / L125 v225: identical views

"] + old_by_name = {Path(row["capture"]).name: row for row in baseline["captures"]} + for row in rows: + name = Path(row["capture"]).name + old = old_by_name[name] + old_path = os.path.relpath(ROOT / "Standalone/Research/WorldAssemblerM3/Linux119" + / old["capture"], CAPTURES) + new_path = os.path.relpath(RESEARCH / row["capture"], CAPTURES) + html.extend(["
", f"

{row['passage']} — {row['station']}

", + f"

{row['kind']} · L119 {old['pixel_quality_status']} · " + f"L125 {row['pixel_quality_status']}

", "
", + f"
L119
", + f"
L125 v225
", + "
", "
"]) + (CAPTURES / "COMPARE.html").write_text("\n".join(html) + "\n", + encoding="utf-8") + print(f"[L125Captures] rendered={len(rows)} views index={index.relative_to(ROOT)}", + flush=True) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux125/RunL125DensityProbe.py b/Standalone/Research/WorldAssemblerM3/Linux125/RunL125DensityProbe.py new file mode 100644 index 0000000..f73b221 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux125/RunL125DensityProbe.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python3 +"""Probe reconstructed tunnel floor roots at the nine L119 stations.""" +from __future__ import annotations + +import csv +import json +import math +import os +import re +import statistics +import subprocess +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / os.environ.get("L125_PROBE_DIR", "Saved/Linux/l125/density-probe") +BINARY = ROOT / os.environ.get("L125_PROBE_BINARY", + "Saved/Linux/l125/bin/VoxelForgeCoreHeadless-l125-clang") +DATA = ROOT / "Standalone/data/owner_world.json" +SLOPE = re.compile( + r"^\[L115DensitySlopeSample\] passage=(\S+) station=(\S+) s_m=([\d.]+) " + r".*?planned_floor_m=(-?[\d.]+) root_floor_m=(-?[\d.]+|nan) " + r"residual_m=(-?[\d.]+|nan)", re.M) + + +def main() -> int: + OUT.mkdir(parents=True, exist_ok=True) + log, layout = OUT / "owner4-clang.log", OUT / "layout.json" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1740s", str(BINARY), str(DATA), "--world-assembler-prototype", + "--stream-benchmark", "--stream-pipeline", "--workers=12", "--clip-radius=3", + "--max-clip-level=8", "--max-level=8", + "--camera=8,16,-372.2626953125,0,0", "--audit-resolved-layout-passages", + f"--resolved-layout-output={layout}", + ] + with log.open("w", encoding="utf-8") as stream: + result = subprocess.run(command, cwd=ROOT, + env={**os.environ, "VOXELFORGE_L115_DENSITY_PROFILE": "1"}, + stdout=stream, stderr=subprocess.STDOUT, check=False, timeout=1740) + if result.returncode: + raise SystemExit(f"density probe failed: {log}; exit={result.returncode}") + text = log.read_text(encoding="utf-8", errors="replace") + groups: dict[tuple[str, str], list[dict]] = {} + for passage, station, distance, planned, root, residual in SLOPE.findall(text): + root_value = float(root) if root != "nan" else math.nan + residual_value = float(residual) if residual != "nan" else math.nan + groups.setdefault((passage, station), []).append({ + "route_s_m": float(distance), "planned_floor_m": float(planned), + "root_floor_m": root_value, "offset_m": residual_value}) + summary = [] + with (OUT / "zero-crossing-offsets.csv").open("w", newline="", encoding="utf-8") as stream: + writer = csv.DictWriter(stream, fieldnames=("passage", "station", "route_s_m", + "planned_floor_m", "root_floor_m", "offset_m")) + writer.writeheader() + for (passage, station), samples in sorted(groups.items()): + for sample in samples: + writer.writerow({"passage": passage, "station": station, **sample}) + finite = [sample["offset_m"] for sample in samples + if math.isfinite(sample["offset_m"])] + summary.append({"passage": passage, "station": station, + "samples": len(samples), "finite_roots": len(finite), + "max_abs_offset_m": max(map(abs, finite)) if finite else None, + "median_abs_offset_m": statistics.median(map(abs, finite)) + if finite else None, + "p95_abs_offset_m": sorted(map(abs, finite))[ + min(len(finite)-1, math.ceil(0.95*len(finite))-1)] + if finite else None}) + if not summary or any(item["samples"] != 51 for item in summary): + raise RuntimeError("density profile is missing 51-sample route stations") + (OUT / "zero-crossing-summary.json").write_text( + json.dumps(summary, indent=2) + "\n", encoding="utf-8") + print(f"[L125DensityProbe] exit={result.returncode} stations={len(summary)} " + f"log={log.relative_to(ROOT)}", flush=True) + return result.returncode + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux125/RunL125HashMatrix.py b/Standalone/Research/WorldAssemblerM3/Linux125/RunL125HashMatrix.py new file mode 100644 index 0000000..4f9a9d0 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux125/RunL125HashMatrix.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python3 +"""Check Clang/GCC W1/W8/W12 hashes and compare the candidate with L119.""" +from __future__ import annotations + +import json +import os +import re +import subprocess +import time +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / os.environ.get("L125_HASH_DIR", "Saved/Linux/l125/hashes") +DATASETS = { + "owner4": ROOT / "Standalone/data/owner_world.json", + "owner2": ROOT / "Standalone/data/regression/owner_world_2strate_l61.json", +} +BINARIES = { + "clang": ROOT / os.environ.get("L125_HASH_CLANG", + "Saved/Linux/l125/bin-stamp10/VoxelForgeCoreHeadless-l125-stamp10-clang"), + "gcc": ROOT / os.environ.get("L125_HASH_GCC", + "Saved/Linux/l125/bin-stamp10/VoxelForgeCoreHeadless-l125-stamp10-gcc"), +} +HASH = re.compile(r"^\[Pipeline(?:FullDetailHash|WholeViewHash|LODHash|ExactQueryHash)\].*$", re.M) +STAMP = re.compile(r"^\[VoxelForgeSourceStamp\] sha256=(\S+)$", re.M) + + +def run(dataset: str, recipe: str, workers: int, compiler: str) -> dict: + OUT.mkdir(parents=True, exist_ok=True) + label = f"{dataset}-{recipe}-w{workers}-{compiler}" + log = OUT / f"{label}.log" + layout = OUT / f"{label}.layout.json" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1740s", str(BINARIES[compiler]), str(DATASETS[dataset]), + f"--workers={workers}", "--world-assembler-prototype", "--stream-benchmark", + "--stream-pipeline", "--force-generate", "--clip-radius=3", + "--max-clip-level=8", "--max-level=8", f"--recipe={recipe}", + "--stream-hash", f"--resolved-layout-output={layout}", + ] + started = time.monotonic() + with log.open("w", encoding="utf-8") as stream: + result = subprocess.run(command, cwd=ROOT, stdout=stream, + stderr=subprocess.STDOUT, check=False, timeout=1740) + output = log.read_text(encoding="utf-8", errors="replace") + hashes = HASH.findall(output) + if result.returncode or len(hashes) != 12: + raise SystemExit(f"hash run failed or incomplete: {label}; exit={result.returncode} " + f"hashes={len(hashes)} log={log}") + row = {"dataset": dataset, "recipe": recipe, "workers": workers, + "compiler": compiler, "exit_code": result.returncode, "hashes": hashes, + "source_stamp": (STAMP.search(output).group(1) + if STAMP.search(output) else None), + "elapsed_s": round(time.monotonic() - started, 3), + "log": str(log.relative_to(ROOT))} + print("[L125HashRun] " + json.dumps(row, sort_keys=True), flush=True) + return row + + +def main() -> int: + if any(not path.is_file() for path in (*DATASETS.values(), *BINARIES.values())): + raise SystemExit("missing L125 hash input") + previous_path = ROOT / "Saved/Linux/l119/hashes/summary.json" + previous_doc = json.loads(previous_path.read_text(encoding="utf-8")) + previous = {(row["dataset"], row["recipe"], row["workers"], row["compiler"]): row + for row in previous_doc["runs"]} + rows = [] + recipes = {"owner4": ("surface-world",), + "owner2": ("surface-world", "floating-islands")} + for dataset, dataset_recipes in recipes.items(): + for recipe in dataset_recipes: + for workers in (1, 8, 12): + for compiler in ("clang", "gcc"): + rows.append(run(dataset, recipe, workers, compiler)) + (OUT / "runs-partial.json").write_text( + json.dumps(rows, indent=2) + "\n", encoding="utf-8") + groups = {} + for dataset, dataset_recipes in recipes.items(): + for recipe in dataset_recipes: + key = f"{dataset}/{recipe}" + group = [row for row in rows if row["dataset"] == dataset + and row["recipe"] == recipe] + reference = group[0]["hashes"] + stable = all(row["hashes"] == reference for row in group) + old = previous[(dataset, recipe, 12, "clang")]["hashes"] + groups[key] = { + "all_worker_compiler_hashes_match": stable, + "matches_l119_v224": next(row for row in group + if row["workers"] == 12 and row["compiler"] == "clang")["hashes"] == old, + "source_stamps": sorted({row["source_stamp"] for row in group}), + "runs": [{"workers": row["workers"], "compiler": row["compiler"], + "log": row["log"]} for row in group], + } + if not stable: + raise SystemExit(f"determinism mismatch: {key}") + summary = {"runs": rows, "groups": groups} + (OUT / "summary.json").write_text(json.dumps(summary, indent=2) + "\n", + encoding="utf-8") + baseline_dir = ROOT / "Standalone/Tools/verify/baselines/owner-hash/canonical" + for dataset, recipe, style, baseline_name in ( + ("owner4", "surface-world", 1, + "owner-hash-owner4-surface-world-style1-v225.baseline"), + ("owner2", "surface-world", 1, + "owner-hash-surface-world-style1-v225.baseline"), + ("owner2", "floating-islands", 2, + "owner-hash-floating-islands-style2-v225.baseline"), + ): + canonical = next(row for row in rows if row["dataset"] == dataset + and row["recipe"] == recipe and row["workers"] == 12 + and row["compiler"] == "clang") + baseline = baseline_dir / baseline_name + baseline.write_text("\n".join(canonical["hashes"]) + "\n", + encoding="utf-8") + print("[L125HashSummary] " + json.dumps(groups, sort_keys=True), flush=True) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux125/RunL125PassageCounts.py b/Standalone/Research/WorldAssemblerM3/Linux125/RunL125PassageCounts.py new file mode 100644 index 0000000..0d7286f --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux125/RunL125PassageCounts.py @@ -0,0 +1,172 @@ +#!/usr/bin/env python3 +"""Measure passage sweep work by stratum and LOD.""" +from __future__ import annotations + +import json +import os +import re +import subprocess +import time +from collections import defaultdict +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / os.environ.get("L125_COUNTS_DIR", "Saved/Linux/l125/counts") +DATA = ROOT / "Standalone/data/owner_world.json" +BINARY = ROOT / os.environ.get("L125_COUNTS_BINARY", + "Saved/Linux/l125/bin/VoxelForgeCoreHeadless-l125-clang") +CAMERAS = { + 0: (8.0, 16.0, -372.2626953125), + 1: (25.8369140625, 3.19921875, -737.0), + 2: (19.166015625, -14.2001953125, -753.3740234375), + 3: (-20.0625, -5.068359375, -900.353515625), +} +FIELDS = re.compile(r"([a-zA-Z0-9_]+)=([^ ]+)") +CALLERS = ( + "Unknown", "DensityGrid", "GradientNormalFallback", "MidpointCorrection", + "SkirtSurfaceVertex", "SkirtExtrudedVertex", "SkirtClippedVertex", + "SkirtRefinementFace", "SkirtCoarseCentroid", "FarShellSurfaceQuery", + "FarShellProjectionNormal", "FarShellStratumRefinement", +) + + +def records(path: Path, tag: str) -> dict[str, dict[str, str]]: + result = {} + for line in path.read_text(encoding="utf-8", errors="replace").splitlines(): + if line.startswith(tag + " "): + row = dict(FIELDS.findall(line)) + result[row["key"]] = row + return result + + +def lod_of(key: str) -> int: + return int(key.rsplit("lod", 1)[1].rstrip(")")) + + +def run(strate: int, replicate: int) -> dict: + OUT.mkdir(parents=True, exist_ok=True) + label = f"s{strate}-w8-profile{replicate}" + log = OUT / f"{label}.log" + camera = ",".join(f"{value:.12f}" for value in CAMERAS[strate]) + ",0,0" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1740s", str(BINARY), str(DATA), + "--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline", + "--workers=8", "--clip-radius=3", "--max-clip-level=8", "--max-level=8", + f"--camera={camera}", "--profile-lod-work", "--profile-passage-composer", + ] + started = time.monotonic() + peak_tree_rss_kib = 0 + with log.open("w", encoding="utf-8") as output: + process = subprocess.Popen(command, cwd=ROOT, stdout=output, + stderr=subprocess.STDOUT) + deadline = started + 1740 + page_kib = os.sysconf("SC_PAGE_SIZE") // 1024 + while process.poll() is None: + pending = [process.pid] + seen = set() + rss_kib = 0 + while pending: + pid = pending.pop() + if pid in seen: + continue + seen.add(pid) + try: + with open(f"/proc/{pid}/statm", encoding="ascii") as statm: + rss_kib += int(statm.read().split()[1]) * page_kib + with open(f"/proc/{pid}/task/{pid}/children", encoding="ascii") as children: + pending.extend(int(value) for value in children.read().split()) + except (FileNotFoundError, ProcessLookupError, PermissionError, + IndexError, ValueError): + pass + peak_tree_rss_kib = max(peak_tree_rss_kib, rss_kib) + if time.monotonic() >= deadline: + process.kill() + process.wait() + raise SystemExit(f"profile exceeded 30 minutes: {log}") + time.sleep(0.01) + return_code = process.wait() + if return_code: + raise SystemExit(f"profile failed: {log}; exit={return_code}") + + composer = records(log, "[PassageComposerTile]") + stages = records(log, "[CpuTileStages]") + counts = records(log, "[PassageSweepCount]") + per_lod: dict[int, dict] = defaultdict(lambda: { + "tiles": 0, "grid_samples": 0, "sweep_pairs": 0, + "route_candidates": 0, "carve_segment_visits": 0, + "sweep_prepare_ms": 0.0, "passage_worker_ms": 0.0, + "classify_ms": 0.0, "column_ms": 0.0, "mc_ms": 0.0, + "touched": 0, "touched_unique": 0, "body_band": 0, + "stamped_outside": 0, "cache_valid": 0, "cache_valid_unique": 0, + "shell_band": 0, "exact_band_unique": 0, + "contributing_pairs": 0, "overlap_pairs": 0, "cross_passage_overlap": 0, + "floor_profile_calls": 0, + "cache_bytes": 0, "scratch_bytes": 0, + "cache_bytes_max_tile": 0, "scratch_bytes_max_tile": 0, + "lookups": 0, "cache_hits": 0, "missing": 0, + "offgrid_miss": 0, "unprepared_miss": 0, + "missing_by_caller": [0] * len(CALLERS), + "fallback_by_caller": [0] * len(CALLERS), + }) + for key, comp in composer.items(): + lod = lod_of(key) + if lod > 2 or int(comp.get("features", "0")) == 0: + continue + stage = stages.get(key) + count = counts.get(key) + if stage is None or count is None: + raise SystemExit(f"missing stage/count row for {label} {key}") + row = per_lod[lod] + row["tiles"] += 1 + row["grid_samples"] += int(comp["sweep_grid_samples"]) + for name in ("sweep_pairs", "route_candidates", "carve_segment_visits", + "lookups", "cache_hits", "missing"): + source = {"route_candidates": "route_candidates", + "carve_segment_visits": "carve_segment_visits", + "lookups": "sweep_lookups", "cache_hits": "sweep_cache_hits", + "missing": "sweep_missing"}.get(name, name) + row[name] += int(comp[source]) + row["sweep_prepare_ms"] += float(comp["sweep_prepare_ms"]) + row["passage_worker_ms"] += float(comp["worker_ms"]) + for name in ("classify_ms", "column_ms", "mc_ms"): + row[name] += float(stage[name]) + for name in ("touched", "stamped_outside", "cache_valid", "cache_valid_unique", + "touched_unique", "body_band", "shell_band", + "exact_band_unique", "overlap_pairs", "cross_passage_overlap", + "contributing_pairs", "floor_profile_calls", + "cache_bytes", "scratch_bytes", "offgrid_miss", + "unprepared_miss"): + row[name] += int(count[name]) + row["cache_bytes_max_tile"] = max(row["cache_bytes_max_tile"], + int(count["cache_bytes"])) + row["scratch_bytes_max_tile"] = max(row["scratch_bytes_max_tile"], + int(count["scratch_bytes"])) + for name, field in (("missing_by_caller", "sweep_missing_by_caller"), + ("fallback_by_caller", "sweep_exact_fallback_by_caller")): + values = [int(value) for value in stage[field].split(",")] + row[name] = [a + b for a, b in zip(row[name], values)] + + result_row = { + "strate": strate, "workers": 8, "replicate": replicate, + "elapsed_s": round(time.monotonic() - started, 3), + "peak_tree_rss_kib": peak_tree_rss_kib, + "by_lod": {str(lod): values for lod, values in sorted(per_lod.items())}, + "log": str(log.relative_to(ROOT)), + } + print("[L125PassageCounts] " + json.dumps(result_row, sort_keys=True), flush=True) + return result_row + + +def main() -> int: + if not DATA.is_file() or not BINARY.is_file(): + raise SystemExit("missing L125 passage-counter input") + runs = [run(strate, replicate) for strate in range(4) for replicate in (1, 2)] + (OUT / "summary.json").write_text( + json.dumps({"runs": runs, "caller_names": CALLERS}, indent=2) + "\n", + encoding="utf-8") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux125/RunL125ToleranceTiming.py b/Standalone/Research/WorldAssemblerM3/Linux125/RunL125ToleranceTiming.py new file mode 100644 index 0000000..9132d1a --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux125/RunL125ToleranceTiming.py @@ -0,0 +1,138 @@ +#!/usr/bin/env python3 +"""Five interleaved L80 readiness runs for a candidate against L109/L119.""" +from __future__ import annotations + +import json +import os +import re +import statistics +import subprocess +import time +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / os.environ.get("L125_TIMING_DIR", "Saved/Linux/l125/timing") +DATA = ROOT / "Standalone/data/owner_world.json" +CANDIDATE = os.environ.get("L125_CANDIDATE_LABEL", "L125-stamp10") +BINARIES = { + "L109": ROOT / "Saved/Linux/l109/bin-final/VoxelForgeCoreHeadless-l109-clang", + "L119": ROOT / "Saved/Linux/l119/bin/VoxelForgeCoreHeadless-l119-clang", + CANDIDATE: ROOT / os.environ.get("L125_CANDIDATE_BINARY", + "Saved/Linux/l125/bin-stamp10/VoxelForgeCoreHeadless-l125-stamp10-clang"), +} +CAMERAS = { + 0: (8.0, 16.0, -372.2626953125), + 1: (25.8369140625, 3.19921875, -737.0), + 2: (19.166015625, -14.2001953125, -753.3740234375), + 3: (-20.0625, -5.068359375, -900.353515625), +} +PIPELINE = re.compile(r"^\[StreamPipeline\] (.*)$", re.M) +FIELDS = re.compile(r"([a-zA-Z0-9_]+)=([^ ]+)") +NEAR = re.compile( + r"^\[WorldAssemblerNearLODReady\] lods=0-2 tiles=(\d+)/(\d+) cold_ready_s=([0-9.]+)$", + re.M) + + +def run(strate: int, workers: int, version: str, phase: str, replicate: int) -> dict: + OUT.mkdir(parents=True, exist_ok=True) + label = f"s{strate}-w{workers}-{version}-{phase}{replicate}" + log = OUT / f"{label}.log" + camera = ",".join(f"{value:.12f}" for value in CAMERAS[strate]) + ",0,0" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1740s", str(BINARIES[version]), str(DATA), + "--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline", + f"--workers={workers}", "--clip-radius=3", "--max-clip-level=8", + "--max-level=8", f"--camera={camera}", "--profile-lod-work", + "--stream-scheduler-policy=3", + ] + started = time.monotonic() + with log.open("w", encoding="utf-8") as output: + result = subprocess.run(command, cwd=ROOT, stdout=output, + stderr=subprocess.STDOUT, check=False, timeout=1740) + content = log.read_text(encoding="utf-8", errors="replace") + pipeline_match, near_match = PIPELINE.search(content), NEAR.search(content) + if result.returncode or pipeline_match is None or near_match is None: + raise SystemExit(f"readiness run failed: {log}; exit={result.returncode}") + pipeline = dict(FIELDS.findall(pipeline_match.group(1))) + row = {"strate": strate, "workers": workers, "version": version, + "phase": phase, "replicate": replicate, "exit_code": result.returncode, + "wall_s": round(time.monotonic() - started, 3), + "lod02_ready_s": float(near_match.group(3)), + "whole_view_ready_s": float(pipeline["whole_view_ready"].removesuffix("s")), + "whole_tiles": int(pipeline["whole_tiles"].split("/")[0]), + "log": str(log.relative_to(ROOT))} + print("[L125ToleranceTimingRun] " + json.dumps(row, sort_keys=True), flush=True) + return row + + +def cpu_idle_percent(interval_s: float = 2.0) -> float: + def totals() -> tuple[int, int]: + fields = Path("/proc/stat").read_text(encoding="utf-8").splitlines()[0].split() + values = [int(value) for value in fields[1:]] + return sum(values), values[3] + (values[4] if len(values) > 4 else 0) + total_before, idle_before = totals() + time.sleep(interval_s) + total_after, idle_after = totals() + return 100.0 * (idle_after-idle_before) / max(1, total_after-total_before) + + +def main() -> int: + if not DATA.is_file() or any(not binary.is_file() for binary in BINARIES.values()): + raise SystemExit("missing timing input") + OUT.mkdir(parents=True, exist_ok=True) + load_1m, idle_pct = os.getloadavg()[0], cpu_idle_percent() + uptime = subprocess.run(["uptime"], cwd=ROOT, text=True, + capture_output=True, check=True).stdout.strip() + top = subprocess.run(["ps", "-eo", "pid,pcpu,comm", "--sort=-pcpu"], + cwd=ROOT, text=True, capture_output=True, check=True).stdout + (OUT / "machine-load-before.txt").write_text( + f"uptime: {uptime}\n1-minute load: {load_1m:.2f}\n" + f"2-second CPU idle: {idle_pct:.1f}%\ntop CPU users:\n{top}", + encoding="utf-8") + print(f"[L125ToleranceTimingGate] load_1m={load_1m:.2f} " + f"cpu_idle_2s={idle_pct:.1f}% uptime={uptime}", flush=True) + if load_1m >= 0.9 or idle_pct < 97.0: + raise SystemExit("timing refused: machine is above the quiet-load gate") + + rows = [] + versions = ("L109", "L119", CANDIDATE) + for strate in range(4): + for workers in (8, 12): + for version in versions: + run(strate, workers, version, "warmup", 0) + for replicate in range(1, 6): + offset = (replicate - 1) % len(versions) + order = versions[offset:] + versions[:offset] + for version in order: + rows.append(run(strate, workers, version, "measured", replicate)) + (OUT / "runs-partial.json").write_text( + json.dumps(rows, indent=2) + "\n", encoding="utf-8") + summary = [] + for strate in range(4): + for workers in (8, 12): + item = {"strate": strate, "workers": workers, "replicates": 5} + medians = {} + for version in versions: + group = [row for row in rows if row["strate"] == strate + and row["workers"] == workers and row["version"] == version] + medians[version] = {} + for key in ("lod02_ready_s", "whole_view_ready_s"): + values = [row[key] for row in group] + medians[version][key] = statistics.median(values) + item[f"{version}_{key}_values"] = values + item[f"{version}_{key}_median"] = medians[version][key] + for comparison in ("L109", "L119"): + for key in ("lod02_ready_s", "whole_view_ready_s"): + item[f"L125_vs_{comparison}_{key}_delta_pct"] = round( + 100.0 * (medians[CANDIDATE][key] + /medians[comparison][key]-1.0), 2) + summary.append(item) + (OUT / "summary.json").write_text( + json.dumps({"runs": rows, "summary": summary}, indent=2) + "\n", + encoding="utf-8") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux125/captures/COMPARE.html b/Standalone/Research/WorldAssemblerM3/Linux125/captures/COMPARE.html new file mode 100644 index 0000000..1ecb18d --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux125/captures/COMPARE.html @@ -0,0 +1,188 @@ + +L119 / L125 tunnel capture comparison + +

L119 / L125 v225: identical views

+
+

passage/0-1/0 — rock-floor/401.7m

+

rock-floor-close · L119 pass · L125 pass

+
+
L119
+
L125 v225
+
+
+
+

passage/0-1/0 — rock-floor/792.8m

+

rock-floor-close · L119 pass · L125 pass

+
+
L119
+
L125 v225
+
+
+
+

passage/0-1/0 — rock-floor/1634.5m

+

rock-floor-close · L119 pass · L125 pass

+
+
L119
+
L125 v225
+
+
+
+

passage/1-2/0 — rock-floor/27.0m

+

rock-floor-close · L119 pass · L125 pass

+
+
L119
+
L125 v225
+
+
+
+

passage/1-2/0 — rock-floor/52.9m

+

rock-floor-close · L119 pass · L125 pass

+
+
L119
+
L125 v225
+
+
+
+

passage/1-2/0 — rock-floor/78.9m

+

rock-floor-close · L119 pass · L125 pass

+
+
L119
+
L125 v225
+
+
+
+

passage/2-3/0 — rock-floor/323.4m

+

rock-floor-close · L119 low_contrast_geometry_visible · L125 low_contrast_geometry_visible

+
+
L119
+
L125 v225
+
+
+
+

passage/2-3/0 — rock-floor/333.4m

+

rock-floor-close · L119 pass · L125 pass

+
+
L119
+
L125 v225
+
+
+
+

passage/2-3/0 — rock-floor/343.4m

+

rock-floor-close · L119 pass · L125 pass

+
+
L119
+
L125 v225
+
+
+
+

passage/0-1/0 — section-1/4m-outside

+

open-air-close · L119 pass · L125 pass

+
+
L119
+
L125 v225
+
+
+
+

passage/0-1/0 — section-1/4m-interior-wall

+

open-air-close · L119 low_contrast_geometry_visible · L125 low_contrast_geometry_visible

+
+
L119
+
L125 v225
+
+
+
+

passage/0-1/0 — section-2/4m-outside

+

open-air-close · L119 pass · L125 pass

+
+
L119
+
L125 v225
+
+
+
+

passage/0-1/0 — section-2/4m-interior-wall

+

open-air-close · L119 pass · L125 pass

+
+
L119
+
L125 v225
+
+
+
+

passage/0-1/0 — section-3/4m-outside

+

open-air-close · L119 pass · L125 pass

+
+
L119
+
L125 v225
+
+
+
+

passage/0-1/0 — section-3/4m-interior-wall

+

open-air-close · L119 pass · L125 pass

+
+
L119
+
L125 v225
+
+
+
+

passage/1-2/0 — section-1/4m-outside

+

open-air-close · L119 pass · L125 pass

+
+
L119
+
L125 v225
+
+
+
+

passage/1-2/0 — section-1/4m-interior-wall

+

open-air-close · L119 pass · L125 pass

+
+
L119
+
L125 v225
+
+
+
+

passage/1-2/0 — section-2/4m-outside

+

open-air-close · L119 pass · L125 pass

+
+
L119
+
L125 v225
+
+
+
+

passage/1-2/0 — section-2/4m-interior-wall

+

open-air-close · L119 pass · L125 pass

+
+
L119
+
L125 v225
+
+
+
+

passage/2-3/0 — section-1/4m-outside

+

open-air-close · L119 low_contrast_geometry_visible · L125 low_contrast_geometry_visible

+
+
L119
+
L125 v225
+
+
+
+

passage/2-3/0 — section-1/4m-interior-wall

+

open-air-close · L119 low_contrast_geometry_visible · L125 low_contrast_geometry_visible

+
+
L119
+
L125 v225
+
+
+
+

passage/2-3/0 — section-2/4m-outside

+

open-air-close · L119 pass · L125 pass

+
+
L119
+
L125 v225
+
+
+
+

passage/2-3/0 — section-2/4m-interior-wall

+

open-air-close · L119 pass · L125 pass

+
+
L119
+
L125 v225
+
+
diff --git a/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/capture-index.json b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/capture-index.json new file mode 100644 index 0000000..6b146a9 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/capture-index.json @@ -0,0 +1,1562 @@ +{ + "captures": [ + { + "name": "passage-0-1-0-rock-floor-station-1", + "passage": "passage/0-1/0", + "kind": "rock-floor-close", + "station": "rock-floor/401.7m", + "camera": [ + -9.24648786798055, + 19.798675033837775, + -443.9636296749357 + ], + "target": [ + -7.026884524505579, + 20.857335392121104, + -445.66373993191075 + ], + "yaw": 64.50075976736525, + "pitch": -34.65771934187305, + "focus": [ + -7.026884524505579, + 20.857335392121104, + -445.66373993191075 + ], + "center_z": -445.66373993191075, + "route_distance_m": 401.6612010038529, + "requested_route_distance_m": 401.6612010038529, + "route_length_m": 2026.6238040154117, + "planned_floor_m": -445.66373993191075, + "planned_grade_deg": 10.372328677972732, + "variant": "L125-v225", + "capture": "captures/L125/passage-0-1-0-rock-floor-station-1.png", + "scene": "Saved/Linux/l125/captures/L125/passage-0-1-0-rock-floor-station-1.vfmesh", + "drawn_triangles": 122294, + "source_triangles": 146798, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 401.6612010038529, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -9.24648786798055, + 19.798675033837775, + -443.9636296749357 + ], + "target_actual_m": [ + -7.026884524505579, + 20.857335392121104, + -445.66373993191075 + ], + "logs": [ + "Saved/Linux/l125/captures/L125/passage-0-1-0-rock-floor-station-1-mesh.log", + "Saved/Linux/l125/captures/L125/passage-0-1-0-rock-floor-station-1-render.log", + "Saved/Linux/l125/captures/L125/passage-0-1-0-rock-floor-station-1-quality.log" + ], + "floor_anchor_position_m": [ + -7.026885053959959, + 20.857335155432953, + -445.66374310012867 + ], + "floor_anchor_normal": [ + 0.16438021494383692, + 0.07357583212203939, + 0.9836491965444629 + ], + "closeup_camera_to_floor_distance_m": 2.989612610955708, + "closeup_floor_normal_alignment": 0.9836491965444629, + "verified_upward_floor_normal": true + }, + { + "name": "passage-0-1-0-rock-floor-station-2", + "passage": "passage/0-1/0", + "kind": "rock-floor-close", + "station": "rock-floor/792.8m", + "camera": [ + -0.021280083711839648, + -26.43771312964049, + -514.3617561596035 + ], + "target": [ + -2.4714859241065525, + -26.227784739959716, + -516.0616688299093 + ], + "yaw": -85.10297944703369, + "pitch": -34.654210347383824, + "focus": [ + -2.4714859241065525, + -26.227784739959716, + -516.0616688299093 + ], + "center_z": -516.0616688299093, + "route_distance_m": 792.8284020077059, + "requested_route_distance_m": 792.8284020077059, + "route_length_m": 2026.6238040154117, + "planned_floor_m": -516.0616688299093, + "planned_grade_deg": 10.367725129664787, + "variant": "L125-v225", + "capture": "captures/L125/passage-0-1-0-rock-floor-station-2.png", + "scene": "Saved/Linux/l125/captures/L125/passage-0-1-0-rock-floor-station-2.vfmesh", + "drawn_triangles": 586092, + "source_triangles": 626196, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 792.8284020077059, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -0.021280083711839648, + -26.43771312964049, + -514.3617561596035 + ], + "target_actual_m": [ + -2.4714859241065525, + -26.227784739959716, + -516.0616688299093 + ], + "logs": [ + "Saved/Linux/l125/captures/L125/passage-0-1-0-rock-floor-station-2-mesh.log", + "Saved/Linux/l125/captures/L125/passage-0-1-0-rock-floor-station-2-render.log", + "Saved/Linux/l125/captures/L125/passage-0-1-0-rock-floor-station-2-quality.log" + ], + "floor_anchor_position_m": [ + -2.471476828908, + -26.227785976319144, + -516.0617189697925 + ], + "floor_anchor_normal": [ + -0.179115780575022, + 0.024140888419756926, + 0.9835317761289187 + ], + "closeup_camera_to_floor_distance_m": 2.9895496409822853, + "closeup_floor_normal_alignment": 0.9835317761289187, + "verified_upward_floor_normal": true + }, + { + "name": "passage-0-1-0-rock-floor-station-3", + "passage": "passage/0-1/0", + "kind": "rock-floor-close", + "station": "rock-floor/1634.5m", + "camera": [ + 15.717287112180728, + 19.71739973195528, + -665.8352816543407 + ], + "target": [ + 17.336220092016376, + 17.86620742417785, + -667.5348848643227 + ], + "yaw": 138.82915885966676, + "pitch": -34.64871452830556, + "focus": [ + 17.336220092016376, + 17.86620742417785, + -667.5348848643227 + ], + "center_z": -667.5348848643227, + "route_distance_m": 1634.4566030115589, + "requested_route_distance_m": 1634.4566030115589, + "route_length_m": 2026.6238040154117, + "planned_floor_m": -667.5348848643227, + "planned_grade_deg": 10.360515186362372, + "variant": "L125-v225", + "capture": "captures/L125/passage-0-1-0-rock-floor-station-3.png", + "scene": "Saved/Linux/l125/captures/L125/passage-0-1-0-rock-floor-station-3.vfmesh", + "drawn_triangles": 137288, + "source_triangles": 166736, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1634.4566030115589, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 15.717287112180728, + 19.71739973195528, + -665.8352816543407 + ], + "target_actual_m": [ + 17.336220092016376, + 17.86620742417785, + -667.5348848643227 + ], + "logs": [ + "Saved/Linux/l125/captures/L125/passage-0-1-0-rock-floor-station-3-mesh.log", + "Saved/Linux/l125/captures/L125/passage-0-1-0-rock-floor-station-3-render.log", + "Saved/Linux/l125/captures/L125/passage-0-1-0-rock-floor-station-3-quality.log" + ], + "floor_anchor_position_m": [ + 17.33622182815858, + 17.866205324064538, + -667.534869956066 + ], + "floor_anchor_normal": [ + 0.11463807621472542, + -0.13864390562764303, + 0.9836848981834071 + ], + "closeup_camera_to_floor_distance_m": 2.9893930396931125, + "closeup_floor_normal_alignment": 0.9836848981834071, + "verified_upward_floor_normal": true + }, + { + "name": "passage-1-2-0-rock-floor-station-1", + "passage": "passage/1-2/0", + "kind": "rock-floor-close", + "station": "rock-floor/27.0m", + "camera": [ + 15.990262769683945, + 2.495369317804175, + -736.4846720823747 + ], + "target": [ + 15.354493464592624, + 4.868558240151556, + -738.1970266319915 + ], + "yaw": -14.99718988160138, + "pitch": -34.875140724394136, + "focus": [ + 15.354493464592624, + 4.868558240151556, + -738.1970266319915 + ], + "center_z": -738.1970266319915, + "route_distance_m": 26.963657939523273, + "requested_route_distance_m": 26.963657939523273, + "route_length_m": 114.99063175809309, + "planned_floor_m": -738.1970266319915, + "planned_grade_deg": 10.657740387934142, + "variant": "L125-v225", + "capture": "captures/L125/passage-1-2-0-rock-floor-station-1.png", + "scene": "Saved/Linux/l125/captures/L125/passage-1-2-0-rock-floor-station-1.vfmesh", + "drawn_triangles": 652056, + "source_triangles": 719660, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 26.963657939523273, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 15.990262769683945, + 2.495369317804175, + -736.4846720823747 + ], + "target_actual_m": [ + 15.354493464592624, + 4.868558240151556, + -738.1970266319915 + ], + "logs": [ + "Saved/Linux/l125/captures/L125/passage-1-2-0-rock-floor-station-1-mesh.log", + "Saved/Linux/l125/captures/L125/passage-1-2-0-rock-floor-station-1-render.log", + "Saved/Linux/l125/captures/L125/passage-1-2-0-rock-floor-station-1-quality.log" + ], + "floor_anchor_position_m": [ + 15.354124807038394, + 4.869920275450426, + -738.1895881032126 + ], + "floor_anchor_normal": [ + -0.047307387705878, + 0.17883124580074233, + 0.9827417751341397 + ], + "closeup_camera_to_floor_distance_m": 2.9916387475909154, + "closeup_floor_normal_alignment": 0.9827417751341397, + "verified_upward_floor_normal": true + }, + { + "name": "passage-1-2-0-rock-floor-station-2", + "passage": "passage/1-2/0", + "kind": "rock-floor-close", + "station": "rock-floor/52.9m", + "camera": [ + -2.48434493546405, + 15.983647301702653, + -741.2835409028854 + ], + "target": [ + -4.76517685476837, + 15.070128626649932, + -742.995373541633 + ], + "yaw": -111.82708648318167, + "pitch": -34.86587426337977, + "focus": [ + -4.76517685476837, + 15.070128626649932, + -742.995373541633 + ], + "center_z": -742.995373541633, + "route_distance_m": 52.927315879046546, + "requested_route_distance_m": 52.927315879046546, + "route_length_m": 114.99063175809309, + "planned_floor_m": -742.995373541633, + "planned_grade_deg": 10.645569354114926, + "variant": "L125-v225", + "capture": "captures/L125/passage-1-2-0-rock-floor-station-2.png", + "scene": "Saved/Linux/l125/captures/L125/passage-1-2-0-rock-floor-station-2.vfmesh", + "drawn_triangles": 636162, + "source_triangles": 700558, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 52.927315879046546, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -2.48434493546405, + 15.983647301702653, + -741.2835409028854 + ], + "target_actual_m": [ + -4.76517685476837, + 15.070128626649932, + -742.995373541633 + ], + "logs": [ + "Saved/Linux/l125/captures/L125/passage-1-2-0-rock-floor-station-2-mesh.log", + "Saved/Linux/l125/captures/L125/passage-1-2-0-rock-floor-station-2-render.log", + "Saved/Linux/l125/captures/L125/passage-1-2-0-rock-floor-station-2-quality.log" + ], + "floor_anchor_position_m": [ + -4.766428465537912, + 15.069671584786441, + -742.988228337538 + ], + "floor_anchor_normal": [ + -0.1744301807701029, + -0.061608715063684795, + 0.9827402903436447 + ], + "closeup_camera_to_floor_distance_m": 2.9915240428933867, + "closeup_floor_normal_alignment": 0.9827402903436447, + "verified_upward_floor_normal": true + }, + { + "name": "passage-1-2-0-rock-floor-station-3", + "passage": "passage/1-2/0", + "kind": "rock-floor-close", + "station": "rock-floor/78.9m", + "camera": [ + -13.44544511010513, + -3.995230772069307, + -746.0839041050349 + ], + "target": [ + -12.287009401722694, + -6.161841337747165, + -747.7963166548619 + ], + "yaw": 151.8676321960706, + "pitch": -34.87617050502889, + "focus": [ + -12.287009401722694, + -6.161841337747165, + -747.7963166548619 + ], + "center_z": -747.7963166548619, + "route_distance_m": 78.89097381856982, + "requested_route_distance_m": 78.89097381856982, + "route_length_m": 114.99063175809309, + "planned_floor_m": -747.7963166548619, + "planned_grade_deg": 10.659092990906162, + "variant": "L125-v225", + "capture": "captures/L125/passage-1-2-0-rock-floor-station-3.png", + "scene": "Saved/Linux/l125/captures/L125/passage-1-2-0-rock-floor-station-3.vfmesh", + "drawn_triangles": 580472, + "source_triangles": 639376, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 78.89097381856982, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -13.44544511010513, + -3.995230772069307, + -746.0839041050349 + ], + "target_actual_m": [ + -12.287009401722694, + -6.161841337747165, + -747.7963166548619 + ], + "logs": [ + "Saved/Linux/l125/captures/L125/passage-1-2-0-rock-floor-station-3-mesh.log", + "Saved/Linux/l125/captures/L125/passage-1-2-0-rock-floor-station-3-render.log", + "Saved/Linux/l125/captures/L125/passage-1-2-0-rock-floor-station-3-quality.log" + ], + "floor_anchor_position_m": [ + -12.283352972838873, + -6.167679829029396, + -747.554756449892 + ], + "floor_anchor_normal": [ + 0.09692807602747124, + -0.15782686841357624, + 0.9826981366036961 + ], + "closeup_camera_to_floor_distance_m": 2.8693901200350096, + "closeup_floor_normal_alignment": 0.9826981366036961, + "verified_upward_floor_normal": true + }, + { + "name": "passage-2-3-0-rock-floor-station-1", + "passage": "passage/2-3/0", + "kind": "rock-floor-close", + "station": "rock-floor/323.4m", + "camera": [ + 6.997568341188331, + -14.934306981606339, + -869.3796844648476 + ], + "target": [ + 9.102823911740126, + -13.661883549736208, + -871.0755965556104 + ], + "yaw": 58.85109570948622, + "pitch": -34.583159686285406, + "focus": [ + 9.102823911740126, + -13.661883549736208, + -871.0755965556104 + ], + "center_z": -871.0755965556104, + "route_distance_m": 323.4481319239866, + "requested_route_distance_m": 323.4481319239866, + "route_length_m": 494.0722798830563, + "planned_floor_m": -871.0755965556104, + "planned_grade_deg": 10.274530613220444, + "variant": "L125-v225", + "capture": "captures/L125/passage-2-3-0-rock-floor-station-1.png", + "scene": "Saved/Linux/l125/captures/L125/passage-2-3-0-rock-floor-station-1.vfmesh", + "drawn_triangles": 474964, + "source_triangles": 502362, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 323.4481319239866, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 6.997568341188331, + -14.934306981606339, + -869.3796844648476 + ], + "target_actual_m": [ + 9.102823911740126, + -13.661883549736208, + -871.0755965556104 + ], + "logs": [ + "Saved/Linux/l125/captures/L125/passage-2-3-0-rock-floor-station-1-mesh.log", + "Saved/Linux/l125/captures/L125/passage-2-3-0-rock-floor-station-1-render.log", + "Saved/Linux/l125/captures/L125/passage-2-3-0-rock-floor-station-1-quality.log" + ], + "floor_anchor_position_m": [ + 9.103799793973732, + -13.661094033901383, + -871.068656948616 + ], + "floor_anchor_normal": [ + 0.14021616794161246, + 0.11018123609139711, + 0.9839713011369495 + ], + "closeup_camera_to_floor_distance_m": 2.9849472681829123, + "closeup_floor_normal_alignment": 0.9839713011369495, + "verified_upward_floor_normal": true + }, + { + "name": "passage-2-3-0-rock-floor-station-2", + "passage": "passage/2-3/0", + "kind": "rock-floor-close", + "station": "rock-floor/333.4m", + "camera": [ + 14.426607883839745, + -8.501776133009574, + -871.1605818845352 + ], + "target": [ + 15.203729308783775, + -6.16777561793481, + -872.8561420785873 + ], + "yaw": 18.41553205389999, + "pitch": -34.576909662847896, + "focus": [ + 15.203729308783775, + -6.16777561793481, + -872.8561420785873 + ], + "center_z": -872.8561420785873, + "route_distance_m": 333.4481319239866, + "requested_route_distance_m": 333.4481319239866, + "route_length_m": 494.0722798830563, + "planned_floor_m": -872.8561420785873, + "planned_grade_deg": 10.266334408339132, + "variant": "L125-v225", + "capture": "captures/L125/passage-2-3-0-rock-floor-station-2.png", + "scene": "Saved/Linux/l125/captures/L125/passage-2-3-0-rock-floor-station-2.vfmesh", + "drawn_triangles": 494504, + "source_triangles": 524342, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 333.4481319239866, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 14.426607883839745, + -8.501776133009574, + -871.1605818845352 + ], + "target_actual_m": [ + 15.203729308783775, + -6.16777561793481, + -872.8561420785873 + ], + "logs": [ + "Saved/Linux/l125/captures/L125/passage-2-3-0-rock-floor-station-2-mesh.log", + "Saved/Linux/l125/captures/L125/passage-2-3-0-rock-floor-station-2-render.log", + "Saved/Linux/l125/captures/L125/passage-2-3-0-rock-floor-station-2-quality.log" + ], + "floor_anchor_position_m": [ + 15.204108325185125, + -6.1664350574610705, + -872.848494535829 + ], + "floor_anchor_normal": [ + 0.0468360027958031, + 0.17218671405633393, + 0.9839502651783747 + ], + "closeup_camera_to_floor_distance_m": 2.9845224063213145, + "closeup_floor_normal_alignment": 0.9839502651783747, + "verified_upward_floor_normal": true + }, + { + "name": "passage-2-3-0-rock-floor-station-3", + "passage": "passage/2-3/0", + "kind": "rock-floor-close", + "station": "rock-floor/343.4m", + "camera": [ + 16.176045301879554, + 1.1336183974400118, + -872.9426489764151 + ], + "target": [ + 15.465325445603714, + 3.4887437417106955, + -874.6379150751349 + ], + "yaw": -16.792543840841383, + "pitch": -34.57168620892087, + "focus": [ + 15.465325445603714, + 3.4887437417106955, + -874.6379150751349 + ], + "center_z": -874.6379150751349, + "route_distance_m": 343.4481319239866, + "requested_route_distance_m": 343.4481319239866, + "route_length_m": 494.0722798830563, + "planned_floor_m": -874.6379150751349, + "planned_grade_deg": 10.259484647608062, + "variant": "L125-v225", + "capture": "captures/L125/passage-2-3-0-rock-floor-station-3.png", + "scene": "Saved/Linux/l125/captures/L125/passage-2-3-0-rock-floor-station-3.vfmesh", + "drawn_triangles": 485356, + "source_triangles": 512664, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 343.4481319239866, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 16.176045301879554, + 1.1336183974400118, + -872.9426489764151 + ], + "target_actual_m": [ + 15.465325445603714, + 3.4887437417106955, + -874.6379150751349 + ], + "logs": [ + "Saved/Linux/l125/captures/L125/passage-2-3-0-rock-floor-station-3-mesh.log", + "Saved/Linux/l125/captures/L125/passage-2-3-0-rock-floor-station-3-render.log", + "Saved/Linux/l125/captures/L125/passage-2-3-0-rock-floor-station-3-quality.log" + ], + "floor_anchor_position_m": [ + 15.464091528009144, + 3.4924186701988678, + -874.5280427606272 + ], + "floor_anchor_normal": [ + -0.061689200676463656, + 0.16755705537563617, + 0.9839304221913991 + ], + "closeup_camera_to_floor_distance_m": 2.9298959629846824, + "closeup_floor_normal_alignment": 0.9839304221913991, + "verified_upward_floor_normal": true + }, + { + "name": "passage-0-1-0-openair-1-4m-outside", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-1/4m-outside", + "camera": [ + 13.176702021211483, + 7.149068417345486, + -374.402 + ], + "target": [ + 9.197121888971225, + 7.5527291301707695, + -374.402 + ], + "yaw": -84.20812706837869, + "pitch": 0.0, + "focus": [ + 7.272, + 7.748, + -373.197 + ], + "center_z": -373.197, + "open_air_section": 1, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.9948950330600643, + -0.1009151782063209, + 0.0 + ], + "camera_target_distance_m": 4.000000000000001, + "route_distance_m": 8.3545, + "requested_route_distance_m": 8.3545, + "route_length_m": 2026.6238040154117, + "variant": "L125-v225", + "capture": "captures/L125/passage-0-1-0-openair-1-4m-outside.png", + "scene": "Saved/Linux/l125/captures/L125/passage-0-1-0-openair-1-4m-outside.vfmesh", + "drawn_triangles": 275333, + "source_triangles": 327745, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 8.3545, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.999999999999992, + "closeup_target_surface_distance_m": 0.794053842406799, + "closeup_predicted_target_offset_m": 0.794053842406799, + "closeup_wall_normal_alignment": 0.9449803535183738, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 12.920589450293994, + 7.974422667153486, + -375.0086678277374 + ], + "target_actual_m": [ + 9.12386703491211, + 8.0, + -373.75 + ], + "logs": [ + "Saved/Linux/l125/captures/L125/passage-0-1-0-openair-1-4m-outside-mesh.log", + "Saved/Linux/l125/captures/L125/passage-0-1-0-openair-1-4m-outside-render.log", + "Saved/Linux/l125/captures/L125/passage-0-1-0-openair-1-4m-outside-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-1-4m-interior-wall", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-1/4m-interior-wall", + "camera": [ + 7.395778712540976, + 3.8749008126934172, + -374.89997477205173 + ], + "target": [ + 8.778272394312646, + 7.595214286886338, + -374.402 + ], + "yaw": 20.38540702862518, + "pitch": 7.1515181408188955, + "focus": [ + 7.272, + 7.748, + -373.197 + ], + "center_z": -373.197, + "open_air_section": 1, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.9948950330600643, + 0.1009151782063209, + -0.0 + ], + "camera_target_distance_m": 3.9999999999999973, + "route_distance_m": 8.3545, + "requested_route_distance_m": 8.3545, + "route_length_m": 2026.6238040154117, + "variant": "L125-v225", + "capture": "captures/L125/passage-0-1-0-openair-1-4m-interior-wall.png", + "scene": "Saved/Linux/l125/captures/L125/passage-0-1-0-openair-1-4m-interior-wall.vfmesh", + "drawn_triangles": 308012, + "source_triangles": 368124, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 8.3545, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.999999999999992, + "closeup_target_surface_distance_m": 0.8416597466625043, + "closeup_predicted_target_offset_m": 0.8416597466625043, + "closeup_wall_normal_alignment": 0.9449803535183738, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 5.327144619530225, + 8.025577332846515, + -372.4913321722626 + ], + "target_actual_m": [ + 9.12386703491211, + 8.0, + -373.75 + ], + "logs": [ + "Saved/Linux/l125/captures/L125/passage-0-1-0-openair-1-4m-interior-wall-mesh.log", + "Saved/Linux/l125/captures/L125/passage-0-1-0-openair-1-4m-interior-wall-render.log", + "Saved/Linux/l125/captures/L125/passage-0-1-0-openair-1-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-2-4m-outside", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-2/4m-outside", + "camera": [ + 12.814097656232029, + 0.949800892309409, + -375.51163279923776 + ], + "target": [ + 8.842807594702599, + 1.4281890685821654, + -375.51163279923776 + ], + "yaw": -83.1311525734364, + "pitch": 0.0, + "focus": [ + 6.603, + 1.698, + -374.149 + ], + "center_z": -374.149, + "open_air_section": 2, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.9928225153823576, + -0.1195970440681891, + 0.0 + ], + "camera_target_distance_m": 4.0, + "route_distance_m": 14.4925, + "requested_route_distance_m": 14.4925, + "route_length_m": 2026.6238040154117, + "variant": "L125-v225", + "capture": "captures/L125/passage-0-1-0-openair-2-4m-outside.png", + "scene": "Saved/Linux/l125/captures/L125/passage-0-1-0-openair-2-4m-outside.vfmesh", + "drawn_triangles": 275333, + "source_triangles": 327745, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 14.4925, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.999999999999995, + "closeup_target_surface_distance_m": 1.0963161771133416, + "closeup_predicted_target_offset_m": 1.0963161771133416, + "closeup_wall_normal_alignment": 0.39413995490510356, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 9.613469253122387, + 1.5471847686714795, + -379.60073544787906 + ], + "target_actual_m": [ + 7.959597110748291, + 1.0, + -376.0 + ], + "logs": [ + "Saved/Linux/l125/captures/L125/passage-0-1-0-openair-2-4m-outside-mesh.log", + "Saved/Linux/l125/captures/L125/passage-0-1-0-openair-2-4m-outside-render.log", + "Saved/Linux/l125/captures/L125/passage-0-1-0-openair-2-4m-outside-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-2-4m-interior-wall", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-2/4m-interior-wall", + "camera": [ + 6.939570778854576, + -2.1803140897652855, + -376.2060303004211 + ], + "target": [ + 8.388084903173432, + 1.4829657169105679, + -375.51163279923776 + ], + "yaw": 21.574563086437188, + "pitch": 9.997160707081923, + "focus": [ + 6.603, + 1.698, + -374.149 + ], + "center_z": -374.149, + "open_air_section": 2, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.9928225153823576, + 0.1195970440681891, + -0.0 + ], + "camera_target_distance_m": 3.999999999999997, + "route_distance_m": 14.4925, + "requested_route_distance_m": 14.4925, + "route_length_m": 2026.6238040154117, + "variant": "L125-v225", + "capture": "captures/L125/passage-0-1-0-openair-2-4m-interior-wall.png", + "scene": "Saved/Linux/l125/captures/L125/passage-0-1-0-openair-2-4m-interior-wall.vfmesh", + "drawn_triangles": 345026, + "source_triangles": 414658, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 14.4925, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.000000000000001, + "closeup_target_surface_distance_m": 0.7732263275133904, + "closeup_predicted_target_offset_m": 0.7732263275133904, + "closeup_wall_normal_alignment": 0.286757829360229, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 6.619154002331269, + 0.5694445029418322, + -372.249825471136 + ], + "target_actual_m": [ + 7.85216206252137, + 1.2143337388310353, + -376.0 + ], + "logs": [ + "Saved/Linux/l125/captures/L125/passage-0-1-0-openair-2-4m-interior-wall-mesh.log", + "Saved/Linux/l125/captures/L125/passage-0-1-0-openair-2-4m-interior-wall-render.log", + "Saved/Linux/l125/captures/L125/passage-0-1-0-openair-2-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-3-4m-outside", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-3/4m-outside", + "camera": [ + -28.32291429976088, + -16.444327461849063, + -600.6066327992378 + ], + "target": [ + -25.004026673221745, + -14.211619482196229, + -600.6066327992378 + ], + "yaw": 56.07018168236039, + "pitch": 0.0, + "focus": [ + -22.1, + -12.258, + -599.244 + ], + "center_z": -599.244, + "open_air_section": 3, + "closeup_side": "outside", + "closeup_preferred_normal": [ + -0.8297219066347834, + -0.5581769949132084, + 0.0 + ], + "camera_target_distance_m": 4.000000000000001, + "route_distance_m": 1265.3425000000002, + "requested_route_distance_m": 1265.3425000000002, + "route_length_m": 2026.6238040154117, + "variant": "L125-v225", + "capture": "captures/L125/passage-0-1-0-openair-3-4m-outside.png", + "scene": "Saved/Linux/l125/captures/L125/passage-0-1-0-openair-3-4m-outside.vfmesh", + "drawn_triangles": 149234, + "source_triangles": 181128, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1265.3425000000002, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.9999999999999907, + "closeup_target_surface_distance_m": 0.06836631107301705, + "closeup_predicted_target_offset_m": 0.06836631107301705, + "closeup_wall_normal_alignment": 0.9604329420550252, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -28.63982379180018, + -15.582695163623317, + -601.2438490311043 + ], + "target_actual_m": [ + -24.955621627611308, + -14.176566764792845, + -600.5734332352072 + ], + "logs": [ + "Saved/Linux/l125/captures/L125/passage-0-1-0-openair-3-4m-outside-mesh.log", + "Saved/Linux/l125/captures/L125/passage-0-1-0-openair-3-4m-outside-render.log", + "Saved/Linux/l125/captures/L125/passage-0-1-0-openair-3-4m-outside-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-3-4m-interior-wall", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-3/4m-interior-wall", + "camera": [ + -26.071689640946218, + -10.338278587083852, + -601.3036807194 + ], + "target": [ + -24.774901932566983, + -14.057480898923608, + -600.6066327992378 + ], + "yaw": 160.77768453528284, + "pitch": 10.035712777782798, + "focus": [ + -22.1, + -12.258, + -599.244 + ], + "center_z": -599.244, + "open_air_section": 3, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + 0.8297219066347834, + 0.5581769949132084, + -0.0 + ], + "camera_target_distance_m": 4.000000000000005, + "route_distance_m": 1265.3425000000002, + "requested_route_distance_m": 1265.3425000000002, + "route_length_m": 2026.6238040154117, + "variant": "L125-v225", + "capture": "captures/L125/passage-0-1-0-openair-3-4m-interior-wall.png", + "scene": "Saved/Linux/l125/captures/L125/passage-0-1-0-openair-3-4m-interior-wall.vfmesh", + "drawn_triangles": 148100, + "source_triangles": 180244, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1265.3425000000002, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.000000000000004, + "closeup_target_surface_distance_m": 0.15667051955483755, + "closeup_predicted_target_offset_m": 0.15667051955483755, + "closeup_wall_normal_alignment": 0.936006465878356, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -21.875641690065105, + -11.887416826703374, + -599.3020917133557 + ], + "target_actual_m": [ + -24.866552934428398, + -14.149067333208382, + -600.6947104389109 + ], + "logs": [ + "Saved/Linux/l125/captures/L125/passage-0-1-0-openair-3-4m-interior-wall-mesh.log", + "Saved/Linux/l125/captures/L125/passage-0-1-0-openair-3-4m-interior-wall-render.log", + "Saved/Linux/l125/captures/L125/passage-0-1-0-openair-3-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-1-4m-outside", + "passage": "passage/1-2/0", + "kind": "open-air-close", + "station": "section-1/4m-outside", + "camera": [ + -4.699079444431819, + -4.6537955842685985, + -748.15 + ], + "target": [ + -7.452748333327923, + -7.555055250400828, + -748.15 + ], + "yaw": -136.49505148095557, + "pitch": 0.0, + "focus": [ + -9.518, + -9.731, + -745.88 + ], + "center_z": -745.88, + "open_air_section": 1, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.688417222224026, + 0.7253149165330574, + 0.0 + ], + "camera_target_distance_m": 4.000000000000001, + "route_distance_m": 83.504, + "requested_route_distance_m": 83.504, + "route_length_m": 114.99063175809309, + "variant": "L125-v225", + "capture": "captures/L125/passage-1-2-0-openair-1-4m-outside.png", + "scene": "Saved/Linux/l125/captures/L125/passage-1-2-0-openair-1-4m-outside.vfmesh", + "drawn_triangles": 620814, + "source_triangles": 684776, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 83.504, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.9999999999999654, + "closeup_target_surface_distance_m": 0.9023580264896125, + "closeup_predicted_target_offset_m": 0.9023580264896125, + "closeup_wall_normal_alignment": 0.5604211333378514, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -8.046760432303138, + -4.114982136123087, + -749.9844534333902 + ], + "target_actual_m": [ + -8.0, + -7.25, + -747.5006103515625 + ], + "logs": [ + "Saved/Linux/l125/captures/L125/passage-1-2-0-openair-1-4m-outside-mesh.log", + "Saved/Linux/l125/captures/L125/passage-1-2-0-openair-1-4m-outside-render.log", + "Saved/Linux/l125/captures/L125/passage-1-2-0-openair-1-4m-outside-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-1-4m-interior-wall", + "passage": "passage/1-2/0", + "kind": "open-air-close", + "station": "section-1/4m-interior-wall", + "camera": [ + -6.0956279351195075, + -11.653774892861163, + -748.8673569837389 + ], + "target": [ + -8.16773669839842, + -8.308365466344922, + -748.15 + ], + "yaw": -31.773605793127505, + "pitch": 10.331275124559749, + "focus": [ + -9.518, + -9.731, + -745.88 + ], + "center_z": -745.88, + "open_air_section": 1, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.688417222224026, + -0.7253149165330574, + -0.0 + ], + "camera_target_distance_m": 3.999999999999997, + "route_distance_m": 83.504, + "requested_route_distance_m": 83.504, + "route_length_m": 114.99063175809309, + "variant": "L125-v225", + "capture": "captures/L125/passage-1-2-0-openair-1-4m-interior-wall.png", + "scene": "Saved/Linux/l125/captures/L125/passage-1-2-0-openair-1-4m-interior-wall.vfmesh", + "drawn_triangles": 609757, + "source_triangles": 668131, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 83.504, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.999999999999999, + "closeup_target_surface_distance_m": 0.6509430039577998, + "closeup_predicted_target_offset_m": 0.6509430039577998, + "closeup_wall_normal_alignment": 0.7808473937095911, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -8.525095579521167, + -12.94135557024142, + -748.3220319510015 + ], + "target_actual_m": [ + -8.18421537084871, + -8.958641713644115, + -748.1744141343152 + ], + "logs": [ + "Saved/Linux/l125/captures/L125/passage-1-2-0-openair-1-4m-interior-wall-mesh.log", + "Saved/Linux/l125/captures/L125/passage-1-2-0-openair-1-4m-interior-wall-render.log", + "Saved/Linux/l125/captures/L125/passage-1-2-0-openair-1-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-2-4m-outside", + "passage": "passage/1-2/0", + "kind": "open-air-close", + "station": "section-2/4m-outside", + "camera": [ + 6.53817273275958, + -4.657210376135293, + -752.013 + ], + "target": [ + 8.159152142647708, + -8.31404312493838, + -752.013 + ], + "yaw": 156.09352823535562, + "pitch": 0.0, + "focus": [ + 9.43, + -11.181, + -749.743 + ], + "center_z": -749.743, + "open_air_section": 2, + "closeup_side": "outside", + "closeup_preferred_normal": [ + -0.40524485247203174, + 0.9142081872007717, + 0.0 + ], + "camera_target_distance_m": 4.0, + "route_distance_m": 104.362, + "requested_route_distance_m": 104.362, + "route_length_m": 114.99063175809309, + "variant": "L125-v225", + "capture": "captures/L125/passage-1-2-0-openair-2-4m-outside.png", + "scene": "Saved/Linux/l125/captures/L125/passage-1-2-0-openair-2-4m-outside.vfmesh", + "drawn_triangles": 584542, + "source_triangles": 637002, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 104.362, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.0, + "closeup_target_surface_distance_m": 0.5901774459243846, + "closeup_predicted_target_offset_m": 0.5901774459243846, + "closeup_wall_normal_alignment": 0.9891249705782158, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 6.359624549359488, + -5.416552010781576, + -752.0616659309658 + ], + "target_actual_m": [ + 8.5, + -8.79556763526633, + -752.0293187551489 + ], + "logs": [ + "Saved/Linux/l125/captures/L125/passage-1-2-0-openair-2-4m-outside-mesh.log", + "Saved/Linux/l125/captures/L125/passage-1-2-0-openair-2-4m-outside-render.log", + "Saved/Linux/l125/captures/L125/passage-1-2-0-openair-2-4m-outside-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-2-4m-interior-wall", + "passage": "passage/1-2/0", + "kind": "open-air-close", + "station": "section-2/4m-interior-wall", + "camera": [ + 12.438590152225206, + -8.574465388721983, + -752.7261335058829 + ], + "target": [ + 8.55317187096847, + -9.20292810238377, + -752.013 + ], + "yaw": -99.18796190221158, + "pitch": 10.269787281460902, + "focus": [ + 9.43, + -11.181, + -749.743 + ], + "center_z": -749.743, + "open_air_section": 2, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + 0.40524485247203174, + -0.9142081872007717, + -0.0 + ], + "camera_target_distance_m": 3.9999999999999973, + "route_distance_m": 104.362, + "requested_route_distance_m": 104.362, + "route_length_m": 114.99063175809309, + "variant": "L125-v225", + "capture": "captures/L125/passage-1-2-0-openair-2-4m-interior-wall.png", + "scene": "Saved/Linux/l125/captures/L125/passage-1-2-0-openair-2-4m-interior-wall.vfmesh", + "drawn_triangles": 572258, + "source_triangles": 618646, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 104.362, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.000000000000001, + "closeup_target_surface_distance_m": 0.353159827911248, + "closeup_predicted_target_offset_m": 0.353159827911248, + "closeup_wall_normal_alignment": 0.9983988827266467, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 9.748104215680776, + -12.666965794821667, + -752.0265932958123 + ], + "target_actual_m": [ + 8.335827076712103, + -8.924626207433736, + -752.0074179101423 + ], + "logs": [ + "Saved/Linux/l125/captures/L125/passage-1-2-0-openair-2-4m-interior-wall-mesh.log", + "Saved/Linux/l125/captures/L125/passage-1-2-0-openair-2-4m-interior-wall-render.log", + "Saved/Linux/l125/captures/L125/passage-1-2-0-openair-2-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-1-4m-outside", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-1/4m-outside", + "camera": [ + -3.5840423774965293, + -5.521048309862215, + -815.8969999999999 + ], + "target": [ + -5.637732447498513, + -8.953592132798093, + -815.8969999999999 + ], + "yaw": -149.10792796365394, + "pitch": 0.0, + "focus": [ + -7.178, + -11.528, + -813.627 + ], + "center_z": -813.627, + "open_air_section": 1, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.5134225175004958, + 0.8581359557339694, + 0.0 + ], + "camera_target_distance_m": 4.0, + "route_distance_m": 16.616500000000002, + "requested_route_distance_m": 16.616500000000002, + "route_length_m": 494.0722798830563, + "variant": "L125-v225", + "capture": "captures/L125/passage-2-3-0-openair-1-4m-outside.png", + "scene": "Saved/Linux/l125/captures/L125/passage-2-3-0-openair-1-4m-outside.vfmesh", + "drawn_triangles": 104612, + "source_triangles": 129326, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 16.616500000000002, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.0000000000000036, + "closeup_target_surface_distance_m": 0.29188924025474844, + "closeup_predicted_target_offset_m": 0.29188924025474844, + "closeup_wall_normal_alignment": 0.6703275045296155, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -3.7918253987505834, + -7.16028175130118, + -813.227396563761 + ], + "target_actual_m": [ + -5.7833741859987065, + -9.093313475424294, + -816.1078690565205 + ], + "logs": [ + "Saved/Linux/l125/captures/L125/passage-2-3-0-openair-1-4m-outside-mesh.log", + "Saved/Linux/l125/captures/L125/passage-2-3-0-openair-1-4m-outside-render.log", + "Saved/Linux/l125/captures/L125/passage-2-3-0-openair-1-4m-outside-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-1-4m-interior-wall", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-1/4m-interior-wall", + "camera": [ + -3.4141605326349946, + -12.659565888737353, + -816.5879167710818 + ], + "target": [ + -6.170971760123668, + -9.844849940114793, + -815.8969999999999 + ], + "yaw": -44.40454805561343, + "pitch": 9.946538162082001, + "focus": [ + -7.178, + -11.528, + -813.627 + ], + "center_z": -813.627, + "open_air_section": 1, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.5134225175004958, + -0.8581359557339694, + -0.0 + ], + "camera_target_distance_m": 4.000000000000005, + "route_distance_m": 16.616500000000002, + "requested_route_distance_m": 16.616500000000002, + "route_length_m": 494.0722798830563, + "variant": "L125-v225", + "capture": "captures/L125/passage-2-3-0-openair-1-4m-interior-wall.png", + "scene": "Saved/Linux/l125/captures/L125/passage-2-3-0-openair-1-4m-interior-wall.vfmesh", + "drawn_triangles": 94962, + "source_triangles": 118028, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 16.616500000000002, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.0, + "closeup_target_surface_distance_m": 0.41920390486225767, + "closeup_predicted_target_offset_m": 0.41920390486225767, + "closeup_wall_normal_alignment": 0.740744136337711, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -7.998432705401559, + -11.833936581758076, + -818.2481168532394 + ], + "target_actual_m": [ + -5.94757062165508, + -9.608161331921629, + -815.6327986602337 + ], + "logs": [ + "Saved/Linux/l125/captures/L125/passage-2-3-0-openair-1-4m-interior-wall-mesh.log", + "Saved/Linux/l125/captures/L125/passage-2-3-0-openair-1-4m-interior-wall-render.log", + "Saved/Linux/l125/captures/L125/passage-2-3-0-openair-1-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-2-4m-outside", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-2/4m-outside", + "camera": [ + -4.5562890668466025, + 4.648574813628143, + -879.7479999999999 + ], + "target": [ + -7.40869531436283, + 7.452817777269203, + -879.7479999999999 + ], + "yaw": -45.487830534998494, + "pitch": 0.0, + "focus": [ + -9.548, + 9.556, + -877.478 + ], + "center_z": -877.478, + "open_air_section": 2, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.7131015618790567, + -0.7010607409102652, + 0.0 + ], + "camera_target_distance_m": 4.000000000000001, + "route_distance_m": 374.929, + "requested_route_distance_m": 374.929, + "route_length_m": 494.0722798830563, + "variant": "L125-v225", + "capture": "captures/L125/passage-2-3-0-openair-2-4m-outside.png", + "scene": "Saved/Linux/l125/captures/L125/passage-2-3-0-openair-2-4m-outside.vfmesh", + "drawn_triangles": 475860, + "source_triangles": 504244, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 374.929, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.0, + "closeup_target_surface_distance_m": 1.7280841589725482, + "closeup_predicted_target_offset_m": 1.7280841589725482, + "closeup_wall_normal_alignment": 0.6707889779439669, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -7.47193274788199, + 5.182168353356822, + -879.6783722112204 + ], + "target_actual_m": [ + -7.306445568768645, + 9.17777802625833, + -879.7662205769708 + ], + "logs": [ + "Saved/Linux/l125/captures/L125/passage-2-3-0-openair-2-4m-outside-mesh.log", + "Saved/Linux/l125/captures/L125/passage-2-3-0-openair-2-4m-outside-render.log", + "Saved/Linux/l125/captures/L125/passage-2-3-0-openair-2-4m-outside-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-2-4m-interior-wall", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-2/4m-interior-wall", + "camera": [ + -11.533986119377625, + 6.164550123765492, + -880.4395357921604 + ], + "target": [ + -8.149320771422074, + 8.180937668487475, + -879.7479999999999 + ], + "yaw": 59.215963829172296, + "pitch": 9.955540417812847, + "focus": [ + -9.548, + 9.556, + -877.478 + ], + "center_z": -877.478, + "open_air_section": 2, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.7131015618790567, + 0.7010607409102652, + -0.0 + ], + "camera_target_distance_m": 4.000000000000007, + "route_distance_m": 374.929, + "requested_route_distance_m": 374.929, + "route_length_m": 494.0722798830563, + "variant": "L125-v225", + "capture": "captures/L125/passage-2-3-0-openair-2-4m-interior-wall.png", + "scene": "Saved/Linux/l125/captures/L125/passage-2-3-0-openair-2-4m-interior-wall.vfmesh", + "drawn_triangles": 486480, + "source_triangles": 513552, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 374.929, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.0, + "closeup_target_surface_distance_m": 1.0286227628002445, + "closeup_predicted_target_offset_m": 1.0286227628002445, + "closeup_wall_normal_alignment": 0.720019406420326, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -8.257109087497915, + 13.208090205453457, + -879.7612149430302 + ], + "target_actual_m": [ + -8.149320771422074, + 9.209558486938477, + -879.75 + ], + "logs": [ + "Saved/Linux/l125/captures/L125/passage-2-3-0-openair-2-4m-interior-wall-mesh.log", + "Saved/Linux/l125/captures/L125/passage-2-3-0-openair-2-4m-interior-wall-render.log", + "Saved/Linux/l125/captures/L125/passage-2-3-0-openair-2-4m-interior-wall-quality.log" + ] + } + ] +} diff --git a/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-0-1-0-openair-1-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-0-1-0-openair-1-4m-interior-wall.png new file mode 100644 index 0000000..1fd88a4 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-0-1-0-openair-1-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-0-1-0-openair-1-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-0-1-0-openair-1-4m-outside.png new file mode 100644 index 0000000..87570be Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-0-1-0-openair-1-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-0-1-0-openair-2-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-0-1-0-openair-2-4m-interior-wall.png new file mode 100644 index 0000000..f76e648 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-0-1-0-openair-2-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-0-1-0-openair-2-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-0-1-0-openair-2-4m-outside.png new file mode 100644 index 0000000..c19fc5f Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-0-1-0-openair-2-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-0-1-0-openair-3-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-0-1-0-openair-3-4m-interior-wall.png new file mode 100644 index 0000000..7dcd833 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-0-1-0-openair-3-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-0-1-0-openair-3-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-0-1-0-openair-3-4m-outside.png new file mode 100644 index 0000000..816ba1d Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-0-1-0-openair-3-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-0-1-0-rock-floor-station-1.png b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-0-1-0-rock-floor-station-1.png new file mode 100644 index 0000000..e67e8c5 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-0-1-0-rock-floor-station-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-0-1-0-rock-floor-station-2.png b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-0-1-0-rock-floor-station-2.png new file mode 100644 index 0000000..2b35b85 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-0-1-0-rock-floor-station-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-0-1-0-rock-floor-station-3.png b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-0-1-0-rock-floor-station-3.png new file mode 100644 index 0000000..bed41ff Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-0-1-0-rock-floor-station-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-1-2-0-openair-1-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-1-2-0-openair-1-4m-interior-wall.png new file mode 100644 index 0000000..7569f8c Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-1-2-0-openair-1-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-1-2-0-openair-1-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-1-2-0-openair-1-4m-outside.png new file mode 100644 index 0000000..cd3c8b5 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-1-2-0-openair-1-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-1-2-0-openair-2-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-1-2-0-openair-2-4m-interior-wall.png new file mode 100644 index 0000000..a6be396 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-1-2-0-openair-2-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-1-2-0-openair-2-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-1-2-0-openair-2-4m-outside.png new file mode 100644 index 0000000..c00f532 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-1-2-0-openair-2-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-1-2-0-rock-floor-station-1.png b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-1-2-0-rock-floor-station-1.png new file mode 100644 index 0000000..3611714 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-1-2-0-rock-floor-station-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-1-2-0-rock-floor-station-2.png b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-1-2-0-rock-floor-station-2.png new file mode 100644 index 0000000..9ac3f59 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-1-2-0-rock-floor-station-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-1-2-0-rock-floor-station-3.png b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-1-2-0-rock-floor-station-3.png new file mode 100644 index 0000000..5b0e0d2 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-1-2-0-rock-floor-station-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-2-3-0-openair-1-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-2-3-0-openair-1-4m-interior-wall.png new file mode 100644 index 0000000..8a9efbd Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-2-3-0-openair-1-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-2-3-0-openair-1-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-2-3-0-openair-1-4m-outside.png new file mode 100644 index 0000000..6ce2868 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-2-3-0-openair-1-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-2-3-0-openair-2-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-2-3-0-openair-2-4m-interior-wall.png new file mode 100644 index 0000000..8532d70 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-2-3-0-openair-2-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-2-3-0-openair-2-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-2-3-0-openair-2-4m-outside.png new file mode 100644 index 0000000..e9fef5f Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-2-3-0-openair-2-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-2-3-0-rock-floor-station-1.png b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-2-3-0-rock-floor-station-1.png new file mode 100644 index 0000000..0413199 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-2-3-0-rock-floor-station-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-2-3-0-rock-floor-station-2.png b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-2-3-0-rock-floor-station-2.png new file mode 100644 index 0000000..f823d6e Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-2-3-0-rock-floor-station-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-2-3-0-rock-floor-station-3.png b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-2-3-0-rock-floor-station-3.png new file mode 100644 index 0000000..279866a Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux125/captures/L125/passage-2-3-0-rock-floor-station-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux126/REPORT.md b/Standalone/Research/WorldAssemblerM3/Linux126/REPORT.md new file mode 100644 index 0000000..0bc84c6 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux126/REPORT.md @@ -0,0 +1,20 @@ +# Linux126 — passage preparation + +**No-go for the L109 speed bar.** Two exact-preserving preparation filters were tried. They reduced floor-profile calls by 20–23%, but did not reduce segment/sample pair counts or near-ready time enough. The tested source was restored after the host build. + +The L125 overlap is from each segment’s sweep bounds, expanded by its radius and the 4.335 m route reach. Adjacent segment bounds revisit the same samples. The feature slab only stamps outside sentinels; it does not create the pair count. Floor-profile and shell work multiply the cost of each pair. L125’s LOD0 pair overlap was 67.2%, 72.0%, 72.0%, and 67.6% for S0–S3. The first filter cut floor-profile calls from 3.107M→2.457M, 8.487M→6.549M, 8.303M→6.418M, and 5.269M→4.169M respectively. + +Five interleaved L80 measurements per cell, on a quiet machine (load 0.34, idle 98.2%): + +| Stratum | W8 near-ready vs L109 | W12 near-ready vs L109 | +| --- | ---: | ---: | +| S0 | +3.20% | +4.63% | +| S1 | +9.34% | +7.03% | +| S2 | +6.16% | +7.68% | +| S3 | +10.97% | +8.65% | + +L126 was +0.52% to +2.13% vs L125 in six cells and within 0.20% in the other two. All eight cells missed L109. + +Quality stayed unchanged: 264 fast-tier checks passed; walkability passed 21,425/21,425 samples; the floor probe remained 7.884 mm; four seam pairs matched all 4,900 shared samples bit-for-bit; all 23 captures were verified and byte-identical to L125. Clang/GCC W1/W8/W12 hashes matched, and the v225 baselines were unchanged. The Linux VFHostEditor build succeeded in 37.60 s with `-NoUBA -MaxParallelActions=4` and no `prlimit`. + +No evaluator bump or baseline update was needed. Timing and count logs are under `Saved/Linux/l126/`; captures are under `captures/`. diff --git a/Standalone/Research/WorldAssemblerM3/Linux126/RunL126Captures.py b/Standalone/Research/WorldAssemblerM3/Linux126/RunL126Captures.py new file mode 100644 index 0000000..d2530e0 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux126/RunL126Captures.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python3 +"""Render the 23 L119 camera poses with the L126 candidate.""" +from __future__ import annotations + +import importlib.util +import json +import math +import os +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +RESEARCH = Path(__file__).resolve().parent +CAPTURES = RESEARCH / "captures" +SAVED = ROOT / "Saved/Linux/l126/captures" +BASELINE_INDEX = (ROOT / "Standalone/Research/WorldAssemblerM3/Linux119" + / "captures/L119/capture-index.json") +LAYOUT = ROOT / "Saved/Linux/l126/hashes/owner4-surface-world-w12-clang.layout.json" +CLANG = ROOT / os.environ.get("L126_CAPTURE_CLANG", + "Saved/Linux/l126/design2/bin/VoxelForgeCoreHeadless-l126-design2-clang") +RENDERER = ROOT / os.environ.get("L126_CAPTURE_RENDERER", + "Saved/Linux/l126/design2/bin/VoxelForgeOffscreenCapture-l126-design2-clang") +HELPER_PATH = ROOT / "Standalone/Research/WorldAssemblerM3/Linux113/RunL113Captures.py" + +SPEC = importlib.util.spec_from_file_location("l113_capture_helpers", HELPER_PATH) +if SPEC is None or SPEC.loader is None: + raise SystemExit("cannot load the verified L113 capture helpers") +HELPERS = importlib.util.module_from_spec(SPEC) +SPEC.loader.exec_module(HELPERS) +HELPERS.RESEARCH = RESEARCH +HELPERS.CAPTURES = CAPTURES +HELPERS.SAVED = SAVED +HELPERS.BINARIES = {"L126": CLANG} +HELPERS.RENDERERS = {"L126": RENDERER} + + +def main() -> int: + if any(not path.is_file() for path in (BASELINE_INDEX, LAYOUT, CLANG, RENDERER)): + raise SystemExit("missing L119 camera set, L126 layout, or capture binary") + baseline = json.loads(BASELINE_INDEX.read_text(encoding="utf-8")) + layout = json.loads(LAYOUT.read_text(encoding="utf-8")) + rows = [] + CAPTURES.mkdir(parents=True, exist_ok=True) + SAVED.mkdir(parents=True, exist_ok=True) + for view in baseline["captures"]: + row = HELPERS.capture("L126", view, layout) + row["variant"] = "L126-v225" + if view["kind"] == "rock-floor-close": + scene = ROOT / row["scene"] + anchor = HELPERS.nearest_surface_anchor(scene, view["target"], margin_m=5.0, + preferred_normal=(0.0, 0.0, 1.0), minimum_alignment=0.85) + alignment = HELPERS.dot(anchor["normal"], (0.0, 0.0, 1.0)) + camera_distance = math.dist(row["camera_actual_m"], anchor["position_m"]) + row.update({"floor_anchor_position_m": anchor["position_m"], + "floor_anchor_normal": anchor["normal"], + "closeup_camera_to_floor_distance_m": camera_distance, + "closeup_floor_normal_alignment": alignment, + "verified_upward_floor_normal": alignment >= 0.85}) + if (not row["verified"] or not 2.0 <= camera_distance <= 3.2 + or anchor["distance_m"] > 0.25 or alignment < 0.85 + or row["drawn_triangles"] <= 0 + or row["pixel_quality_status"] not in + ("pass", "low_contrast_geometry_visible")): + raise RuntimeError(f"L126 floor close-up failed at {view['name']}") + rows.append(row) + if len(rows) != len(baseline["captures"]) or len(rows) != 23: + raise RuntimeError(f"expected all 23 L119 views, captured {len(rows)}") + index = CAPTURES / "L126" / "capture-index.json" + index.parent.mkdir(parents=True, exist_ok=True) + index.write_text(json.dumps({"captures": rows}, indent=2) + "\n", + encoding="utf-8") + + html = ["", + "L119 / L126 tunnel capture comparison", + "", "

L119 / L126 v225: identical views

"] + old_by_name = {Path(row["capture"]).name: row for row in baseline["captures"]} + for row in rows: + name = Path(row["capture"]).name + old = old_by_name[name] + old_path = os.path.relpath(ROOT / "Standalone/Research/WorldAssemblerM3/Linux119" + / old["capture"], CAPTURES) + new_path = os.path.relpath(RESEARCH / row["capture"], CAPTURES) + html.extend(["
", f"

{row['passage']} — {row['station']}

", + f"

{row['kind']} · L119 {old['pixel_quality_status']} · " + f"L126 {row['pixel_quality_status']}

", "
", + f"
L119
", + f"
L126 v225
", + "
", "
"]) + (CAPTURES / "COMPARE.html").write_text("\n".join(html) + "\n", encoding="utf-8") + print(f"[L126Captures] rendered={len(rows)} views index={index.relative_to(ROOT)}", + flush=True) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux126/RunL126Timing.py b/Standalone/Research/WorldAssemblerM3/Linux126/RunL126Timing.py new file mode 100644 index 0000000..a78449b --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux126/RunL126Timing.py @@ -0,0 +1,136 @@ +#!/usr/bin/env python3 +"""Five interleaved L80 readiness runs for L109, L125 and L126.""" +from __future__ import annotations + +import json +import os +import re +import statistics +import subprocess +import time +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / os.environ.get("L126_TIMING_DIR", "Saved/Linux/l126/timing") +DATA = ROOT / "Standalone/data/owner_world.json" +BINARIES = { + "L109": ROOT / "Saved/Linux/l109/bin-final/VoxelForgeCoreHeadless-l109-clang", + "L125": ROOT / "Saved/Linux/l125/bin/VoxelForgeCoreHeadless-l125-clang", + "L126": ROOT / os.environ.get("L126_CANDIDATE_BINARY", + "Saved/Linux/l126/design2/bin/VoxelForgeCoreHeadless-l126-design2-clang"), +} +CAMERAS = { + 0: (8.0, 16.0, -372.2626953125), + 1: (25.8369140625, 3.19921875, -737.0), + 2: (19.166015625, -14.2001953125, -753.3740234375), + 3: (-20.0625, -5.068359375, -900.353515625), +} +PIPELINE = re.compile(r"^\[StreamPipeline\] (.*)$", re.M) +FIELDS = re.compile(r"([a-zA-Z0-9_]+)=([^ ]+)") +NEAR = re.compile( + r"^\[WorldAssemblerNearLODReady\] lods=0-2 tiles=(\d+)/(\d+) cold_ready_s=([0-9.]+)$", + re.M) + + +def run(strate: int, workers: int, version: str, phase: str, replicate: int) -> dict: + OUT.mkdir(parents=True, exist_ok=True) + label = f"s{strate}-w{workers}-{version}-{phase}{replicate}" + log = OUT / f"{label}.log" + camera = ",".join(f"{value:.12f}" for value in CAMERAS[strate]) + ",0,0" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", + "timeout", "1740s", str(BINARIES[version]), str(DATA), + "--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline", + f"--workers={workers}", "--clip-radius=3", "--max-clip-level=8", + "--max-level=8", f"--camera={camera}", "--profile-lod-work", + "--stream-scheduler-policy=3", + ] + started = time.monotonic() + with log.open("w", encoding="utf-8") as output: + result = subprocess.run(command, cwd=ROOT, stdout=output, + stderr=subprocess.STDOUT, check=False, timeout=1740) + content = log.read_text(encoding="utf-8", errors="replace") + pipeline_match, near_match = PIPELINE.search(content), NEAR.search(content) + if result.returncode or pipeline_match is None or near_match is None: + raise SystemExit(f"readiness run failed or incomplete: {log}; exit={result.returncode}") + pipeline = dict(FIELDS.findall(pipeline_match.group(1))) + row = {"strate": strate, "workers": workers, "version": version, + "phase": phase, "replicate": replicate, "exit_code": result.returncode, + "wall_s": round(time.monotonic() - started, 3), + "lod02_ready_s": float(near_match.group(3)), + "whole_view_ready_s": float(pipeline["whole_view_ready"].removesuffix("s")), + "whole_tiles": int(pipeline["whole_tiles"].split("/")[0]), + "log": str(log.relative_to(ROOT))} + print("[L126TimingRun] " + json.dumps(row, sort_keys=True), flush=True) + return row + + +def cpu_idle_percent(interval_s: float = 2.0) -> float: + def totals() -> tuple[int, int]: + fields = Path("/proc/stat").read_text(encoding="utf-8").splitlines()[0].split() + values = [int(value) for value in fields[1:]] + return sum(values), values[3] + (values[4] if len(values) > 4 else 0) + before_total, before_idle = totals() + time.sleep(interval_s) + after_total, after_idle = totals() + return 100.0 * (after_idle-before_idle) / max(1, after_total-before_total) + + +def main() -> int: + if not DATA.is_file() or any(not binary.is_file() for binary in BINARIES.values()): + raise SystemExit("missing L109/L125/L126 timing input") + OUT.mkdir(parents=True, exist_ok=True) + load_1m, idle_pct = os.getloadavg()[0], cpu_idle_percent() + uptime = subprocess.run(["uptime"], cwd=ROOT, text=True, + capture_output=True, check=True).stdout.strip() + top = subprocess.run(["ps", "-eo", "pid,pcpu,comm", "--sort=-pcpu"], + cwd=ROOT, text=True, capture_output=True, check=True).stdout + (OUT / "machine-load-before.txt").write_text( + f"uptime: {uptime}\n1-minute load: {load_1m:.2f}\n" + f"2-second CPU idle: {idle_pct:.1f}%\ntop CPU users:\n{top}", encoding="utf-8") + print(f"[L126TimingGate] load_1m={load_1m:.2f} cpu_idle_2s={idle_pct:.1f}%", + flush=True) + if load_1m >= 0.9 or idle_pct < 97.0: + raise SystemExit("timing refused: machine is above the quiet-load gate") + + rows = [] + versions = ("L109", "L125", "L126") + for strate in range(4): + for workers in (8, 12): + for version in versions: + run(strate, workers, version, "warmup", 0) + for replicate in range(1, 6): + offset = (replicate - 1) % len(versions) + order = versions[offset:] + versions[:offset] + for version in order: + rows.append(run(strate, workers, version, "measured", replicate)) + (OUT / "runs-partial.json").write_text( + json.dumps(rows, indent=2) + "\n", encoding="utf-8") + + summary = [] + for strate in range(4): + for workers in (8, 12): + item = {"strate": strate, "workers": workers, "replicates": 5} + medians = {} + for version in versions: + group = [row for row in rows if row["strate"] == strate + and row["workers"] == workers and row["version"] == version] + medians[version] = {} + for key in ("lod02_ready_s", "whole_view_ready_s"): + values = [row[key] for row in group] + medians[version][key] = statistics.median(values) + item[f"{version}_{key}_values"] = values + item[f"{version}_{key}_median"] = medians[version][key] + for comparison in ("L109", "L125"): + for key in ("lod02_ready_s", "whole_view_ready_s"): + item[f"L126_vs_{comparison}_{key}_delta_pct"] = round( + 100.0 * (medians["L126"][key] / medians[comparison][key]-1.0), 2) + summary.append(item) + (OUT / "summary.json").write_text( + json.dumps({"runs": rows, "summary": summary}, indent=2) + "\n", + encoding="utf-8") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux126/captures/COMPARE.html b/Standalone/Research/WorldAssemblerM3/Linux126/captures/COMPARE.html new file mode 100644 index 0000000..815023a --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux126/captures/COMPARE.html @@ -0,0 +1,188 @@ + +L119 / L126 tunnel capture comparison + +

L119 / L126 v225: identical views

+
+

passage/0-1/0 — rock-floor/401.7m

+

rock-floor-close · L119 pass · L126 pass

+
+
L119
+
L126 v225
+
+
+
+

passage/0-1/0 — rock-floor/792.8m

+

rock-floor-close · L119 pass · L126 pass

+
+
L119
+
L126 v225
+
+
+
+

passage/0-1/0 — rock-floor/1634.5m

+

rock-floor-close · L119 pass · L126 pass

+
+
L119
+
L126 v225
+
+
+
+

passage/1-2/0 — rock-floor/27.0m

+

rock-floor-close · L119 pass · L126 pass

+
+
L119
+
L126 v225
+
+
+
+

passage/1-2/0 — rock-floor/52.9m

+

rock-floor-close · L119 pass · L126 pass

+
+
L119
+
L126 v225
+
+
+
+

passage/1-2/0 — rock-floor/78.9m

+

rock-floor-close · L119 pass · L126 pass

+
+
L119
+
L126 v225
+
+
+
+

passage/2-3/0 — rock-floor/323.4m

+

rock-floor-close · L119 low_contrast_geometry_visible · L126 low_contrast_geometry_visible

+
+
L119
+
L126 v225
+
+
+
+

passage/2-3/0 — rock-floor/333.4m

+

rock-floor-close · L119 pass · L126 pass

+
+
L119
+
L126 v225
+
+
+
+

passage/2-3/0 — rock-floor/343.4m

+

rock-floor-close · L119 pass · L126 pass

+
+
L119
+
L126 v225
+
+
+
+

passage/0-1/0 — section-1/4m-outside

+

open-air-close · L119 pass · L126 pass

+
+
L119
+
L126 v225
+
+
+
+

passage/0-1/0 — section-1/4m-interior-wall

+

open-air-close · L119 low_contrast_geometry_visible · L126 low_contrast_geometry_visible

+
+
L119
+
L126 v225
+
+
+
+

passage/0-1/0 — section-2/4m-outside

+

open-air-close · L119 pass · L126 pass

+
+
L119
+
L126 v225
+
+
+
+

passage/0-1/0 — section-2/4m-interior-wall

+

open-air-close · L119 pass · L126 pass

+
+
L119
+
L126 v225
+
+
+
+

passage/0-1/0 — section-3/4m-outside

+

open-air-close · L119 pass · L126 pass

+
+
L119
+
L126 v225
+
+
+
+

passage/0-1/0 — section-3/4m-interior-wall

+

open-air-close · L119 pass · L126 pass

+
+
L119
+
L126 v225
+
+
+
+

passage/1-2/0 — section-1/4m-outside

+

open-air-close · L119 pass · L126 pass

+
+
L119
+
L126 v225
+
+
+
+

passage/1-2/0 — section-1/4m-interior-wall

+

open-air-close · L119 pass · L126 pass

+
+
L119
+
L126 v225
+
+
+
+

passage/1-2/0 — section-2/4m-outside

+

open-air-close · L119 pass · L126 pass

+
+
L119
+
L126 v225
+
+
+
+

passage/1-2/0 — section-2/4m-interior-wall

+

open-air-close · L119 pass · L126 pass

+
+
L119
+
L126 v225
+
+
+
+

passage/2-3/0 — section-1/4m-outside

+

open-air-close · L119 low_contrast_geometry_visible · L126 low_contrast_geometry_visible

+
+
L119
+
L126 v225
+
+
+
+

passage/2-3/0 — section-1/4m-interior-wall

+

open-air-close · L119 low_contrast_geometry_visible · L126 low_contrast_geometry_visible

+
+
L119
+
L126 v225
+
+
+
+

passage/2-3/0 — section-2/4m-outside

+

open-air-close · L119 pass · L126 pass

+
+
L119
+
L126 v225
+
+
+
+

passage/2-3/0 — section-2/4m-interior-wall

+

open-air-close · L119 pass · L126 pass

+
+
L119
+
L126 v225
+
+
diff --git a/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/capture-index.json b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/capture-index.json new file mode 100644 index 0000000..507505c --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/capture-index.json @@ -0,0 +1,1562 @@ +{ + "captures": [ + { + "name": "passage-0-1-0-rock-floor-station-1", + "passage": "passage/0-1/0", + "kind": "rock-floor-close", + "station": "rock-floor/401.7m", + "camera": [ + -9.24648786798055, + 19.798675033837775, + -443.9636296749357 + ], + "target": [ + -7.026884524505579, + 20.857335392121104, + -445.66373993191075 + ], + "yaw": 64.50075976736525, + "pitch": -34.65771934187305, + "focus": [ + -7.026884524505579, + 20.857335392121104, + -445.66373993191075 + ], + "center_z": -445.66373993191075, + "route_distance_m": 401.6612010038529, + "requested_route_distance_m": 401.6612010038529, + "route_length_m": 2026.6238040154117, + "planned_floor_m": -445.66373993191075, + "planned_grade_deg": 10.372328677972732, + "variant": "L126-v225", + "capture": "captures/L126/passage-0-1-0-rock-floor-station-1.png", + "scene": "Saved/Linux/l126/captures/L126/passage-0-1-0-rock-floor-station-1.vfmesh", + "drawn_triangles": 122294, + "source_triangles": 146798, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 401.6612010038529, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -9.24648786798055, + 19.798675033837775, + -443.9636296749357 + ], + "target_actual_m": [ + -7.026884524505579, + 20.857335392121104, + -445.66373993191075 + ], + "logs": [ + "Saved/Linux/l126/captures/L126/passage-0-1-0-rock-floor-station-1-mesh.log", + "Saved/Linux/l126/captures/L126/passage-0-1-0-rock-floor-station-1-render.log", + "Saved/Linux/l126/captures/L126/passage-0-1-0-rock-floor-station-1-quality.log" + ], + "floor_anchor_position_m": [ + -7.026885053959959, + 20.857335155432953, + -445.66374310012867 + ], + "floor_anchor_normal": [ + 0.16438021494383692, + 0.07357583212203939, + 0.9836491965444629 + ], + "closeup_camera_to_floor_distance_m": 2.989612610955708, + "closeup_floor_normal_alignment": 0.9836491965444629, + "verified_upward_floor_normal": true + }, + { + "name": "passage-0-1-0-rock-floor-station-2", + "passage": "passage/0-1/0", + "kind": "rock-floor-close", + "station": "rock-floor/792.8m", + "camera": [ + -0.021280083711839648, + -26.43771312964049, + -514.3617561596035 + ], + "target": [ + -2.4714859241065525, + -26.227784739959716, + -516.0616688299093 + ], + "yaw": -85.10297944703369, + "pitch": -34.654210347383824, + "focus": [ + -2.4714859241065525, + -26.227784739959716, + -516.0616688299093 + ], + "center_z": -516.0616688299093, + "route_distance_m": 792.8284020077059, + "requested_route_distance_m": 792.8284020077059, + "route_length_m": 2026.6238040154117, + "planned_floor_m": -516.0616688299093, + "planned_grade_deg": 10.367725129664787, + "variant": "L126-v225", + "capture": "captures/L126/passage-0-1-0-rock-floor-station-2.png", + "scene": "Saved/Linux/l126/captures/L126/passage-0-1-0-rock-floor-station-2.vfmesh", + "drawn_triangles": 586092, + "source_triangles": 626196, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 792.8284020077059, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -0.021280083711839648, + -26.43771312964049, + -514.3617561596035 + ], + "target_actual_m": [ + -2.4714859241065525, + -26.227784739959716, + -516.0616688299093 + ], + "logs": [ + "Saved/Linux/l126/captures/L126/passage-0-1-0-rock-floor-station-2-mesh.log", + "Saved/Linux/l126/captures/L126/passage-0-1-0-rock-floor-station-2-render.log", + "Saved/Linux/l126/captures/L126/passage-0-1-0-rock-floor-station-2-quality.log" + ], + "floor_anchor_position_m": [ + -2.471476828908, + -26.227785976319144, + -516.0617189697925 + ], + "floor_anchor_normal": [ + -0.179115780575022, + 0.024140888419756926, + 0.9835317761289187 + ], + "closeup_camera_to_floor_distance_m": 2.9895496409822853, + "closeup_floor_normal_alignment": 0.9835317761289187, + "verified_upward_floor_normal": true + }, + { + "name": "passage-0-1-0-rock-floor-station-3", + "passage": "passage/0-1/0", + "kind": "rock-floor-close", + "station": "rock-floor/1634.5m", + "camera": [ + 15.717287112180728, + 19.71739973195528, + -665.8352816543407 + ], + "target": [ + 17.336220092016376, + 17.86620742417785, + -667.5348848643227 + ], + "yaw": 138.82915885966676, + "pitch": -34.64871452830556, + "focus": [ + 17.336220092016376, + 17.86620742417785, + -667.5348848643227 + ], + "center_z": -667.5348848643227, + "route_distance_m": 1634.4566030115589, + "requested_route_distance_m": 1634.4566030115589, + "route_length_m": 2026.6238040154117, + "planned_floor_m": -667.5348848643227, + "planned_grade_deg": 10.360515186362372, + "variant": "L126-v225", + "capture": "captures/L126/passage-0-1-0-rock-floor-station-3.png", + "scene": "Saved/Linux/l126/captures/L126/passage-0-1-0-rock-floor-station-3.vfmesh", + "drawn_triangles": 137288, + "source_triangles": 166736, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1634.4566030115589, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 15.717287112180728, + 19.71739973195528, + -665.8352816543407 + ], + "target_actual_m": [ + 17.336220092016376, + 17.86620742417785, + -667.5348848643227 + ], + "logs": [ + "Saved/Linux/l126/captures/L126/passage-0-1-0-rock-floor-station-3-mesh.log", + "Saved/Linux/l126/captures/L126/passage-0-1-0-rock-floor-station-3-render.log", + "Saved/Linux/l126/captures/L126/passage-0-1-0-rock-floor-station-3-quality.log" + ], + "floor_anchor_position_m": [ + 17.33622182815858, + 17.866205324064538, + -667.534869956066 + ], + "floor_anchor_normal": [ + 0.11463807621472542, + -0.13864390562764303, + 0.9836848981834071 + ], + "closeup_camera_to_floor_distance_m": 2.9893930396931125, + "closeup_floor_normal_alignment": 0.9836848981834071, + "verified_upward_floor_normal": true + }, + { + "name": "passage-1-2-0-rock-floor-station-1", + "passage": "passage/1-2/0", + "kind": "rock-floor-close", + "station": "rock-floor/27.0m", + "camera": [ + 15.990262769683945, + 2.495369317804175, + -736.4846720823747 + ], + "target": [ + 15.354493464592624, + 4.868558240151556, + -738.1970266319915 + ], + "yaw": -14.99718988160138, + "pitch": -34.875140724394136, + "focus": [ + 15.354493464592624, + 4.868558240151556, + -738.1970266319915 + ], + "center_z": -738.1970266319915, + "route_distance_m": 26.963657939523273, + "requested_route_distance_m": 26.963657939523273, + "route_length_m": 114.99063175809309, + "planned_floor_m": -738.1970266319915, + "planned_grade_deg": 10.657740387934142, + "variant": "L126-v225", + "capture": "captures/L126/passage-1-2-0-rock-floor-station-1.png", + "scene": "Saved/Linux/l126/captures/L126/passage-1-2-0-rock-floor-station-1.vfmesh", + "drawn_triangles": 652056, + "source_triangles": 719660, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 26.963657939523273, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 15.990262769683945, + 2.495369317804175, + -736.4846720823747 + ], + "target_actual_m": [ + 15.354493464592624, + 4.868558240151556, + -738.1970266319915 + ], + "logs": [ + "Saved/Linux/l126/captures/L126/passage-1-2-0-rock-floor-station-1-mesh.log", + "Saved/Linux/l126/captures/L126/passage-1-2-0-rock-floor-station-1-render.log", + "Saved/Linux/l126/captures/L126/passage-1-2-0-rock-floor-station-1-quality.log" + ], + "floor_anchor_position_m": [ + 15.354124807038394, + 4.869920275450426, + -738.1895881032126 + ], + "floor_anchor_normal": [ + -0.047307387705878, + 0.17883124580074233, + 0.9827417751341397 + ], + "closeup_camera_to_floor_distance_m": 2.9916387475909154, + "closeup_floor_normal_alignment": 0.9827417751341397, + "verified_upward_floor_normal": true + }, + { + "name": "passage-1-2-0-rock-floor-station-2", + "passage": "passage/1-2/0", + "kind": "rock-floor-close", + "station": "rock-floor/52.9m", + "camera": [ + -2.48434493546405, + 15.983647301702653, + -741.2835409028854 + ], + "target": [ + -4.76517685476837, + 15.070128626649932, + -742.995373541633 + ], + "yaw": -111.82708648318167, + "pitch": -34.86587426337977, + "focus": [ + -4.76517685476837, + 15.070128626649932, + -742.995373541633 + ], + "center_z": -742.995373541633, + "route_distance_m": 52.927315879046546, + "requested_route_distance_m": 52.927315879046546, + "route_length_m": 114.99063175809309, + "planned_floor_m": -742.995373541633, + "planned_grade_deg": 10.645569354114926, + "variant": "L126-v225", + "capture": "captures/L126/passage-1-2-0-rock-floor-station-2.png", + "scene": "Saved/Linux/l126/captures/L126/passage-1-2-0-rock-floor-station-2.vfmesh", + "drawn_triangles": 636162, + "source_triangles": 700558, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 52.927315879046546, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -2.48434493546405, + 15.983647301702653, + -741.2835409028854 + ], + "target_actual_m": [ + -4.76517685476837, + 15.070128626649932, + -742.995373541633 + ], + "logs": [ + "Saved/Linux/l126/captures/L126/passage-1-2-0-rock-floor-station-2-mesh.log", + "Saved/Linux/l126/captures/L126/passage-1-2-0-rock-floor-station-2-render.log", + "Saved/Linux/l126/captures/L126/passage-1-2-0-rock-floor-station-2-quality.log" + ], + "floor_anchor_position_m": [ + -4.766428465537912, + 15.069671584786441, + -742.988228337538 + ], + "floor_anchor_normal": [ + -0.1744301807701029, + -0.061608715063684795, + 0.9827402903436447 + ], + "closeup_camera_to_floor_distance_m": 2.9915240428933867, + "closeup_floor_normal_alignment": 0.9827402903436447, + "verified_upward_floor_normal": true + }, + { + "name": "passage-1-2-0-rock-floor-station-3", + "passage": "passage/1-2/0", + "kind": "rock-floor-close", + "station": "rock-floor/78.9m", + "camera": [ + -13.44544511010513, + -3.995230772069307, + -746.0839041050349 + ], + "target": [ + -12.287009401722694, + -6.161841337747165, + -747.7963166548619 + ], + "yaw": 151.8676321960706, + "pitch": -34.87617050502889, + "focus": [ + -12.287009401722694, + -6.161841337747165, + -747.7963166548619 + ], + "center_z": -747.7963166548619, + "route_distance_m": 78.89097381856982, + "requested_route_distance_m": 78.89097381856982, + "route_length_m": 114.99063175809309, + "planned_floor_m": -747.7963166548619, + "planned_grade_deg": 10.659092990906162, + "variant": "L126-v225", + "capture": "captures/L126/passage-1-2-0-rock-floor-station-3.png", + "scene": "Saved/Linux/l126/captures/L126/passage-1-2-0-rock-floor-station-3.vfmesh", + "drawn_triangles": 580472, + "source_triangles": 639376, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 78.89097381856982, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -13.44544511010513, + -3.995230772069307, + -746.0839041050349 + ], + "target_actual_m": [ + -12.287009401722694, + -6.161841337747165, + -747.7963166548619 + ], + "logs": [ + "Saved/Linux/l126/captures/L126/passage-1-2-0-rock-floor-station-3-mesh.log", + "Saved/Linux/l126/captures/L126/passage-1-2-0-rock-floor-station-3-render.log", + "Saved/Linux/l126/captures/L126/passage-1-2-0-rock-floor-station-3-quality.log" + ], + "floor_anchor_position_m": [ + -12.283352972838873, + -6.167679829029396, + -747.554756449892 + ], + "floor_anchor_normal": [ + 0.09692807602747124, + -0.15782686841357624, + 0.9826981366036961 + ], + "closeup_camera_to_floor_distance_m": 2.8693901200350096, + "closeup_floor_normal_alignment": 0.9826981366036961, + "verified_upward_floor_normal": true + }, + { + "name": "passage-2-3-0-rock-floor-station-1", + "passage": "passage/2-3/0", + "kind": "rock-floor-close", + "station": "rock-floor/323.4m", + "camera": [ + 6.997568341188331, + -14.934306981606339, + -869.3796844648476 + ], + "target": [ + 9.102823911740126, + -13.661883549736208, + -871.0755965556104 + ], + "yaw": 58.85109570948622, + "pitch": -34.583159686285406, + "focus": [ + 9.102823911740126, + -13.661883549736208, + -871.0755965556104 + ], + "center_z": -871.0755965556104, + "route_distance_m": 323.4481319239866, + "requested_route_distance_m": 323.4481319239866, + "route_length_m": 494.0722798830563, + "planned_floor_m": -871.0755965556104, + "planned_grade_deg": 10.274530613220444, + "variant": "L126-v225", + "capture": "captures/L126/passage-2-3-0-rock-floor-station-1.png", + "scene": "Saved/Linux/l126/captures/L126/passage-2-3-0-rock-floor-station-1.vfmesh", + "drawn_triangles": 474964, + "source_triangles": 502362, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 323.4481319239866, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 6.997568341188331, + -14.934306981606339, + -869.3796844648476 + ], + "target_actual_m": [ + 9.102823911740126, + -13.661883549736208, + -871.0755965556104 + ], + "logs": [ + "Saved/Linux/l126/captures/L126/passage-2-3-0-rock-floor-station-1-mesh.log", + "Saved/Linux/l126/captures/L126/passage-2-3-0-rock-floor-station-1-render.log", + "Saved/Linux/l126/captures/L126/passage-2-3-0-rock-floor-station-1-quality.log" + ], + "floor_anchor_position_m": [ + 9.103799793973732, + -13.661094033901383, + -871.068656948616 + ], + "floor_anchor_normal": [ + 0.14021616794161246, + 0.11018123609139711, + 0.9839713011369495 + ], + "closeup_camera_to_floor_distance_m": 2.9849472681829123, + "closeup_floor_normal_alignment": 0.9839713011369495, + "verified_upward_floor_normal": true + }, + { + "name": "passage-2-3-0-rock-floor-station-2", + "passage": "passage/2-3/0", + "kind": "rock-floor-close", + "station": "rock-floor/333.4m", + "camera": [ + 14.426607883839745, + -8.501776133009574, + -871.1605818845352 + ], + "target": [ + 15.203729308783775, + -6.16777561793481, + -872.8561420785873 + ], + "yaw": 18.41553205389999, + "pitch": -34.576909662847896, + "focus": [ + 15.203729308783775, + -6.16777561793481, + -872.8561420785873 + ], + "center_z": -872.8561420785873, + "route_distance_m": 333.4481319239866, + "requested_route_distance_m": 333.4481319239866, + "route_length_m": 494.0722798830563, + "planned_floor_m": -872.8561420785873, + "planned_grade_deg": 10.266334408339132, + "variant": "L126-v225", + "capture": "captures/L126/passage-2-3-0-rock-floor-station-2.png", + "scene": "Saved/Linux/l126/captures/L126/passage-2-3-0-rock-floor-station-2.vfmesh", + "drawn_triangles": 494504, + "source_triangles": 524342, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 333.4481319239866, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 14.426607883839745, + -8.501776133009574, + -871.1605818845352 + ], + "target_actual_m": [ + 15.203729308783775, + -6.16777561793481, + -872.8561420785873 + ], + "logs": [ + "Saved/Linux/l126/captures/L126/passage-2-3-0-rock-floor-station-2-mesh.log", + "Saved/Linux/l126/captures/L126/passage-2-3-0-rock-floor-station-2-render.log", + "Saved/Linux/l126/captures/L126/passage-2-3-0-rock-floor-station-2-quality.log" + ], + "floor_anchor_position_m": [ + 15.204108325185125, + -6.1664350574610705, + -872.848494535829 + ], + "floor_anchor_normal": [ + 0.0468360027958031, + 0.17218671405633393, + 0.9839502651783747 + ], + "closeup_camera_to_floor_distance_m": 2.9845224063213145, + "closeup_floor_normal_alignment": 0.9839502651783747, + "verified_upward_floor_normal": true + }, + { + "name": "passage-2-3-0-rock-floor-station-3", + "passage": "passage/2-3/0", + "kind": "rock-floor-close", + "station": "rock-floor/343.4m", + "camera": [ + 16.176045301879554, + 1.1336183974400118, + -872.9426489764151 + ], + "target": [ + 15.465325445603714, + 3.4887437417106955, + -874.6379150751349 + ], + "yaw": -16.792543840841383, + "pitch": -34.57168620892087, + "focus": [ + 15.465325445603714, + 3.4887437417106955, + -874.6379150751349 + ], + "center_z": -874.6379150751349, + "route_distance_m": 343.4481319239866, + "requested_route_distance_m": 343.4481319239866, + "route_length_m": 494.0722798830563, + "planned_floor_m": -874.6379150751349, + "planned_grade_deg": 10.259484647608062, + "variant": "L126-v225", + "capture": "captures/L126/passage-2-3-0-rock-floor-station-3.png", + "scene": "Saved/Linux/l126/captures/L126/passage-2-3-0-rock-floor-station-3.vfmesh", + "drawn_triangles": 485356, + "source_triangles": 512664, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 343.4481319239866, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": null, + "closeup_target_surface_distance_m": null, + "closeup_predicted_target_offset_m": null, + "closeup_wall_normal_alignment": null, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 16.176045301879554, + 1.1336183974400118, + -872.9426489764151 + ], + "target_actual_m": [ + 15.465325445603714, + 3.4887437417106955, + -874.6379150751349 + ], + "logs": [ + "Saved/Linux/l126/captures/L126/passage-2-3-0-rock-floor-station-3-mesh.log", + "Saved/Linux/l126/captures/L126/passage-2-3-0-rock-floor-station-3-render.log", + "Saved/Linux/l126/captures/L126/passage-2-3-0-rock-floor-station-3-quality.log" + ], + "floor_anchor_position_m": [ + 15.464091528009144, + 3.4924186701988678, + -874.5280427606272 + ], + "floor_anchor_normal": [ + -0.061689200676463656, + 0.16755705537563617, + 0.9839304221913991 + ], + "closeup_camera_to_floor_distance_m": 2.9298959629846824, + "closeup_floor_normal_alignment": 0.9839304221913991, + "verified_upward_floor_normal": true + }, + { + "name": "passage-0-1-0-openair-1-4m-outside", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-1/4m-outside", + "camera": [ + 13.176702021211483, + 7.149068417345486, + -374.402 + ], + "target": [ + 9.197121888971225, + 7.5527291301707695, + -374.402 + ], + "yaw": -84.20812706837869, + "pitch": 0.0, + "focus": [ + 7.272, + 7.748, + -373.197 + ], + "center_z": -373.197, + "open_air_section": 1, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.9948950330600643, + -0.1009151782063209, + 0.0 + ], + "camera_target_distance_m": 4.000000000000001, + "route_distance_m": 8.3545, + "requested_route_distance_m": 8.3545, + "route_length_m": 2026.6238040154117, + "variant": "L126-v225", + "capture": "captures/L126/passage-0-1-0-openair-1-4m-outside.png", + "scene": "Saved/Linux/l126/captures/L126/passage-0-1-0-openair-1-4m-outside.vfmesh", + "drawn_triangles": 275333, + "source_triangles": 327745, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 8.3545, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.999999999999992, + "closeup_target_surface_distance_m": 0.794053842406799, + "closeup_predicted_target_offset_m": 0.794053842406799, + "closeup_wall_normal_alignment": 0.9449803535183738, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 12.920589450293994, + 7.974422667153486, + -375.0086678277374 + ], + "target_actual_m": [ + 9.12386703491211, + 8.0, + -373.75 + ], + "logs": [ + "Saved/Linux/l126/captures/L126/passage-0-1-0-openair-1-4m-outside-mesh.log", + "Saved/Linux/l126/captures/L126/passage-0-1-0-openair-1-4m-outside-render.log", + "Saved/Linux/l126/captures/L126/passage-0-1-0-openair-1-4m-outside-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-1-4m-interior-wall", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-1/4m-interior-wall", + "camera": [ + 7.395778712540976, + 3.8749008126934172, + -374.89997477205173 + ], + "target": [ + 8.778272394312646, + 7.595214286886338, + -374.402 + ], + "yaw": 20.38540702862518, + "pitch": 7.1515181408188955, + "focus": [ + 7.272, + 7.748, + -373.197 + ], + "center_z": -373.197, + "open_air_section": 1, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.9948950330600643, + 0.1009151782063209, + -0.0 + ], + "camera_target_distance_m": 3.9999999999999973, + "route_distance_m": 8.3545, + "requested_route_distance_m": 8.3545, + "route_length_m": 2026.6238040154117, + "variant": "L126-v225", + "capture": "captures/L126/passage-0-1-0-openair-1-4m-interior-wall.png", + "scene": "Saved/Linux/l126/captures/L126/passage-0-1-0-openair-1-4m-interior-wall.vfmesh", + "drawn_triangles": 308012, + "source_triangles": 368124, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 8.3545, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.999999999999992, + "closeup_target_surface_distance_m": 0.8416597466625043, + "closeup_predicted_target_offset_m": 0.8416597466625043, + "closeup_wall_normal_alignment": 0.9449803535183738, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 5.327144619530225, + 8.025577332846515, + -372.4913321722626 + ], + "target_actual_m": [ + 9.12386703491211, + 8.0, + -373.75 + ], + "logs": [ + "Saved/Linux/l126/captures/L126/passage-0-1-0-openair-1-4m-interior-wall-mesh.log", + "Saved/Linux/l126/captures/L126/passage-0-1-0-openair-1-4m-interior-wall-render.log", + "Saved/Linux/l126/captures/L126/passage-0-1-0-openair-1-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-2-4m-outside", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-2/4m-outside", + "camera": [ + 12.814097656232029, + 0.949800892309409, + -375.51163279923776 + ], + "target": [ + 8.842807594702599, + 1.4281890685821654, + -375.51163279923776 + ], + "yaw": -83.1311525734364, + "pitch": 0.0, + "focus": [ + 6.603, + 1.698, + -374.149 + ], + "center_z": -374.149, + "open_air_section": 2, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.9928225153823576, + -0.1195970440681891, + 0.0 + ], + "camera_target_distance_m": 4.0, + "route_distance_m": 14.4925, + "requested_route_distance_m": 14.4925, + "route_length_m": 2026.6238040154117, + "variant": "L126-v225", + "capture": "captures/L126/passage-0-1-0-openair-2-4m-outside.png", + "scene": "Saved/Linux/l126/captures/L126/passage-0-1-0-openair-2-4m-outside.vfmesh", + "drawn_triangles": 275333, + "source_triangles": 327745, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 14.4925, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.999999999999995, + "closeup_target_surface_distance_m": 1.0963161771133416, + "closeup_predicted_target_offset_m": 1.0963161771133416, + "closeup_wall_normal_alignment": 0.39413995490510356, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 9.613469253122387, + 1.5471847686714795, + -379.60073544787906 + ], + "target_actual_m": [ + 7.959597110748291, + 1.0, + -376.0 + ], + "logs": [ + "Saved/Linux/l126/captures/L126/passage-0-1-0-openair-2-4m-outside-mesh.log", + "Saved/Linux/l126/captures/L126/passage-0-1-0-openair-2-4m-outside-render.log", + "Saved/Linux/l126/captures/L126/passage-0-1-0-openair-2-4m-outside-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-2-4m-interior-wall", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-2/4m-interior-wall", + "camera": [ + 6.939570778854576, + -2.1803140897652855, + -376.2060303004211 + ], + "target": [ + 8.388084903173432, + 1.4829657169105679, + -375.51163279923776 + ], + "yaw": 21.574563086437188, + "pitch": 9.997160707081923, + "focus": [ + 6.603, + 1.698, + -374.149 + ], + "center_z": -374.149, + "open_air_section": 2, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.9928225153823576, + 0.1195970440681891, + -0.0 + ], + "camera_target_distance_m": 3.999999999999997, + "route_distance_m": 14.4925, + "requested_route_distance_m": 14.4925, + "route_length_m": 2026.6238040154117, + "variant": "L126-v225", + "capture": "captures/L126/passage-0-1-0-openair-2-4m-interior-wall.png", + "scene": "Saved/Linux/l126/captures/L126/passage-0-1-0-openair-2-4m-interior-wall.vfmesh", + "drawn_triangles": 345026, + "source_triangles": 414658, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 14.4925, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.000000000000001, + "closeup_target_surface_distance_m": 0.7732263275133904, + "closeup_predicted_target_offset_m": 0.7732263275133904, + "closeup_wall_normal_alignment": 0.286757829360229, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 6.619154002331269, + 0.5694445029418322, + -372.249825471136 + ], + "target_actual_m": [ + 7.85216206252137, + 1.2143337388310353, + -376.0 + ], + "logs": [ + "Saved/Linux/l126/captures/L126/passage-0-1-0-openair-2-4m-interior-wall-mesh.log", + "Saved/Linux/l126/captures/L126/passage-0-1-0-openair-2-4m-interior-wall-render.log", + "Saved/Linux/l126/captures/L126/passage-0-1-0-openair-2-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-3-4m-outside", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-3/4m-outside", + "camera": [ + -28.32291429976088, + -16.444327461849063, + -600.6066327992378 + ], + "target": [ + -25.004026673221745, + -14.211619482196229, + -600.6066327992378 + ], + "yaw": 56.07018168236039, + "pitch": 0.0, + "focus": [ + -22.1, + -12.258, + -599.244 + ], + "center_z": -599.244, + "open_air_section": 3, + "closeup_side": "outside", + "closeup_preferred_normal": [ + -0.8297219066347834, + -0.5581769949132084, + 0.0 + ], + "camera_target_distance_m": 4.000000000000001, + "route_distance_m": 1265.3425000000002, + "requested_route_distance_m": 1265.3425000000002, + "route_length_m": 2026.6238040154117, + "variant": "L126-v225", + "capture": "captures/L126/passage-0-1-0-openair-3-4m-outside.png", + "scene": "Saved/Linux/l126/captures/L126/passage-0-1-0-openair-3-4m-outside.vfmesh", + "drawn_triangles": 149234, + "source_triangles": 181128, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1265.3425000000002, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.9999999999999907, + "closeup_target_surface_distance_m": 0.06836631107301705, + "closeup_predicted_target_offset_m": 0.06836631107301705, + "closeup_wall_normal_alignment": 0.9604329420550252, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -28.63982379180018, + -15.582695163623317, + -601.2438490311043 + ], + "target_actual_m": [ + -24.955621627611308, + -14.176566764792845, + -600.5734332352072 + ], + "logs": [ + "Saved/Linux/l126/captures/L126/passage-0-1-0-openair-3-4m-outside-mesh.log", + "Saved/Linux/l126/captures/L126/passage-0-1-0-openair-3-4m-outside-render.log", + "Saved/Linux/l126/captures/L126/passage-0-1-0-openair-3-4m-outside-quality.log" + ] + }, + { + "name": "passage-0-1-0-openair-3-4m-interior-wall", + "passage": "passage/0-1/0", + "kind": "open-air-close", + "station": "section-3/4m-interior-wall", + "camera": [ + -26.071689640946218, + -10.338278587083852, + -601.3036807194 + ], + "target": [ + -24.774901932566983, + -14.057480898923608, + -600.6066327992378 + ], + "yaw": 160.77768453528284, + "pitch": 10.035712777782798, + "focus": [ + -22.1, + -12.258, + -599.244 + ], + "center_z": -599.244, + "open_air_section": 3, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + 0.8297219066347834, + 0.5581769949132084, + -0.0 + ], + "camera_target_distance_m": 4.000000000000005, + "route_distance_m": 1265.3425000000002, + "requested_route_distance_m": 1265.3425000000002, + "route_length_m": 2026.6238040154117, + "variant": "L126-v225", + "capture": "captures/L126/passage-0-1-0-openair-3-4m-interior-wall.png", + "scene": "Saved/Linux/l126/captures/L126/passage-0-1-0-openair-3-4m-interior-wall.vfmesh", + "drawn_triangles": 148100, + "source_triangles": 180244, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 1265.3425000000002, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.000000000000004, + "closeup_target_surface_distance_m": 0.15667051955483755, + "closeup_predicted_target_offset_m": 0.15667051955483755, + "closeup_wall_normal_alignment": 0.936006465878356, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -21.875641690065105, + -11.887416826703374, + -599.3020917133557 + ], + "target_actual_m": [ + -24.866552934428398, + -14.149067333208382, + -600.6947104389109 + ], + "logs": [ + "Saved/Linux/l126/captures/L126/passage-0-1-0-openair-3-4m-interior-wall-mesh.log", + "Saved/Linux/l126/captures/L126/passage-0-1-0-openair-3-4m-interior-wall-render.log", + "Saved/Linux/l126/captures/L126/passage-0-1-0-openair-3-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-1-4m-outside", + "passage": "passage/1-2/0", + "kind": "open-air-close", + "station": "section-1/4m-outside", + "camera": [ + -4.699079444431819, + -4.6537955842685985, + -748.15 + ], + "target": [ + -7.452748333327923, + -7.555055250400828, + -748.15 + ], + "yaw": -136.49505148095557, + "pitch": 0.0, + "focus": [ + -9.518, + -9.731, + -745.88 + ], + "center_z": -745.88, + "open_air_section": 1, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.688417222224026, + 0.7253149165330574, + 0.0 + ], + "camera_target_distance_m": 4.000000000000001, + "route_distance_m": 83.504, + "requested_route_distance_m": 83.504, + "route_length_m": 114.99063175809309, + "variant": "L126-v225", + "capture": "captures/L126/passage-1-2-0-openair-1-4m-outside.png", + "scene": "Saved/Linux/l126/captures/L126/passage-1-2-0-openair-1-4m-outside.vfmesh", + "drawn_triangles": 620814, + "source_triangles": 684776, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 83.504, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.9999999999999654, + "closeup_target_surface_distance_m": 0.9023580264896125, + "closeup_predicted_target_offset_m": 0.9023580264896125, + "closeup_wall_normal_alignment": 0.5604211333378514, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -8.046760432303138, + -4.114982136123087, + -749.9844534333902 + ], + "target_actual_m": [ + -8.0, + -7.25, + -747.5006103515625 + ], + "logs": [ + "Saved/Linux/l126/captures/L126/passage-1-2-0-openair-1-4m-outside-mesh.log", + "Saved/Linux/l126/captures/L126/passage-1-2-0-openair-1-4m-outside-render.log", + "Saved/Linux/l126/captures/L126/passage-1-2-0-openair-1-4m-outside-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-1-4m-interior-wall", + "passage": "passage/1-2/0", + "kind": "open-air-close", + "station": "section-1/4m-interior-wall", + "camera": [ + -6.0956279351195075, + -11.653774892861163, + -748.8673569837389 + ], + "target": [ + -8.16773669839842, + -8.308365466344922, + -748.15 + ], + "yaw": -31.773605793127505, + "pitch": 10.331275124559749, + "focus": [ + -9.518, + -9.731, + -745.88 + ], + "center_z": -745.88, + "open_air_section": 1, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.688417222224026, + -0.7253149165330574, + -0.0 + ], + "camera_target_distance_m": 3.999999999999997, + "route_distance_m": 83.504, + "requested_route_distance_m": 83.504, + "route_length_m": 114.99063175809309, + "variant": "L126-v225", + "capture": "captures/L126/passage-1-2-0-openair-1-4m-interior-wall.png", + "scene": "Saved/Linux/l126/captures/L126/passage-1-2-0-openair-1-4m-interior-wall.vfmesh", + "drawn_triangles": 609757, + "source_triangles": 668131, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 83.504, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 3.999999999999999, + "closeup_target_surface_distance_m": 0.6509430039577998, + "closeup_predicted_target_offset_m": 0.6509430039577998, + "closeup_wall_normal_alignment": 0.7808473937095911, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -8.525095579521167, + -12.94135557024142, + -748.3220319510015 + ], + "target_actual_m": [ + -8.18421537084871, + -8.958641713644115, + -748.1744141343152 + ], + "logs": [ + "Saved/Linux/l126/captures/L126/passage-1-2-0-openair-1-4m-interior-wall-mesh.log", + "Saved/Linux/l126/captures/L126/passage-1-2-0-openair-1-4m-interior-wall-render.log", + "Saved/Linux/l126/captures/L126/passage-1-2-0-openair-1-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-2-4m-outside", + "passage": "passage/1-2/0", + "kind": "open-air-close", + "station": "section-2/4m-outside", + "camera": [ + 6.53817273275958, + -4.657210376135293, + -752.013 + ], + "target": [ + 8.159152142647708, + -8.31404312493838, + -752.013 + ], + "yaw": 156.09352823535562, + "pitch": 0.0, + "focus": [ + 9.43, + -11.181, + -749.743 + ], + "center_z": -749.743, + "open_air_section": 2, + "closeup_side": "outside", + "closeup_preferred_normal": [ + -0.40524485247203174, + 0.9142081872007717, + 0.0 + ], + "camera_target_distance_m": 4.0, + "route_distance_m": 104.362, + "requested_route_distance_m": 104.362, + "route_length_m": 114.99063175809309, + "variant": "L126-v225", + "capture": "captures/L126/passage-1-2-0-openair-2-4m-outside.png", + "scene": "Saved/Linux/l126/captures/L126/passage-1-2-0-openair-2-4m-outside.vfmesh", + "drawn_triangles": 584542, + "source_triangles": 637002, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 104.362, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.0, + "closeup_target_surface_distance_m": 0.5901774459243846, + "closeup_predicted_target_offset_m": 0.5901774459243846, + "closeup_wall_normal_alignment": 0.9891249705782158, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 6.359624549359488, + -5.416552010781576, + -752.0616659309658 + ], + "target_actual_m": [ + 8.5, + -8.79556763526633, + -752.0293187551489 + ], + "logs": [ + "Saved/Linux/l126/captures/L126/passage-1-2-0-openair-2-4m-outside-mesh.log", + "Saved/Linux/l126/captures/L126/passage-1-2-0-openair-2-4m-outside-render.log", + "Saved/Linux/l126/captures/L126/passage-1-2-0-openair-2-4m-outside-quality.log" + ] + }, + { + "name": "passage-1-2-0-openair-2-4m-interior-wall", + "passage": "passage/1-2/0", + "kind": "open-air-close", + "station": "section-2/4m-interior-wall", + "camera": [ + 12.438590152225206, + -8.574465388721983, + -752.7261335058829 + ], + "target": [ + 8.55317187096847, + -9.20292810238377, + -752.013 + ], + "yaw": -99.18796190221158, + "pitch": 10.269787281460902, + "focus": [ + 9.43, + -11.181, + -749.743 + ], + "center_z": -749.743, + "open_air_section": 2, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + 0.40524485247203174, + -0.9142081872007717, + -0.0 + ], + "camera_target_distance_m": 3.9999999999999973, + "route_distance_m": 104.362, + "requested_route_distance_m": 104.362, + "route_length_m": 114.99063175809309, + "variant": "L126-v225", + "capture": "captures/L126/passage-1-2-0-openair-2-4m-interior-wall.png", + "scene": "Saved/Linux/l126/captures/L126/passage-1-2-0-openair-2-4m-interior-wall.vfmesh", + "drawn_triangles": 572258, + "source_triangles": 618646, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 104.362, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.000000000000001, + "closeup_target_surface_distance_m": 0.353159827911248, + "closeup_predicted_target_offset_m": 0.353159827911248, + "closeup_wall_normal_alignment": 0.9983988827266467, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + 9.748104215680776, + -12.666965794821667, + -752.0265932958123 + ], + "target_actual_m": [ + 8.335827076712103, + -8.924626207433736, + -752.0074179101423 + ], + "logs": [ + "Saved/Linux/l126/captures/L126/passage-1-2-0-openair-2-4m-interior-wall-mesh.log", + "Saved/Linux/l126/captures/L126/passage-1-2-0-openair-2-4m-interior-wall-render.log", + "Saved/Linux/l126/captures/L126/passage-1-2-0-openair-2-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-1-4m-outside", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-1/4m-outside", + "camera": [ + -3.5840423774965293, + -5.521048309862215, + -815.8969999999999 + ], + "target": [ + -5.637732447498513, + -8.953592132798093, + -815.8969999999999 + ], + "yaw": -149.10792796365394, + "pitch": 0.0, + "focus": [ + -7.178, + -11.528, + -813.627 + ], + "center_z": -813.627, + "open_air_section": 1, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.5134225175004958, + 0.8581359557339694, + 0.0 + ], + "camera_target_distance_m": 4.0, + "route_distance_m": 16.616500000000002, + "requested_route_distance_m": 16.616500000000002, + "route_length_m": 494.0722798830563, + "variant": "L126-v225", + "capture": "captures/L126/passage-2-3-0-openair-1-4m-outside.png", + "scene": "Saved/Linux/l126/captures/L126/passage-2-3-0-openair-1-4m-outside.vfmesh", + "drawn_triangles": 104612, + "source_triangles": 129326, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 16.616500000000002, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.0000000000000036, + "closeup_target_surface_distance_m": 0.29188924025474844, + "closeup_predicted_target_offset_m": 0.29188924025474844, + "closeup_wall_normal_alignment": 0.6703275045296155, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -3.7918253987505834, + -7.16028175130118, + -813.227396563761 + ], + "target_actual_m": [ + -5.7833741859987065, + -9.093313475424294, + -816.1078690565205 + ], + "logs": [ + "Saved/Linux/l126/captures/L126/passage-2-3-0-openair-1-4m-outside-mesh.log", + "Saved/Linux/l126/captures/L126/passage-2-3-0-openair-1-4m-outside-render.log", + "Saved/Linux/l126/captures/L126/passage-2-3-0-openair-1-4m-outside-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-1-4m-interior-wall", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-1/4m-interior-wall", + "camera": [ + -3.4141605326349946, + -12.659565888737353, + -816.5879167710818 + ], + "target": [ + -6.170971760123668, + -9.844849940114793, + -815.8969999999999 + ], + "yaw": -44.40454805561343, + "pitch": 9.946538162082001, + "focus": [ + -7.178, + -11.528, + -813.627 + ], + "center_z": -813.627, + "open_air_section": 1, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.5134225175004958, + -0.8581359557339694, + -0.0 + ], + "camera_target_distance_m": 4.000000000000005, + "route_distance_m": 16.616500000000002, + "requested_route_distance_m": 16.616500000000002, + "route_length_m": 494.0722798830563, + "variant": "L126-v225", + "capture": "captures/L126/passage-2-3-0-openair-1-4m-interior-wall.png", + "scene": "Saved/Linux/l126/captures/L126/passage-2-3-0-openair-1-4m-interior-wall.vfmesh", + "drawn_triangles": 94962, + "source_triangles": 118028, + "verified": true, + "pixel_quality_status": "low_contrast_geometry_visible", + "route_distance_actual_m": 16.616500000000002, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.0, + "closeup_target_surface_distance_m": 0.41920390486225767, + "closeup_predicted_target_offset_m": 0.41920390486225767, + "closeup_wall_normal_alignment": 0.740744136337711, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -7.998432705401559, + -11.833936581758076, + -818.2481168532394 + ], + "target_actual_m": [ + -5.94757062165508, + -9.608161331921629, + -815.6327986602337 + ], + "logs": [ + "Saved/Linux/l126/captures/L126/passage-2-3-0-openair-1-4m-interior-wall-mesh.log", + "Saved/Linux/l126/captures/L126/passage-2-3-0-openair-1-4m-interior-wall-render.log", + "Saved/Linux/l126/captures/L126/passage-2-3-0-openair-1-4m-interior-wall-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-2-4m-outside", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-2/4m-outside", + "camera": [ + -4.5562890668466025, + 4.648574813628143, + -879.7479999999999 + ], + "target": [ + -7.40869531436283, + 7.452817777269203, + -879.7479999999999 + ], + "yaw": -45.487830534998494, + "pitch": 0.0, + "focus": [ + -9.548, + 9.556, + -877.478 + ], + "center_z": -877.478, + "open_air_section": 2, + "closeup_side": "outside", + "closeup_preferred_normal": [ + 0.7131015618790567, + -0.7010607409102652, + 0.0 + ], + "camera_target_distance_m": 4.000000000000001, + "route_distance_m": 374.929, + "requested_route_distance_m": 374.929, + "route_length_m": 494.0722798830563, + "variant": "L126-v225", + "capture": "captures/L126/passage-2-3-0-openair-2-4m-outside.png", + "scene": "Saved/Linux/l126/captures/L126/passage-2-3-0-openair-2-4m-outside.vfmesh", + "drawn_triangles": 475860, + "source_triangles": 504244, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 374.929, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.0, + "closeup_target_surface_distance_m": 1.7280841589725482, + "closeup_predicted_target_offset_m": 1.7280841589725482, + "closeup_wall_normal_alignment": 0.6707889779439669, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -7.47193274788199, + 5.182168353356822, + -879.6783722112204 + ], + "target_actual_m": [ + -7.306445568768645, + 9.17777802625833, + -879.7662205769708 + ], + "logs": [ + "Saved/Linux/l126/captures/L126/passage-2-3-0-openair-2-4m-outside-mesh.log", + "Saved/Linux/l126/captures/L126/passage-2-3-0-openair-2-4m-outside-render.log", + "Saved/Linux/l126/captures/L126/passage-2-3-0-openair-2-4m-outside-quality.log" + ] + }, + { + "name": "passage-2-3-0-openair-2-4m-interior-wall", + "passage": "passage/2-3/0", + "kind": "open-air-close", + "station": "section-2/4m-interior-wall", + "camera": [ + -11.533986119377625, + 6.164550123765492, + -880.4395357921604 + ], + "target": [ + -8.149320771422074, + 8.180937668487475, + -879.7479999999999 + ], + "yaw": 59.215963829172296, + "pitch": 9.955540417812847, + "focus": [ + -9.548, + 9.556, + -877.478 + ], + "center_z": -877.478, + "open_air_section": 2, + "closeup_side": "interior-wall", + "closeup_preferred_normal": [ + -0.7131015618790567, + 0.7010607409102652, + -0.0 + ], + "camera_target_distance_m": 4.000000000000007, + "route_distance_m": 374.929, + "requested_route_distance_m": 374.929, + "route_length_m": 494.0722798830563, + "variant": "L126-v225", + "capture": "captures/L126/passage-2-3-0-openair-2-4m-interior-wall.png", + "scene": "Saved/Linux/l126/captures/L126/passage-2-3-0-openair-2-4m-interior-wall.vfmesh", + "drawn_triangles": 486480, + "source_triangles": 513552, + "verified": true, + "pixel_quality_status": "pass", + "route_distance_actual_m": 374.929, + "route_station_adjustment_m": 0.0, + "closeup_camera_target_distance_m": 4.0, + "closeup_target_surface_distance_m": 1.0286227628002445, + "closeup_predicted_target_offset_m": 1.0286227628002445, + "closeup_wall_normal_alignment": 0.720019406420326, + "fallback_kind": null, + "fallback_surface_distance_m": null, + "camera_actual_m": [ + -8.257109087497915, + 13.208090205453457, + -879.7612149430302 + ], + "target_actual_m": [ + -8.149320771422074, + 9.209558486938477, + -879.75 + ], + "logs": [ + "Saved/Linux/l126/captures/L126/passage-2-3-0-openair-2-4m-interior-wall-mesh.log", + "Saved/Linux/l126/captures/L126/passage-2-3-0-openair-2-4m-interior-wall-render.log", + "Saved/Linux/l126/captures/L126/passage-2-3-0-openair-2-4m-interior-wall-quality.log" + ] + } + ] +} diff --git a/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-0-1-0-openair-1-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-0-1-0-openair-1-4m-interior-wall.png new file mode 100644 index 0000000..1fd88a4 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-0-1-0-openair-1-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-0-1-0-openair-1-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-0-1-0-openair-1-4m-outside.png new file mode 100644 index 0000000..87570be Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-0-1-0-openair-1-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-0-1-0-openair-2-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-0-1-0-openair-2-4m-interior-wall.png new file mode 100644 index 0000000..f76e648 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-0-1-0-openair-2-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-0-1-0-openair-2-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-0-1-0-openair-2-4m-outside.png new file mode 100644 index 0000000..c19fc5f Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-0-1-0-openair-2-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-0-1-0-openair-3-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-0-1-0-openair-3-4m-interior-wall.png new file mode 100644 index 0000000..7dcd833 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-0-1-0-openair-3-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-0-1-0-openair-3-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-0-1-0-openair-3-4m-outside.png new file mode 100644 index 0000000..816ba1d Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-0-1-0-openair-3-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-0-1-0-rock-floor-station-1.png b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-0-1-0-rock-floor-station-1.png new file mode 100644 index 0000000..e67e8c5 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-0-1-0-rock-floor-station-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-0-1-0-rock-floor-station-2.png b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-0-1-0-rock-floor-station-2.png new file mode 100644 index 0000000..2b35b85 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-0-1-0-rock-floor-station-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-0-1-0-rock-floor-station-3.png b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-0-1-0-rock-floor-station-3.png new file mode 100644 index 0000000..bed41ff Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-0-1-0-rock-floor-station-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-1-2-0-openair-1-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-1-2-0-openair-1-4m-interior-wall.png new file mode 100644 index 0000000..7569f8c Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-1-2-0-openair-1-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-1-2-0-openair-1-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-1-2-0-openair-1-4m-outside.png new file mode 100644 index 0000000..cd3c8b5 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-1-2-0-openair-1-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-1-2-0-openair-2-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-1-2-0-openair-2-4m-interior-wall.png new file mode 100644 index 0000000..a6be396 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-1-2-0-openair-2-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-1-2-0-openair-2-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-1-2-0-openair-2-4m-outside.png new file mode 100644 index 0000000..c00f532 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-1-2-0-openair-2-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-1-2-0-rock-floor-station-1.png b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-1-2-0-rock-floor-station-1.png new file mode 100644 index 0000000..3611714 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-1-2-0-rock-floor-station-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-1-2-0-rock-floor-station-2.png b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-1-2-0-rock-floor-station-2.png new file mode 100644 index 0000000..9ac3f59 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-1-2-0-rock-floor-station-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-1-2-0-rock-floor-station-3.png b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-1-2-0-rock-floor-station-3.png new file mode 100644 index 0000000..5b0e0d2 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-1-2-0-rock-floor-station-3.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-2-3-0-openair-1-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-2-3-0-openair-1-4m-interior-wall.png new file mode 100644 index 0000000..8a9efbd Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-2-3-0-openair-1-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-2-3-0-openair-1-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-2-3-0-openair-1-4m-outside.png new file mode 100644 index 0000000..6ce2868 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-2-3-0-openair-1-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-2-3-0-openair-2-4m-interior-wall.png b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-2-3-0-openair-2-4m-interior-wall.png new file mode 100644 index 0000000..8532d70 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-2-3-0-openair-2-4m-interior-wall.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-2-3-0-openair-2-4m-outside.png b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-2-3-0-openair-2-4m-outside.png new file mode 100644 index 0000000..e9fef5f Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-2-3-0-openair-2-4m-outside.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-2-3-0-rock-floor-station-1.png b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-2-3-0-rock-floor-station-1.png new file mode 100644 index 0000000..0413199 Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-2-3-0-rock-floor-station-1.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-2-3-0-rock-floor-station-2.png b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-2-3-0-rock-floor-station-2.png new file mode 100644 index 0000000..f823d6e Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-2-3-0-rock-floor-station-2.png differ diff --git a/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-2-3-0-rock-floor-station-3.png b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-2-3-0-rock-floor-station-3.png new file mode 100644 index 0000000..279866a Binary files /dev/null and b/Standalone/Research/WorldAssemblerM3/Linux126/captures/L126/passage-2-3-0-rock-floor-station-3.png differ diff --git a/Standalone/Source/OwnerWorldLoader.h b/Standalone/Source/OwnerWorldLoader.h index 4d58f3b..784c249 100644 --- a/Standalone/Source/OwnerWorldLoader.h +++ b/Standalone/Source/OwnerWorldLoader.h @@ -24,37 +24,6 @@ struct FStandaloneParitySample int32 StrateIndex = INDEX_NONE; }; -struct FStandalonePassageVoidCrossing -{ - std::size_t passageIndex=0; - std::size_t firstSegment=0; - std::size_t lastSegment=0; - std::uint64_t unsupportedSamples=0; - double unsupportedLengthMetres=0.0; - std::array startPoint{}; - std::array endPoint{}; - bool needsColumn=false; - bool connectedAtStart=false; - bool connectedAtEnd=false; - std::int64_t centerXSubvoxels=0; - std::int64_t centerYSubvoxels=0; - std::int64_t topZSubvoxels=0; - std::int64_t bottomZSubvoxels=0; - std::int64_t minimumRadiusSubvoxels=0; - std::int64_t nominalRadiusSubvoxels=0; - std::int64_t maximumRadiusSubvoxels=0; - double naturalSurfaceReliefMetres=0.0; - double maximumRouteOffsetMetres=0.0; - double maximumBoreRadiusMetres=0.0; - bool needsRootTaper=false; -}; - -struct FStandalonePassageVoidCrossingCache -{ - std::mutex mutex; - std::unordered_map> byLayout; -}; - struct FStandaloneOwnerWorld { std::unique_ptr Settings; @@ -81,8 +50,6 @@ struct FStandaloneOwnerWorld std::uint32_t StrateLayoutChunkSizeMicrometres = 8000000; std::int64_t StrateLayoutChunkWidthSubvoxels = 8192; bool bHasUnrealResolvedCorePlan = false; - std::shared_ptr PassageVoidCrossingCache = - std::make_shared(); }; namespace StandaloneOwnerLoader diff --git a/Standalone/Source/StreamBenchmarkHeadless.cpp b/Standalone/Source/StreamBenchmarkHeadless.cpp index e249f5d..bb39a9a 100644 --- a/Standalone/Source/StreamBenchmarkHeadless.cpp +++ b/Standalone/Source/StreamBenchmarkHeadless.cpp @@ -59,6 +59,7 @@ namespace int ShapeHelperLimit=8; bool AuditBasePageEquivalence=false; bool AuditRouteParity=false; + bool AuditPassageTileSeams=false; bool AuditPassageSourceClamp=false; bool AuditPassageCarveReach=false; bool RegionCrossing=false; @@ -1465,6 +1466,7 @@ namespace " --shape-helper-limit=8|12 (default 8; shape build A/B)\n" " --audit-base-page-equivalence (hash one tile through both shape routes)\n" " --audit-route-parity (compare page, native-only, exact-query and mesh routes)\n" + " --audit-passage-tile-seams (compare shared LOD0 density samples in adjacent route tiles)\n" " --audit-passage-source-clamp (compare passage source floors 2,3,4,6 over all near tiles)\n" " --audit-passage-carve-reach (compare post-composer reaches 1.5,2,2.5,4 m over all near tiles)\n" " --audit-tile-shape-readiness (run a deliberately mis-marked tile against the native-only guard)\n" @@ -1547,6 +1549,7 @@ namespace } else if(arg=="--audit-base-page-equivalence")options.AuditBasePageEquivalence=true; else if(arg=="--audit-route-parity")options.AuditRouteParity=true; + else if(arg=="--audit-passage-tile-seams")options.AuditPassageTileSeams=true; else if(arg=="--audit-passage-source-clamp")options.AuditPassageSourceClamp=true; else if(arg=="--audit-passage-carve-reach")options.AuditPassageCarveReach=true; else if(arg=="--region-crossing")options.RegionCrossing=true; @@ -2330,5 +2333,6 @@ int main(int argc,char** argv) options.StreamingSchedulerPolicy,options.MovingCameraTrace, options.MovingCameraSpeedMetersPerSecond,options.MovingCameraDurationSeconds, options.MovingCameraDwellSeconds,options.ColdWorkerTimeline, - options.AuditPassageSourceClamp,options.AuditPassageCarveReach); + options.AuditPassageSourceClamp,options.AuditPassageCarveReach, + options.AuditPassageTileSeams); } diff --git a/Standalone/Source/StreamBenchmarkPipeline.h b/Standalone/Source/StreamBenchmarkPipeline.h index a4c3d18..820aac2 100644 --- a/Standalone/Source/StreamBenchmarkPipeline.h +++ b/Standalone/Source/StreamBenchmarkPipeline.h @@ -3,6 +3,8 @@ #include "OwnerWorldLoader.h" #include "StreamingWorld.h" #include "LinuxScreenSpaceGate.h" +#include "../Core/src/VoxelForgeFieldShared.h" +#include "../Core/include/VoxelForgeCore/PassageSpline.h" #include #include @@ -15,12 +17,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include #include #include @@ -458,7 +462,6 @@ namespace StandaloneStreamBenchmark baseOptions.forceFullDensityCapture=true; baseOptions.skipUvAndColors=true; baseOptions.skipMaterialGroups=true; - baseOptions.diagnosticPassageSourceFloorVoxels=0.0; baseOptions.diagnosticPassageCarveReachMetres=0.0; VoxelForgeCore::TileGenerationOptions candidateOptions=baseOptions; candidateOptions.profilePassageComposer=true; @@ -483,14 +486,10 @@ namespace StandaloneStreamBenchmark key.lod,error.c_str()); continue; } - if(!bAuditCarveReach) - GatherPassageSourceGradients(Shape,*base,Layout,gradientStats); for(std::size_t floorIndex=0;floorIndex,8> firstBlocked{}; std::array,8> firstUnsupported{}; - std::array,8> firstSupportMasks{}; std::size_t firstBlockedCount=0,firstUnsupportedCount=0; - std::array firstDeepUnsupported{}; - std::array firstDeepSupportMask{}; - bool hasDeepUnsupported=false; bool passed=false; }; - struct FPassageSegmentSupportAudit - { - std::uint64_t centers=0,unsupported=0,nativeUnsupported=0; - std::array firstUnsupported{}; - std::array firstNativeDensities{}; - std::uint32_t firstNativeSupportedProbes=0; - bool hasUnsupported=false; - }; const double coreMetres=static_cast(World.CoreVoxelSizeMicrons)/1000000.0; const auto auditPlayerPath=[&](const VoxelForgeCore::World& Field, const std::vector>& path, double supportStartMetres,double supportStepMetres, double supportMaximumMetres,std::uint32_t minimumSupportProbes, double supportProbeRadiusMetres, - const VoxelForgeCore::World* nativeField=nullptr, - std::vector* segmentSupport=nullptr) + const std::function& supportExemption={}) { FWalkAudit audit; if(path.size()<2)return audit; - if(segmentSupport)segmentSupport->assign(path.size()-1,{}); constexpr std::array heights{{-0.84,-0.60,-0.30,0.0,0.30,0.60,0.84}}; constexpr std::array,8> directions{{ {{1.0,0.0}},{{0.7071067811865475,0.7071067811865475}},{{0.0,1.0}}, @@ -2907,9 +2893,6 @@ namespace StandaloneStreamBenchmark const double y=(a[1]+dy*t)*coreMetres; const double z=(a[2]+dz*t)*coreMetres; ++audit.centers; - FPassageSegmentSupportAudit* segmentAudit=segmentSupport - ?&(*segmentSupport)[segment-1]:nullptr; - if(segmentAudit)++segmentAudit->centers; for(const double h:heights) { const double capOffset=std::max(0.0,std::abs(h)-0.54); @@ -2926,7 +2909,6 @@ namespace StandaloneStreamBenchmark {{0.0,supportProbeRadiusMetres}}, {{0.0,-supportProbeRadiusMetres}}}}; std::uint32_t supportedProbes=0; - std::uint32_t nativeSupportedProbes=0; double firstUnsupportedX=x,firstUnsupportedY=y, firstUnsupportedZ=footZ,lastUnsupportedDensity=0.0; std::array supportMask{}; @@ -2936,6 +2918,14 @@ namespace StandaloneStreamBenchmark const double supportX=x+offset[0],supportY=y+offset[1]; bool supported=false; double offsetSampleZ=footZ; + if(supportExemption&&supportExemption(supportX,supportY, + footZ-supportStartMetres)) + { + ++audit.supportOverlapSkips; + ++supportedProbes; + supportMask[offsetIndex]=true; + continue; + } for(double depth=supportStartMetres; depth<=supportMaximumMetres+1.0e-6;depth+=supportStepMetres) { @@ -2948,14 +2938,6 @@ namespace StandaloneStreamBenchmark supported=true;break; } } - if(nativeField) - { - for(double depth=supportStartMetres; - depth<=supportMaximumMetres+1.0e-6;depth+=supportStepMetres) - if(nativeField->densityAt({supportX/coreMetres, - supportY/coreMetres,(footZ-depth)/coreMetres})<0.0f) - {++nativeSupportedProbes;break;} - } if(supported){++supportedProbes;supportMask[offsetIndex]=true;} else { @@ -2963,44 +2945,15 @@ namespace StandaloneStreamBenchmark firstUnsupportedZ=offsetSampleZ*coreMetres; } } - if(nativeField&&segmentAudit - &&nativeSupportedProbesnativeUnsupported; if(supportedProbesunsupported; - if(!segmentAudit->hasUnsupported) - { - segmentAudit->hasUnsupported=true; - segmentAudit->firstUnsupported={x,y,footZ}; - segmentAudit->firstNativeSupportedProbes=nativeSupportedProbes; - if(nativeField) - { - constexpr std::array depths{{0.125,1.0,2.0,4.0}}; - for(std::size_t depthIndex=0;depthIndexfirstNativeDensities[depthIndex]=nativeField->densityAt({ - x/coreMetres,y/coreMetres, - (footZ-depths[depthIndex])/coreMetres}); - } - } - } - if(!audit.hasDeepUnsupported&&footZ<-80.0) - { - audit.hasDeepUnsupported=true; - audit.firstDeepUnsupported={firstUnsupportedX,firstUnsupportedY, - firstUnsupportedZ,lastUnsupportedDensity}; - audit.firstDeepSupportMask=supportMask; - } if(audit.firstUnsupportedCount(q)*World.CoreVoxelSizeMicrons /(VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel*1000000.0);}; + const auto passageUpperMouthFloorDepth=[&]( + const VoxelForgeCore::ResolvedLayoutPassageV1& passage) + { + const double controlZ=qToMetres( + passage.controlPoints.front().positionSubvoxels[2]); + const double authoredMouthDepth=std::max(0.0,controlZ + -qToMetres(passage.upperMouthSubvoxels[2])+1.13); + const auto upperStratum=std::find_if(ResolvedLayout->strates.begin(), + ResolvedLayout->strates.end(),[&](const auto& stratum) + {return stratum.strateIndex==passage.upperStrateIndex;}); + if(upperStratum==ResolvedLayout->strates.end() + ||upperStratum->generatorKind!="FloatingIslands") + return authoredMouthDepth; + std::vector> route; + for(const auto& anchor:upperStratum->anchors) + if(anchor.kind=="route_point"&&anchor.values.size()>=3) + route.push_back({qToMetres(anchor.values[0]), + qToMetres(anchor.values[1]),qToMetres(anchor.values[2])}); + double routeHeight=0.0,distanceSquared=0.0; + const double mouthX=qToMetres(passage.controlPoints.front().positionSubvoxels[0]); + const double mouthY=qToMetres(passage.controlPoints.front().positionSubvoxels[1]); + if(!VoxelForgeCore::PassageSpline::ClosestRouteHeightAtXY( + route,mouthX,mouthY,routeHeight,distanceSquared) + ||distanceSquared>std::pow( + qToMetres(passage.controlPoints.front().radiusSubvoxels)+2.0,2.0)) + return authoredMouthDepth; + const double routeAlignedDepth=std::max(0.0,controlZ-routeHeight+1.13); + return std::max(authoredMouthDepth,routeAlignedDepth); + }; + const auto passageSplineControls=[&]( + const VoxelForgeCore::ResolvedLayoutPassageV1& passage) + { + std::vector controls; + controls.reserve(passage.controlPoints.size()); + for(const auto& point:passage.controlPoints) + controls.push_back({qToMetres(point.positionSubvoxels[0]), + qToMetres(point.positionSubvoxels[1]), + qToMetres(point.positionSubvoxels[2]), + qToMetres(point.radiusSubvoxels)}); + if(!controls.empty()) + controls.front()[3]=std::max(controls.front()[3], + passageUpperMouthFloorDepth(passage)); + return controls; + }; + const auto passageSplineFloorProfile=[&]( + const VoxelForgeCore::ResolvedLayoutPassageV1& passage) + { + std::vector profile; + profile.reserve(passage.controlPoints.size()); + for(const auto& point:passage.controlPoints) + profile.push_back(qToMetres(point.positionSubvoxels[2] + -point.radiusSubvoxels)); + return profile; + }; + const auto passageBodyFloorDepth=[&]( + const VoxelForgeCore::ResolvedLayoutPassageV1& passage) + { + if(passage.controlPoints.size()<2)return 0.0; + const std::size_t routeEnd=std::clamp( + passage.lowerMouthControlIndex,1,passage.controlPoints.size()-1); + double minimumRadius=std::numeric_limits::infinity(); + double minimumBodyRadius=minimumRadius; + double totalLength=0.0; + const auto controls=passageSplineControls(passage); + const auto floorProfile=passageSplineFloorProfile(passage); + const auto segments=VoxelForgeCore::PassageSpline::BuildSegments( + controls,routeEnd,8.0,1.0,floorProfile,0.100); + const auto consider=[&](double distance,double radius) + { + minimumRadius=std::min(minimumRadius,radius); + if(distance>=10.0&&totalLength-distance>=10.0) + minimumBodyRadius=std::min(minimumBodyRadius,radius); + }; + for(const auto& segment:segments)totalLength=segment.alongMetres + +segment.lengthMetres; + consider(0.0,controls.front()[3]); + for(const auto& segment:segments) + consider(segment.alongMetres+segment.lengthMetres,segment.b[3]); + if(!std::isfinite(minimumBodyRadius))minimumBodyRadius=minimumRadius; + return std::max(0.5,minimumBodyRadius-0.23); + }; + const auto passageTubeDepthAt=[](double radiusMetres,double bodyDepthMetres) + { + return std::min(bodyDepthMetres, + std::max(0.0,radiusMetres-0.23)); + }; + struct FPassageAuditRoutePoint + { + double x=0.0,y=0.0,z=0.0,floorZ=0.0,radius=0.0,distance=0.0; + std::size_t segmentIndex=0; + }; + const auto passageSmoothRoute=[&]( + const VoxelForgeCore::ResolvedLayoutPassageV1& passage,double bodyDepth) + { + std::vector route; + if(passage.controlPoints.size()<2)return route; + const std::size_t routeEnd=std::clamp( + passage.lowerMouthControlIndex,1,passage.controlPoints.size()-1); + const auto controls=passageSplineControls(passage); + const auto floorProfile=passageSplineFloorProfile(passage); + const auto segments=VoxelForgeCore::PassageSpline::BuildSegments( + controls,routeEnd,8.0,1.0,floorProfile,0.100); + const auto effectiveCenterZ=[&](const auto& point,double plannedFloor) + { + return plannedFloor+passageTubeDepthAt(point[3],bodyDepth); + }; + if(!segments.empty()) + { + const auto& first=segments.front(); + route.push_back({first.a[0],first.a[1], + effectiveCenterZ(first.a,first.plannedFloorA), + first.plannedFloorA,first.a[3], + first.alongMetres,0}); + for(const auto& segment:segments) + route.push_back({segment.b[0],segment.b[1], + effectiveCenterZ(segment.b,segment.plannedFloorB), + segment.plannedFloorB,segment.b[3], + segment.alongMetres+segment.lengthMetres, + segment.controlSpan+1}); + } + return route; + }; + std::vector allPassageBodyFloorDepths; + std::vector> allPassageSmoothRoutes; + struct FUpperMouthFloorBlend + { + std::vector> receivingRoute; + double mouthX=0.0,mouthY=0.0,mouthFloor=0.0; + double tangentX=0.0,tangentY=0.0; + }; + std::vector allUpperMouthFloorBlends; + allPassageBodyFloorDepths.reserve(ResolvedLayout->passages.size()); + allPassageSmoothRoutes.reserve(ResolvedLayout->passages.size()); + allUpperMouthFloorBlends.reserve(ResolvedLayout->passages.size()); + for(const auto& passage:ResolvedLayout->passages) + { + const double bodyDepth=passageBodyFloorDepth(passage); + allPassageBodyFloorDepths.push_back(bodyDepth); + allPassageSmoothRoutes.push_back(passageSmoothRoute(passage,bodyDepth)); + FUpperMouthFloorBlend blend; + const auto upperStratum=std::find_if(ResolvedLayout->strates.begin(), + ResolvedLayout->strates.end(),[&](const auto& stratum) + {return stratum.strateIndex==passage.upperStrateIndex;}); + if(upperStratum!=ResolvedLayout->strates.end() + &&upperStratum->generatorKind=="FloatingIslands") + { + for(const auto& anchor:upperStratum->anchors) + if(anchor.kind=="route_point"&&anchor.values.size()>=3) + blend.receivingRoute.push_back({ + qToMetres(anchor.values[0]),qToMetres(anchor.values[1]), + qToMetres(anchor.values[2])}); + const auto controls=passageSplineControls(passage); + const auto floorProfile=passageSplineFloorProfile(passage); + const std::size_t routeEnd=std::clamp( + passage.lowerMouthControlIndex,1,passage.controlPoints.size()-1); + const auto segments=VoxelForgeCore::PassageSpline::BuildSegments( + controls,routeEnd,8.0,1.0,floorProfile,0.100); + if(!segments.empty()) + { + blend.mouthX=segments.front().a[0]; + blend.mouthY=segments.front().a[1]; + blend.mouthFloor=floorProfile.front(); + blend.tangentX=segments.front().b[0]-segments.front().a[0]; + blend.tangentY=segments.front().b[1]-segments.front().a[1]; + } + } + allUpperMouthFloorBlends.push_back(std::move(blend)); + } + const auto passageFloorAtXY=[&](std::size_t passageIndex,double x,double y, + double plannedFloor) + { + if(passageIndex>=allUpperMouthFloorBlends.size())return plannedFloor; + const auto& blend=allUpperMouthFloorBlends[passageIndex]; + return VoxelForgeCore::PassageSpline::BlendUpperMouthFloorAtXY( + blend.receivingRoute,x,y,plannedFloor,blend.mouthX,blend.mouthY, + blend.mouthFloor, + blend.tangentX,blend.tangentY, + VoxelForgeCore::PassageSpline::UpperMouthFloorBlendRadiusMetres, + 1.13); + }; + const auto interpolatePassageRoute=[]( + const std::vector& route,double distance) + { + if(route.empty())return FPassageAuditRoutePoint{}; + distance=std::clamp(distance,0.0,route.back().distance); + const auto upper=std::lower_bound(route.begin()+1,route.end(),distance, + [](const FPassageAuditRoutePoint& point,double value) + {return point.distance1.0e-9?(distance-a.distance)/span:0.0; + return FPassageAuditRoutePoint{ + std::lerp(a.x,b.x,t),std::lerp(a.y,b.y,t),std::lerp(a.z,b.z,t), + std::lerp(a.floorZ,b.floorZ,t), + std::lerp(a.radius,b.radius,t),distance,b.segmentIndex}; + }; + struct FPassageRouteProjection + { + double centerDistanceSquared=std::numeric_limits::infinity(); + double tubeDistance=std::numeric_limits::infinity(); + double centerAlong=0.0,tubeAlong=0.0; + }; + const auto projectPassageRoute=[]( + const std::vector& route, + double x,double y,double z) + { + FPassageRouteProjection projection; + for(std::size_t segment=1;segment1.0e-12 + ?((x-a.x)*dx+(y-a.y)*dy)/horizontalLengthSquared + :std::clamp((z-a.z)*dz/lengthSquared,0.0,1.0); + const double t=std::clamp(((x-a.x)*dx+(y-a.y)*dy + +(z-a.z)*dz)/lengthSquared,0.0,1.0); + const double ex=x-(a.x+t*dx),ey=y-(a.y+t*dy),ez=z-(a.z+t*dz); + const double distanceSquared=ex*ex+ey*ey+ez*ez; + const double along=std::lerp(a.distance,b.distance,t); + const double centerAlong=std::lerp(a.distance,b.distance,horizontalT); + if(distanceSquaredpassages.size();++passageIndex) + { + const auto& passage=ResolvedLayout->passages[passageIndex]; + const auto& route=allPassageSmoothRoutes[passageIndex]; + if(route.size()<2)continue; + const auto densityMetres=[&](double x,double y,double z) + { + return static_cast(Shape.densityAt({x/coreMetres, + y/coreMetres,z/coreMetres}))*coreMetres; + }; + const auto floorRoot=[&](const FPassageAuditRoutePoint& pose) + { + double low=pose.floorZ-0.75,high=pose.floorZ+0.75; + double lowDensity=densityMetres(pose.x,pose.y,low); + double highDensity=densityMetres(pose.x,pose.y,high); + if(!(lowDensity<0.0&&highDensity>=0.0)) + return std::numeric_limits::quiet_NaN(); + for(int iteration=0;iteration<24;++iteration) + { + const double middle=(low+high)*0.5; + if(densityMetres(pose.x,pose.y,middle)<0.0)low=middle; + else high=middle; + } + return (low+high)*0.5; + }; + constexpr std::array labels{{ + "route-station-25","route-station-50","route-station-75"}}; + for(std::size_t targetIndex=0;targetIndex(targetIndex+1)/4.0; + const char* label=labels[targetIndex]; + const auto center=interpolatePassageRoute(route,targetDistance); + const VoxelForgeCore::Vec3d centerVoxel={center.x/coreMetres, + center.y/coreMetres,center.floorZ/coreMetres}; + std::printf("[L115DensityColumn] passage=%s station=%s route_s_m=%.3f route_length_m=%.3f x_m=%.6f y_m=%.6f planned_floor_m=%.6f dispatch=%s source_density_m=%.9f unclamped_density_m=%.9f\n", + passage.stableId.c_str(),label,targetDistance, + route.back().distance,center.x,center.y,center.floorZ, + Shape.densityDispatchPathAt(centerVoxel).c_str(), + static_cast(Shape.passageSourceDensityAt(centerVoxel))*coreMetres, + static_cast(Shape.unclampedDensityAt(centerVoxel))*coreMetres); + for(int sample=0;sample<=40;++sample) + { + const double offset=-0.50+sample*0.025; + std::printf("[L115DensityColumnSample] passage=%s station=%s dz_m=%.3f density_m=%.9f\n", + passage.stableId.c_str(),label,offset,densityMetres(center.x,center.y, + center.floorZ+offset)); + } + for(int sample=-25;sample<=25;++sample) + { + const double distance=std::clamp(targetDistance + +sample*0.10,0.0,route.back().distance); + const auto pose=interpolatePassageRoute(route,distance); + const double root=floorRoot(pose); + std::printf("[L115DensitySlopeSample] passage=%s station=%s s_m=%.3f x_m=%.6f y_m=%.6f planned_floor_m=%.6f root_floor_m=%.6f residual_m=%.6f density_minus_0p1_m=%.9f density_plane_m=%.9f density_plus_0p1_m=%.9f\n", + passage.stableId.c_str(),label,distance,pose.x,pose.y, + pose.floorZ,root, + root-pose.floorZ, + densityMetres(pose.x,pose.y,pose.floorZ-0.1), + densityMetres(pose.x,pose.y,pose.floorZ), + densityMetres(pose.x,pose.y,pose.floorZ+0.1)); + } + } + } + } + const auto passageInteriorWinsAt=[&](double xMetres,double yMetres, + double zMetres,std::size_t ignoredPassage=std::numeric_limits::max(), + std::size_t ignoredSegment=std::numeric_limits::max()) + { + constexpr double CornerBlendMetres=0.50; + constexpr double WallReliefMetres=0.21; + const auto smoothMax=[](double left,double right,double radius) + { + if(!(radius>0.0))return std::max(left,right); + const double h=std::clamp(radius-std::abs(left-right),0.0,radius) + /radius; + return std::max(left,right)+h*h*h*(radius/6.0); + }; + for(std::size_t passageIndex=0; + passageIndexpassages.size();++passageIndex) + { + const auto& passage=ResolvedLayout->passages[passageIndex]; + if(passage.controlPoints.size()<2)continue; + const auto& route=allPassageSmoothRoutes[passageIndex]; + if(route.size()<2)continue; + double bestRoundDistance=std::numeric_limits::infinity(); + double bestFloorCenterDistanceSquared= + std::numeric_limits::infinity(); + double bestCenterZ=0.0,bestFloorCenterZ=0.0,bestRadius=0.0; + std::size_t bestTubeSegment=std::numeric_limits::max(); + std::size_t bestFloorSegment=std::numeric_limits::max(); + for(std::size_t segment=1;segment1.0e-12 + ?((xMetres-a.x)*dx+(yMetres-a.y)*dy) + /horizontalLengthSquared + :std::clamp((zMetres-a.z)*dz/lengthSquared,0.0,1.0); + const double floorAlong=std::lerp(a.distance,b.distance,horizontalT); + const double t=std::clamp(((xMetres-a.x)*dx+(yMetres-a.y)*dy + +(zMetres-a.z)*dz)/lengthSquared,0.0,1.0); + const double centerX=a.x+t*dx,centerY=a.y+t*dy,centerZ=a.z+t*dz; + const double radius=std::lerp(a.radius,b.radius,t); + const double ex=xMetres-centerX,ey=yMetres-centerY, + ez=zMetres-centerZ; + const double roundDistance=std::sqrt(ex*ex+ey*ey+ez*ez)-radius; + const double floorCenterDistanceSquared=ex*ex+ey*ey+ez*ez; + const auto floorPose=interpolatePassageRoute(route,floorAlong); + const double floorCenterZ=passageFloorAtXY(passageIndex, + xMetres,yMetres,floorPose.floorZ); + // A self-overlap can place another route span's open bore + // through this nominal floor probe. Such a point is interior, + // not a missing floor shell, even when a different span is + // nearest by a few floating-point ulps. + if(smoothMax(roundDistance,floorCenterZ-zMetres, + CornerBlendMetres)<=0.0) + return true; + if(floorCenterDistanceSquared::max())continue; + if(!std::isfinite(bestFloorCenterDistanceSquared))continue; + const double floorCenterZ=bestFloorCenterZ; + const double floorDistance=bestFloorCenterZ-zMetres; + // The composer uses the nearest round tube segment, then the + // nearest route station for its continuous floor plane. + const auto& a=route[bestTubeSegment-1]; + const auto& b=route[bestTubeSegment]; + const double dx=b.x-a.x,dy=b.y-a.y,dz=b.z-a.z; + const double lengthSquared=dx*dx+dy*dy+dz*dz; + if(lengthSquared<=1.0e-12)continue; + const double t=std::clamp(((xMetres-a.x)*dx+(yMetres-a.y)*dy + +(zMetres-a.z)*dz)/lengthSquared,0.0,1.0); + const double centerX=a.x+t*dx,centerY=a.y+t*dy; + const double centerZ=a.z+t*dz; + const double distanceToCenter=std::max(1.0e-9, + bestRoundDistance+bestRadius); + const double verticalWallAlignment=std::clamp( + -(zMetres-centerZ)/distanceToCenter,0.0,1.0); + const double wallElevationMetres=zMetres-floorCenterZ; + const double crestFade=std::clamp((1.0-wallElevationMetres)/0.25, + 0.0,1.0); + const double smoothCrestFade=crestFade*crestFade + *(3.0-2.0*crestFade); + const double wallReliefWeight=(0.05+0.95 + *(1.0-verticalWallAlignment))*smoothCrestFade; + const float relief=VF_FieldPassageWallRelief( + static_cast(xMetres/coreMetres), + static_cast(yMetres/coreMetres), + static_cast(zMetres/coreMetres), + static_cast(World.Seed)); + const double roughRoundDistance=bestRoundDistance + +static_cast(std::clamp(relief,-1.0f,1.0f)) + *WallReliefMetres*wallReliefWeight; + const double shapedDistance=smoothMax(roughRoundDistance, + floorDistance,CornerBlendMetres); + if(shapedDistance<=0.0)return true; + } + return false; + }; struct FPassageNaturalnessAudit { double maximumFlatRunMetres=0.0; @@ -3029,6 +3408,7 @@ namespace StandaloneStreamBenchmark double floorFlatStepRunMetres=0.0,floorStepMetres=0.0; double wallFlatStepRunMetres=0.0,wallStepMetres=0.0; std::uint64_t floorSamples=0,wallSamples=0,missingFloorSamples=0,missingWallSamples=0; + std::uint64_t expectedFloorSamples=0,floorOverlapSkips=0; bool passed=false; }; struct FPassageRippleAudit @@ -3042,9 +3422,13 @@ namespace StandaloneStreamBenchmark std::vector> floorPeakProfile; double floorPeakWindowStartMetres=0.0; std::uint64_t samples=0,expectedSamples=0; + std::uint64_t wallWindowSamples=0,wallWindowExpectedSamples=0; + std::uint64_t wallQualifiedWindows=0; std::uint64_t floorSamples=0,floorExpectedSamples=0; + std::uint64_t floorInteriorWins=0; bool controlDetected=false,passed=false; bool floorControlDetected=false; + bool floorOverlapOnly=false; double floorStepControlAmplitudeMetres=0.0; bool floorStepControlDetected=false; }; @@ -3085,42 +3469,25 @@ namespace StandaloneStreamBenchmark { FPassageMouthProfileAudit audit; if(passage.controlPoints.size()<2)return audit; - const std::size_t end=std::min(passage.lowerMouthControlIndex, - passage.controlPoints.size()-1); - if(end<1)return audit; + const std::size_t passageIndex=static_cast( + &passage-ResolvedLayout->passages.data()); + if(passageIndex>=allPassageSmoothRoutes.size())return audit; + const auto& smoothRoute=allPassageSmoothRoutes[passageIndex]; + if(smoothRoute.size()<3)return audit; struct FProfilePose { - double distance=0.0,x=0.0,y=0.0,z=0.0,radius=0.0; + double distance=0.0,x=0.0,y=0.0,z=0.0,floorZ=0.0,radius=0.0; + std::size_t segmentIndex=0; }; std::vector path; - path.reserve(end*8+1); - double distance=0.0; - for(std::size_t segment=0;segment1.0e-8))continue; - const std::size_t steps=std::max(1, - static_cast(std::ceil(length/PassageProfileSpacingMetres))); - for(std::size_t step=segment==0?0:1;step<=steps;++step) - { - const double t=static_cast(step)/steps; - path.push_back({distance+length*t,std::lerp(ax,bx,t), - std::lerp(ay,by,t),std::lerp(az,bz,t),std::lerp(ar,br,t)}); - } - distance+=length; + path.push_back({point.distance,point.x,point.y,point.z, + point.floorZ,point.radius,point.segmentIndex}); } if(path.size()<3)return audit; - const double lowerMouthDistance=distance; + const double lowerMouthDistance=path.back().distance; constexpr double DensitySearchStepMetres=0.0625; const auto densityMetres=[&](double x,double y,double z) { @@ -3130,7 +3497,7 @@ namespace StandaloneStreamBenchmark }; const auto firstFloorCrossing=[&](const FProfilePose& pose,double x,double y)->double { - const double expectedFloor=pose.z-pose.radius; + const double expectedFloor=pose.floorZ; const double maximumRise=std::min(2.0*pose.radius-0.25, std::max(0.75,pose.radius-1.20+0.50)); double previousZ=expectedFloor-1.50; @@ -3154,18 +3521,20 @@ namespace StandaloneStreamBenchmark } return highestFloor; }; - const auto findWallRadius=[&](const FProfilePose& pose,double nx,double ny) + const auto findWallRadius=[&](const FProfilePose& pose,double nx,double ny, + double wallHeightMetres) { const double maximum=pose.radius+2.0; double previousRadius=0.0; - double previous=densityMetres(pose.x,pose.y,pose.z); + const double wallZ=pose.floorZ+wallHeightMetres; + double previous=densityMetres(pose.x,pose.y,wallZ); if(!std::isfinite(previous)||previous<0.0) return std::numeric_limits::quiet_NaN(); for(double radius=DensitySearchStepMetres;radius<=maximum; radius+=DensitySearchStepMetres) { const double current=densityMetres(pose.x+nx*radius, - pose.y+ny*radius,pose.z); + pose.y+ny*radius,wallZ); if(!std::isfinite(current))return std::numeric_limits::quiet_NaN(); if(previous>=0.0&¤t<=0.0) { @@ -3180,7 +3549,8 @@ namespace StandaloneStreamBenchmark }; std::array>,3>,2> floorProfiles; std::array>,2>,2> wallProfiles; - std::array endpointFloorCounts{}; + std::array endpointFloorCounts{},endpointFloorExpected{}, + endpointFloorOverlapSkips{}; for(std::size_t i=0;i(&passage- + ResolvedLayout->passages.data()),pose.segmentIndex)) + { + ++audit.floorOverlapSkips; + ++endpointFloorOverlapSkips[endpoint]; + continue; + } + const double floor=firstFloorCrossing(pose,sampleX,sampleY); if(lane!=0&&localDistance>=4.0&&localDistance<=5.5) std::printf("[PassageMouthProfileProbe] id=%s endpoint=%s d_m=%.3f lane_m=%.2f x_m=%.3f y_m=%.3f route_floor_m=%.3f field_floor_m=%.3f\n", passage.stableId.c_str(),endpoint==0?"upper":"lower", - localDistance,lateral,pose.x+nx*lateral, - pose.y+ny*lateral,pose.z-pose.radius,floor); + localDistance,lateral,sampleX,sampleY,pose.floorZ,floor); if(std::isfinite(floor)) { floorProfiles[endpoint][lane].push_back({localDistance,floor}); @@ -3220,14 +3606,58 @@ namespace StandaloneStreamBenchmark } else ++audit.missingFloorSamples; } - if(i%4!=0)continue; + } + } + // Keep wall probe density tied to route distance, not to the number + // of adaptive spline segments. A coarser chord tolerance may leave + // long segments around a mouth; fixed stations still exercise the + // same wall geometry without weakening the coverage requirement. + for(std::size_t endpoint=0;endpoint<2;++endpoint) + { + for(double localDistance=0.0; + localDistance<=PassageMouthProfileReachMetres+1.0e-9; + localDistance+=1.0) + { + const double routeDistance=endpoint==0?localDistance + :lowerMouthDistance-localDistance; + if(routeDistance<0.0||routeDistance>lowerMouthDistance)continue; + const auto upper=std::lower_bound(path.begin(),path.end(),routeDistance, + [](const FProfilePose& pose,double value) + {return pose.distancedistance-a->distance; + const double t=span>1.0e-12 + ?std::clamp((routeDistance-a->distance)/span,0.0,1.0):0.0; + const double dx=b->x-a->x,dy=b->y-a->y; + const double tangentLength=std::hypot(dx,dy); + if(tangentLength<=1.0e-6) + { + audit.missingWallSamples+=2; + continue; + } + const double nx=-dy/tangentLength,ny=dx/tangentLength; + FProfilePose pose; + pose.distance=routeDistance; + pose.x=std::lerp(a->x,b->x,t); + pose.y=std::lerp(a->y,b->y,t); + pose.z=std::lerp(a->z,b->z,t); + pose.floorZ=std::lerp(a->floorZ,b->floorZ,t); + pose.radius=std::lerp(a->radius,b->radius,t); + pose.segmentIndex=t<0.5?a->segmentIndex:b->segmentIndex; for(std::size_t side=0;side<2;++side) { const double sign=side==0?-1.0:1.0; - const double radius=findWallRadius(pose,sign*nx,sign*ny); + // The open-air half-pipe has side walls only one metre + // above its floor. Probe at mid-wall height so this check + // measures those walls instead of the absent roof-height + // shell at the centreline. + const double radius=findWallRadius( + pose,sign*nx,sign*ny,0.50); if(std::isfinite(radius)) { - wallProfiles[endpoint][side].push_back({localDistance,radius}); + wallProfiles[endpoint][side].push_back( + {localDistance,radius}); ++audit.wallSamples; } else ++audit.missingWallSamples; @@ -3245,10 +3675,12 @@ namespace StandaloneStreamBenchmark std::sort(wallProfiles[endpoint][side].begin(), wallProfiles[endpoint][side].end(), [](const auto& a,const auto& b){return a[0](path.size(), - PassageMouthProfileReachMetres/PassageProfileSpacingMetres)+1.0; + const double expectedFloor=static_cast( + endpointFloorExpected[endpoint]); + const double resolvedFloor=static_cast(endpointFloorCounts[endpoint] + +endpointFloorOverlapSkips[endpoint]); worstEndpointFloorCoverage=std::min(worstEndpointFloorCoverage, - expectedFloor>0?endpointFloorCounts[endpoint]/expectedFloor:0.0); + expectedFloor>0?resolvedFloor/expectedFloor:0.0); // Lateral probes confirm floor coverage, but do not define a longitudinal // floor profile: the normal rotates around tight bends and can jump across // unrelated terrain. The centerline is the stable passage-floor trace. @@ -3286,20 +3718,20 @@ namespace StandaloneStreamBenchmark >=PassageProfilePlateauMinimumMetres &&l23TerraceControlResult.second>=PassageProfileStepThresholdMetres; const auto auditPassageNaturalness=[&](const VoxelForgeCore::World& Field, - const VoxelForgeCore::ResolvedLayoutPassageV1& passage) + std::size_t passageIndex) { FPassageNaturalnessAudit audit; - const std::size_t end=std::min(passage.lowerMouthControlIndex, - passage.controlPoints.size()-1); + const auto& path=allPassageSmoothRoutes[passageIndex]; + if(path.size()<3)return audit; + const double bodyFloorDepth=allPassageBodyFloorDepths[passageIndex]; double flatRun=0.0; - for(std::size_t i=1;i<=end;++i) + for(std::size_t i=1;i1.0e-6&&std::abs(dz)/horizontal @@ -3308,27 +3740,31 @@ namespace StandaloneStreamBenchmark audit.maximumFlatRunMetres,flatRun);} else flatRun=0.0; } - if(end>=6) + if(path.size()>=8) { - const std::size_t sampleCount=std::min(64,end-4); + const std::size_t sampleCount=std::min(64,path.size()-4); double minimumRadius=std::numeric_limits::infinity(); double maximumRadius=-std::numeric_limits::infinity(); for(std::size_t sample=0;sample(1,sampleCount-1); - const auto& point=passage.controlPoints[index]; - const auto& before=passage.controlPoints[index-1]; - const auto& after=passage.controlPoints[index+1]; - const double tangentX=qToMetres(after.positionSubvoxels[0]-before.positionSubvoxels[0]); - const double tangentY=qToMetres(after.positionSubvoxels[1]-before.positionSubvoxels[1]); + const auto& point=path[index]; + const auto& before=path[index-1]; + const auto& after=path[index+1]; + const double tangentX=after.x-before.x; + const double tangentY=after.y-before.y; const double tangentLength=std::hypot(tangentX,tangentY); if(tangentLength<=1.0e-6){++audit.missingWallSamples;continue;} - const double radiusMetres=qToMetres(point.radiusSubvoxels); - const double sampleRadius=std::max(0.20,radiusMetres-0.18); - const double centerX=qToMetres(point.positionSubvoxels[0]); - const double centerY=qToMetres(point.positionSubvoxels[1]); - const double centerZ=qToMetres(point.positionSubvoxels[2]); + constexpr double WallProbeHeightMetres=0.75; + const double floorDepth=passageTubeDepthAt(point.radius,bodyFloorDepth); + const double vertical=WallProbeHeightMetres-floorDepth; + const double wallRadiusSquared=point.radius*point.radius-vertical*vertical; + if(wallRadiusSquared<=0.0){audit.missingWallSamples+=2;continue;} + const double sampleRadius=std::max(0.20, + std::sqrt(wallRadiusSquared)-0.18); + const double centerX=point.x,centerY=point.y; + const double centerZ=point.z-floorDepth+WallProbeHeightMetres; const double nx=-tangentY/tangentLength,ny=tangentX/tangentLength; for(const double side:{-1.0,1.0}) { @@ -3359,7 +3795,7 @@ namespace StandaloneStreamBenchmark return audit; }; const auto auditPassageRipples=[&](const VoxelForgeCore::World& Field, - const VoxelForgeCore::ResolvedLayoutPassageV1& passage) + std::size_t passageIndex) { FPassageRippleAudit audit; constexpr double SampleSpacingMetres=0.125; @@ -3371,29 +3807,18 @@ namespace StandaloneStreamBenchmark constexpr double FloorRippleAmplitudeLimitMetres=0.025; struct FPathPoint { - double x=0.0,y=0.0,z=0.0,radius=0.0,distance=0.0; + double x=0.0,y=0.0,z=0.0,floorZ=0.0,radius=0.0,distance=0.0; + std::size_t segmentIndex=0; }; - const std::size_t end=std::min(passage.lowerMouthControlIndex, - passage.controlPoints.size()-1); - if(end<2)return audit; + const auto& passage=ResolvedLayout->passages[passageIndex]; + const auto& smoothRoute=allPassageSmoothRoutes[passageIndex]; + if(smoothRoute.size()<2)return audit; std::vector path; - path.reserve(end+1); - for(std::size_t i=0;i<=end;++i) + path.reserve(smoothRoute.size()); + for(const auto& point:smoothRoute) { - const auto& point=passage.controlPoints[i]; - FPathPoint value{qToMetres(point.positionSubvoxels[0]), - qToMetres(point.positionSubvoxels[1]), - qToMetres(point.positionSubvoxels[2]), - qToMetres(point.radiusSubvoxels),0.0}; - if(!path.empty()) - { - const auto& previous=path.back(); - value.distance=previous.distance+std::sqrt( - (value.x-previous.x)*(value.x-previous.x) - +(value.y-previous.y)*(value.y-previous.y) - +(value.z-previous.z)*(value.z-previous.z)); - } - path.push_back(value); + path.push_back({point.x,point.y,point.z,point.floorZ,point.radius, + point.distance,point.segmentIndex}); } const double total=path.back().distance; if(total1.0e-9?(distance-a.distance)/length:0.0; return FPathPoint{std::lerp(a.x,b.x,t),std::lerp(a.y,b.y,t), - std::lerp(a.z,b.z,t),std::lerp(a.radius,b.radius,t),distance}; + std::lerp(a.z,b.z,t),std::lerp(a.floorZ,b.floorZ,t), + std::lerp(a.radius,b.radius,t),distance, + b.segmentIndex}; }; const auto sinusoidAmplitude=[&](const std::vector>& samples, double& bestPeriod) @@ -3581,6 +4008,9 @@ namespace StandaloneStreamBenchmark const double start=(total-WindowLengthMetres)*fraction; std::vector radii; radii.reserve(static_cast(WindowLengthMetres/SampleSpacingMetres)+1); + std::size_t wallProbeNonfinite=0,wallProbeOutOfBand=0; + double wallProbeMinimum=std::numeric_limits::infinity(); + double wallProbeMaximum=-std::numeric_limits::infinity(); std::vector> floorResiduals; floorResiduals.reserve(static_cast(WindowLengthMetres/ SampleSpacingMetres)+1); @@ -3592,14 +4022,20 @@ namespace StandaloneStreamBenchmark ++sample) { ++audit.expectedSamples; - ++audit.floorExpectedSamples; const double distance=start+static_cast(sample)*SampleSpacingMetres; const auto pose=interpolate(distance); // Recover the composed walk surface from its zero crossing. // The support strip is segment-built and is not itself a true // signed-distance field, so a fixed centerline radius misses // the stepped top that the player actually walks on. - const double expectedFloor=pose.z-pose.radius+0.20; + const double expectedFloor=pose.floorZ; + const bool floorInteriorWins=passageInteriorWinsAt(pose.x,pose.y, + expectedFloor+0.125,passageIndex,pose.segmentIndex); + if(floorInteriorWins) + ++audit.floorInteriorWins; + else + { + ++audit.floorExpectedSamples; constexpr double FloorProbeStepMetres=0.25; constexpr int FloorProbeCount=7; double previousDensity=0.0,previousZ=0.0; @@ -3647,6 +4083,7 @@ namespace StandaloneStreamBenchmark pose.x,pose.y,pose.z}); ++audit.floorSamples; } + } const auto before=interpolate(std::max(0.0,distance-0.25)); const auto after=interpolate(std::min(total,distance+0.25)); const double tangentX=after.x-before.x,tangentY=after.y-before.y; @@ -3660,8 +4097,12 @@ namespace StandaloneStreamBenchmark {x0+nx*offset,y0+ny*offset,z0}))*coreMetres; const double right=static_cast(Field.densityAt( {x0-nx*offset,y0-ny*offset,z0}))*coreMetres; - if(!std::isfinite(left)||!std::isfinite(right) - ||left< -0.75||left>0.75||right< -0.75||right>0.75)continue; + if(!std::isfinite(left)||!std::isfinite(right)) + {++wallProbeNonfinite;continue;} + wallProbeMinimum=std::min({wallProbeMinimum,left,right}); + wallProbeMaximum=std::max({wallProbeMaximum,left,right}); + if(left< -0.75||left>0.75||right< -0.75||right>0.75) + {++wallProbeOutOfBand;continue;} // The probes sit 0.18 m inside the authored radius. Add that // radius back to the signed wall distance so radius-carried ribs // remain visible; the cubic detrend removes the smooth mouth flare. @@ -3669,7 +4110,22 @@ namespace StandaloneStreamBenchmark ++audit.samples; } if(radii.size()(WindowLengthMetres/ - SampleSpacingMetres)*3/4)continue; + SampleSpacingMetres)*3/4) + { + std::printf("[PassageWallRippleCoverage] id=%s start_m=%.3f " + "valid=%zu expected=%zu nonfinite=%zu out_of_band=%zu " + "probe_range_m=%.4f..%.4f status=UNDERCOVERED\n", + passage.stableId.c_str(),start,radii.size(), + static_cast(WindowLengthMetres/ + SampleSpacingMetres)+1, + wallProbeNonfinite,wallProbeOutOfBand, + wallProbeMinimum,wallProbeMaximum); + continue; + } + ++audit.wallQualifiedWindows; + audit.wallWindowSamples+=radii.size(); + audit.wallWindowExpectedSamples+=static_cast( + WindowLengthMetres/SampleSpacingMetres)+1; std::vector> windowSamples; appendDetrendedProfile(radii,start,windowSamples); double localPeriod=0.0; @@ -3726,15 +4182,24 @@ namespace StandaloneStreamBenchmark audit.floorCoherentAmplitudeMetres=sinusoidAmplitude(coherentFloorSamples, audit.floorCoherentPeriodMetres); audit.amplitudeMetres=audit.localPeakAmplitudeMetres; - const double coverage=audit.expectedSamples>0 - ?static_cast(audit.samples)/audit.expectedSamples:0.0; + const double wallWindowCoverage=audit.wallWindowExpectedSamples>0 + ?static_cast(audit.wallWindowSamples) + /audit.wallWindowExpectedSamples:0.0; const double floorCoverage=audit.floorExpectedSamples>0 ?static_cast(audit.floorSamples)/audit.floorExpectedSamples:0.0; - audit.passed=audit.controlDetected&&coverage>=0.75 + audit.floorOverlapOnly=audit.expectedSamples>0 + &&audit.floorExpectedSamples==0 + &&audit.floorInteriorWins==audit.expectedSamples; + // Long passages can include open-air spans where the side-wall + // probe has no zero crossing. Judge ripple only in windows with + // enough measured wall samples; naturalness separately requires + // visible relief on the route as a whole. + audit.passed=audit.controlDetected&&audit.wallQualifiedWindows>0 + &&wallWindowCoverage>=0.75 &&audit.localPeakAmplitudeMetres=0.75 - &&audit.floorAmplitudeMetres=0.75 + &&audit.floorAmplitudeMetres,8> firstViolations{}; + std::uint64_t floorSamples=0,floorViolations=0,openAirSamples=0; + std::uint64_t wallSamples=0,wallViolations=0; + std::uint64_t floorInteriorWins=0,wallInteriorWins=0; + std::uint64_t floorMouthBlendSkips=0,wallMouthBlendSkips=0; + std::uint64_t interiorSamples=0,interiorViolations=0; + std::vector openAirDistancesMetres; + std::array,8> firstViolations{}; std::size_t firstViolationCount=0; + std::array,8> firstWallViolations{}; + std::size_t firstWallViolationCount=0; }; - constexpr double PassageSupportAuditSpacingMetres=0.25; - constexpr std::array PassageSupportAuditDepthsMetres{{0.125,0.375}}; - constexpr std::array,16> PassageSupportAuditDirections{{ - {{1.0000000000000000,0.0000000000000000}}, - {{0.9238795325112867,0.3826834323650898}}, - {{0.7071067811865476,0.7071067811865476}}, - {{0.3826834323650898,0.9238795325112867}}, - {{0.0000000000000000,1.0000000000000000}}, - {{-0.3826834323650898,0.9238795325112867}}, - {{-0.7071067811865476,0.7071067811865476}}, - {{-0.9238795325112867,0.3826834323650898}}, - {{-1.0000000000000000,0.0000000000000000}}, - {{-0.9238795325112867,-0.3826834323650898}}, - {{-0.7071067811865476,-0.7071067811865476}}, - {{-0.3826834323650898,-0.9238795325112867}}, - {{0.0000000000000000,-1.0000000000000000}}, - {{0.3826834323650898,-0.9238795325112867}}, - {{0.7071067811865476,-0.7071067811865476}}, - {{0.9238795325112867,-0.3826834323650898}}}}; - const auto auditPassageOpenAir=[&](const VoxelForgeCore::World& Field, + constexpr double PassageShellAuditSpacingMetres=0.25; + constexpr std::array PassageShellAuditDepthsMetres{{0.125,0.375}}; + constexpr float PassageShellDensityTolerance=1.0e-6f; + const auto expectedPassageShellAt=[&](double xMetres,double yMetres, + double zMetres) + { + constexpr double CornerBlendMetres=0.50; + constexpr double ReliefBoundMetres=0.21; + double nearestWallShellDistance=std::numeric_limits::infinity(); + bool mouthBlend=false; + if(passageInteriorWinsAt(xMetres,yMetres,zMetres)) + return std::pair{0,nearestWallShellDistance}; + for(std::size_t passageIndex=0; + passageIndexpassages.size();++passageIndex) + { + const auto& passage=ResolvedLayout->passages[passageIndex]; + if(passage.controlPoints.size()<2)continue; + const auto& path=allPassageSmoothRoutes[passageIndex]; + if(path.size()<2)continue; + const double totalLength=path.back().distance; + for(std::size_t segment=1;segment1.0e-12 + ?((xMetres-ax)*dx+(yMetres-ay)*dy) + /horizontalLengthSquared + :std::clamp((zMetres-az)*dz/lengthSquared,0.0,1.0); + const double floorAlong=std::lerp(a.distance,b.distance,horizontalT); + const double t=std::clamp(((xMetres-ax)*dx+(yMetres-ay)*dy + +(zMetres-az)*dz)/lengthSquared,0.0,1.0); + const double centerX=ax+t*dx,centerY=ay+t*dy,centerZ=az+t*dz; + const double radius=std::lerp(a.radius,b.radius,t); + const double along=std::lerp(a.distance,b.distance,t); + const auto floorPose=interpolatePassageRoute(path,floorAlong); + const double floorCenterZ=passageFloorAtXY(passageIndex, + xMetres,yMetres,floorPose.floorZ); + const double roundDistance=std::sqrt((xMetres-centerX)*(xMetres-centerX) + +(yMetres-centerY)*(yMetres-centerY) + +(zMetres-centerZ)*(zMetres-centerZ))-radius; + const double floorDistance=floorCenterZ-zMetres; + const double blend=std::max(CornerBlendMetres- + std::abs(roundDistance-floorDistance),0.0)/CornerBlendMetres; + const double flatDistance=std::max(roundDistance,floorDistance) + +blend*blend*blend*(CornerBlendMetres/6.0); + const double mouthDistance=std::max(0.0,std::min(along, + totalLength-along)); + if(flatDistance<=0.0)continue; + const double fade=std::clamp(mouthDistance/5.0,0.0,1.0); + const double smoothFade=fade*fade*(3.0-2.0*fade); + const double wallElevation=-floorDistance; + const double wallThickness=wallElevation>=0.0&&wallElevation<=1.0 + ?smoothFade*0.75:0.0; + if(wallThickness>1.0e-9) + { + const double shellRadius=wallThickness*0.5; + const double capCenter=1.0-shellRadius; + const double x=flatDistance-shellRadius; + const double boxHalfHeight=capCenter*0.5; + const double boxX=std::abs(x)-shellRadius; + const double boxY=std::abs(wallElevation-boxHalfHeight) + -boxHalfHeight; + const double boxDistance=std::min(std::max(boxX,boxY),0.0) + +std::hypot(std::max(boxX,0.0),std::max(boxY,0.0)); + const double capDistance=std::hypot(x,wallElevation-capCenter) + -shellRadius; + nearestWallShellDistance=std::min(nearestWallShellDistance, + std::min(boxDistance,capDistance)); + } + else if(mouthDistance<5.0)mouthBlend=true; + } + } + if(nearestWallShellDistance<-ReliefBoundMetres) + return std::pair{1,nearestWallShellDistance}; + if(nearestWallShellDistance{-1,nearestWallShellDistance}; + return std::pair{0,nearestWallShellDistance}; + }; + const auto auditPassageShell=[&](const VoxelForgeCore::World& Field, const VoxelForgeCore::World& Native, const VoxelForgeCore::ResolvedLayoutPassageV1& passage, std::size_t passageIndex) { - FPassageOpenAirAudit audit; - const auto inspect=[&](double xMetres,double yMetres,double floorMetres, - double depthMetres,double supportThicknessMetres,bool routeSupport=false, - std::size_t passageSegment=std::numeric_limits::max()) + FPassageShellAudit audit; + const auto& route=allPassageSmoothRoutes[passageIndex]; + if(route.size()<2)return audit; + const double totalRouteLength=route.back().distance; + const double bodyFloorDepth=allPassageBodyFloorDepths[passageIndex]; + constexpr std::array,5> floorOffsets{{ + {{0.0,0.0}},{{0.30,0.0}},{{-0.30,0.0}}, + {{0.0,0.30}},{{0.0,-0.30}}}}; + const auto expectedFloorShellMarginAt=[&](double xMetres, + double yMetres,double zMetres) { - if(depthMetres<=0.0||depthMetres>supportThicknessMetres+1.0e-6)return; - ++audit.supportSamples; - audit.routeSupportSamples+=routeSupport; - const VoxelForgeCore::Vec3d sample{xMetres/coreMetres,yMetres/coreMetres, - (floorMetres-depthMetres)/coreMetres}; - const float nativeDensity=Native.densityAt(sample); - const float passageDensity=Field.densityAt(sample); - const float legacySupportDensity=std::min(nativeDensity, - static_cast(-depthMetres/coreMetres)); - if(nativeDensity>=0.0f&&legacySupportDensity<0.0f) - ++audit.legacyViolations; - if(nativeDensity>=0.0f&&passageDensity<0.0f) + constexpr double CornerBlendMetres=0.50; + double minimumShellDistance=std::numeric_limits::infinity(); + for(std::size_t candidatePassage=0; + candidatePassage::max() - &&Field.isPassageColumnSample(passageIndex,passageSegment,sample); - if(connectedColumn){++audit.columnSamples;return;} - const bool groundedShortSpan=!routeSupport - &&passageSegment!=std::numeric_limits::max() - &&Field.isPassageShortSpanSample(passageIndex,passageSegment,sample); - if(groundedShortSpan){++audit.shortSpanSamples;return;} - audit.routeSupportViolations+=routeSupport; - if(audit.firstViolationCount::max()) - { - const std::size_t radialSteps=static_cast(std::ceil( - supportRadiusMetres/PassageSupportAuditSpacingMetres)); - for(std::size_t radialStep=0;radialStep<=radialSteps;++radialStep) - { - const double radial=std::min(supportRadiusMetres, - radialStep*PassageSupportAuditSpacingMetres); - for(const auto& direction:PassageSupportAuditDirections) - inspect(xMetres+direction[0]*radial,yMetres+direction[1]*radial, - floorMetres,depthMetres,supportThicknessMetres,routeSupport, - passageSegment); - } - }; - for(std::size_t segment=1;segment(1,static_cast( - std::ceil(length/PassageSupportAuditSpacingMetres))); - for(std::size_t sample=0;sample<=intervals;++sample) - { - if(segment>1&&sample==0)continue; - const double t=static_cast(sample)/intervals; - const double centerX=ax+(bx-ax)*t,centerY=ay+(by-ay)*t; - const double centerZ=az+(bz-az)*t; - const double radius=qToMetres(a.radiusSubvoxels) - +(qToMetres(b.radiusSubvoxels)-qToMetres(a.radiusSubvoxels))*t; - const double floorZ=centerZ-radius+0.20; - for(const double depth:PassageSupportAuditDepthsMetres) - inspectFloorDisc(centerX,centerY,floorZ,radius,depth,1.0, - false,segment-1); - } - } - const auto upperStratum=std::find_if(ResolvedLayout->strates.begin(), - ResolvedLayout->strates.end(),[&](const auto& value) - {return value.strateIndex==passage.upperStrateIndex;}); - if(upperStratum!=ResolvedLayout->strates.end()) - { - std::array route{}; - std::size_t routeCount=0; - for(const auto& anchor:upperStratum->anchors) - if(anchor.kind=="route_point"&&anchor.values.size()>=3) + const auto& candidateRoute= + allPassageSmoothRoutes[candidatePassage]; + if(candidateRoute.size()<2)continue; + const double candidateLength=candidateRoute.back().distance; + for(std::size_t candidateSegment=1; + candidateSegment1.0e-12 + ?((xMetres-a.x)*dx+(yMetres-a.y)*dy) + /horizontalLengthSquared:t; + const double centerX=a.x+t*dx,centerY=a.y+t*dy, + centerZ=a.z+t*dz; + const double radius=std::lerp(a.radius,b.radius,t); + const double along=std::lerp(a.distance,b.distance,t); + const double floorAlong=std::lerp(a.distance,b.distance,floorT); + const double plannedFloor=passageFloorAtXY(candidatePassage, + xMetres,yMetres,interpolatePassageRoute(candidateRoute, + floorAlong).floorZ); + const double roundDistance=std::sqrt( + (xMetres-centerX)*(xMetres-centerX) + +(yMetres-centerY)*(yMetres-centerY) + +(zMetres-centerZ)*(zMetres-centerZ))-radius; + const double floorDistance=plannedFloor-zMetres; + const double blend=std::max(CornerBlendMetres + -std::abs(roundDistance-floorDistance),0.0) + /CornerBlendMetres; + const double flatDistance=std::max(roundDistance,floorDistance) + +blend*blend*blend*(CornerBlendMetres/6.0); + const double mouthDistance=std::max(0.0,std::min(along, + candidateLength-along)); + const double fade=std::clamp(mouthDistance/5.0,0.0,1.0); + const double smoothFade=fade*fade*(3.0-2.0*fade); + const double floorBlend=std::clamp(floorDistance/0.25,0.0,1.0); + const double smoothFloorBlend=floorBlend*floorBlend + *(3.0-2.0*floorBlend); + const double thickness=0.75*smoothFade*smoothFloorBlend; + const double shellDistance=std::max(-flatDistance, + flatDistance-thickness); + minimumShellDistance=std::min(minimumShellDistance, + shellDistance); + } + } + return minimumShellDistance; + }; + for(std::size_t segment=1;segment(1, + static_cast(std::ceil( + length/PassageShellAuditSpacingMetres))); + for(std::size_t sampleIndex=segment==1?0:1; + sampleIndex<=intervals;++sampleIndex) + { + const double t=static_cast(sampleIndex)/intervals; + const double centerX=a.x+dx*t,centerY=a.y+dy*t,centerZ=a.z+dz*t; + const double along=a.distance+alongLength*t; + const double radius=std::lerp(a.radius,b.radius,t); + if(std::min(along,totalRouteLength-along)>0.0) + { + for(const auto& offset:floorOffsets) + for(const double depth:PassageShellAuditDepthsMetres) + { + const double sampleX=centerX+offset[0]; + const double sampleY=centerY+offset[1]; + double floorZ=passageFloorAtXY(passageIndex, + sampleX,sampleY,interpolatePassageRoute(route,along).floorZ); + FPassageRouteProjection floorProjection; + for(int projectionStep=0;projectionStep<2;++projectionStep) + { + floorProjection=projectPassageRoute(route,sampleX,sampleY, + floorZ-depth); + const auto floorPose=interpolatePassageRoute(route, + floorProjection.centerAlong); + floorZ=passageFloorAtXY(passageIndex,sampleX,sampleY, + floorPose.floorZ); + } + const VoxelForgeCore::Vec3d position{ + sampleX/coreMetres,sampleY/coreMetres, + (floorZ-depth)/coreMetres}; + const double sampleZ=floorZ-depth; + if(passageInteriorWinsAt(sampleX,sampleY,sampleZ)) + { + ++audit.floorInteriorWins; + continue; + } + ++audit.floorSamples; + if(Native.densityAt(position)>=0.0f) + { + ++audit.openAirSamples; + audit.openAirDistancesMetres.push_back(along); + const double shellMargin=expectedFloorShellMarginAt( + sampleX,sampleY,sampleZ); + if(std::abs(shellMargin)<=0.011) + { + ++audit.floorMouthBlendSkips; + continue; + } + const bool shellExpected=shellMargin<-0.011; + const float density=Field.densityAt(position); + if((shellExpected&&density>=PassageShellDensityTolerance) + ||(!shellExpected&&density<-PassageShellDensityTolerance)) + { + ++audit.floorViolations; + if(audit.firstViolationCount wallProbes{{ + {0.0,0.0,true},{-1.0,0.25,false},{1.0,0.25,false}, + {-1.0,0.75,false},{1.0,0.75,false}}}; + for(const auto& probe:wallProbes) + { + double sampleX=centerX,sampleY=centerY,sampleZ=0.0; + if(probe.roof) + sampleZ=centerZ+radius+0.375; else { - std::move(route.begin()+1,route.end(),route.begin()); - route.back()=&anchor; - } - } - const double mouthX=qToMetres(passage.upperMouthSubvoxels[0]); - const double mouthY=qToMetres(passage.upperMouthSubvoxels[1]); - constexpr double RouteSupportReachMetres=13.0; - constexpr double RouteFloorOffsetMetres=1.20; - constexpr double RouteSupportThicknessMetres=1.0; - constexpr double RouteSupportDepthStepMetres=0.125; - for(std::size_t segment=1;segment(1, - static_cast(std::ceil(length - /PassageSupportAuditSpacingMetres))); - const double routeRadius=a.values.size()>=4 - ?std::max(0.75,qToMetres(a.values[3])):0.75; - for(std::size_t sample=0;sample<=intervals;++sample) - { - if(segment>1&&sample==0)continue; - const double t=static_cast(sample)/intervals; - const double centerX=ax+dx*t,centerY=ay+dy*t; - const double centerZ=az+dz*t; - for(std::size_t radialStep=0;radialStep<=static_cast( - std::ceil(routeRadius/PassageSupportAuditSpacingMetres));++radialStep) - { - const double radial=std::min(routeRadius, - radialStep*PassageSupportAuditSpacingMetres); - for(const auto& direction:PassageSupportAuditDirections) + const double vertical=probe.height-floorDepth; + const double wallRadiusSquared=radius*radius-vertical*vertical; + if(wallRadiusSquared<=0.0)continue; + const double wallRadius=std::sqrt(wallRadiusSquared); + sampleX+=nx*probe.side*(wallRadius+0.375); + sampleY+=ny*probe.side*(wallRadius+0.375); + for(int projectionStep=0;projectionStep<2;++projectionStep) { - const double x=centerX+direction[0]*radial; - const double y=centerY+direction[1]*radial; - if(std::hypot(x-mouthX,y-mouthY)>RouteSupportReachMetres)continue; - const double floorZ=centerZ-RouteFloorOffsetMetres; - for(double depth=RouteSupportDepthStepMetres; - depth<=RouteSupportThicknessMetres+1.0e-6; - depth+=RouteSupportDepthStepMetres) - inspect(x,y,floorZ,depth,RouteSupportThicknessMetres,true); + sampleZ=floorZ+probe.height; + const auto floorProjection=projectPassageRoute(route, + sampleX,sampleY,sampleZ); + const auto floorPose=interpolatePassageRoute(route, + floorProjection.centerAlong); + floorZ=passageFloorAtXY(passageIndex,sampleX,sampleY, + floorPose.floorZ); } + sampleZ=floorZ+probe.height; } + const VoxelForgeCore::Vec3d wallPosition{sampleX/coreMetres, + sampleY/coreMetres,sampleZ/coreMetres}; + if(passageInteriorWinsAt(sampleX,sampleY,sampleZ)) + { + ++audit.wallInteriorWins; + continue; + } + if(Native.densityAt(wallPosition)<0.0f)continue; + ++audit.openAirSamples; + ++audit.wallSamples; + audit.openAirDistancesMetres.push_back(along); + const float density=Field.densityAt(wallPosition); + const auto [shellExpected,wallShellMargin]= + expectedPassageShellAt(sampleX,sampleY,sampleZ); + if(shellExpected>=0 + &&((shellExpected==1 + &&density>=PassageShellDensityTolerance) + ||(shellExpected==0 + &&density<-PassageShellDensityTolerance))) + { + ++audit.wallViolations; + if(audit.firstWallViolationCount + & mouth) { - std::uint64_t columns=0,shortSpans=0,connectedEnds=0,routeSections=0; - std::uint64_t routeSectionFailures=0,wallSections=0,wallFailures=0; - double minimumWallMetres=std::numeric_limits::infinity(); - double minimumSurfaceRadiusMetres=std::numeric_limits::infinity(); - double maximumSurfaceRadiusMetres=0.0; - double surfaceRadiusReliefMetres=0.0; - double longestShortSpanMetres=0.0; - bool passed=true; - bool disconnectedEndControlApplicable=false; - bool disconnectedEndControlDetected=false; - }; - const auto auditPassageColumns=[&](const VoxelForgeCore::World& Field, - const VoxelForgeCore::World& Native, - const VoxelForgeCore::ResolvedLayoutPassageV1& passage, - std::size_t passageIndex) - { - FPassageColumnAudit audit; - const double qMetres=coreMetres - /VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel; - constexpr std::array,5> supportOffsets{{ - {{0.0,0.0}},{{0.45,0.0}},{{-0.45,0.0}},{{0.0,0.45}},{{0.0,-0.45}}}}; - const auto endpointSupportCount=[&](const std::array& point) - { - const double x=point[0]*qMetres,y=point[1]*qMetres; - const double floor=point[2]*qMetres-point[3]*qMetres+0.13; - std::uint32_t supported=0; - for(const auto& offset:supportOffsets) - { - bool solid=false; - for(const double depth:{0.125,0.25}) - if(Native.densityAt({(x+offset[0])/coreMetres, - (y+offset[1])/coreMetres,(floor-depth)/coreMetres})<0.0f) - {solid=true;break;} - supported+=solid; - } - return supported; - }; - const auto endpointConnected=[&](const std::array& point) - {return endpointSupportCount(point)>=3;}; - struct FColumnCapProbe - { - std::uint64_t columnSamples=0,nativeOverlapSamples=0; - double firstOverlapDepthMetres=std::numeric_limits::infinity(); - double minimumNativeDensity=std::numeric_limits::infinity(); - }; - const auto probeColumnCap=[&](const VoxelForgeCore::PassageVoidCrossingAuditV1& crossing, - std::size_t segment,double capZMetres,bool upperCap,double depthLimitMetres) - { - FColumnCapProbe probe; - constexpr double DepthStepMetres=0.25; - constexpr double RadialStepMetres=0.50; - constexpr std::size_t DirectionCount=16; - const double axisX=qToMetres(crossing.columnAxisSubvoxels[0]); - const double axisY=qToMetres(crossing.columnAxisSubvoxels[1]); - for(double depth=DepthStepMetres;depth<=depthLimitMetres+1.0e-6; - depth+=DepthStepMetres) - { - const double z=capZMetres+(upperCap?-depth:depth); - const double maxRadius=qToMetres(crossing.columnMaximumRadiusSubvoxels); - const std::size_t radialSteps=static_cast( - std::ceil(maxRadius/RadialStepMetres)); - for(std::size_t radialStep=0;radialStep<=radialSteps;++radialStep) - { - const double radius=std::min(maxRadius, - radialStep*RadialStepMetres); - for(std::size_t direction=0;direction::infinity(); - bool disconnectedEndControlApplicable=false; - bool disconnectedEndControlDetected=false; - for(const auto& crossing:crossings) - { - if(crossing.passageIndex!=passageIndex)continue; - const bool connectedStart=endpointConnected(crossing.startPointSubvoxels); - const bool connectedEnd=endpointConnected(crossing.endPointSubvoxels); - if(!crossing.needsColumn) - { - ++audit.shortSpans; - audit.longestShortSpanMetres=std::max(audit.longestShortSpanMetres, - crossing.unsupportedLengthMetres); - const bool shortSpanPass=connectedStart&&connectedEnd - &&crossing.unsupportedLengthMetres<=12.5 - &&crossing.lastSegment+1(connectedStart)+static_cast(connectedEnd), - shortSpanPass?"PASS":"FAIL"); - const std::size_t segment=std::min(crossing.firstSegment, - passage.controlPoints.size()-2); - const auto& a=passage.controlPoints[segment]; - const auto& b=passage.controlPoints[segment+1]; - const double x=(qToMetres(a.positionSubvoxels[0]) - +qToMetres(b.positionSubvoxels[0]))*0.5; - const double y=(qToMetres(a.positionSubvoxels[1]) - +qToMetres(b.positionSubvoxels[1]))*0.5; - const double z=(qToMetres(a.positionSubvoxels[2]) - +qToMetres(b.positionSubvoxels[2]))*0.5 - -qToMetres(a.radiusSubvoxels+b.radiusSubvoxels)*0.5+0.13; - audit.passed&=shortSpanSolidAt(segment,x,y,z-0.25); - continue; - } - if(crossing.lastSegment+1>=passage.controlPoints.size()) - {audit.passed=false;continue;} - const double capTopMetres=qToMetres(crossing.columnTopZSubvoxels); - const double capBottomMetres=qToMetres(crossing.columnBottomZSubvoxels); - const auto topCap=probeColumnCap(crossing,crossing.firstSegment, - capTopMetres,true,6.0); - const auto bottomCap=probeColumnCap(crossing,crossing.lastSegment, - capBottomMetres,false,6.0); - const bool topCapConnected=topCap.nativeOverlapSamples>0; - const bool bottomCapConnected=bottomCap.nativeOverlapSamples>0; - const std::uint32_t routeStartSupport=endpointSupportCount( - crossing.startPointSubvoxels); - const std::uint32_t routeEndSupport=endpointSupportCount( - crossing.endPointSubvoxels); - std::printf("[PassageColumnRouteEndpointSupport] id=%s start=%u/5 start_z_m=%.3f end=%u/5 end_z_m=%.3f threshold=3/5\n", - passage.stableId.c_str(),routeStartSupport, - qToMetres(crossing.startPointSubvoxels[2]),routeEndSupport, - qToMetres(crossing.endPointSubvoxels[2])); - const auto printCap=[&](const char* endName,const char* side,double capZ, - const FColumnCapProbe& probe,bool connected) - { - std::printf("[PassageColumnCapAudit] id=%s end=%s side=%s cap_z_m=%.3f column_samples=%llu native_overlap_samples=%llu first_overlap_depth_m=%.3f minimum_native_density=%.6f search_depth_m=6.000 status=%s\n", - passage.stableId.c_str(),endName,side,capZ, - static_cast(probe.columnSamples), - static_cast(probe.nativeOverlapSamples), - probe.firstOverlapDepthMetres,probe.minimumNativeDensity, - connected?"PASS":"FAIL"); - }; - printCap("top","upper",capTopMetres,topCap,topCapConnected); - printCap("bottom","lower",capBottomMetres,bottomCap,bottomCapConnected); - const auto upper=std::find_if(ResolvedLayout->strates.begin(), - ResolvedLayout->strates.end(),[&](const auto& value) - {return value.strateIndex==passage.upperStrateIndex;}); - const double startRouteZ=qToMetres(crossing.startPointSubvoxels[2]); - const double endRouteZ=qToMetres(crossing.endPointSubvoxels[2]); - const double lowerRouteZ=std::min(startRouteZ,endRouteZ); - if(upper!=ResolvedLayout->strates.end() - &&upper->generatorKind=="FloatingIslands" - &&lowerRouteZ0; - disconnectedEndControlDetected=disconnectedEndControlApplicable - &&disconnectedControl.nativeOverlapSamples==0; - std::printf("[PassageColumnDisconnectedEndControl] source=air_gap_truncated_lower_cap cap_z_m=%.3f column_samples=%llu native_overlap_samples=%llu minimum_native_density=%.6f detected=%s\n", - hypotheticalBottomZ, - static_cast(disconnectedControl.columnSamples), - static_cast(disconnectedControl.nativeOverlapSamples), - disconnectedControl.minimumNativeDensity, - disconnectedEndControlDetected?"true":"false"); - } - ++audit.columns; - audit.connectedEnds+=topCapConnected+bottomCapConnected; - const double axisX=qToMetres(crossing.columnAxisSubvoxels[0]); - const double axisY=qToMetres(crossing.columnAxisSubvoxels[1]); - const double minimumRadius=qToMetres(crossing.columnMinimumRadiusSubvoxels); - const double maximumRadius=qToMetres(crossing.columnMaximumRadiusSubvoxels); - const double minimumWall=minimumRadius-crossing.maximumRouteOffsetMetres - -crossing.maximumBoreRadiusMetres-0.50; - audit.minimumWallMetres=std::min(audit.minimumWallMetres,minimumWall); - const std::size_t segmentCount=crossing.lastSegment-crossing.firstSegment+1; - const std::size_t probeCount=std::min(128,segmentCount); - std::uint64_t crossingRouteFailures=0,crossingWallFailures=0; - for(std::size_t probe=0;probe1.0e-6?(x-axisX)/radial:1.0; - const double outwardY=radial>1.0e-6?(y-axisY)/radial:0.0; - const bool wallSolid=columnSolidAt(segment, - axisX+outwardX*wallRadius,axisY+outwardY*wallRadius,z); - ++audit.wallSections; - audit.wallFailures+=!wallSolid; - crossingWallFailures+=!wallSolid; - if(!wallSolid&&crossingWallFailures<=8) - std::printf("[PassageRockColumnWallProbe] id=%s segment=%zu xyz_m=(%.3f,%.3f,%.3f) axis_m=(%.3f,%.3f) centerline_radius_m=%.3f bore_radius_m=%.3f wall_probe_radius_m=%.3f\n", - passage.stableId.c_str(),segment,x,y,z,axisX,axisY,radial,radius,wallRadius); - } - double crossingMinimumSurfaceRadius=std::numeric_limits::infinity(); - double crossingMaximumSurfaceRadius=0.0; - std::array meanRadiusByHeight{}; - std::size_t heightSamples=0; - constexpr double RayStepMetres=0.25; - constexpr std::array HeightFractions{{0.25,0.35,0.45,0.55,0.65,0.75}}; - constexpr std::size_t DirectionCount=16; - const double topMetres=qToMetres(crossing.columnTopZSubvoxels); - const double bottomMetres=qToMetres(crossing.columnBottomZSubvoxels); - const double rayStart=crossing.maximumRouteOffsetMetres - +crossing.maximumBoreRadiusMetres+0.75; - for(const double heightFraction:HeightFractions) - { - const double z=topMetres+(bottomMetres-topMetres)*heightFraction; - double heightMeanRadius=0.0; - std::uint64_t heightRayCount=0; - for(std::size_t direction=0;direction(std::ceil( - (maximumRadius+2.0-rayStart)/RayStepMetres)); - for(std::size_t step=0;step<=raySteps;++step) - { - const double rayRadius=rayStart+step*RayStepMetres; - const VoxelForgeCore::Vec3d point{ - (axisX+rayRadius*std::cos(angle))/coreMetres, - (axisY+rayRadius*std::sin(angle))/coreMetres, - z/coreMetres}; - if(Field.densityAt(point)<0.0f) - {enteredColumn=true;lastSolidRadius=rayRadius;} - else if(enteredColumn)break; - } - if(!enteredColumn)continue; - heightMeanRadius+=lastSolidRadius; - ++heightRayCount; - crossingMinimumSurfaceRadius=std::min(crossingMinimumSurfaceRadius, - lastSolidRadius); - crossingMaximumSurfaceRadius=std::max(crossingMaximumSurfaceRadius, - lastSolidRadius); - } - if(heightRayCount==0)continue; - meanRadiusByHeight[heightSamples++]=heightMeanRadius/heightRayCount; - } - const double crossingSurfaceRelief=heightSamples>=2 - ?*std::max_element(meanRadiusByHeight.begin(), - meanRadiusByHeight.begin()+heightSamples) - -*std::min_element(meanRadiusByHeight.begin(), - meanRadiusByHeight.begin()+heightSamples):0.0; - std::printf("[PassageColumnReliefProfile] id=%s heights=%zu radii_m=", - passage.stableId.c_str(),heightSamples); - for(std::size_t height=0;height=1.50&&crossingRouteFailures==0 - &&crossingWallFailures==0&&std::isfinite(measuredWall) - &&measuredWall>=1.50&&crossingSurfaceRelief>=0.20; - audit.passed&=columnPass; - std::printf("[PassageRockColumnAudit] id=%s segments=%zu..%zu span_m=%.3f axis_m=(%.3f,%.3f) connected=%d/2 route_support=%llu/%llu wall_failures=%llu wall_margin_m=%.3f threshold_m=1.500 radii_m=%.3f..%.3f relief_p2p_m=%.3f nominal_radius_m=%.3f status=%s\n", - passage.stableId.c_str(),crossing.firstSegment,crossing.lastSegment, - crossing.unsupportedLengthMetres,axisX,axisY, - static_cast(topCapConnected)+static_cast(bottomCapConnected), - static_cast(probeCount-crossingRouteFailures), - static_cast(probeCount), - static_cast(crossingWallFailures),measuredWall, - crossingMinimumSurfaceRadius,crossingMaximumSurfaceRadius, - crossingSurfaceRelief,qToMetres(crossing.columnNominalRadiusSubvoxels), - columnPass?"PASS":"FAIL"); - } - audit.disconnectedEndControlApplicable|=disconnectedEndControlApplicable; - audit.disconnectedEndControlDetected|=disconnectedEndControlDetected; - if(disconnectedEndControlApplicable&&!disconnectedEndControlDetected) - audit.passed=false; - return audit; - }; - if(Assembly) - for(const auto& stratum:ResolvedLayout->strates) - { - if(stratum.generatorKind!="FloatingIslands")continue; - const auto anchor=std::find_if(stratum.anchors.begin(),stratum.anchors.end(), - [](const auto& value){return value.kind=="passage_anchor"&&value.values.size()>=7;}); - const auto islandPlan=std::find_if(Assembly->floatingIslands.begin(), - Assembly->floatingIslands.end(),[&](const auto& value) - {return value.strateIndex==stratum.strateIndex;}); - if(anchor==stratum.anchors.end()||islandPlan==Assembly->floatingIslands.end())continue; - if(islandPlan->manifest.recipe.geometryVersion>=8)continue; - const auto ordinal=islandPlan->manifest.recipe.anchorIslandOrdinal; - if(ordinal>=islandPlan->manifest.plan.islands.size())continue; - const auto& anchorIsland=islandPlan->manifest.plan.islands[ordinal]; - const double axisX=qToMetres(anchor->values[0]); - const double axisY=qToMetres(anchor->values[1]); - const double rootBottom=qToMetres(anchor->values[5]); - const auto& islandRecipe=islandPlan->manifest.recipe; - const std::int64_t crustRatioQ16=islandRecipe.thicknessRatioQ16 - +islandRecipe.crustDepthBonusQ16; - const std::int64_t crustDepthQ=(anchorIsland.radiusSubvoxels*crustRatioQ16 - +32768)/65536; - const double rootTop=qToMetres(anchorIsland.topZSubvoxels-crustDepthQ); - const double nominalRootRadius=qToMetres(anchor->values[2]); - double helixMinimumRadius=std::numeric_limits::infinity(); - double helixMaximumRadius=0.0; - for(const auto& passage:ResolvedLayout->passages) - if(passage.upperStrateIndex==stratum.strateIndex) - for(const auto& point:passage.controlPoints) - { - const double z=qToMetres(point.positionSubvoxels[2]); - if(zrootTop)continue; - const double radial=std::hypot( - qToMetres(point.positionSubvoxels[0]-anchor->values[0]), - qToMetres(point.positionSubvoxels[1]-anchor->values[1])); - helixMinimumRadius=std::min(helixMinimumRadius,radial); - helixMaximumRadius=std::max(helixMaximumRadius,radial); - } - if(!std::isfinite(helixMinimumRadius))continue; - double minimumMeasuredRootRadius=std::numeric_limits::infinity(); - std::uint64_t rootRaySamples=0; - constexpr std::array RootHeightFractions{{0.01,0.25,0.5,0.75,0.99}}; - for(const double fraction:RootHeightFractions) - { - const double z=rootTop+(rootBottom-rootTop)*fraction; - double minimumRadius=std::numeric_limits::infinity(); - double maximumRadius=0.0,meanRadius=0.0; - constexpr std::size_t DirectionCount=32; - constexpr double RayStepMetres=0.125; - const std::size_t raySteps=static_cast(std::ceil( - (nominalRootRadius+2.0)/RayStepMetres)); - for(std::size_t direction=0;direction=0.0f)break; - radius=probeRadius; - } - minimumRadius=std::min(minimumRadius,radius); - maximumRadius=std::max(maximumRadius,radius); - meanRadius+=radius; - ++rootRaySamples; - } - meanRadius/=DirectionCount; - minimumMeasuredRootRadius=std::min(minimumMeasuredRootRadius,minimumRadius); - std::printf("[PassageRootRadiusMeasure] strate=%d z_m=%.3f solid_radius_min_m=%.3f mean_m=%.3f max_m=%.3f nominal_root_m=%.3f rays=%zu\n", - stratum.strateIndex,z,minimumRadius,meanRadius,maximumRadius, - nominalRootRadius,DirectionCount); - } - const auto firstRootPassage=std::find_if(ResolvedLayout->passages.begin(), - ResolvedLayout->passages.end(),[&](const auto& passage) - {return passage.upperStrateIndex==stratum.strateIndex;}); - const double mouthBoreRadius=firstRootPassage==ResolvedLayout->passages.end()?0.0 - :qToMetres(firstRootPassage->mouthRadiusSubvoxels); - const double midBoreRadius=firstRootPassage==ResolvedLayout->passages.end()?0.0 - :qToMetres(firstRootPassage->midRadiusSubvoxels); - const double maximumBoreRadius=std::max(mouthBoreRadius,midBoreRadius); - std::printf("[PassageRootMeasure] strate=%d axis_m=(%.3f,%.3f) helix_centerline_radius_min_m=%.3f max_m=%.3f mouth_bore_radius_m=%.3f mid_bore_radius_m=%.3f nominal_root_m=%.3f measured_min_root_m=%.3f minimum_wall_m=%.3f samples=%llu\n", - stratum.strateIndex,axisX,axisY,helixMinimumRadius,helixMaximumRadius, - mouthBoreRadius,midBoreRadius,nominalRootRadius,minimumMeasuredRootRadius, - minimumMeasuredRootRadius-helixMaximumRadius-maximumBoreRadius, - static_cast(rootRaySamples)); - } - const auto mouthInContent=[&](std::int32_t index,const std::array& mouth) - { - const auto* stratum=findStratum(index);if(!stratum)return false; + const auto* stratum=findStratum(index); + if(!stratum)return false; const std::int64_t zUm=static_cast(std::llround( static_cast(mouth[2])*World.CoreVoxelSizeMicrons /VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel)); - return zUm>=stratum->content.bottomMicrometres&&zUmcontent.topMicrometres; + return zUm>=stratum->content.bottomMicrometres + &&zUmcontent.topMicrometres; }; std::uint64_t passageCount=0,passagePasses=0,blockedControls=0,naturalPasses=0; - std::uint64_t mouthProfilePasses=0,ripplePasses=0,rippleControlsDetected=0; + std::uint64_t mouthProfilePasses=0,ripplePasses=0,rippleControlsDetected=0; std::uint64_t floorRippleControlsDetected=0,floorStepRippleControlsDetected=0; - std::uint64_t openAirViolations=0,openAirLegacyViolations=0,openAirSamples=0; - std::uint64_t openAirAudits=0,openAirColumnSamples=0,openAirShortSpanSamples=0; - std::uint64_t columnCrossings=0,shortGroundedSpans=0,columnConnectedEnds=0; - std::uint64_t columnRouteFailures=0,columnWallFailures=0; - double longestUncolumnedSpanMetres=0.0,longestShortSpanMetres=0.0; - double l26LegacyBridgeSpanMetres=0.0; - bool columnAuditsPassed=true,noLongBridgeAuditPassed=true; - bool columnDisconnectedEndControlApplicable=false; - bool columnDisconnectedEndControlDetected=false; - bool l26NegativeControlApplicable=false; - const auto plannedVoidCrossings=Shape.passageVoidCrossings(); - for(const auto& crossing:plannedVoidCrossings) - { - if(crossing.needsColumn)continue; - longestUncolumnedSpanMetres=std::max(longestUncolumnedSpanMetres, - crossing.unsupportedLengthMetres); - } - for(std::size_t passageIndex=0;passageIndexpassages.size(); - ++passageIndex) - { - const auto& passage=ResolvedLayout->passages[passageIndex]; - const auto* upper=findStratum(passage.upperStrateIndex); - const auto* lower=findStratum(passage.lowerStrateIndex); - if(!upper||!lower||lower->generatorKind!="SurfaceWorld" - ||upper->generatorKind=="FloatingIslands")continue; - l26NegativeControlApplicable=true; - for(const auto& crossing:plannedVoidCrossings) - if(crossing.passageIndex==passageIndex) - l26LegacyBridgeSpanMetres=std::max(l26LegacyBridgeSpanMetres, - crossing.unsupportedLengthMetres); - } + std::uint64_t shellAudits=0,shellFloorSamples=0,shellFloorViolations=0; + std::uint64_t shellFloorMouthBlendSkips=0; + std::uint64_t shellOpenAirSamples=0,shellWallSamples=0,shellWallViolations=0; + std::uint64_t shellInteriorSamples=0,shellInteriorViolations=0; for(std::size_t passageIndex=0;passageIndexpassages.size();++passageIndex) { const auto& passage=ResolvedLayout->passages[passageIndex]; - std::vector> path;path.reserve(passage.controlPoints.size()); - for(const auto& point:passage.controlPoints) + const auto& smoothRoute=allPassageSmoothRoutes[passageIndex]; + std::vector> path;path.reserve(smoothRoute.size()); + for(const auto& point:smoothRoute) { - const double playerZ=static_cast(point.positionSubvoxels[2] - -point.radiusSubvoxels)+1.13*VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel - *1000000.0/World.CoreVoxelSizeMicrons; - path.push_back({qToMetres(point.positionSubvoxels[0])/coreMetres, - qToMetres(point.positionSubvoxels[1])/coreMetres,playerZ/256.0}); + const double playerZ=point.floorZ+1.13; + path.push_back({point.x/coreMetres,point.y/coreMetres, + playerZ/coreMetres}); } - std::vector segmentSupport; - const FWalkAudit passageAudit=auditPlayerPath(Shape,path,0.125,0.125,0.25,3,0.45, - &blockedWorld,&segmentSupport); - const FPassageNaturalnessAudit naturalAudit=auditPassageNaturalness(Shape,passage); + // Probe below the capsule feet far enough to enter the new 0.75 m + // floor shell; the old quarter-metre search only checked the air + // above the walk surface. + const std::function passageSupportExemption= + [&](double x,double y,double z) + {return passageInteriorWinsAt(x,y,z-0.25);}; + const FWalkAudit passageAudit=auditPlayerPath(Shape,path,0.375,0.125, + 1.125,3,0.45,passageSupportExemption); + const FPassageNaturalnessAudit naturalAudit= + auditPassageNaturalness(Shape,passageIndex); const auto lowerProfileStratum=std::find_if(ResolvedLayout->strates.begin(), ResolvedLayout->strates.end(),[&](const auto& stratum) {return stratum.strateIndex==passage.lowerStrateIndex;}); @@ -4420,27 +4594,38 @@ namespace StandaloneStreamBenchmark {return anchor.kind=="heightfield_profile";}); const FPassageMouthProfileAudit mouthProfileAudit= auditPassageMouthProfiles(Shape,passage,profiledLowerSurface); - const FPassageRippleAudit rippleAudit=auditPassageRipples(Shape,passage); - const FPassageOpenAirAudit openAirAudit=auditPassageOpenAir(Shape,blockedWorld, + const FPassageRippleAudit rippleAudit= + auditPassageRipples(Shape,passageIndex); + const FPassageShellAudit shellAudit=auditPassageShell(Shape,blockedWorld, passage,passageIndex); - const FPassageColumnAudit columnAudit=auditPassageColumns(Shape,blockedWorld, - passage,passageIndex); - openAirSamples+=openAirAudit.supportSamples; - openAirViolations+=openAirAudit.violations; - openAirLegacyViolations+=openAirAudit.legacyViolations; - openAirColumnSamples+=openAirAudit.columnSamples; - openAirShortSpanSamples+=openAirAudit.shortSpanSamples; - columnCrossings+=columnAudit.columns; - shortGroundedSpans+=columnAudit.shortSpans; - columnConnectedEnds+=columnAudit.connectedEnds; - columnRouteFailures+=columnAudit.routeSectionFailures; - columnWallFailures+=columnAudit.wallFailures; - longestShortSpanMetres=std::max(longestShortSpanMetres, - columnAudit.longestShortSpanMetres); - columnAuditsPassed&=columnAudit.passed; - columnDisconnectedEndControlApplicable|=columnAudit.disconnectedEndControlApplicable; - columnDisconnectedEndControlDetected|=columnAudit.disconnectedEndControlDetected; - ++openAirAudits; + std::vector openAirDistances=shellAudit.openAirDistancesMetres; + std::sort(openAirDistances.begin(),openAirDistances.end()); + openAirDistances.erase(std::unique(openAirDistances.begin(), + openAirDistances.end(),[](double a,double b){return std::abs(a-b)<0.01;}), + openAirDistances.end()); + for(std::size_t first=0,section=0;first& p) {return p[0]*p[0]+p[1]*p[1];}; const bool mouthsInRadius=radialSquared(passage.upperMouthSubvoxels) @@ -4457,12 +4642,13 @@ namespace StandaloneStreamBenchmark floorStepRippleControlsDetected+=rippleAudit.floorStepControlDetected; passagePasses+=passageAudit.passed&&mouthsInRadius&&mouthsInContent &&naturalAudit.passed&&mouthProfileAudit.passed&&rippleAudit.passed; - std::printf("[ResolvedPassageAudit] id=%s interface=%d-%d control_points=%zu center_samples=%llu capsule_samples=%llu blocked=%llu support_samples=%llu unsupported=%llu grade_failures=%llu mouth_content=%d/2 mouth_radius=%d/2 walkability=%s\n", + std::printf("[ResolvedPassageAudit] id=%s interface=%d-%d control_points=%zu center_samples=%llu capsule_samples=%llu blocked=%llu support_samples=%llu support_overlap_skips=%llu unsupported=%llu grade_failures=%llu mouth_content=%d/2 mouth_radius=%d/2 walkability=%s\n", passage.stableId.c_str(),passage.upperStrateIndex,passage.lowerStrateIndex, passage.controlPoints.size(),static_cast(passageAudit.centers), static_cast(passageAudit.capsuleSamples), static_cast(passageAudit.blocked), static_cast(passageAudit.supportSamples), + static_cast(passageAudit.supportOverlapSkips), static_cast(passageAudit.unsupported), static_cast(passageAudit.gradeFailures),mouthsInContent?2:0, mouthsInRadius?2:0,passageAudit.passed?"PASS":"FAIL"); @@ -4472,9 +4658,11 @@ namespace StandaloneStreamBenchmark static_cast(naturalAudit.wallSamples), static_cast(naturalAudit.missingWallSamples), naturalAudit.passed?"PASS":"FAIL"); - std::printf("[PassageMouthProfileAudit] id=%s floor_samples=%llu floor_missing=%llu wall_samples=%llu wall_missing=%llu floor_step_scan=centerline profiled_lower_surface=%s floor_flat_step_run_m=%.3f floor_step_m=%.3f wall_flat_step_run_m=%.3f wall_step_m=%.3f spacing_m=%.3f plateau=(%.3f,%.3f) status=%s\n", + std::printf("[PassageMouthProfileAudit] id=%s floor_samples=%llu floor_missing=%llu floor_overlap_skips=%llu floor_expected=%llu wall_samples=%llu wall_missing=%llu floor_step_scan=centerline profiled_lower_surface=%s floor_flat_step_run_m=%.3f floor_step_m=%.3f wall_flat_step_run_m=%.3f wall_step_m=%.3f spacing_m=%.3f plateau=(%.3f,%.3f) status=%s\n", passage.stableId.c_str(),static_cast(mouthProfileAudit.floorSamples), static_cast(mouthProfileAudit.missingFloorSamples), + static_cast(mouthProfileAudit.floorOverlapSkips), + static_cast(mouthProfileAudit.expectedFloorSamples), static_cast(mouthProfileAudit.wallSamples), static_cast(mouthProfileAudit.missingWallSamples), profiledLowerSurface?"true":"false", @@ -4482,7 +4670,7 @@ namespace StandaloneStreamBenchmark mouthProfileAudit.wallFlatStepRunMetres,mouthProfileAudit.wallStepMetres, PassageProfileSpacingMetres,PassageProfilePlateauMinimumMetres, PassageProfileStepThresholdMetres,mouthProfileAudit.passed?"PASS":"FAIL"); - std::printf("[PassageRippleAudit] id=%s window_m=32.000 spacing_m=0.125 period_m=%.3f amplitude_m=%.4f amplitude_cm=%.2f coherent_period_m=%.3f coherent_amplitude_m=%.4f coherent_amplitude_cm=%.2f local_peak_amplitude_m=%.4f coverage=%llu/%llu threshold_m=0.035 synthetic_spheres_period_m=1.500 synthetic_spheres_amplitude_m=%.4f synthetic_spheres_detected=%s floor_period_m=%.3f floor_amplitude_m=%.4f floor_amplitude_cm=%.2f floor_coherent_period_m=%.3f floor_coherent_amplitude_m=%.4f floor_coverage=%llu/%llu floor_threshold_m=0.025 floor_beaded_control_amplitude_m=%.4f floor_beaded_control_detected=%s floor_step_control_amplitude_m=%.4f floor_step_control_detected=%s status=%s\n", + std::printf("[PassageRippleAudit] id=%s window_m=32.000 spacing_m=0.125 period_m=%.3f amplitude_m=%.4f amplitude_cm=%.2f coherent_period_m=%.3f coherent_amplitude_m=%.4f coherent_amplitude_cm=%.2f local_peak_amplitude_m=%.4f coverage=%llu/%llu wall_windows=%llu/5 wall_window_coverage=%llu/%llu threshold_m=0.035 synthetic_spheres_period_m=1.500 synthetic_spheres_amplitude_m=%.4f synthetic_spheres_detected=%s floor_period_m=%.3f floor_amplitude_m=%.4f floor_amplitude_cm=%.2f floor_coherent_period_m=%.3f floor_coherent_amplitude_m=%.4f floor_coverage=%llu/%llu floor_overlap_skips=%llu floor_mode=%s floor_threshold_m=0.025 floor_beaded_control_amplitude_m=%.4f floor_beaded_control_detected=%s floor_step_control_amplitude_m=%.4f floor_step_control_detected=%s status=%s\n", passage.stableId.c_str(),rippleAudit.periodMetres, rippleAudit.amplitudeMetres,rippleAudit.amplitudeMetres*100.0, rippleAudit.coherentPeriodMetres,rippleAudit.coherentAmplitudeMetres, @@ -4490,12 +4678,18 @@ namespace StandaloneStreamBenchmark rippleAudit.localPeakAmplitudeMetres, static_cast(rippleAudit.samples), static_cast(rippleAudit.expectedSamples), + static_cast(rippleAudit.wallQualifiedWindows), + static_cast(rippleAudit.wallWindowSamples), + static_cast(rippleAudit.wallWindowExpectedSamples), rippleAudit.controlAmplitudeMetres,rippleAudit.controlDetected?"true":"false", rippleAudit.floorPeriodMetres,rippleAudit.floorAmplitudeMetres, rippleAudit.floorAmplitudeMetres*100.0, rippleAudit.floorCoherentPeriodMetres,rippleAudit.floorCoherentAmplitudeMetres, static_cast(rippleAudit.floorSamples), static_cast(rippleAudit.floorExpectedSamples), + static_cast(rippleAudit.floorInteriorWins), + rippleAudit.floorOverlapOnly?"overlap_only": + (rippleAudit.floorInteriorWins>0?"measured_with_overlap":"measured"), rippleAudit.floorControlAmplitudeMetres, rippleAudit.floorControlDetected?"true":"false", rippleAudit.floorStepControlAmplitudeMetres, @@ -4513,29 +4707,66 @@ namespace StandaloneStreamBenchmark passage.stableId.c_str(),value[0],value[1],value[2],value[2]-value[1], value[3],value[4],value[5]); } - std::printf("[PassageOpenAirAudit] id=%s support_samples=%llu violations=%llu column_samples=%llu short_span_samples=%llu l24_ungated_violations=%llu route_support_samples=%llu route_support_violations=%llu spacing_m=%.3f status=%s\n", - passage.stableId.c_str(),static_cast(openAirAudit.supportSamples), - static_cast(openAirAudit.violations), - static_cast(openAirAudit.columnSamples), - static_cast(openAirAudit.shortSpanSamples), - static_cast(openAirAudit.legacyViolations), - static_cast(openAirAudit.routeSupportSamples), - static_cast(openAirAudit.routeSupportViolations), - PassageSupportAuditSpacingMetres, - openAirAudit.violations==0?"PASS":"FAIL"); - for(std::size_t i=0;i(shellAudit.floorSamples), + static_cast(shellAudit.floorViolations), + static_cast(shellAudit.floorInteriorWins), + static_cast(shellAudit.floorMouthBlendSkips), + static_cast(shellAudit.openAirSamples), + static_cast(shellAudit.wallSamples), + static_cast(shellAudit.wallViolations), + static_cast(shellAudit.wallInteriorWins), + static_cast(shellAudit.wallMouthBlendSkips), + static_cast(shellAudit.interiorSamples), + static_cast(shellAudit.interiorViolations), + PassageShellAuditSpacingMetres, + shellAudit.floorViolations==0&&shellAudit.wallViolations==0 + &&shellAudit.interiorViolations==0 + ?"PASS":"FAIL"); + for(std::size_t i=0;i(Shape.passageSourceDensityAt({ + sample[0]/coreMetres,sample[1]/coreMetres, + sample[2]/coreMetres})), + static_cast(Shape.unclampedDensityAt({ + sample[0]/coreMetres,sample[1]/coreMetres, + sample[2]/coreMetres}))); + } for(std::size_t i=0;i::infinity(); std::size_t nearestSegment=0; double nearestT=0.0; - double nearestPassageSdf=std::numeric_limits::infinity(); - std::size_t nearestPassageSegment=0; for(std::size_t segment=0;segment+10.0?std::clamp( - ((sample[0]-ax)*dx+(sample[1]-ay)*dy+(sample[2]-az)*dz) - /lengthSquared,0.0,1.0):0.0; - const double ex=sample[0]-(ax+t*dx),ey=sample[1]-(ay+t*dy), - ez=sample[2]-(az+t*dz); - const double radius=qToMetres(a.radiusSubvoxels) - +(qToMetres(b.radiusSubvoxels)-qToMetres(a.radiusSubvoxels))*t; - const double signedDistance=std::sqrt(ex*ex+ey*ey+ez*ez)-radius; - if(signedDistance(item.centers), - static_cast(item.unsupported), - static_cast(item.nativeUnsupported), - sample[0],sample[1],sample[2],columnAtSupport?1:0, - item.firstNativeSupportedProbes,item.firstNativeDensities[0],item.firstNativeDensities[1], - item.firstNativeDensities[2],item.firstNativeDensities[3], - blockedWorld.densityDispatchPathAt({firstX,firstY,firstZ}).c_str()); - } } std::uint64_t routePoints=0,routePasses=0,routeWalkPasses=0,routeBindings=0,routeBindingFailures=0; - struct FRouteAuditInput - { - std::int32_t strateIndex=0; - std::vector> path; - double supportStart=0.125,supportStep=0.125,supportMaximum=0.25, - supportProbeRadius=0.45; - std::uint32_t minimumSupportProbes=3; - }; - std::vector routeAuditInputs; for(const auto& stratum:ResolvedLayout->strates) { std::vector anchors; @@ -4687,10 +4863,7 @@ namespace StandaloneStreamBenchmark } const FWalkAudit routeAudit=auditPlayerPath(Shape,route,supportStartMetres, supportStepMetres,supportMaximumMetres,minimumSupportProbes, - supportProbeRadiusMetres,nullptr,nullptr); - routeAuditInputs.push_back({stratum.strateIndex,route,supportStartMetres, - supportStepMetres,supportMaximumMetres,supportProbeRadiusMetres, - minimumSupportProbes}); + supportProbeRadiusMetres); bool binding=true; for(const auto& passage:ResolvedLayout->passages) { @@ -4735,81 +4908,57 @@ namespace StandaloneStreamBenchmark static_cast(routeAudit.gradeFailures),binding?"PASS":"FAIL", routeAudit.passed&&binding?"PASS":"FAIL"); for(std::size_t i=0;ipassages) + for(std::size_t passageIndex=0; + passageIndexpassages.size();++passageIndex) { + const auto& passage=ResolvedLayout->passages[passageIndex]; + const auto& smoothRoute=allPassageSmoothRoutes[passageIndex]; std::vector> path;path.reserve(passage.controlPoints.size()); - for(const auto& point:passage.controlPoints) + path.reserve(smoothRoute.size()); + for(const auto& point:smoothRoute) { - const double playerZ=static_cast(point.positionSubvoxels[2] - -point.radiusSubvoxels)+1.13*VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel - *1000000.0/World.CoreVoxelSizeMicrons; - path.push_back({qToMetres(point.positionSubvoxels[0])/coreMetres, - qToMetres(point.positionSubvoxels[1])/coreMetres,playerZ/256.0}); + const double playerZ=point.floorZ+1.13; + path.push_back({point.x/coreMetres,point.y/coreMetres, + playerZ/coreMetres}); } const FWalkAudit blockedAudit=auditPlayerPath(blockedWorld,path, - 0.125,0.125,0.25,3,0.45,nullptr,nullptr); + 0.125,0.125,0.25,3,0.45); blockedControls+=blockedAudit.blocked>0&&!blockedAudit.passed; std::printf("[ResolvedPassageBlockedControl] id=%s blocked_capsule_samples=%llu detected=%s\n", passage.stableId.c_str(),static_cast(blockedAudit.blocked), blockedAudit.blocked>0&&!blockedAudit.passed?"true":"false"); } - for(const auto& input:routeAuditInputs) - { - const FWalkAudit controlRoute=auditPlayerPath(blockedWorld,input.path, - input.supportStart,input.supportStep,input.supportMaximum, - input.minimumSupportProbes,input.supportProbeRadius,nullptr,nullptr); - std::printf("[ResolvedStrateRouteBlockedControl] strate=%d blocked=%llu unsupported=%llu status=%s\n", - input.strateIndex,static_cast(controlRoute.blocked), - static_cast(controlRoute.unsupported), - controlRoute.passed?"PASS":"FAIL"); - } - const bool l24OpenAirControlDetected=openAirLegacyViolations>0; - std::printf("[PassageOpenAirNegativeControl] source=L24_ungated_support unsupported_samples=%llu detected=%s\n", - static_cast(openAirLegacyViolations), - l24OpenAirControlDetected?"true":"false"); - std::printf("[PassageOpenAirAuditSummary] interfaces=%llu samples=%llu violations=%llu column_samples=%llu short_span_samples=%llu l24_negative_control=%s status=%s\n", - static_cast(openAirAudits), - static_cast(openAirSamples), - static_cast(openAirViolations), - static_cast(openAirColumnSamples), - static_cast(openAirShortSpanSamples), - l24OpenAirControlDetected?"DETECTED":"MISSED", - openAirAudits==passageCount&&openAirViolations==0&&l24OpenAirControlDetected - ?"PASS":"FAIL"); - const bool l26NoLongBridgeControlDetected=l26NegativeControlApplicable - &&l26LegacyBridgeSpanMetres>12.5; - const bool l26NoLongBridgeControlPass=!l26NegativeControlApplicable - ||l26NoLongBridgeControlDetected; - noLongBridgeAuditPassed=longestUncolumnedSpanMetres<=12.5 - &&l26NoLongBridgeControlPass; - std::printf("[PassageNoLongBridgeNegativeControl] source=L26_SurfaceWorld_bridge applicable=%s longest_uncolumned_m=%.3f threshold_m=12.500 detected=%s\n", - l26NegativeControlApplicable?"true":"false",l26LegacyBridgeSpanMetres, - l26NoLongBridgeControlDetected?"true":"false"); - std::printf("[PassageNoLongBridgeAudit] columns=%llu short_grounded_spans=%llu longest_uncolumned_m=%.3f threshold_m=12.500 longest_short_span_m=%.3f l26_negative_control=%s status=%s\n", - static_cast(columnCrossings), - static_cast(shortGroundedSpans),longestUncolumnedSpanMetres, - longestShortSpanMetres,l26NegativeControlApplicable - ?(l26NoLongBridgeControlDetected?"DETECTED":"MISSED"):"NOT_APPLICABLE", - noLongBridgeAuditPassed?"PASS":"FAIL"); - std::printf("[PassageRockColumnAuditSummary] columns=%llu connected_ends=%llu/%llu short_spans=%llu wall_or_support_failures=%llu disconnected_end_control=%s status=%s\n", - static_cast(columnCrossings), - static_cast(columnConnectedEnds), - static_cast(columnCrossings*2), - static_cast(shortGroundedSpans), - static_cast(columnRouteFailures+columnWallFailures), - columnDisconnectedEndControlApplicable - ?(columnDisconnectedEndControlDetected?"DETECTED":"MISSED") - :"NOT_APPLICABLE", - columnAuditsPassed?"PASS":"FAIL"); + const bool shellAuditPassed=shellAudits==passageCount + &&shellFloorViolations==0&&shellWallViolations==0 + &&shellInteriorViolations==0&&shellOpenAirSamples>0; + std::printf("[PassageShellAuditSummary] interfaces=%llu floor_samples=%llu floor_violations=%llu floor_mouth_blend_skips=%llu open_air_shell_samples=%llu wall_samples=%llu wall_violations=%llu interior_samples=%llu interior_violations=%llu status=%s\n", + static_cast(shellAudits), + static_cast(shellFloorSamples), + static_cast(shellFloorViolations), + static_cast(shellFloorMouthBlendSkips), + static_cast(shellOpenAirSamples), + static_cast(shellWallSamples), + static_cast(shellWallViolations), + static_cast(shellInteriorSamples), + static_cast(shellInteriorViolations), + shellAuditPassed?"PASS":"FAIL"); const bool l23SmoothWallDetected=!looksNatural(0.0,0.0); std::printf("[PassageNaturalnessNegativeControl] source=L23_smooth_unrelieved_wall relief_p2p_m=0.000 threshold_m=%.3f detected=%s\n", MinimumWallReliefMetres,l23SmoothWallDetected?"true":"false"); @@ -4838,8 +4987,7 @@ namespace StandaloneStreamBenchmark &&naturalPasses==passageCount&&l23SmoothWallDetected &&mouthProfilePasses==passageCount&&l23TerraceControlDetected &&ripplePasses==passageCount - &&openAirAudits==passageCount&&openAirViolations==0&&l24OpenAirControlDetected - &&columnAuditsPassed&&noLongBridgeAuditPassed + &&shellAuditPassed &&routePasses>0&&routePasses==routeWalkPasses&&routePasses==routeBindings &&routeBindingFailures==0 &&blockedCompiled&&blockedControls==passageCount; @@ -5529,6 +5677,125 @@ namespace StandaloneStreamBenchmark return 9; } } + if(bAuditPassageTileSeams) + { + std::unordered_set desiredKeys( + Desired.Tiles.begin(),Desired.Tiles.end()); + std::vector> candidates; + candidates.reserve(128); + for(const FVoxelTileKey& nativeA:Desired.Tiles) + { + if(nativeA.Level!=0)continue; + const VoxelForgeCore::TileKey a{{nativeA.Coord.X,nativeA.Coord.Y, + nativeA.Coord.Z},0}; + if(Shape.passageOverlapScore(a)==0)continue; + for(std::size_t axis=0;axis<3;++axis) + { + FVoxelTileKey nativeB=nativeA; + if(axis==0)++nativeB.Coord.X; + else if(axis==1)++nativeB.Coord.Y; + else ++nativeB.Coord.Z; + if(!desiredKeys.contains(nativeB))continue; + const VoxelForgeCore::TileKey b{{nativeB.Coord.X,nativeB.Coord.Y, + nativeB.Coord.Z},0}; + if(Shape.passageOverlapScore(b)>0) + candidates.emplace_back(a,b,axis); + } + } + + VoxelForgeCore::TileGenerationOptions seamOptions; + seamOptions.hashDensity=true; + seamOptions.captureDensitySamples=true; + seamOptions.forceFullDensityCapture=true; + seamOptions.profilePassageComposer=true; + const auto sampleIndex=[](std::int32_t x,std::int32_t y,std::int32_t z) + { + constexpr std::size_t Dim=VoxelForgeCore::CoreTileVoxelCount+3; + return (static_cast(z)*Dim+static_cast(y))*Dim + +static_cast(x); + }; + std::uint64_t comparedSamples=0,mismatches=0; + std::size_t testedPairs=0,examinedPairs=0; + double maximumDelta=0.0; + bool passed=false; + for(const auto& [a,b,axis]:candidates) + { + if(examinedPairs++>=128)break; + std::string errorA,errorB; + const auto tileA=Shape.generateTile(a,seamOptions,errorA); + const auto tileB=Shape.generateTile(b,seamOptions,errorB); + if(!tileA||!tileB) + { + if(examinedPairs==128) + std::printf("[PassageTileSeamCandidate] keyA=(%d,%d,%d,lod0) keyB=(%d,%d,%d,lod0) status=SKIP errorA=%s errorB=%s\n", + a.coordinate.x,a.coordinate.y,a.coordinate.z,b.coordinate.x, + b.coordinate.y,b.coordinate.z,errorA.c_str(),errorB.c_str()); + continue; + } + if(tileA->diagnostics.passageSweepRouteSegmentCandidates==0 + ||tileB->diagnostics.passageSweepRouteSegmentCandidates==0)continue; + constexpr std::int32_t Dim=VoxelForgeCore::CoreTileVoxelCount+3; + const std::size_t expected=static_cast(Dim)*Dim*Dim; + if(tileA->debugDensitySamples.size()!=expected + ||tileB->debugDensitySamples.size()!=expected) + { + std::printf("[PassageTileSeam] axis=%c keyA=(%d,%d,%d,lod0) keyB=(%d,%d,%d,lod0) shared_samples=0 mismatches=1 max_abs_delta=inf status=FAIL reason=missing_full_density_capture\n", + "xyz"[axis],a.coordinate.x,a.coordinate.y,a.coordinate.z, + b.coordinate.x,b.coordinate.y,b.coordinate.z); + ++mismatches; + break; + } + std::uint64_t pairMismatches=0; + double pairMaximumDelta=0.0; + for(std::int32_t v=0;v coordinateA{},coordinateB{}; + coordinateA[axis]=Dim-2; + coordinateB[axis]=1; + coordinateA[(axis+1)%3]=v; + coordinateB[(axis+1)%3]=v; + coordinateA[(axis+2)%3]=w; + coordinateB[(axis+2)%3]=w; + const float densityA=tileA->debugDensitySamples[sampleIndex( + coordinateA[0],coordinateA[1],coordinateA[2])]; + const float densityB=tileB->debugDensitySamples[sampleIndex( + coordinateB[0],coordinateB[1],coordinateB[2])]; + if(std::bit_cast(densityA) + !=std::bit_cast(densityB)) + { + ++pairMismatches; + pairMaximumDelta=std::max(pairMaximumDelta, + std::abs(static_cast(densityA)-densityB)); + } + } + ++testedPairs; + comparedSamples+=static_cast(Dim)*Dim; + mismatches+=pairMismatches; + maximumDelta=std::max(maximumDelta,pairMaximumDelta); + std::printf("[PassageTileSeam] axis=%c keyA=(%d,%d,%d,lod0) keyB=(%d,%d,%d,lod0) shared_samples=%llu mismatches=%llu max_abs_delta=%.9g status=%s\n", + "xyz"[axis],a.coordinate.x,a.coordinate.y,a.coordinate.z, + b.coordinate.x,b.coordinate.y,b.coordinate.z, + static_cast(static_cast(Dim)*Dim), + static_cast(pairMismatches),pairMaximumDelta, + pairMismatches==0?"PASS":"FAIL"); + if(pairMismatches)break; + if(testedPairs>=4)break; + } + passed=testedPairs>0&&mismatches==0; + std::printf("[PassageTileSeamAudit] candidates=%zu examined=%zu pairs=%zu shared_samples=%llu mismatches=%llu max_abs_delta=%.9g status=%s\n", + candidates.size(),examinedPairs,testedPairs, + static_cast(comparedSamples), + static_cast(mismatches),maximumDelta, + passed?"PASS":"FAIL"); + if(!passed) + { + Streamer.Stop(); + return 10; + } + } + FStandaloneDesiredTileSet EarlyDesired=Desired; if(bDeferFarWorld) std::erase_if(EarlyDesired.Tiles,[](const FVoxelTileKey& Key){return Key.Level>1;}); @@ -6511,7 +6778,7 @@ namespace StandaloneStreamBenchmark PayloadBuildMsByLOD[LOD]); static constexpr std::array LegacyTermNames={ "primitive_scan","detail","surface_relief_noise","owner_noise_warp", - "composer_cavern","composer_boundary","composer_passage_support", + "composer_cavern","composer_boundary","composer_passage", "composer_stamps","edit_brushes"}; std::uint64_t TermCalls=0; for(const auto Calls:LegacyFieldTermCallsByLOD[LOD])TermCalls+=Calls; diff --git a/Standalone/Source/StreamingWorld.h b/Standalone/Source/StreamingWorld.h index 6c73af1..a97541d 100644 --- a/Standalone/Source/StreamingWorld.h +++ b/Standalone/Source/StreamingWorld.h @@ -1580,40 +1580,22 @@ private: static_cast(D.islandSharedCacheConflictReplacements), static_cast(D.islandSharedCacheLockWaitNanoseconds)/1000.0); if(D.passageComposerProfiled) - std::printf("[PassageComposerTile] key=(%d,%d,%d,lod%d) worker_ms=%.3f samples=%llu native_field_calls=%llu features=%llu route_candidates=%llu mouth_candidates=%llu boundary_band_queries=%llu queries=%llu passage_iterations=%llu tile_bound_checks=%llu tile_bound_rejects=%llu tile_bound_skipped_iterations=%llu upper_mouth_checks=%llu column_candidates=%llu column_distance_calls=%llu negative_bounds=%llu negative_rejects=%llu positive_bounds=%llu positive_rejects=%llu carve_segment_visits=%llu smooth_carve_joins=%llu support_segment_visits=%llu smooth_support_joins=%llu support_capsule_checks=%llu later_bore_checks=%llu other_capsule_checks=%llu mouth_support_calls=%llu mouth_route_segment_checks=%llu relief_field_calls=%llu smoothstep_evaluations=%llu sweep_segments=%llu sweep_pairs=%llu sweep_outside_pairs=%llu sweep_min_updates=%llu sweep_base_samples=%llu sweep_detail_samples=%llu sweep_grid_samples=%llu sweep_no_influence_samples=%llu sweep_lookups=%llu sweep_cache_hits=%llu sweep_base_hits=%llu sweep_outside_hits=%llu sweep_missing=%llu\n", + std::printf("[PassageComposerTile] key=(%d,%d,%d,lod%d) worker_ms=%.3f samples=%llu native_field_calls=%llu features=%llu route_candidates=%llu boundary_band_queries=%llu queries=%llu passage_iterations=%llu carve_segment_visits=%llu relief_field_calls=%llu sweep_segments=%llu sweep_pairs=%llu sweep_prepare_ms=%.3f sweep_outside_pairs=%llu sweep_shell_support_skips=%llu sweep_min_updates=%llu sweep_base_samples=%llu sweep_detail_samples=%llu sweep_grid_samples=%llu sweep_no_influence_samples=%llu sweep_lookups=%llu sweep_cache_hits=%llu sweep_base_hits=%llu sweep_outside_hits=%llu sweep_missing=%llu\n", Event.Key.Coord.X,Event.Key.Coord.Y,Event.Key.Coord.Z,Event.Key.Level, Event.WorkerMilliseconds,static_cast(Event.DensitySamples), static_cast(D.fieldCalls), static_cast(D.passageTileFeatureCount), static_cast(D.passageTileRouteSegmentCandidates), - static_cast(D.passageTileMouthSegmentCandidates), static_cast(D.resolvedBoundaryBandQueries), static_cast(D.passageComposerQueries), static_cast(D.passageIterations), - static_cast(D.passageTileBoundChecks), - static_cast(D.passageTileBoundRejects), - static_cast(D.passageTileBoundSkippedIterations), - static_cast(D.passageUpperMouthFilterChecks), - static_cast(D.passageColumnCandidates), - static_cast(D.passageColumnDistanceCalls), - static_cast(D.passageNegativeBoundChecks), - static_cast(D.passageNegativeBoundRejects), - static_cast(D.passagePositiveBoundChecks), - static_cast(D.passagePositiveBoundRejects), static_cast(D.passageCarveSegmentVisits), - static_cast(D.passageSmoothCarveJoins), - static_cast(D.passageSupportSegmentVisits), - static_cast(D.passageSmoothSupportJoins), - static_cast(D.passageSupportCapsuleChecks), - static_cast(D.passageLaterBoreChecks), - static_cast(D.passageOtherCapsuleChecks), - static_cast(D.passageMouthSupportCalls), - static_cast(D.passageMouthRouteSegmentChecks), static_cast(D.passageReliefFieldCalls), - static_cast(D.passageSmoothstepEvaluations), static_cast(D.passageSweepRouteSegmentCandidates), static_cast(D.passageSweepSegmentSamplePairs), + static_cast(D.passageSweepPrepareNanoseconds)/1.0e6, static_cast(D.passageSweepOutsideInfluencePairs), + static_cast(D.passageSweepShellSupportSkips), static_cast(D.passageSweepMinimumUpdates), static_cast(D.passageSweepBaseInfluenceSamples), static_cast(D.passageSweepDetailShellSamples), @@ -1624,6 +1606,25 @@ private: static_cast(D.passageSweepBaseInfluenceHits), static_cast(D.passageSweepOutOfInfluenceHits), static_cast(D.passageSweepMissingSamples)); + if(D.passageComposerProfiled) + std::printf("[PassageSweepCount] key=(%d,%d,%d,lod%d) touched=%llu stamped_outside=%llu cache_valid=%llu cache_valid_unique=%llu touched_unique=%llu body_band=%llu shell_band=%llu exact_band_unique=%llu contributing_pairs=%llu overlap_pairs=%llu cross_passage_overlap=%llu floor_profile_calls=%llu cache_bytes=%llu scratch_bytes=%llu offgrid_miss=%llu unprepared_miss=%llu\n", + Event.Key.Coord.X,Event.Key.Coord.Y,Event.Key.Coord.Z,Event.Key.Level, + static_cast(D.passageSweepTouchedSamples), + static_cast(D.passageSweepStampedOutsideSamples), + static_cast(D.passageSweepCacheValidSamples), + static_cast(D.passageSweepCacheValidUniqueSamples), + static_cast(D.passageSweepUniqueTouchedSamples), + static_cast(D.passageSweepBodyBandSamples), + static_cast(D.passageSweepShellBandSamples), + static_cast(D.passageSweepUniqueBandSamples), + static_cast(D.passageSweepContributingPairs), + static_cast(D.passageSweepOverlapPairs), + static_cast(D.passageSweepCrossPassageOverlaps), + static_cast(D.passageSweepFloorProfileCalls), + static_cast(D.passageSweepAllocatedBytes), + static_cast(D.passageSweepPrepareScratchBytes), + static_cast(D.passageSweepOffGridMisses), + static_cast(D.passageSweepUnpreparedMisses)); } void RecordTimelineEvent(FStandaloneCpuTileTimelineEvent::EType Type, const FVoxelTileKey& Key,int32 WorkerId,size_t QueueDepth,size_t ActiveWorkers, diff --git a/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-floating-islands-style2-v217.baseline b/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-floating-islands-style2-v217.baseline new file mode 100644 index 0000000..8e5a343 --- /dev/null +++ b/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-floating-islands-style2-v217.baseline @@ -0,0 +1,12 @@ +[PipelineFullDetailHash] tiles=960 density=0x91931a57a067fd92 mesh=0xa818654be89790ac payload=0x370ff80451105a39 topology=0x06e507557aa70173 +[PipelineWholeViewHash] tiles=2370 density=0x10a9ced1f1c82780 mesh=0xd66b373f5f1f29e7 payload=0xe9e3dcf76003eb6a topology=0xed76a541ebdf8703 +[PipelineLODHash] lod=0 tiles=512 density=0x2fd4c78685a43cfe mesh=0x50478cff1c1f8ca0 payload=0x54e48e57e0af26de topology=0x860c011cfdb9833a +[PipelineLODHash] lod=1 tiles=448 density=0x4b8d9a6dcd2942ad mesh=0x17e89b7087bfe711 payload=0x2389c109eb780db6 topology=0x7eccd4cf560d0630 +[PipelineLODHash] lod=2 tiles=320 density=0xf52c8e8b17cbc844 mesh=0x5028c077393d5b6a payload=0x166fe0ffad8fe7ee topology=0xd178a7b8abf7f72a +[PipelineLODHash] lod=3 tiles=208 density=0x2891139e358828d9 mesh=0x3e80c76107a40395 payload=0x562ed93f9084db6a topology=0x93f0f24947493a03 +[PipelineLODHash] lod=4 tiles=240 density=0xfb11591772a3d18e mesh=0xebf2baee8764591b payload=0xe491d7ac9c0061ad topology=0xd618ac33b95ce494 +[PipelineLODHash] lod=5 tiles=144 density=0x2f8b7b7fb1e67258 mesh=0x4cd508cbe97344fd payload=0x2b6e96a6050458c9 topology=0x4ff6d0eda8988573 +[PipelineLODHash] lod=6 tiles=96 density=0x0114a34c8b8d6113 mesh=0xb1fec4d01ae1fa44 payload=0x3e50cfd429b8e950 topology=0x08090c96d15c1618 +[PipelineLODHash] lod=7 tiles=96 density=0x3836ed8cfce73418 mesh=0x40bc6589c5fc1aac payload=0x677349bcae16790f topology=0x36e3aa53192e6a6b +[PipelineLODHash] lod=8 tiles=306 density=0x144f3c1fd722708b mesh=0xef77b28bf7fd9453 payload=0xe3f47b37fcd61489 topology=0x5a3c73e295494e04 +[PipelineExactQueryHash] probes=9 density=0x7b7c50ac24ccadcc unclamped=0x7b7c50ac24ccadcc detail=0xefcba20c0c70c415 collision=0xe604823a249029bf path=direct-Core-queries diff --git a/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-floating-islands-style2-v219.baseline b/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-floating-islands-style2-v219.baseline new file mode 100644 index 0000000..feb0a8c --- /dev/null +++ b/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-floating-islands-style2-v219.baseline @@ -0,0 +1,12 @@ +[PipelineFullDetailHash] tiles=960 density=0x91931a57a067fd92 mesh=0xa818654be89790ac payload=0x370ff80451105a39 topology=0x06e507557aa70173 +[PipelineWholeViewHash] tiles=2370 density=0x0a15a039462fe17e mesh=0xf30b861767091847 payload=0x5a892d42cdfb43f0 topology=0x9b9e2bca48cd4261 +[PipelineLODHash] lod=0 tiles=512 density=0x2fd4c78685a43cfe mesh=0x50478cff1c1f8ca0 payload=0x54e48e57e0af26de topology=0x860c011cfdb9833a +[PipelineLODHash] lod=1 tiles=448 density=0x4b8d9a6dcd2942ad mesh=0x17e89b7087bfe711 payload=0x2389c109eb780db6 topology=0x7eccd4cf560d0630 +[PipelineLODHash] lod=2 tiles=320 density=0x547c5c876701abd8 mesh=0x33d6150a2e67a02c payload=0x02664763a1a9cb97 topology=0xcf631628b8b93755 +[PipelineLODHash] lod=3 tiles=208 density=0xb00099f8ed2a1e4f mesh=0x4c87fe067b3c7663 payload=0x2e9ce94c84dfdc29 topology=0xc25000e325b8240e +[PipelineLODHash] lod=4 tiles=240 density=0xfb11591772a3d18e mesh=0xebf2baee8764591b payload=0xe491d7ac9c0061ad topology=0xd618ac33b95ce494 +[PipelineLODHash] lod=5 tiles=144 density=0x2f8b7b7fb1e67258 mesh=0x4cd508cbe97344fd payload=0x2b6e96a6050458c9 topology=0x4ff6d0eda8988573 +[PipelineLODHash] lod=6 tiles=96 density=0x0114a34c8b8d6113 mesh=0xb1fec4d01ae1fa44 payload=0x3e50cfd429b8e950 topology=0x08090c96d15c1618 +[PipelineLODHash] lod=7 tiles=96 density=0x3836ed8cfce73418 mesh=0x40bc6589c5fc1aac payload=0x677349bcae16790f topology=0x36e3aa53192e6a6b +[PipelineLODHash] lod=8 tiles=306 density=0x144f3c1fd722708b mesh=0xef77b28bf7fd9453 payload=0xe3f47b37fcd61489 topology=0x5a3c73e295494e04 +[PipelineExactQueryHash] probes=9 density=0x7b7c50ac24ccadcc unclamped=0x7b7c50ac24ccadcc detail=0xefcba20c0c70c415 collision=0xe604823a249029bf path=direct-Core-queries diff --git a/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-floating-islands-style2-v220.baseline b/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-floating-islands-style2-v220.baseline new file mode 100644 index 0000000..6e8c6c7 --- /dev/null +++ b/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-floating-islands-style2-v220.baseline @@ -0,0 +1,12 @@ +[PipelineFullDetailHash] tiles=960 density=0x91931a57a067fd92 mesh=0xa818654be89790ac payload=0x370ff80451105a39 topology=0x06e507557aa70173 +[PipelineWholeViewHash] tiles=2370 density=0xbfae1fa5dba170d6 mesh=0xe7b37fa7a2a0c251 payload=0x0cc21cc96a70ad5a topology=0xe930ccebdfe78935 +[PipelineLODHash] lod=0 tiles=512 density=0x2fd4c78685a43cfe mesh=0x50478cff1c1f8ca0 payload=0x54e48e57e0af26de topology=0x860c011cfdb9833a +[PipelineLODHash] lod=1 tiles=448 density=0x4b8d9a6dcd2942ad mesh=0x17e89b7087bfe711 payload=0x2389c109eb780db6 topology=0x7eccd4cf560d0630 +[PipelineLODHash] lod=2 tiles=320 density=0x944d0d019ab80d3a mesh=0x0c2f9d65fc90702e payload=0x78868bc6c75a66a0 topology=0x51bc901cc030f64b +[PipelineLODHash] lod=3 tiles=208 density=0xeff7152574a49e31 mesh=0x855d44b1e644ab5b payload=0xe8631aa2adb95228 topology=0xe4770e9c1a880ef8 +[PipelineLODHash] lod=4 tiles=240 density=0xfb11591772a3d18e mesh=0xebf2baee8764591b payload=0xe491d7ac9c0061ad topology=0xd618ac33b95ce494 +[PipelineLODHash] lod=5 tiles=144 density=0x2f8b7b7fb1e67258 mesh=0x4cd508cbe97344fd payload=0x2b6e96a6050458c9 topology=0x4ff6d0eda8988573 +[PipelineLODHash] lod=6 tiles=96 density=0x0114a34c8b8d6113 mesh=0xb1fec4d01ae1fa44 payload=0x3e50cfd429b8e950 topology=0x08090c96d15c1618 +[PipelineLODHash] lod=7 tiles=96 density=0x3836ed8cfce73418 mesh=0x40bc6589c5fc1aac payload=0x677349bcae16790f topology=0x36e3aa53192e6a6b +[PipelineLODHash] lod=8 tiles=306 density=0x144f3c1fd722708b mesh=0xef77b28bf7fd9453 payload=0xe3f47b37fcd61489 topology=0x5a3c73e295494e04 +[PipelineExactQueryHash] probes=9 density=0x7b7c50ac24ccadcc unclamped=0x7b7c50ac24ccadcc detail=0xefcba20c0c70c415 collision=0xe604823a249029bf path=direct-Core-queries diff --git a/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-floating-islands-style2-v222.baseline b/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-floating-islands-style2-v222.baseline new file mode 100644 index 0000000..4c61fb2 --- /dev/null +++ b/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-floating-islands-style2-v222.baseline @@ -0,0 +1,12 @@ +[PipelineFullDetailHash] tiles=960 density=0x91931a57a067fd92 mesh=0xa818654be89790ac payload=0x370ff80451105a39 topology=0x06e507557aa70173 +[PipelineWholeViewHash] tiles=2370 density=0x6b7a252b16f4fb54 mesh=0x912d124579189efa payload=0x8abe8d1270377503 topology=0x19a5fe8c2962598c +[PipelineLODHash] lod=0 tiles=512 density=0x2fd4c78685a43cfe mesh=0x50478cff1c1f8ca0 payload=0x54e48e57e0af26de topology=0x860c011cfdb9833a +[PipelineLODHash] lod=1 tiles=448 density=0x4b8d9a6dcd2942ad mesh=0x17e89b7087bfe711 payload=0x2389c109eb780db6 topology=0x7eccd4cf560d0630 +[PipelineLODHash] lod=2 tiles=320 density=0xdad28a7fa1b9766b mesh=0xf5263c751cc5af4f payload=0xb882e4c989d07b53 topology=0x874e27ae4e73ec39 +[PipelineLODHash] lod=3 tiles=208 density=0x6e050028a242875e mesh=0x0b9d3d5662314869 payload=0x6722ab1369ea33b6 topology=0x63c9c29f4568f5e3 +[PipelineLODHash] lod=4 tiles=240 density=0xfb11591772a3d18e mesh=0xebf2baee8764591b payload=0xe491d7ac9c0061ad topology=0xd618ac33b95ce494 +[PipelineLODHash] lod=5 tiles=144 density=0x2f8b7b7fb1e67258 mesh=0x4cd508cbe97344fd payload=0x2b6e96a6050458c9 topology=0x4ff6d0eda8988573 +[PipelineLODHash] lod=6 tiles=96 density=0x0114a34c8b8d6113 mesh=0xb1fec4d01ae1fa44 payload=0x3e50cfd429b8e950 topology=0x08090c96d15c1618 +[PipelineLODHash] lod=7 tiles=96 density=0x3836ed8cfce73418 mesh=0x40bc6589c5fc1aac payload=0x677349bcae16790f topology=0x36e3aa53192e6a6b +[PipelineLODHash] lod=8 tiles=306 density=0x144f3c1fd722708b mesh=0xef77b28bf7fd9453 payload=0xe3f47b37fcd61489 topology=0x5a3c73e295494e04 +[PipelineExactQueryHash] probes=9 density=0x7b7c50ac24ccadcc unclamped=0x7b7c50ac24ccadcc detail=0xefcba20c0c70c415 collision=0xe604823a249029bf path=direct-Core-queries diff --git a/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-floating-islands-style2-v223.baseline b/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-floating-islands-style2-v223.baseline new file mode 100644 index 0000000..387f9d4 --- /dev/null +++ b/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-floating-islands-style2-v223.baseline @@ -0,0 +1,12 @@ +[PipelineFullDetailHash] tiles=960 density=0x91931a57a067fd92 mesh=0xa818654be89790ac payload=0x370ff80451105a39 topology=0x06e507557aa70173 +[PipelineWholeViewHash] tiles=2370 density=0x24c4b5eac2413d22 mesh=0xb9f3a6b9b413e5d4 payload=0x30a1d2de354e7331 topology=0xaf6be92d376df824 +[PipelineLODHash] lod=0 tiles=512 density=0x2fd4c78685a43cfe mesh=0x50478cff1c1f8ca0 payload=0x54e48e57e0af26de topology=0x860c011cfdb9833a +[PipelineLODHash] lod=1 tiles=448 density=0x4b8d9a6dcd2942ad mesh=0x17e89b7087bfe711 payload=0x2389c109eb780db6 topology=0x7eccd4cf560d0630 +[PipelineLODHash] lod=2 tiles=320 density=0x39c648c16c7a5eaf mesh=0x9fd2005db5a5355c payload=0x2c5d7ffd168f768c topology=0x2ee8f3a9eb82f6ae +[PipelineLODHash] lod=3 tiles=208 density=0x7d1fd74cb7fcbe50 mesh=0xa94e442025574cc8 payload=0xb2ef1431b68db0bb topology=0xbafd034ec099755c +[PipelineLODHash] lod=4 tiles=240 density=0xfb11591772a3d18e mesh=0xebf2baee8764591b payload=0xe491d7ac9c0061ad topology=0xd618ac33b95ce494 +[PipelineLODHash] lod=5 tiles=144 density=0x2f8b7b7fb1e67258 mesh=0x4cd508cbe97344fd payload=0x2b6e96a6050458c9 topology=0x4ff6d0eda8988573 +[PipelineLODHash] lod=6 tiles=96 density=0x0114a34c8b8d6113 mesh=0xb1fec4d01ae1fa44 payload=0x3e50cfd429b8e950 topology=0x08090c96d15c1618 +[PipelineLODHash] lod=7 tiles=96 density=0x3836ed8cfce73418 mesh=0x40bc6589c5fc1aac payload=0x677349bcae16790f topology=0x36e3aa53192e6a6b +[PipelineLODHash] lod=8 tiles=306 density=0x144f3c1fd722708b mesh=0xef77b28bf7fd9453 payload=0xe3f47b37fcd61489 topology=0x5a3c73e295494e04 +[PipelineExactQueryHash] probes=9 density=0x7b7c50ac24ccadcc unclamped=0x7b7c50ac24ccadcc detail=0xefcba20c0c70c415 collision=0xe604823a249029bf path=direct-Core-queries diff --git a/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-floating-islands-style2-v224.baseline b/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-floating-islands-style2-v224.baseline new file mode 100644 index 0000000..0f40fff --- /dev/null +++ b/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-floating-islands-style2-v224.baseline @@ -0,0 +1,12 @@ +[PipelineFullDetailHash] tiles=960 density=0x91931a57a067fd92 mesh=0xa818654be89790ac payload=0x370ff80451105a39 topology=0x06e507557aa70173 +[PipelineWholeViewHash] tiles=2370 density=0xa35a371ce6acca32 mesh=0x4543248df5bcd68e payload=0xc09831a7789624f4 topology=0x8a90dd2c5eb27f3e +[PipelineLODHash] lod=0 tiles=512 density=0x2fd4c78685a43cfe mesh=0x50478cff1c1f8ca0 payload=0x54e48e57e0af26de topology=0x860c011cfdb9833a +[PipelineLODHash] lod=1 tiles=448 density=0x4b8d9a6dcd2942ad mesh=0x17e89b7087bfe711 payload=0x2389c109eb780db6 topology=0x7eccd4cf560d0630 +[PipelineLODHash] lod=2 tiles=320 density=0x44883ae9ac5b1293 mesh=0x6060e05ca9ef6ee5 payload=0x8a24b5284ddf8940 topology=0xabd668b48ff3d62a +[PipelineLODHash] lod=3 tiles=208 density=0xc779dd70120f47e4 mesh=0x2bbe518f85284a47 payload=0x1ab3ba13eb39c252 topology=0x7004b6f87b54afe6 +[PipelineLODHash] lod=4 tiles=240 density=0xfb11591772a3d18e mesh=0xebf2baee8764591b payload=0xe491d7ac9c0061ad topology=0xd618ac33b95ce494 +[PipelineLODHash] lod=5 tiles=144 density=0x2f8b7b7fb1e67258 mesh=0x4cd508cbe97344fd payload=0x2b6e96a6050458c9 topology=0x4ff6d0eda8988573 +[PipelineLODHash] lod=6 tiles=96 density=0x0114a34c8b8d6113 mesh=0xb1fec4d01ae1fa44 payload=0x3e50cfd429b8e950 topology=0x08090c96d15c1618 +[PipelineLODHash] lod=7 tiles=96 density=0x3836ed8cfce73418 mesh=0x40bc6589c5fc1aac payload=0x677349bcae16790f topology=0x36e3aa53192e6a6b +[PipelineLODHash] lod=8 tiles=306 density=0x144f3c1fd722708b mesh=0xef77b28bf7fd9453 payload=0xe3f47b37fcd61489 topology=0x5a3c73e295494e04 +[PipelineExactQueryHash] probes=9 density=0x7b7c50ac24ccadcc unclamped=0x7b7c50ac24ccadcc detail=0xefcba20c0c70c415 collision=0xe604823a249029bf path=direct-Core-queries diff --git a/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-floating-islands-style2-v225.baseline b/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-floating-islands-style2-v225.baseline new file mode 100644 index 0000000..cab68d6 --- /dev/null +++ b/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-floating-islands-style2-v225.baseline @@ -0,0 +1,12 @@ +[PipelineFullDetailHash] tiles=960 density=0x91931a57a067fd92 mesh=0xa818654be89790ac payload=0x370ff80451105a39 topology=0x06e507557aa70173 +[PipelineWholeViewHash] tiles=2370 density=0x3ce77475b5908860 mesh=0x80d3ca4b215ddb16 payload=0xf838e9c8ece70933 topology=0xdf790ec894e60a20 +[PipelineLODHash] lod=0 tiles=512 density=0x2fd4c78685a43cfe mesh=0x50478cff1c1f8ca0 payload=0x54e48e57e0af26de topology=0x860c011cfdb9833a +[PipelineLODHash] lod=1 tiles=448 density=0x4b8d9a6dcd2942ad mesh=0x17e89b7087bfe711 payload=0x2389c109eb780db6 topology=0x7eccd4cf560d0630 +[PipelineLODHash] lod=2 tiles=320 density=0xb3e6e0585b0fc92d mesh=0x16c9a82c59e0f3d3 payload=0x1b32fc2e695144de topology=0x89a1eddead8849c1 +[PipelineLODHash] lod=3 tiles=208 density=0xe7c3ce8c79544110 mesh=0xff01589508cbbe69 payload=0xe4370a5d39da57c3 topology=0x2ea4ffeae7c72463 +[PipelineLODHash] lod=4 tiles=240 density=0xfb11591772a3d18e mesh=0xebf2baee8764591b payload=0xe491d7ac9c0061ad topology=0xd618ac33b95ce494 +[PipelineLODHash] lod=5 tiles=144 density=0x2f8b7b7fb1e67258 mesh=0x4cd508cbe97344fd payload=0x2b6e96a6050458c9 topology=0x4ff6d0eda8988573 +[PipelineLODHash] lod=6 tiles=96 density=0x0114a34c8b8d6113 mesh=0xb1fec4d01ae1fa44 payload=0x3e50cfd429b8e950 topology=0x08090c96d15c1618 +[PipelineLODHash] lod=7 tiles=96 density=0x3836ed8cfce73418 mesh=0x40bc6589c5fc1aac payload=0x677349bcae16790f topology=0x36e3aa53192e6a6b +[PipelineLODHash] lod=8 tiles=306 density=0x144f3c1fd722708b mesh=0xef77b28bf7fd9453 payload=0xe3f47b37fcd61489 topology=0x5a3c73e295494e04 +[PipelineExactQueryHash] probes=9 density=0x7b7c50ac24ccadcc unclamped=0x7b7c50ac24ccadcc detail=0xefcba20c0c70c415 collision=0xe604823a249029bf path=direct-Core-queries diff --git a/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-owner4-surface-world-style1-v225.baseline b/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-owner4-surface-world-style1-v225.baseline new file mode 100644 index 0000000..4ee2634 --- /dev/null +++ b/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-owner4-surface-world-style1-v225.baseline @@ -0,0 +1,12 @@ +[PipelineFullDetailHash] tiles=960 density=0xafe828ccd81da549 mesh=0xa23718cb26e18c0e payload=0xc524fb57b6254d28 topology=0x46478bffbdcd90c4 +[PipelineWholeViewHash] tiles=2578 density=0x7ed7c508dc890a62 mesh=0x4fd8654dfe4d53e2 payload=0xfc44de3f8111ce9f topology=0x481236023f075f96 +[PipelineLODHash] lod=0 tiles=512 density=0xd7648f18f861312f mesh=0x9e31100f4bc349c9 payload=0xea4ccb601f71dbb6 topology=0x6f4145693c581d15 +[PipelineLODHash] lod=1 tiles=448 density=0x7150ca8c361ffb83 mesh=0xa803bb427deeba9a payload=0xf4718f1ce85d4f4f topology=0x7b770585aafd8174 +[PipelineLODHash] lod=2 tiles=320 density=0x2ff1b4f5511a4f96 mesh=0x27be33efad378dfe payload=0xe7de01a67e16d564 topology=0x82c0a268d6328dd5 +[PipelineLODHash] lod=3 tiles=272 density=0xb50cb8ec0d827890 mesh=0x5cbaebc6fe2c0a37 payload=0x9827477f3a7f69e6 topology=0xb61d889f9393c4ec +[PipelineLODHash] lod=4 tiles=272 density=0xb743eb64967bddcd mesh=0xf6b5bd36b0ebfead payload=0xd1284c1540f50636 topology=0x4a6e197e2a1a9500 +[PipelineLODHash] lod=5 tiles=208 density=0x38706b628a74dd17 mesh=0x445b1c7b51489cbb payload=0x713efc66290768f7 topology=0x56486b919146bb1e +[PipelineLODHash] lod=6 tiles=144 density=0xd53849b2002a1faa mesh=0xaa210abc8498c415 payload=0xd109aef8639706d1 topology=0x61a4d75fbbc35268 +[PipelineLODHash] lod=7 tiles=96 density=0xb0ea9a140275c9cc mesh=0x3ffd8365c8b0ec29 payload=0x3577afb0a2e4a420 topology=0x97530aafde15b7e0 +[PipelineLODHash] lod=8 tiles=306 density=0x8b3d1816799d67a0 mesh=0x80bf554f17700e1e payload=0xccbe22c3333a9c34 topology=0xcb11b28f6b6bcc50 +[PipelineExactQueryHash] probes=9 density=0xf2df67b38b7802df unclamped=0x48b347986345b557 detail=0xefcba20c0c70c415 collision=0x137e8f6c0b03a624 path=direct-Core-queries diff --git a/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-surface-world-style1-v217.baseline b/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-surface-world-style1-v217.baseline new file mode 100644 index 0000000..2e4dfea --- /dev/null +++ b/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-surface-world-style1-v217.baseline @@ -0,0 +1,12 @@ +[PipelineFullDetailHash] tiles=960 density=0xace56c8f205238ad mesh=0xa9c603a1248de6b8 payload=0xea55f1f4fcc6a894 topology=0x5ea7bc78a1b678ae +[PipelineWholeViewHash] tiles=2370 density=0x451ec18d7a6ca916 mesh=0x9032bb6a7e815169 payload=0xf8d99b0efe90a693 topology=0x871d1a10633160fa +[PipelineLODHash] lod=0 tiles=512 density=0xcd6ab28cfa504aca mesh=0xf03dc80a669fca31 payload=0x397aded1c3d2d297 topology=0xb4a1dc84fabc1fe3 +[PipelineLODHash] lod=1 tiles=448 density=0xce6e713828b2a20a mesh=0x1cf408c25d67d18c payload=0x8a2b5d20571c997e topology=0x51cd985fe8e7d100 +[PipelineLODHash] lod=2 tiles=320 density=0x600148cbe643b155 mesh=0x3627f903d13416fd payload=0x2dd1350e704fe268 topology=0xf9b6bc363d71e191 +[PipelineLODHash] lod=3 tiles=208 density=0x78e0ec638dfea587 mesh=0x25f88e807977f548 payload=0x4a3822253c2355a6 topology=0x9b6bc448957acb86 +[PipelineLODHash] lod=4 tiles=240 density=0x0be8798407724eaf mesh=0x131c303cbbe51434 payload=0x2a90ecf0a2411ca0 topology=0xe3e054a371152e08 +[PipelineLODHash] lod=5 tiles=144 density=0xf20897ad272103a9 mesh=0x13d00b6253ae1f72 payload=0x0db3880693a962fa topology=0x462bd87a80f15e89 +[PipelineLODHash] lod=6 tiles=96 density=0xc040fcac457d6313 mesh=0x1ed132eeb718fb62 payload=0xcd0214e35577c6e3 topology=0x2c56c69e6fdcfd64 +[PipelineLODHash] lod=7 tiles=96 density=0xc2d419446355fdb8 mesh=0x4ea44452574fc84b payload=0xfd9779bedfc9ae0f topology=0x8948546e770c9b72 +[PipelineLODHash] lod=8 tiles=306 density=0x62db31696f2da831 mesh=0xd373f9e9481532fe payload=0x540a60526e0e3e46 topology=0xc725cb901e6dc335 +[PipelineExactQueryHash] probes=9 density=0xc949c4df2ce6f9d9 unclamped=0xc949c4df2ce6f9d9 detail=0x114c501e2d830d94 collision=0xe6011d3a248d4849 path=direct-Core-queries diff --git a/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-surface-world-style1-v219.baseline b/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-surface-world-style1-v219.baseline new file mode 100644 index 0000000..1c35852 --- /dev/null +++ b/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-surface-world-style1-v219.baseline @@ -0,0 +1,12 @@ +[PipelineFullDetailHash] tiles=960 density=0xace56c8f205238ad mesh=0xa9c603a1248de6b8 payload=0xea55f1f4fcc6a894 topology=0x5ea7bc78a1b678ae +[PipelineWholeViewHash] tiles=2370 density=0x51237b896a190321 mesh=0xfd53f271fba5a8aa payload=0xb7b84a6b6ee6c445 topology=0xe90c5c4fc617b317 +[PipelineLODHash] lod=0 tiles=512 density=0xcd6ab28cfa504aca mesh=0xf03dc80a669fca31 payload=0x397aded1c3d2d297 topology=0xb4a1dc84fabc1fe3 +[PipelineLODHash] lod=1 tiles=448 density=0xce6e713828b2a20a mesh=0x1cf408c25d67d18c payload=0x8a2b5d20571c997e topology=0x51cd985fe8e7d100 +[PipelineLODHash] lod=2 tiles=320 density=0x000c1cc799606f1d mesh=0x27d2dc114337aa7b payload=0xa1e0dccf666e4d8d topology=0x575342ccac6ab8de +[PipelineLODHash] lod=3 tiles=208 density=0x0ae55cf5f2c889d4 mesh=0x9e6f17d0ba9d72e1 payload=0x8197d920d1c76399 topology=0x88102d22bdef4ab4 +[PipelineLODHash] lod=4 tiles=240 density=0x0be8798407724eaf mesh=0x131c303cbbe51434 payload=0x2a90ecf0a2411ca0 topology=0xe3e054a371152e08 +[PipelineLODHash] lod=5 tiles=144 density=0xf20897ad272103a9 mesh=0x13d00b6253ae1f72 payload=0x0db3880693a962fa topology=0x462bd87a80f15e89 +[PipelineLODHash] lod=6 tiles=96 density=0xc040fcac457d6313 mesh=0x1ed132eeb718fb62 payload=0xcd0214e35577c6e3 topology=0x2c56c69e6fdcfd64 +[PipelineLODHash] lod=7 tiles=96 density=0xc2d419446355fdb8 mesh=0x4ea44452574fc84b payload=0xfd9779bedfc9ae0f topology=0x8948546e770c9b72 +[PipelineLODHash] lod=8 tiles=306 density=0x62db31696f2da831 mesh=0xd373f9e9481532fe payload=0x540a60526e0e3e46 topology=0xc725cb901e6dc335 +[PipelineExactQueryHash] probes=9 density=0xc949c4df2ce6f9d9 unclamped=0xc949c4df2ce6f9d9 detail=0x114c501e2d830d94 collision=0xe6011d3a248d4849 path=direct-Core-queries diff --git a/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-surface-world-style1-v220.baseline b/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-surface-world-style1-v220.baseline new file mode 100644 index 0000000..8f760eb --- /dev/null +++ b/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-surface-world-style1-v220.baseline @@ -0,0 +1,12 @@ +[PipelineFullDetailHash] tiles=960 density=0xace56c8f205238ad mesh=0xa9c603a1248de6b8 payload=0xea55f1f4fcc6a894 topology=0x5ea7bc78a1b678ae +[PipelineWholeViewHash] tiles=2370 density=0xd90f371b71f0c87b mesh=0x547bf0776cba5998 payload=0x160a59a73597bf71 topology=0xd87c11128214e4d7 +[PipelineLODHash] lod=0 tiles=512 density=0xcd6ab28cfa504aca mesh=0xf03dc80a669fca31 payload=0x397aded1c3d2d297 topology=0xb4a1dc84fabc1fe3 +[PipelineLODHash] lod=1 tiles=448 density=0xce6e713828b2a20a mesh=0x1cf408c25d67d18c payload=0x8a2b5d20571c997e topology=0x51cd985fe8e7d100 +[PipelineLODHash] lod=2 tiles=320 density=0xd810d83e56b91fa2 mesh=0xb15854f2a64b81bf payload=0x32683ea168ba19fd topology=0xe8e5b770fa830d13 +[PipelineLODHash] lod=3 tiles=208 density=0x466c1d3bd7f69d9d mesh=0x54407050bff65fdf payload=0xfe2f7ff9e3e7e97d topology=0x2663680e42a4dcdd +[PipelineLODHash] lod=4 tiles=240 density=0x0be8798407724eaf mesh=0x131c303cbbe51434 payload=0x2a90ecf0a2411ca0 topology=0xe3e054a371152e08 +[PipelineLODHash] lod=5 tiles=144 density=0xf20897ad272103a9 mesh=0x13d00b6253ae1f72 payload=0x0db3880693a962fa topology=0x462bd87a80f15e89 +[PipelineLODHash] lod=6 tiles=96 density=0xc040fcac457d6313 mesh=0x1ed132eeb718fb62 payload=0xcd0214e35577c6e3 topology=0x2c56c69e6fdcfd64 +[PipelineLODHash] lod=7 tiles=96 density=0xc2d419446355fdb8 mesh=0x4ea44452574fc84b payload=0xfd9779bedfc9ae0f topology=0x8948546e770c9b72 +[PipelineLODHash] lod=8 tiles=306 density=0x62db31696f2da831 mesh=0xd373f9e9481532fe payload=0x540a60526e0e3e46 topology=0xc725cb901e6dc335 +[PipelineExactQueryHash] probes=9 density=0xc949c4df2ce6f9d9 unclamped=0xc949c4df2ce6f9d9 detail=0x114c501e2d830d94 collision=0xe6011d3a248d4849 path=direct-Core-queries diff --git a/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-surface-world-style1-v222.baseline b/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-surface-world-style1-v222.baseline new file mode 100644 index 0000000..e8c80e9 --- /dev/null +++ b/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-surface-world-style1-v222.baseline @@ -0,0 +1,12 @@ +[PipelineFullDetailHash] tiles=960 density=0xace56c8f205238ad mesh=0xa9c603a1248de6b8 payload=0xea55f1f4fcc6a894 topology=0x5ea7bc78a1b678ae +[PipelineWholeViewHash] tiles=2370 density=0xfa232c4422e2e610 mesh=0xce56a238f93d6206 payload=0xcf7b1f5aeaaedf99 topology=0xad24679ddf040575 +[PipelineLODHash] lod=0 tiles=512 density=0xcd6ab28cfa504aca mesh=0xf03dc80a669fca31 payload=0x397aded1c3d2d297 topology=0xb4a1dc84fabc1fe3 +[PipelineLODHash] lod=1 tiles=448 density=0xce6e713828b2a20a mesh=0x1cf408c25d67d18c payload=0x8a2b5d20571c997e topology=0x51cd985fe8e7d100 +[PipelineLODHash] lod=2 tiles=320 density=0x2047609972d09d73 mesh=0xae66aa3b34004b82 payload=0x8f81f605def21b18 topology=0xd9cef4942e0bc09e +[PipelineLODHash] lod=3 tiles=208 density=0x2ed5ccb4d6e39e53 mesh=0x896a64c1f3e2c360 payload=0x79325ad522c83de8 topology=0x49de5799ff8ea38e +[PipelineLODHash] lod=4 tiles=240 density=0x0be8798407724eaf mesh=0x131c303cbbe51434 payload=0x2a90ecf0a2411ca0 topology=0xe3e054a371152e08 +[PipelineLODHash] lod=5 tiles=144 density=0xf20897ad272103a9 mesh=0x13d00b6253ae1f72 payload=0x0db3880693a962fa topology=0x462bd87a80f15e89 +[PipelineLODHash] lod=6 tiles=96 density=0xc040fcac457d6313 mesh=0x1ed132eeb718fb62 payload=0xcd0214e35577c6e3 topology=0x2c56c69e6fdcfd64 +[PipelineLODHash] lod=7 tiles=96 density=0xc2d419446355fdb8 mesh=0x4ea44452574fc84b payload=0xfd9779bedfc9ae0f topology=0x8948546e770c9b72 +[PipelineLODHash] lod=8 tiles=306 density=0x62db31696f2da831 mesh=0xd373f9e9481532fe payload=0x540a60526e0e3e46 topology=0xc725cb901e6dc335 +[PipelineExactQueryHash] probes=9 density=0xc949c4df2ce6f9d9 unclamped=0xc949c4df2ce6f9d9 detail=0x114c501e2d830d94 collision=0xe6011d3a248d4849 path=direct-Core-queries diff --git a/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-surface-world-style1-v223.baseline b/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-surface-world-style1-v223.baseline new file mode 100644 index 0000000..11bf48b --- /dev/null +++ b/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-surface-world-style1-v223.baseline @@ -0,0 +1,12 @@ +[PipelineFullDetailHash] tiles=960 density=0xace56c8f205238ad mesh=0xa9c603a1248de6b8 payload=0xea55f1f4fcc6a894 topology=0x5ea7bc78a1b678ae +[PipelineWholeViewHash] tiles=2370 density=0x134e05bb2f1cb230 mesh=0x8e949829cdf96ae2 payload=0xc80c0474009a0d9f topology=0xd1a5eb8855451bf4 +[PipelineLODHash] lod=0 tiles=512 density=0xcd6ab28cfa504aca mesh=0xf03dc80a669fca31 payload=0x397aded1c3d2d297 topology=0xb4a1dc84fabc1fe3 +[PipelineLODHash] lod=1 tiles=448 density=0xce6e713828b2a20a mesh=0x1cf408c25d67d18c payload=0x8a2b5d20571c997e topology=0x51cd985fe8e7d100 +[PipelineLODHash] lod=2 tiles=320 density=0xb4853d0641e11fee mesh=0x26f79c8d8acdf042 payload=0xaf70f7188cdfaf14 topology=0xd1f2e3638ea429aa +[PipelineLODHash] lod=3 tiles=208 density=0x0aff8a79d5472b9e mesh=0xecae6f1d16b27fbc payload=0xa93c0d823b8185fe topology=0x8fe982d0c84843df +[PipelineLODHash] lod=4 tiles=240 density=0x0be8798407724eaf mesh=0x131c303cbbe51434 payload=0x2a90ecf0a2411ca0 topology=0xe3e054a371152e08 +[PipelineLODHash] lod=5 tiles=144 density=0xf20897ad272103a9 mesh=0x13d00b6253ae1f72 payload=0x0db3880693a962fa topology=0x462bd87a80f15e89 +[PipelineLODHash] lod=6 tiles=96 density=0xc040fcac457d6313 mesh=0x1ed132eeb718fb62 payload=0xcd0214e35577c6e3 topology=0x2c56c69e6fdcfd64 +[PipelineLODHash] lod=7 tiles=96 density=0xc2d419446355fdb8 mesh=0x4ea44452574fc84b payload=0xfd9779bedfc9ae0f topology=0x8948546e770c9b72 +[PipelineLODHash] lod=8 tiles=306 density=0x62db31696f2da831 mesh=0xd373f9e9481532fe payload=0x540a60526e0e3e46 topology=0xc725cb901e6dc335 +[PipelineExactQueryHash] probes=9 density=0xc949c4df2ce6f9d9 unclamped=0xc949c4df2ce6f9d9 detail=0x114c501e2d830d94 collision=0xe6011d3a248d4849 path=direct-Core-queries diff --git a/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-surface-world-style1-v224.baseline b/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-surface-world-style1-v224.baseline new file mode 100644 index 0000000..93c412d --- /dev/null +++ b/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-surface-world-style1-v224.baseline @@ -0,0 +1,12 @@ +[PipelineFullDetailHash] tiles=960 density=0xace56c8f205238ad mesh=0xa9c603a1248de6b8 payload=0xea55f1f4fcc6a894 topology=0x5ea7bc78a1b678ae +[PipelineWholeViewHash] tiles=2370 density=0x836f4c7ea35fc78c mesh=0xbe6b16363b1d1886 payload=0x24746690daed16a8 topology=0xc52f31c52006cec9 +[PipelineLODHash] lod=0 tiles=512 density=0xcd6ab28cfa504aca mesh=0xf03dc80a669fca31 payload=0x397aded1c3d2d297 topology=0xb4a1dc84fabc1fe3 +[PipelineLODHash] lod=1 tiles=448 density=0xce6e713828b2a20a mesh=0x1cf408c25d67d18c payload=0x8a2b5d20571c997e topology=0x51cd985fe8e7d100 +[PipelineLODHash] lod=2 tiles=320 density=0xf80a6131d2a43307 mesh=0xecb91b4a6429d557 payload=0x9dcb563bac3f2a0a topology=0xac65521b9bea7f7c +[PipelineLODHash] lod=3 tiles=208 density=0x651a069b131bcff3 mesh=0x85886d10f751fe19 payload=0x818c568d0aaae4e3 topology=0x572fe40864ac6710 +[PipelineLODHash] lod=4 tiles=240 density=0x0be8798407724eaf mesh=0x131c303cbbe51434 payload=0x2a90ecf0a2411ca0 topology=0xe3e054a371152e08 +[PipelineLODHash] lod=5 tiles=144 density=0xf20897ad272103a9 mesh=0x13d00b6253ae1f72 payload=0x0db3880693a962fa topology=0x462bd87a80f15e89 +[PipelineLODHash] lod=6 tiles=96 density=0xc040fcac457d6313 mesh=0x1ed132eeb718fb62 payload=0xcd0214e35577c6e3 topology=0x2c56c69e6fdcfd64 +[PipelineLODHash] lod=7 tiles=96 density=0xc2d419446355fdb8 mesh=0x4ea44452574fc84b payload=0xfd9779bedfc9ae0f topology=0x8948546e770c9b72 +[PipelineLODHash] lod=8 tiles=306 density=0x62db31696f2da831 mesh=0xd373f9e9481532fe payload=0x540a60526e0e3e46 topology=0xc725cb901e6dc335 +[PipelineExactQueryHash] probes=9 density=0xc949c4df2ce6f9d9 unclamped=0xc949c4df2ce6f9d9 detail=0x114c501e2d830d94 collision=0xe6011d3a248d4849 path=direct-Core-queries diff --git a/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-surface-world-style1-v225.baseline b/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-surface-world-style1-v225.baseline new file mode 100644 index 0000000..1f591cf --- /dev/null +++ b/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-surface-world-style1-v225.baseline @@ -0,0 +1,12 @@ +[PipelineFullDetailHash] tiles=960 density=0xace56c8f205238ad mesh=0xa9c603a1248de6b8 payload=0xea55f1f4fcc6a894 topology=0x5ea7bc78a1b678ae +[PipelineWholeViewHash] tiles=2370 density=0xb91a65f2b5d23dd1 mesh=0xcb21ea0acbcf7482 payload=0x812c3d1f7ff8d3b8 topology=0xb18b9bc29e243ba2 +[PipelineLODHash] lod=0 tiles=512 density=0xcd6ab28cfa504aca mesh=0xf03dc80a669fca31 payload=0x397aded1c3d2d297 topology=0xb4a1dc84fabc1fe3 +[PipelineLODHash] lod=1 tiles=448 density=0xce6e713828b2a20a mesh=0x1cf408c25d67d18c payload=0x8a2b5d20571c997e topology=0x51cd985fe8e7d100 +[PipelineLODHash] lod=2 tiles=320 density=0xe06c3509977d89df mesh=0x4d81f55877e78bde payload=0x4dff71b395ce032c topology=0x8af5aa065efee965 +[PipelineLODHash] lod=3 tiles=208 density=0x60940ca350c1110a mesh=0xd386632a7d9271c0 payload=0x02e312e98024ef89 topology=0x0a5335eabb257106 +[PipelineLODHash] lod=4 tiles=240 density=0x0be8798407724eaf mesh=0x131c303cbbe51434 payload=0x2a90ecf0a2411ca0 topology=0xe3e054a371152e08 +[PipelineLODHash] lod=5 tiles=144 density=0xf20897ad272103a9 mesh=0x13d00b6253ae1f72 payload=0x0db3880693a962fa topology=0x462bd87a80f15e89 +[PipelineLODHash] lod=6 tiles=96 density=0xc040fcac457d6313 mesh=0x1ed132eeb718fb62 payload=0xcd0214e35577c6e3 topology=0x2c56c69e6fdcfd64 +[PipelineLODHash] lod=7 tiles=96 density=0xc2d419446355fdb8 mesh=0x4ea44452574fc84b payload=0xfd9779bedfc9ae0f topology=0x8948546e770c9b72 +[PipelineLODHash] lod=8 tiles=306 density=0x62db31696f2da831 mesh=0xd373f9e9481532fe payload=0x540a60526e0e3e46 topology=0xc725cb901e6dc335 +[PipelineExactQueryHash] probes=9 density=0xc949c4df2ce6f9d9 unclamped=0xc949c4df2ce6f9d9 detail=0x114c501e2d830d94 collision=0xe6011d3a248d4849 path=direct-Core-queries diff --git a/Standalone/Tools/verify/verify.py b/Standalone/Tools/verify/verify.py index 53345cb..5fc1584 100644 --- a/Standalone/Tools/verify/verify.py +++ b/Standalone/Tools/verify/verify.py @@ -122,11 +122,11 @@ RECIPE_RE = re.compile( def owner_hash_baseline(recipe: str, style: int) -> tuple[Path, str]: if recipe == "surface-world" and style == 1: - return (BASELINES / "owner-hash/canonical/owner-hash-surface-world-style1-v216.baseline", - "L100-v216-tunnel-owns-interior") + return (BASELINES / "owner-hash/canonical/owner-hash-surface-world-style1-v225.baseline", + "L125-v225-stamped-passage-sweep") if recipe == "floating-islands" and style == 2: - return (BASELINES / "owner-hash/canonical/owner-hash-floating-islands-style2-v216.baseline", - "L100-v216-tunnel-owns-interior") + return (BASELINES / "owner-hash/canonical/owner-hash-floating-islands-style2-v225.baseline", + "L125-v225-stamped-passage-sweep") raise VerificationFailure(f"no pinned owner hash baseline for {recipe} style {style}") @@ -176,9 +176,7 @@ def validate_passage(runner: VerificationRunner, name: str, output: str, ("mouth-profile", r"^\[PassageMouthProfileAudit\].*status=PASS$"), ("route-binding", r"^\[ResolvedStrateRouteAudit\].*mouth_binding=PASS status=PASS$"), ("naturalness", r"^\[PassageNaturalnessSummary\].*status=PASS$"), - ("open-air", r"^\[PassageOpenAirAuditSummary\].*status=PASS$"), - ("no-long-bridge", r"^\[PassageNoLongBridgeAudit\].*status=PASS$"), - ("rock-columns", r"^\[PassageRockColumnAuditSummary\].*status=PASS$"), + ("tunnel-shell", r"^\[PassageShellAuditSummary\].*status=PASS$"), ("ripple-controls", r"^\[PassageRippleAuditSummary\].*status=PASS$"), ("passage-summary", r"^\[ResolvedPassageAuditSummary\].*route_binding_failures=0 .*status=PASS$"), ) @@ -201,16 +199,31 @@ def validate_passage(runner: VerificationRunner, name: str, output: str, wall_threshold = re.search(r"threshold_m=([-0-9.]+)", line) floor = re.search(r"floor_amplitude_m=([-0-9.]+)", line) floor_threshold = re.search(r"floor_threshold_m=([-0-9.]+)", line) - wall_coverage = parse_ratio(line, "coverage") + wall_window_count = parse_ratio(line, "wall_windows") + wall_window_coverage = parse_ratio(line, "wall_window_coverage") floor_coverage = parse_ratio(line, "floor_coverage") + floor_coverage_pair = re.search(r"floor_coverage=(\d+)/(\d+)", line) + floor_overlap_skips = re.search(r"floor_overlap_skips=(\d+)", line) + floor_mode = re.search(r"floor_mode=([^ ]+)", line) + floor_overlap_only = bool( + floor_mode and floor_mode.group(1) == "overlap_only" + and floor_coverage_pair and floor_coverage_pair.groups() == ("0", "0") + and floor_overlap_skips and int(floor_overlap_skips.group(1)) > 0) + floor_measured = bool( + floor_mode and floor_mode.group(1) in ("measured", "measured_with_overlap") + and floor_coverage is not None and floor_coverage >= 0.75) + wall_measured = bool(wall_window_count is not None and wall_window_count > 0 + and wall_window_coverage is not None and wall_window_coverage >= 0.75) ripple_ok &= bool( "status=PASS" in line and wall and wall_threshold and floor and floor_threshold - and wall_coverage is not None and floor_coverage is not None + and wall_measured and floor_coverage is not None and float(wall.group(1)) <= float(wall_threshold.group(1)) and float(floor.group(1)) <= float(floor_threshold.group(1)) - and wall_coverage >= 0.75 and floor_coverage >= 0.75) + and (floor_measured or floor_overlap_only)) passed_all &= ripple_ok - detail = f"profiles={len(rows)} wall/floor amplitudes under their thresholds; coverage>=0.75" + detail = (f"profiles={len(rows)} wall/floor amplitudes under their thresholds; " + "measured wall windows cover>=0.75 and floor measured coverage>=0.75 or all probes " + "explicitly masked by overlapping tunnel interior air") if defer: defer_requirement(runner, f"{name}:wall-floor-ripple-and-coverage", ripple_ok, detail) else: @@ -256,11 +269,34 @@ def run_owner_passages(runner: VerificationRunner, binaries: tuple[Path, ...]) - if compiler == "clang": measured = measure_owner_step(output) worst = measured.get("worst") + ripple_rows = re.findall(r"^\[PassageRippleAudit\].*$", output, re.M) + overlap_only = bool(ripple_rows) and all( + (mode := re.search(r"floor_mode=([^ ]+)", line)) is not None + and mode.group(1) == "overlap_only" + and (coverage := re.search(r"floor_coverage=(\d+)/(\d+)", line)) is not None + and coverage.groups() == ("0", "0") + and (skips := re.search(r"floor_overlap_skips=(\d+)", line)) is not None + and int(skips.group(1)) > 0 + for line in ripple_rows) + walkability_rows = re.findall(r"^\[ResolvedPassageAudit\].*$", output, re.M) + walkability_clear = bool(walkability_rows) and all( + "walkability=PASS" in line + and (blocked := re.search(r"blocked=(\d+)", line)) is not None + and blocked.group(1) == "0" + and (unsupported := re.search(r"unsupported=(\d+)", line)) is not None + and unsupported.group(1) == "0" + and (grade := re.search(r"grade_failures=(\d+)", line)) is not None + and grade.group(1) == "0" + for line in walkability_rows) + masked_by_overlap = (measured["adjacent_pairs"] == 0 + and overlap_only and walkability_clear) + step_passed = bool(measured["passed"] or masked_by_overlap) runner.require(f"{name}:adjacent-owner-step", - bool(measured["passed"]), + step_passed, f"max_step_m={measured['maximum_adjacent_step_m']:.6f} " f"limit_m=0.100 pairs={measured['adjacent_pairs']} " f"fitted_periods_m={measured['fitted_periods_m']} " + f"overlap_only_mask={str(masked_by_overlap).lower()} " f"period_role=diagnostic worst={worst}") return result @@ -663,7 +699,7 @@ def run_hash_pairs(runner: VerificationRunner, diagnostic = {"name": "owner-hash-surface-world-matches-L52-diagnostic", "status": "DIAGNOSTIC", "detail": f"matches={hashes[12] == l52_hashes} L52 rows={len(l52_hashes)}; " - "the v216 passage interior ownership change has its own pinned baseline"} + "the v217 flat-floor hollow-shell geometry has its own pinned baseline"} runner.steps.append(diagnostic) print(f"[{runner.tier}] {diagnostic['name']} {diagnostic['detail']}", flush=True) baseline = BASELINES / "owner-hash/l46" / f"owner-hash-{recipe}-style{style}-w12.baseline"