Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
044cd6d9c5 |
No files matched your search
@@ -494,7 +494,10 @@ namespace VoxelForgeCore
|
|||||||
// Version 223 projects the floor onto one continuous arc-length profile and groups
|
// 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
|
// dense passage samples into coarse tile candidates. Version 224 keeps the same
|
||||||
// continuous floor while relaxing the spline chord tolerance and bounding shell work.
|
// continuous floor while relaxing the spline chord tolerance and bounding shell work.
|
||||||
inline constexpr std::uint32_t WorldAssemblyEvaluatorVersion = 225;
|
// Version 226 unifies the passage influence reach in metres and converts it to core
|
||||||
|
// voxels for every broadphase and proof bound. Version 227 uses the exact smooth-max
|
||||||
|
// support width/6 when deriving that reach.
|
||||||
|
inline constexpr std::uint32_t WorldAssemblyEvaluatorVersion = 227;
|
||||||
|
|
||||||
enum class FieldChannel : std::uint32_t
|
enum class FieldChannel : std::uint32_t
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -72,11 +72,28 @@ static bool VF_IsL98PassagePrepareTraceEnabled()
|
|||||||
return bEnabled;
|
return bEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
static double VF_L93PassageCarveReachMetres()
|
static bool VF_IsL130PassageReachProofAuditEnabled()
|
||||||
{
|
{
|
||||||
// The generated world uses a fixed bounded tube influence. An explicit diagnostic
|
static const bool bEnabled=VF_IsL88DiagnosticSwitchEnabled(
|
||||||
// option can still select the legacy point-evaluation path for comparisons.
|
"VOXELFORGE_L130_PASSAGE_REACH_PROOF_AUDIT");
|
||||||
return 4.0;
|
return bEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr double VF_PassageShellThicknessMetres=0.75;
|
||||||
|
static constexpr double VF_PassageWallReliefMetres=0.21;
|
||||||
|
static constexpr double VF_PassageCornerBlendMetres=0.50;
|
||||||
|
static constexpr double VF_PassageReachMarginMetres=0.01;
|
||||||
|
// Radial support in metres: shell + maximum relief + the smooth-max support
|
||||||
|
// (corner-blend width / 6) + a 1 cm guard for float and bound rounding.
|
||||||
|
static constexpr double VF_PassageInfluenceReachMetres=
|
||||||
|
VF_PassageShellThicknessMetres+VF_PassageWallReliefMetres
|
||||||
|
+VF_PassageCornerBlendMetres/6.0+VF_PassageReachMarginMetres;
|
||||||
|
|
||||||
|
static double VF_PassageInfluenceReachCoreVoxels(
|
||||||
|
std::uint32_t coreVoxelSizeMicrometres)
|
||||||
|
{
|
||||||
|
return VF_PassageInfluenceReachMetres*1000000.0
|
||||||
|
/std::max<std::uint32_t>(1,coreVoxelSizeMicrometres);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class EPassageDensityQueryCaller : std::size_t
|
enum class EPassageDensityQueryCaller : std::size_t
|
||||||
@@ -306,7 +323,7 @@ public:
|
|||||||
profileStats_(profileStats),profileLod_(profileLod),
|
profileStats_(profileStats),profileLod_(profileLod),
|
||||||
passageCarveReachMetres_(std::isfinite(passageCarveReachMetres)
|
passageCarveReachMetres_(std::isfinite(passageCarveReachMetres)
|
||||||
&&passageCarveReachMetres>=0.0?passageCarveReachMetres
|
&&passageCarveReachMetres>=0.0?passageCarveReachMetres
|
||||||
:VF_L93PassageCarveReachMetres())
|
:VF_PassageInfluenceReachMetres)
|
||||||
{
|
{
|
||||||
mayContainResolvedBoundaryBand_=shape.ResolvedBoundaryBandsIntersectSubvoxelRange(
|
mayContainResolvedBoundaryBand_=shape.ResolvedBoundaryBandsIntersectSubvoxelRange(
|
||||||
minimumSubvoxels_[2],maximumSubvoxels_[2]);
|
minimumSubvoxels_[2],maximumSubvoxels_[2]);
|
||||||
@@ -1204,8 +1221,8 @@ public:
|
|||||||
if(!ResolvedLayout||ResolvedLayout->passages.empty()||!std::isfinite(X)
|
if(!ResolvedLayout||ResolvedLayout->passages.empty()||!std::isfinite(X)
|
||||||
||!std::isfinite(Y)||!std::isfinite(Z))return density;
|
||!std::isfinite(Y)||!std::isfinite(Z))return density;
|
||||||
constexpr double Q=static_cast<double>(VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel);
|
constexpr double Q=static_cast<double>(VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel);
|
||||||
constexpr double FloorShellThicknessMetres=0.75;
|
constexpr double FloorShellThicknessMetres=VF_PassageShellThicknessMetres;
|
||||||
constexpr double WallReliefMetres=0.21;
|
constexpr double WallReliefMetres=VF_PassageWallReliefMetres;
|
||||||
constexpr double OpenAirSideWallHeightMetres=1.0;
|
constexpr double OpenAirSideWallHeightMetres=1.0;
|
||||||
constexpr double MouthShellBlendMetres=5.0;
|
constexpr double MouthShellBlendMetres=5.0;
|
||||||
const double qPerMetre=Q*1000000.0/
|
const double qPerMetre=Q*1000000.0/
|
||||||
@@ -1630,8 +1647,8 @@ public:
|
|||||||
{
|
{
|
||||||
constexpr double Q=static_cast<double>(
|
constexpr double Q=static_cast<double>(
|
||||||
VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel);
|
VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel);
|
||||||
const double qPerMetre=Q*1000000.0/
|
const double reachCoreVoxels=VF_PassageInfluenceReachCoreVoxels(
|
||||||
std::max<std::uint32_t>(1,ResolvedLayout->coreVoxelSizeMicrometres);
|
ResolvedLayout->coreVoxelSizeMicrometres);
|
||||||
const auto overlaps=[&](const double low[3],const double high[3])
|
const auto overlaps=[&](const double low[3],const double high[3])
|
||||||
{
|
{
|
||||||
for(int axis=0;axis<3;++axis)
|
for(int axis=0;axis<3;++axis)
|
||||||
@@ -1648,7 +1665,8 @@ public:
|
|||||||
const auto& p3=passage.controlPoints[
|
const auto& p3=passage.controlPoints[
|
||||||
std::min(segment+2,passage.controlPoints.size()-1)];
|
std::min(segment+2,passage.controlPoints.size()-1)];
|
||||||
const double radius=std::max(static_cast<double>(a.radiusSubvoxels),
|
const double radius=std::max(static_cast<double>(a.radiusSubvoxels),
|
||||||
static_cast<double>(b.radiusSubvoxels))/Q+1.0;
|
static_cast<double>(b.radiusSubvoxels))/Q
|
||||||
|
+reachCoreVoxels+0.01;
|
||||||
double low[3]{},high[3]{};
|
double low[3]{},high[3]{};
|
||||||
for(int axis=0;axis<3;++axis)
|
for(int axis=0;axis<3;++axis)
|
||||||
{
|
{
|
||||||
@@ -3499,7 +3517,7 @@ private:
|
|||||||
double centerZSubvoxels,double queryZSubvoxels,double floorDepthSubvoxels,
|
double centerZSubvoxels,double queryZSubvoxels,double floorDepthSubvoxels,
|
||||||
double qPerMetre)
|
double qPerMetre)
|
||||||
{
|
{
|
||||||
constexpr double CornerBlendMetres=0.50;
|
constexpr double CornerBlendMetres=VF_PassageCornerBlendMetres;
|
||||||
const float floorDistance=static_cast<float>(centerZSubvoxels
|
const float floorDistance=static_cast<float>(centerZSubvoxels
|
||||||
-floorDepthSubvoxels-queryZSubvoxels);
|
-floorDepthSubvoxels-queryZSubvoxels);
|
||||||
return SmoothMaxDistance(roundDistanceSubvoxels,floorDistance,
|
return SmoothMaxDistance(roundDistanceSubvoxels,floorDistance,
|
||||||
@@ -4811,13 +4829,9 @@ private:
|
|||||||
PassageNearestNodes.resize(ResolvedLayout?ResolvedLayout->passages.size():0);
|
PassageNearestNodes.resize(ResolvedLayout?ResolvedLayout->passages.size():0);
|
||||||
if(!ResolvedLayout||ResolvedLayout->passages.empty())return;
|
if(!ResolvedLayout||ResolvedLayout->passages.empty())return;
|
||||||
constexpr double Q=static_cast<double>(VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel);
|
constexpr double Q=static_cast<double>(VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel);
|
||||||
constexpr double PassageShellMetres=0.75;
|
|
||||||
constexpr double ReliefMetres=0.21;
|
|
||||||
constexpr double SweepReachMetres=4.0;
|
|
||||||
constexpr double CornerBlendMetres=0.50;
|
|
||||||
constexpr std::size_t CandidateFineSamplesPerSpan=5;
|
constexpr std::size_t CandidateFineSamplesPerSpan=5;
|
||||||
const double requiredReach=std::max(SweepReachMetres+ReliefMetres
|
const double requiredReachCoreVoxels=VF_PassageInfluenceReachCoreVoxels(
|
||||||
+CornerBlendMetres*0.25,PassageShellMetres+ReliefMetres);
|
ResolvedLayout->coreVoxelSizeMicrometres);
|
||||||
for(std::size_t passageIndex=0;passageIndex<ResolvedLayout->passages.size();
|
for(std::size_t passageIndex=0;passageIndex<ResolvedLayout->passages.size();
|
||||||
++passageIndex)
|
++passageIndex)
|
||||||
{
|
{
|
||||||
@@ -4854,7 +4868,7 @@ private:
|
|||||||
routeMinimum[axis]=std::min(routeMinimum[axis],localMinimum[axis]);
|
routeMinimum[axis]=std::min(routeMinimum[axis],localMinimum[axis]);
|
||||||
routeMaximum[axis]=std::max(routeMaximum[axis],localMaximum[axis]);
|
routeMaximum[axis]=std::max(routeMaximum[axis],localMaximum[axis]);
|
||||||
}
|
}
|
||||||
const double localExtent=requiredReach
|
const double localExtent=requiredReachCoreVoxels
|
||||||
+std::max(prepared.radiusA,prepared.radiusB)/Q+0.01;
|
+std::max(prepared.radiusA,prepared.radiusB)/Q+0.01;
|
||||||
FPassageProofBound proof;
|
FPassageProofBound proof;
|
||||||
for(std::size_t axis=0;axis<3;++axis)
|
for(std::size_t axis=0;axis<3;++axis)
|
||||||
@@ -4872,7 +4886,8 @@ private:
|
|||||||
std::ceil((localMaximum[axis]+localExtent)*Q));
|
std::ceil((localMaximum[axis]+localExtent)*Q));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const double routeExtent=maximumRadiusSubvoxels/Q+requiredReach+0.01;
|
const double routeExtent=maximumRadiusSubvoxels/Q
|
||||||
|
+requiredReachCoreVoxels+0.01;
|
||||||
const double tileExtent=routeExtent;
|
const double tileExtent=routeExtent;
|
||||||
std::array<std::int64_t,3> featureMinimum{},featureMaximum{};
|
std::array<std::int64_t,3> featureMinimum{},featureMaximum{};
|
||||||
for(std::size_t axis=0;axis<3;++axis)
|
for(std::size_t axis=0;axis<3;++axis)
|
||||||
@@ -4899,6 +4914,113 @@ private:
|
|||||||
BuildPassageFeatureNode(0,PassageFeatureOrder.size());
|
BuildPassageFeatureNode(0,PassageFeatureOrder.size());
|
||||||
if(!PassageProofBounds.empty())
|
if(!PassageProofBounds.empty())
|
||||||
BuildPassageProofNode(0,PassageProofBounds.size());
|
BuildPassageProofNode(0,PassageProofBounds.size());
|
||||||
|
|
||||||
|
if(VF_IsL130PassageReachProofAuditEnabled())
|
||||||
|
{
|
||||||
|
constexpr double Q=static_cast<double>(
|
||||||
|
VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel);
|
||||||
|
constexpr std::array<std::array<double,2>,8> RadialDirections={{
|
||||||
|
{1.0,0.0},{0.7071067811865475,0.7071067811865475},
|
||||||
|
{0.0,1.0},{-0.7071067811865475,0.7071067811865475},
|
||||||
|
{-1.0,0.0},{-0.7071067811865475,-0.7071067811865475},
|
||||||
|
{0.0,-1.0},{0.7071067811865475,-0.7071067811865475}}};
|
||||||
|
constexpr std::array<double,2> CrestHeightsMetres={0.625,0.875};
|
||||||
|
const double qPerMetre=Q*1000000.0/
|
||||||
|
std::max<std::uint32_t>(1,ResolvedLayout->coreVoxelSizeMicrometres);
|
||||||
|
const std::array<double,6> shellOffsetsMetres={0.70,0.78,0.86,0.94,
|
||||||
|
VF_PassageInfluenceReachMetres-0.005,
|
||||||
|
VF_PassageInfluenceReachMetres+0.005};
|
||||||
|
std::uint64_t sampled=0,signRelevant=0,proofMisses=0,featureMisses=0;
|
||||||
|
for(std::size_t passageIndex=0;
|
||||||
|
passageIndex<PassageSegmentData.size();++passageIndex)
|
||||||
|
{
|
||||||
|
const auto& segments=PassageSegmentData[passageIndex];
|
||||||
|
if(segments.empty())continue;
|
||||||
|
const auto& constants=PassageComposerConstants[passageIndex];
|
||||||
|
const std::size_t stride=std::max<std::size_t>(1,
|
||||||
|
(segments.size()+127)/128);
|
||||||
|
for(std::size_t segmentIndex=0;segmentIndex<segments.size();
|
||||||
|
segmentIndex+=stride)
|
||||||
|
{
|
||||||
|
const auto& segment=segments[segmentIndex];
|
||||||
|
if(segment.lengthSq<=1.0e-12)continue;
|
||||||
|
constexpr double T=0.5;
|
||||||
|
const double centerX=segment.a[0]+T*segment.delta[0];
|
||||||
|
const double centerY=segment.a[1]+T*segment.delta[1];
|
||||||
|
const double centerZ=segment.a[2]+T*segment.delta[2];
|
||||||
|
const double radius=segment.radiusA+T*segment.radiusDelta;
|
||||||
|
const double floorDepth=PassageFlatFloorDepthSubvoxels(
|
||||||
|
constants,segmentIndex,T,radius,qPerMetre);
|
||||||
|
const double floorCenterZ=PassageFlatFloorCenterZSubvoxels(
|
||||||
|
constants,segments,segmentIndex,T,segment,centerX,centerY,
|
||||||
|
floorDepth,qPerMetre);
|
||||||
|
for(const double crestHeightMetres:CrestHeightsMetres)
|
||||||
|
{
|
||||||
|
const double sampleZ=floorCenterZ-floorDepth
|
||||||
|
+crestHeightMetres*qPerMetre;
|
||||||
|
const double verticalDelta=sampleZ-centerZ;
|
||||||
|
for(const double shellOffsetMetres:shellOffsetsMetres)
|
||||||
|
{
|
||||||
|
const double radialDistance=radius
|
||||||
|
+shellOffsetMetres*qPerMetre;
|
||||||
|
if(radialDistance*radialDistance
|
||||||
|
<=verticalDelta*verticalDelta)continue;
|
||||||
|
const double horizontalDistance=std::sqrt(
|
||||||
|
radialDistance*radialDistance
|
||||||
|
-verticalDelta*verticalDelta);
|
||||||
|
for(const auto& direction:RadialDirections)
|
||||||
|
{
|
||||||
|
const double sampleQ[3]={
|
||||||
|
centerX+direction[0]*horizontalDistance,
|
||||||
|
centerY+direction[1]*horizontalDistance,sampleZ};
|
||||||
|
const double sampleVoxel[3]={sampleQ[0]/Q,
|
||||||
|
sampleQ[1]/Q,sampleQ[2]/Q};
|
||||||
|
const float contribution=ApplyResolvedStratePassageCarves(
|
||||||
|
0.0f,static_cast<float>(sampleVoxel[0]),
|
||||||
|
static_cast<float>(sampleVoxel[1]),
|
||||||
|
static_cast<float>(sampleVoxel[2]));
|
||||||
|
++sampled;
|
||||||
|
if(std::abs(contribution)<=1.0e-6f)continue;
|
||||||
|
++signRelevant;
|
||||||
|
if(PassageProofNodes.empty()
|
||||||
|
||!PassageProofBoundsOverlapNode(0,sampleVoxel,
|
||||||
|
sampleVoxel))
|
||||||
|
++proofMisses;
|
||||||
|
std::array<std::int64_t,3> sampleMinimum{},sampleMaximum{};
|
||||||
|
for(std::size_t axis=0;axis<3;++axis)
|
||||||
|
{
|
||||||
|
sampleMinimum[axis]=static_cast<std::int64_t>(
|
||||||
|
std::floor(sampleQ[axis]));
|
||||||
|
sampleMaximum[axis]=static_cast<std::int64_t>(
|
||||||
|
std::ceil(sampleQ[axis]));
|
||||||
|
}
|
||||||
|
const auto candidates=BuildPassageFeatureTileList(
|
||||||
|
sampleMinimum,sampleMaximum);
|
||||||
|
const bool featureContainsSample=std::any_of(
|
||||||
|
candidates.begin(),candidates.end(),
|
||||||
|
[&](std::uint32_t featureIndex)
|
||||||
|
{
|
||||||
|
return featureIndex<PassageTileFeatures.size()
|
||||||
|
&&PassageTileFeatures[featureIndex].passageIndex
|
||||||
|
==passageIndex;
|
||||||
|
});
|
||||||
|
if(!featureContainsSample)++featureMisses;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const bool auditPassed=sampled>0&&signRelevant>0
|
||||||
|
&&proofMisses==0&&featureMisses==0;
|
||||||
|
std::printf("[L130PassageReachProofAudit] reach_m=%.3f sampled=%llu sign_relevant=%llu proof_misses=%llu feature_misses=%llu status=%s\n",
|
||||||
|
VF_PassageInfluenceReachMetres,
|
||||||
|
static_cast<unsigned long long>(sampled),
|
||||||
|
static_cast<unsigned long long>(signRelevant),
|
||||||
|
static_cast<unsigned long long>(proofMisses),
|
||||||
|
static_cast<unsigned long long>(featureMisses),
|
||||||
|
auditPassed?"PASS":"FAIL");
|
||||||
|
if(!auditPassed)std::abort();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PassageProofBoundsOverlapNode(int nodeIndex,const double minimum[3],
|
bool PassageProofBoundsOverlapNode(int nodeIndex,const double minimum[3],
|
||||||
@@ -11442,10 +11564,9 @@ inline void FStandaloneShapeWorld::FScopedPassageTileQueries::prepareSweptTubeBa
|
|||||||
const FIntVector& origin,std::int32_t step,std::int32_t cells,std::uint32_t seed)
|
const FIntVector& origin,std::int32_t step,std::int32_t cells,std::uint32_t seed)
|
||||||
{
|
{
|
||||||
constexpr std::int64_t Q=VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel;
|
constexpr std::int64_t Q=VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel;
|
||||||
constexpr double InfluenceMetres=4.0;
|
|
||||||
constexpr double OpenAirSideWallHeightMetres=1.0;
|
constexpr double OpenAirSideWallHeightMetres=1.0;
|
||||||
if(!shape_||step<=0||cells<=0||!std::isfinite(passageCarveReachMetres_)
|
if(!shape_||step<=0||cells<=0||!std::isfinite(passageCarveReachMetres_)
|
||||||
||std::abs(passageCarveReachMetres_-InfluenceMetres)>1.0e-9)return;
|
||std::abs(passageCarveReachMetres_-VF_PassageInfluenceReachMetres)>1.0e-9)return;
|
||||||
const bool profile=profileStats_!=nullptr;
|
const bool profile=profileStats_!=nullptr;
|
||||||
const auto prepareStart=profile?std::chrono::steady_clock::now()
|
const auto prepareStart=profile?std::chrono::steady_clock::now()
|
||||||
:std::chrono::steady_clock::time_point{};
|
:std::chrono::steady_clock::time_point{};
|
||||||
@@ -11459,7 +11580,7 @@ inline void FStandaloneShapeWorld::FScopedPassageTileQueries::prepareSweptTubeBa
|
|||||||
sweep->dimension=cells+3;
|
sweep->dimension=cells+3;
|
||||||
const std::size_t gridSampleCount=static_cast<std::size_t>(sweep->dimension)
|
const std::size_t gridSampleCount=static_cast<std::size_t>(sweep->dimension)
|
||||||
*static_cast<std::size_t>(sweep->dimension)*static_cast<std::size_t>(sweep->dimension);
|
*static_cast<std::size_t>(sweep->dimension)*static_cast<std::size_t>(sweep->dimension);
|
||||||
sweep->influenceSubvoxels=InfluenceMetres*static_cast<double>(Q)*1000000.0
|
sweep->influenceSubvoxels=passageCarveReachMetres_*static_cast<double>(Q)*1000000.0
|
||||||
/std::max<std::uint32_t>(1,shape_->ResolvedLayout
|
/std::max<std::uint32_t>(1,shape_->ResolvedLayout
|
||||||
?shape_->ResolvedLayout->coreVoxelSizeMicrometres:250000);
|
?shape_->ResolvedLayout->coreVoxelSizeMicrometres:250000);
|
||||||
sweep->passageToSweep.assign(passageRouteSegments_.size(),-1);
|
sweep->passageToSweep.assign(passageRouteSegments_.size(),-1);
|
||||||
@@ -11473,7 +11594,7 @@ inline void FStandaloneShapeWorld::FScopedPassageTileQueries::prepareSweptTubeBa
|
|||||||
const double qPerMetre=static_cast<double>(Q)*1000000.0/
|
const double qPerMetre=static_cast<double>(Q)*1000000.0/
|
||||||
std::max<std::uint32_t>(1,shape_->ResolvedLayout
|
std::max<std::uint32_t>(1,shape_->ResolvedLayout
|
||||||
?shape_->ResolvedLayout->coreVoxelSizeMicrometres:250000);
|
?shape_->ResolvedLayout->coreVoxelSizeMicrometres:250000);
|
||||||
const double shellThickness=0.75*qPerMetre;
|
const double shellThickness=VF_PassageShellThicknessMetres*qPerMetre;
|
||||||
const double stampedOutsideDistance=sweep->influenceSubvoxels+1.0;
|
const double stampedOutsideDistance=sweep->influenceSubvoxels+1.0;
|
||||||
constexpr double MouthShellBlendMetres=5.0;
|
constexpr double MouthShellBlendMetres=5.0;
|
||||||
const double wallReliefShell=0.41*qPerMetre;
|
const double wallReliefShell=0.41*qPerMetre;
|
||||||
@@ -11633,7 +11754,7 @@ inline void FStandaloneShapeWorld::FScopedPassageTileQueries::prepareSweptTubeBa
|
|||||||
// more than cornerWidth/6. Skip its work for pairs outside this exact
|
// more than cornerWidth/6. Skip its work for pairs outside this exact
|
||||||
// support, with a small subvoxel guard for float rounding. The final
|
// support, with a small subvoxel guard for float rounding. The final
|
||||||
// shell union only consumes negative distances.
|
// shell union only consumes negative distances.
|
||||||
constexpr double CornerBlendMetres=0.50;
|
constexpr double CornerBlendMetres=VF_PassageCornerBlendMetres;
|
||||||
const float roundDistanceFloat=static_cast<float>(signedDistance);
|
const float roundDistanceFloat=static_cast<float>(signedDistance);
|
||||||
const float floorDistanceFloat=static_cast<float>(floorCenterZ-floorDepth-qz);
|
const float floorDistanceFloat=static_cast<float>(floorCenterZ-floorDepth-qz);
|
||||||
const double flatDistanceLowerBound=std::max(
|
const double flatDistanceLowerBound=std::max(
|
||||||
|
|||||||
@@ -1,294 +0,0 @@
|
|||||||
#include <algorithm>
|
|
||||||
#include <array>
|
|
||||||
#include <cmath>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <fstream>
|
|
||||||
#include <iomanip>
|
|
||||||
#include <iostream>
|
|
||||||
#include <limits>
|
|
||||||
#include <map>
|
|
||||||
#include <sstream>
|
|
||||||
#include <string>
|
|
||||||
#include <utility>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
struct FSegment
|
|
||||||
{
|
|
||||||
int passage=0,index=0;
|
|
||||||
std::array<double,3> a{},b{};
|
|
||||||
double radiusA=0.0,radiusB=0.0;
|
|
||||||
};
|
|
||||||
struct FTile
|
|
||||||
{
|
|
||||||
int strate=0,x=0,y=0,z=0,lod=0;
|
|
||||||
std::uint64_t baselineFeatures=0,baselineCandidates=0,baselinePairs=0;
|
|
||||||
};
|
|
||||||
struct FTotals
|
|
||||||
{
|
|
||||||
std::uint64_t tiles=0,featureTiles=0,proofTiles=0,groups=0,segments=0;
|
|
||||||
std::uint64_t pairs=0,contributingPairs=0,touched=0,support=0;
|
|
||||||
std::uint64_t overlapPairs=0,crossPassageOverlap=0;
|
|
||||||
std::uint64_t baselineFeatureTiles=0,baselineFeatures=0,baselineCandidates=0;
|
|
||||||
std::uint64_t baselinePairs=0;
|
|
||||||
};
|
|
||||||
|
|
||||||
static bool Intersects(const std::array<double,3>& amin,
|
|
||||||
const std::array<double,3>& amax,const std::array<double,3>& bmin,
|
|
||||||
const std::array<double,3>& bmax)
|
|
||||||
{
|
|
||||||
for(int axis=0;axis<3;++axis)
|
|
||||||
if(amax[axis]<bmin[axis]||amin[axis]>bmax[axis])return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int GridFirst(double bound,const double gridMin[3],double spacing,int axis)
|
|
||||||
{
|
|
||||||
const auto boundSub=static_cast<std::int64_t>(std::floor(bound*1024.0));
|
|
||||||
const auto gridMinSub=static_cast<std::int64_t>(std::llround(gridMin[axis]*1024.0));
|
|
||||||
const auto stepSub=static_cast<std::int64_t>(std::llround(spacing*1024.0));
|
|
||||||
const auto numerator=boundSub-gridMinSub;
|
|
||||||
auto quotient=numerator/stepSub;
|
|
||||||
if(numerator%stepSub>0)++quotient;
|
|
||||||
return static_cast<int>(quotient);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int GridLast(double bound,const double gridMin[3],double spacing,int axis)
|
|
||||||
{
|
|
||||||
const auto boundSub=static_cast<std::int64_t>(std::ceil(bound*1024.0));
|
|
||||||
const auto gridMinSub=static_cast<std::int64_t>(std::llround(gridMin[axis]*1024.0));
|
|
||||||
const auto stepSub=static_cast<std::int64_t>(std::llround(spacing*1024.0));
|
|
||||||
const auto numerator=boundSub-gridMinSub;
|
|
||||||
auto quotient=numerator/stepSub;
|
|
||||||
if(numerator%stepSub<0)--quotient;
|
|
||||||
return static_cast<int>(quotient);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc,char** argv)
|
|
||||||
{
|
|
||||||
if(argc!=3)
|
|
||||||
{
|
|
||||||
std::cerr<<"usage: CountReachCandidates <input.tsv> <output.csv>\n";
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
std::ifstream input(argv[1]);
|
|
||||||
if(!input){std::cerr<<"cannot open input\n";return 2;}
|
|
||||||
std::vector<std::vector<FSegment>> passages(3);
|
|
||||||
std::vector<FTile> tiles;
|
|
||||||
std::string line;
|
|
||||||
while(std::getline(input,line))
|
|
||||||
{
|
|
||||||
std::istringstream row(line);
|
|
||||||
char kind=0;row>>kind;
|
|
||||||
if(kind=='S')
|
|
||||||
{
|
|
||||||
FSegment s;row>>s.passage>>s.index
|
|
||||||
>>s.a[0]>>s.a[1]>>s.a[2]>>s.b[0]>>s.b[1]>>s.b[2]
|
|
||||||
>>s.radiusA>>s.radiusB;
|
|
||||||
if(!row||s.passage<0||s.passage>=static_cast<int>(passages.size()))
|
|
||||||
{std::cerr<<"bad segment row\n";return 2;}
|
|
||||||
passages[static_cast<std::size_t>(s.passage)].push_back(s);
|
|
||||||
}
|
|
||||||
else if(kind=='T')
|
|
||||||
{
|
|
||||||
FTile t;row>>t.strate>>t.x>>t.y>>t.z>>t.lod
|
|
||||||
>>t.baselineFeatures>>t.baselineCandidates>>t.baselinePairs;
|
|
||||||
if(!row){std::cerr<<"bad tile row\n";return 2;}
|
|
||||||
tiles.push_back(t);
|
|
||||||
}
|
|
||||||
else if(kind!='#'&&kind!='\0')
|
|
||||||
{std::cerr<<"unknown row\n";return 2;}
|
|
||||||
}
|
|
||||||
for(auto& p:passages)
|
|
||||||
std::sort(p.begin(),p.end(),[](const auto& a,const auto& b)
|
|
||||||
{return a.index<b.index;});
|
|
||||||
|
|
||||||
std::ofstream output(argv[2]);
|
|
||||||
if(!output){std::cerr<<"cannot open output\n";return 2;}
|
|
||||||
output<<"reach_m,bounds_mode,strate,lod,tiles,feature_tiles,proof_tiles,feature_groups,segment_pairs,contributing_pairs,touched_samples,round_support_samples,overlap_pairs,cross_passage_overlaps,baseline_feature_tiles,baseline_features,baseline_candidates,baseline_pairs\n";
|
|
||||||
constexpr std::array<double,4> reaches={4.0,3.0,2.0,1.5};
|
|
||||||
const std::array<std::pair<const char*,double>,2> boundsModes={{{"v225_core_voxel_units",0.25},
|
|
||||||
{"physical_metres",1.0}}};
|
|
||||||
constexpr double coreVoxelMetres=0.25;
|
|
||||||
constexpr double marginMetres=0.01;
|
|
||||||
for(const auto& [boundsMode,boundsScale]:boundsModes)
|
|
||||||
for(const double reach:reaches)
|
|
||||||
{
|
|
||||||
const double requiredReach=std::max(reach+0.21+0.125,0.75+0.21);
|
|
||||||
std::map<std::pair<int,int>,FTotals> totals;
|
|
||||||
for(const auto& tile:tiles)
|
|
||||||
{
|
|
||||||
const int stepVoxels=1<<tile.lod;
|
|
||||||
const double spacing=stepVoxels*coreVoxelMetres;
|
|
||||||
const int dim=32+3;
|
|
||||||
const double tileOrigin[3]={tile.x*32.0*spacing,tile.y*32.0*spacing,
|
|
||||||
tile.z*32.0*spacing};
|
|
||||||
const double gridMin[3]={tileOrigin[0]-spacing,tileOrigin[1]-spacing,
|
|
||||||
tileOrigin[2]-spacing};
|
|
||||||
const double gridMax[3]={gridMin[0]+(dim-1)*spacing,
|
|
||||||
gridMin[1]+(dim-1)*spacing,gridMin[2]+(dim-1)*spacing};
|
|
||||||
const std::array<double,3> queryMin={gridMin[0],gridMin[1],gridMin[2]};
|
|
||||||
const std::array<double,3> queryMax={gridMax[0],gridMax[1],gridMax[2]};
|
|
||||||
const std::array<double,3> proofMin={tileOrigin[0],tileOrigin[1],tileOrigin[2]};
|
|
||||||
const std::array<double,3> proofMax={tileOrigin[0]+32.0*spacing,
|
|
||||||
tileOrigin[1]+32.0*spacing,tileOrigin[2]+32.0*spacing};
|
|
||||||
|
|
||||||
const std::size_t sampleCount=static_cast<std::size_t>(dim)*dim*dim;
|
|
||||||
std::vector<std::vector<std::uint8_t>> touchedMasks(passages.size(),
|
|
||||||
std::vector<std::uint8_t>(sampleCount,0));
|
|
||||||
std::vector<std::vector<std::uint8_t>> supportMasks(passages.size(),
|
|
||||||
std::vector<std::uint8_t>(sampleCount,0));
|
|
||||||
std::vector<std::uint8_t> unionMask(sampleCount,0);
|
|
||||||
FTotals local;
|
|
||||||
bool anyFeature=false,anyProof=false;
|
|
||||||
|
|
||||||
for(std::size_t p=0;p<passages.size();++p)
|
|
||||||
{
|
|
||||||
const auto& segments=passages[p];
|
|
||||||
const std::size_t groupCount=(segments.size()+4)/5;
|
|
||||||
for(std::size_t group=0;group<groupCount;++group)
|
|
||||||
{
|
|
||||||
const std::size_t begin=group*5,end=std::min(begin+5,segments.size());
|
|
||||||
std::array<double,3> routeMin={
|
|
||||||
std::numeric_limits<double>::infinity(),
|
|
||||||
std::numeric_limits<double>::infinity(),
|
|
||||||
std::numeric_limits<double>::infinity()};
|
|
||||||
std::array<double,3> routeMax={
|
|
||||||
-std::numeric_limits<double>::infinity(),
|
|
||||||
-std::numeric_limits<double>::infinity(),
|
|
||||||
-std::numeric_limits<double>::infinity()};
|
|
||||||
double maxRadius=0.0;
|
|
||||||
for(std::size_t i=begin;i<end;++i)
|
|
||||||
{
|
|
||||||
const auto& s=segments[i];
|
|
||||||
maxRadius=std::max({maxRadius,s.radiusA,s.radiusB});
|
|
||||||
for(int axis=0;axis<3;++axis)
|
|
||||||
{
|
|
||||||
routeMin[axis]=std::min({routeMin[axis],s.a[axis],s.b[axis]});
|
|
||||||
routeMax[axis]=std::max({routeMax[axis],s.a[axis],s.b[axis]});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// The v225 implementation divides positions and radii by Q
|
|
||||||
// (Core voxels), then adds its *_Metres constants directly.
|
|
||||||
// Reproduce that code-unit behavior here for the baseline check.
|
|
||||||
const double featureExtent=maxRadius
|
|
||||||
+(requiredReach+marginMetres)*boundsScale;
|
|
||||||
for(int axis=0;axis<3;++axis)
|
|
||||||
{routeMin[axis]-=featureExtent;routeMax[axis]+=featureExtent;}
|
|
||||||
if(!Intersects(routeMin,routeMax,queryMin,queryMax))continue;
|
|
||||||
anyFeature=true;++local.groups;
|
|
||||||
|
|
||||||
for(std::size_t i=begin;i<end;++i)
|
|
||||||
{
|
|
||||||
const auto& s=segments[i];
|
|
||||||
const double extent=std::max(s.radiusA,s.radiusB)
|
|
||||||
+(requiredReach+marginMetres)*boundsScale;
|
|
||||||
std::array<double,3> low{},high{};
|
|
||||||
int first[3]{},last[3]{};
|
|
||||||
bool valid=true;
|
|
||||||
for(int axis=0;axis<3;++axis)
|
|
||||||
{
|
|
||||||
low[axis]=std::min(s.a[axis],s.b[axis])-extent;
|
|
||||||
high[axis]=std::max(s.a[axis],s.b[axis])+extent;
|
|
||||||
first[axis]=std::max(0,GridFirst(low[axis],gridMin,spacing,axis));
|
|
||||||
last[axis]=std::min(dim-1,GridLast(high[axis],gridMin,spacing,axis));
|
|
||||||
valid=valid&&first[axis]<=last[axis];
|
|
||||||
}
|
|
||||||
// Proof bounds are per segment and include the same conservative
|
|
||||||
// reach; they test the full tile box without the sample halo.
|
|
||||||
if(Intersects(low,high,proofMin,proofMax))anyProof=true;
|
|
||||||
if(!valid)continue;
|
|
||||||
++local.segments;
|
|
||||||
for(int axis=0;axis<3;++axis)
|
|
||||||
{
|
|
||||||
const auto subLo=static_cast<std::int64_t>(std::floor(low[axis]*1024.0));
|
|
||||||
const auto subHi=static_cast<std::int64_t>(std::ceil(high[axis]*1024.0));
|
|
||||||
const auto gridLo=static_cast<std::int64_t>(std::llround(gridMin[axis]*1024.0));
|
|
||||||
const auto subStep=static_cast<std::int64_t>(std::llround(spacing*1024.0));
|
|
||||||
const auto expectedFirst=std::max<std::int64_t>(0,
|
|
||||||
(subLo-gridLo+subStep-1)/subStep);
|
|
||||||
const auto expectedLast=std::min<std::int64_t>(dim-1,
|
|
||||||
(subHi-gridLo)/subStep);
|
|
||||||
first[axis]=static_cast<int>(expectedFirst);
|
|
||||||
last[axis]=static_cast<int>(expectedLast);
|
|
||||||
}
|
|
||||||
if(first[0]>last[0]||first[1]>last[1]||first[2]>last[2])continue;
|
|
||||||
const std::uint64_t nx=static_cast<std::uint64_t>(last[0]-first[0]+1);
|
|
||||||
const std::uint64_t ny=static_cast<std::uint64_t>(last[1]-first[1]+1);
|
|
||||||
const std::uint64_t nz=static_cast<std::uint64_t>(last[2]-first[2]+1);
|
|
||||||
local.pairs+=nx*ny*nz;
|
|
||||||
|
|
||||||
for(int gz=first[2];gz<=last[2];++gz)
|
|
||||||
for(int gy=first[1];gy<=last[1];++gy)
|
|
||||||
for(int gx=first[0];gx<=last[0];++gx)
|
|
||||||
{
|
|
||||||
const double q[3]={gridMin[0]+gx*spacing,
|
|
||||||
gridMin[1]+gy*spacing,gridMin[2]+gz*spacing};
|
|
||||||
const double dx=s.b[0]-s.a[0],dy=s.b[1]-s.a[1],dz=s.b[2]-s.a[2];
|
|
||||||
const double lengthSq=dx*dx+dy*dy+dz*dz;
|
|
||||||
if(!(lengthSq>0.0))continue;
|
|
||||||
const double projection=(q[0]-s.a[0])*dx+(q[1]-s.a[1])*dy
|
|
||||||
+(q[2]-s.a[2])*dz;
|
|
||||||
const double t=std::clamp(projection/lengthSq,0.0,1.0);
|
|
||||||
const double ex=q[0]-(s.a[0]+t*dx);
|
|
||||||
const double ey=q[1]-(s.a[1]+t*dy);
|
|
||||||
const double ez=q[2]-(s.a[2]+t*dz);
|
|
||||||
const double radius=s.radiusA+t*(s.radiusB-s.radiusA);
|
|
||||||
const double distance=std::sqrt(ex*ex+ey*ey+ez*ez)-radius;
|
|
||||||
const double oneSubvoxel=1.0/1024.0;
|
|
||||||
if(distance<reach+oneSubvoxel)
|
|
||||||
{
|
|
||||||
++local.contributingPairs;
|
|
||||||
const std::size_t index=(static_cast<std::size_t>(gz)*dim+gy)*dim+gx;
|
|
||||||
touchedMasks[p][index]=1;
|
|
||||||
unionMask[index]=1;
|
|
||||||
if(distance<=reach)supportMasks[p][index]=1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
local.tiles=1;
|
|
||||||
local.featureTiles=anyFeature?1:0;
|
|
||||||
local.proofTiles=anyProof?1:0;
|
|
||||||
local.baselineFeatureTiles=tile.baselineFeatures?1:0;
|
|
||||||
local.baselineFeatures=tile.baselineFeatures;
|
|
||||||
local.baselineCandidates=tile.baselineCandidates;
|
|
||||||
local.baselinePairs=tile.baselinePairs;
|
|
||||||
for(const auto& mask:touchedMasks)
|
|
||||||
local.touched+=static_cast<std::uint64_t>(
|
|
||||||
std::count(mask.begin(),mask.end(),static_cast<std::uint8_t>(1)));
|
|
||||||
for(std::size_t p=0;p<passages.size();++p)
|
|
||||||
{
|
|
||||||
const auto& mask=supportMasks[p];
|
|
||||||
local.support+=static_cast<std::uint64_t>(
|
|
||||||
std::count(mask.begin(),mask.end(),static_cast<std::uint8_t>(1)));
|
|
||||||
}
|
|
||||||
const std::uint64_t unique=static_cast<std::uint64_t>(
|
|
||||||
std::count(unionMask.begin(),unionMask.end(),static_cast<std::uint8_t>(1)));
|
|
||||||
local.crossPassageOverlap=local.touched-unique;
|
|
||||||
local.overlapPairs=local.contributingPairs-local.touched;
|
|
||||||
auto& total=totals[{tile.strate,tile.lod}];
|
|
||||||
total.tiles+=local.tiles;total.featureTiles+=local.featureTiles;
|
|
||||||
total.proofTiles+=local.proofTiles;total.groups+=local.groups;
|
|
||||||
total.segments+=local.segments;total.pairs+=local.pairs;
|
|
||||||
total.contributingPairs+=local.contributingPairs;total.touched+=local.touched;
|
|
||||||
total.support+=local.support;total.overlapPairs+=local.overlapPairs;
|
|
||||||
total.crossPassageOverlap+=local.crossPassageOverlap;
|
|
||||||
total.baselineFeatureTiles+=local.baselineFeatureTiles;
|
|
||||||
total.baselineFeatures+=local.baselineFeatures;
|
|
||||||
total.baselineCandidates+=local.baselineCandidates;
|
|
||||||
total.baselinePairs+=local.baselinePairs;
|
|
||||||
}
|
|
||||||
for(const auto& [key,t]:totals)
|
|
||||||
output<<std::fixed<<std::setprecision(2)<<reach<<','<<boundsMode<<','
|
|
||||||
<<key.first<<','<<key.second
|
|
||||||
<<','<<t.tiles<<','<<t.featureTiles<<','<<t.proofTiles<<','<<t.groups
|
|
||||||
<<','<<t.pairs<<','<<t.contributingPairs<<','<<t.touched<<','<<t.support
|
|
||||||
<<','<<t.overlapPairs<<','<<t.crossPassageOverlap<<','
|
|
||||||
<<t.baselineFeatureTiles<<','<<t.baselineFeatures<<','
|
|
||||||
<<t.baselineCandidates<<','<<t.baselinePairs<<'\n';
|
|
||||||
std::cerr<<"[L129Precount] reach_m="<<reach<<" required_reach_m="<<requiredReach
|
|
||||||
<<" grouped_rows="<<totals.size()<<"\n";
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -1,310 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
"""Count reach-bound work from the saved v225 layout and L125 tile profiles."""
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
import json
|
|
||||||
import math
|
|
||||||
import re
|
|
||||||
import subprocess
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
ROOT = Path(__file__).resolve().parents[4]
|
|
||||||
HERE = Path(__file__).resolve().parent
|
|
||||||
OUT = ROOT / "Saved/Linux/l129/precount"
|
|
||||||
LAYOUT = ROOT / "Saved/Linux/l125/hashes/owner4-surface-world-w8-clang.layout.json"
|
|
||||||
BASELINE_LOGS = [ROOT / f"Saved/Linux/l125/counts/s{s}-w8-profile1.log" for s in range(4)]
|
|
||||||
CORE_VOXEL_METRES = 0.25
|
|
||||||
SUBVOXELS_PER_METRE = 1024.0
|
|
||||||
PROFILE = re.compile(r"([a-zA-Z0-9_]+)=([^ ]+)")
|
|
||||||
TILE_KEY = re.compile(r"\((-?\d+),(-?\d+),(-?\d+),lod(\d+)\)")
|
|
||||||
|
|
||||||
|
|
||||||
def knot_span(a: list[float], b: list[float], units_per_metre: float) -> float:
|
|
||||||
dx, dy = (b[0] - a[0]) / units_per_metre, (b[1] - a[1]) / units_per_metre
|
|
||||||
return max(1.0e-6, math.sqrt(math.sqrt(dx * dx + dy * dy)))
|
|
||||||
|
|
||||||
|
|
||||||
def evaluate_raw(controls: list[list[float]], span: int, t: float,
|
|
||||||
units_per_metre: float) -> list[float]:
|
|
||||||
p1, p2 = controls[span], controls[span + 1]
|
|
||||||
p0, p3 = controls[max(0, span - 1)], controls[min(span + 2, len(controls) - 1)]
|
|
||||||
dt0, dt1, dt2 = (knot_span(p0, p1, units_per_metre),
|
|
||||||
knot_span(p1, p2, units_per_metre),
|
|
||||||
knot_span(p2, p3, units_per_metre))
|
|
||||||
t2, t3 = t * t, t * t * t
|
|
||||||
result = [0.0, 0.0, 0.0, 0.0]
|
|
||||||
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.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] = 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 build_raw_segments(controls: list[list[float]], units_per_metre: float,
|
|
||||||
spacing_metres: float = 8.0,
|
|
||||||
chord_error_metres: float = 0.1) -> list[dict]:
|
|
||||||
result: list[dict] = []
|
|
||||||
along_metres = 0.0
|
|
||||||
for span in range(len(controls) - 1):
|
|
||||||
horizontal_arc = [0.0] * 33
|
|
||||||
previous = evaluate_raw(controls, span, 0.0, units_per_metre)
|
|
||||||
for step in range(1, 33):
|
|
||||||
current = evaluate_raw(controls, span, step / 32.0, units_per_metre)
|
|
||||||
dx = (current[0] - previous[0]) / units_per_metre
|
|
||||||
dy = (current[1] - previous[1]) / units_per_metre
|
|
||||||
horizontal_arc[step] = horizontal_arc[step - 1] + math.hypot(dx, dy)
|
|
||||||
previous = current
|
|
||||||
span_length = horizontal_arc[-1]
|
|
||||||
base_count = max(1, math.ceil(span_length / spacing_metres))
|
|
||||||
|
|
||||||
def parameter_at_arc(target: float) -> float:
|
|
||||||
upper = 1
|
|
||||||
while upper < len(horizontal_arc) and horizontal_arc[upper] < target:
|
|
||||||
upper += 1
|
|
||||||
upper = min(upper, 32)
|
|
||||||
lower = upper - 1
|
|
||||||
arc_span = horizontal_arc[upper] - horizontal_arc[lower]
|
|
||||||
arc_t = ((target - horizontal_arc[lower]) / arc_span
|
|
||||||
if arc_span > 1.0e-12 else 0.0)
|
|
||||||
return (lower + min(max(arc_t, 0.0), 1.0)) / 32.0
|
|
||||||
|
|
||||||
parameters = [0.0]
|
|
||||||
|
|
||||||
def append_adaptive(t_a: float, t_b: float, a: list[float], b: list[float],
|
|
||||||
depth: int) -> None:
|
|
||||||
fractions = (0.25, 0.5, 0.75)
|
|
||||||
maximum_error, polyline_length = 0.0, 0.0
|
|
||||||
previous_point = a
|
|
||||||
for fraction in fractions:
|
|
||||||
current = evaluate_raw(controls, span, t_a + (t_b - t_a) * fraction,
|
|
||||||
units_per_metre)
|
|
||||||
dx = (current[0] - (a[0] + (b[0] - a[0]) * fraction)) / units_per_metre
|
|
||||||
dy = (current[1] - (a[1] + (b[1] - a[1]) * fraction)) / units_per_metre
|
|
||||||
dr = (current[3] - (a[3] + (b[3] - a[3]) * fraction)) / units_per_metre
|
|
||||||
maximum_error = max(maximum_error, math.sqrt(dx * dx + dy * dy + dr * dr))
|
|
||||||
sx = (current[0] - previous_point[0]) / units_per_metre
|
|
||||||
sy = (current[1] - previous_point[1]) / units_per_metre
|
|
||||||
polyline_length += math.hypot(sx, sy)
|
|
||||||
previous_point = current
|
|
||||||
sx = (b[0] - previous_point[0]) / units_per_metre
|
|
||||||
sy = (b[1] - previous_point[1]) / units_per_metre
|
|
||||||
polyline_length += math.hypot(sx, sy)
|
|
||||||
split = ((polyline_length > spacing_metres * (1.0 + 1.0e-9)
|
|
||||||
or maximum_error > chord_error_metres) and depth < 12)
|
|
||||||
if split:
|
|
||||||
t_mid = (t_a + t_b) * 0.5
|
|
||||||
middle = evaluate_raw(controls, span, t_mid, units_per_metre)
|
|
||||||
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, base_count + 1):
|
|
||||||
target_a = span_length * (segment - 1) / base_count
|
|
||||||
target_b = span_length * segment / base_count
|
|
||||||
t_a, t_b = parameter_at_arc(target_a), parameter_at_arc(target_b)
|
|
||||||
append_adaptive(t_a, t_b,
|
|
||||||
evaluate_raw(controls, span, t_a, units_per_metre),
|
|
||||||
evaluate_raw(controls, span, t_b, units_per_metre), 0)
|
|
||||||
|
|
||||||
points = [evaluate_raw(controls, span, t, units_per_metre) for t in parameters]
|
|
||||||
sampled_arc = [0.0] * len(points)
|
|
||||||
for index in range(1, len(points)):
|
|
||||||
dx = (points[index][0] - points[index - 1][0]) / units_per_metre
|
|
||||||
dy = (points[index][1] - points[index - 1][1]) / units_per_metre
|
|
||||||
sampled_arc[index] = sampled_arc[index - 1] + math.hypot(dx, dy)
|
|
||||||
sampled_span_length = sampled_arc[-1]
|
|
||||||
for index, point in enumerate(points):
|
|
||||||
progress = (sampled_arc[index] / sampled_span_length
|
|
||||||
if sampled_span_length > 1.0e-12 else parameters[index])
|
|
||||||
point[2] = controls[span][2] + (controls[span + 1][2] - controls[span][2]) * progress
|
|
||||||
|
|
||||||
for index in range(1, len(points)):
|
|
||||||
dx = (points[index][0] - points[index - 1][0]) / units_per_metre
|
|
||||||
dy = (points[index][1] - points[index - 1][1]) / units_per_metre
|
|
||||||
dz = (points[index][2] - points[index - 1][2]) / units_per_metre
|
|
||||||
length = math.sqrt(dx * dx + dy * dy + dz * dz)
|
|
||||||
progress_a = (sampled_arc[index - 1] / sampled_span_length
|
|
||||||
if sampled_span_length > 1.0e-12 else parameters[index - 1])
|
|
||||||
progress_b = (sampled_arc[index] / sampled_span_length
|
|
||||||
if sampled_span_length > 1.0e-12 else parameters[index])
|
|
||||||
floor_a = controls[span][2] - controls[span][3]
|
|
||||||
floor_b = controls[span + 1][2] - controls[span + 1][3]
|
|
||||||
result.append({"a": points[index - 1], "b": points[index],
|
|
||||||
"along": along_metres, "length": length, "span": span,
|
|
||||||
"floor_a": floor_a + (floor_b - floor_a) * progress_a,
|
|
||||||
"floor_b": floor_a + (floor_b - floor_a) * progress_b})
|
|
||||||
along_metres += length
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def closest_route_height(route: list[list[float]], x: float, y: float) -> tuple[float, float]:
|
|
||||||
best_height, best_distance_sq = 0.0, float("inf")
|
|
||||||
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(max(((x - a[0]) * dx + (y - a[1]) * dy) / length_sq, 0.0), 1.0) \
|
|
||||||
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_distance_sq:
|
|
||||||
best_distance_sq = distance_sq
|
|
||||||
best_height = a[2] + (b[2] - a[2]) * t
|
|
||||||
return best_height, best_distance_sq
|
|
||||||
|
|
||||||
|
|
||||||
def prepared_segments(layout: dict) -> list[list[dict]]:
|
|
||||||
qpm = SUBVOXELS_PER_METRE
|
|
||||||
strata = {item["strate_index"]: item for item in layout["strates"]}
|
|
||||||
all_passages: list[list[dict]] = []
|
|
||||||
for passage in layout["passages"]:
|
|
||||||
controls_q = [[float(value) for value in point["position_q"]]
|
|
||||||
+ [float(point["radius_q"])] for point in passage["control_points"]]
|
|
||||||
controls = [point.copy() for point in controls_q]
|
|
||||||
upper_mouth = [value / qpm for value in passage["upper_mouth_q"]]
|
|
||||||
upper_depth = max(0.0, (controls[0][2] / qpm) - upper_mouth[2] + 1.13)
|
|
||||||
upper_stratum = strata.get(passage["upper_strate_index"], {})
|
|
||||||
if upper_stratum.get("generator_kind") == "FloatingIslands":
|
|
||||||
route = []
|
|
||||||
for anchor in upper_stratum.get("anchors", []):
|
|
||||||
if anchor.get("kind") == "route_point" and len(anchor.get("values", [])) >= 3:
|
|
||||||
route.append([value / qpm for value in anchor["values"][:3]])
|
|
||||||
if route:
|
|
||||||
route_height, distance_sq = closest_route_height(
|
|
||||||
route, controls[0][0] / qpm, controls[0][1] / qpm)
|
|
||||||
if distance_sq <= (controls[0][3] / qpm + 2.0) ** 2:
|
|
||||||
upper_depth = max(upper_depth,
|
|
||||||
controls[0][2] / qpm - route_height + 1.13)
|
|
||||||
controls[0][3] = max(controls[0][3], upper_depth * qpm)
|
|
||||||
|
|
||||||
lower_mouth = [value for value in passage["lower_mouth_q"]]
|
|
||||||
player_center_q = round(1.13 * qpm)
|
|
||||||
route_end = len(controls) - 1
|
|
||||||
for index in range(1, len(controls_q)):
|
|
||||||
p = controls_q[index]
|
|
||||||
if (int(p[0]) == lower_mouth[0] and int(p[1]) == lower_mouth[1]
|
|
||||||
and int(p[2] - p[3] + player_center_q) == lower_mouth[2]):
|
|
||||||
route_end = index
|
|
||||||
|
|
||||||
raw = build_raw_segments(controls, qpm)
|
|
||||||
total_path = 0.0
|
|
||||||
for segment in raw:
|
|
||||||
if segment["span"] + 1 == route_end:
|
|
||||||
total_path = segment["along"] + segment["length"]
|
|
||||||
radii = [(0.0, controls[0][3] / qpm)]
|
|
||||||
for segment in raw:
|
|
||||||
if segment["span"] < route_end:
|
|
||||||
radii.append((segment["along"] + segment["length"],
|
|
||||||
segment["b"][3] / qpm))
|
|
||||||
body_radii = [radius for along, radius in radii
|
|
||||||
if along >= 10.0 and total_path - along >= 10.0]
|
|
||||||
minimum_body = min(body_radii) if body_radii else min(radius for _, radius in radii)
|
|
||||||
floor_depth = max(0.5, minimum_body - 0.23)
|
|
||||||
|
|
||||||
prepared = []
|
|
||||||
for segment in raw:
|
|
||||||
route_segment = segment["span"] < route_end
|
|
||||||
along_b = segment["along"] + segment["length"]
|
|
||||||
|
|
||||||
def effective_z(raw_z: float, radius: float, planned_floor: float,
|
|
||||||
along: float) -> float:
|
|
||||||
raw_z /= qpm
|
|
||||||
radius /= qpm
|
|
||||||
planned_floor /= qpm
|
|
||||||
local_depth = min(floor_depth, max(0.0, radius - 0.23))
|
|
||||||
if route_segment or abs(along - total_path) <= 1.0e-9:
|
|
||||||
return planned_floor + local_depth
|
|
||||||
route_depth = max(0.0, radius - 0.23)
|
|
||||||
return raw_z - route_depth + local_depth
|
|
||||||
|
|
||||||
a = [segment["a"][0] / qpm, segment["a"][1] / qpm,
|
|
||||||
effective_z(segment["a"][2], segment["a"][3],
|
|
||||||
segment["floor_a"], segment["along"])]
|
|
||||||
b = [segment["b"][0] / qpm, segment["b"][1] / qpm,
|
|
||||||
effective_z(segment["b"][2], segment["b"][3],
|
|
||||||
segment["floor_b"], along_b)]
|
|
||||||
prepared.append({"a": a, "b": b, "radius_a": segment["a"][3] / qpm,
|
|
||||||
"radius_b": segment["b"][3] / qpm})
|
|
||||||
all_passages.append(prepared)
|
|
||||||
return all_passages
|
|
||||||
|
|
||||||
|
|
||||||
def profile_tiles() -> list[tuple[int, int, int, int, int, int, int, int]]:
|
|
||||||
result = []
|
|
||||||
for strate, path in enumerate(BASELINE_LOGS):
|
|
||||||
if not path.is_file():
|
|
||||||
raise SystemExit(f"missing baseline profile: {path}")
|
|
||||||
seen = set()
|
|
||||||
for line in path.read_text(encoding="utf-8", errors="replace").splitlines():
|
|
||||||
if not line.startswith("[PassageComposerTile] "):
|
|
||||||
continue
|
|
||||||
row = dict(PROFILE.findall(line))
|
|
||||||
match = TILE_KEY.search(row.get("key", ""))
|
|
||||||
if not match:
|
|
||||||
continue
|
|
||||||
x, y, z, lod = map(int, match.groups())
|
|
||||||
if lod > 2:
|
|
||||||
continue
|
|
||||||
key = (x, y, z, lod)
|
|
||||||
if key in seen:
|
|
||||||
continue
|
|
||||||
seen.add(key)
|
|
||||||
result.append((strate, x, y, z, lod, int(row.get("features", 0)),
|
|
||||||
int(row.get("route_candidates", 0)),
|
|
||||||
int(row.get("sweep_pairs", 0))))
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def main() -> int:
|
|
||||||
if not LAYOUT.is_file():
|
|
||||||
raise SystemExit(f"missing resolved layout: {LAYOUT}")
|
|
||||||
OUT.mkdir(parents=True, exist_ok=True)
|
|
||||||
layout = json.loads(LAYOUT.read_text(encoding="utf-8"))
|
|
||||||
passages = prepared_segments(layout)
|
|
||||||
tiles = profile_tiles()
|
|
||||||
input_path = OUT / "reach-input.tsv"
|
|
||||||
with input_path.open("w", encoding="utf-8") as output:
|
|
||||||
for passage_index, segments in enumerate(passages):
|
|
||||||
for segment_index, segment in enumerate(segments):
|
|
||||||
values = [*segment["a"], *segment["b"],
|
|
||||||
segment["radius_a"], segment["radius_b"]]
|
|
||||||
output.write("S {} {} {}\n".format(passage_index, segment_index,
|
|
||||||
" ".join(f"{value:.15g}" for value in values)))
|
|
||||||
for tile in tiles:
|
|
||||||
output.write("T {}\n".format(" ".join(str(value) for value in tile)))
|
|
||||||
|
|
||||||
binary = OUT / "CountReachCandidates"
|
|
||||||
compile_log = OUT / "compile.log"
|
|
||||||
with compile_log.open("w", encoding="utf-8") as log:
|
|
||||||
built = subprocess.run(["g++", "-std=c++20", "-O3", "-DNDEBUG",
|
|
||||||
str(HERE / "CountReachCandidates.cpp"), "-o", str(binary)],
|
|
||||||
cwd=ROOT, stdout=log, stderr=subprocess.STDOUT,
|
|
||||||
check=False)
|
|
||||||
if built.returncode:
|
|
||||||
raise SystemExit(f"counter compile failed: {compile_log}")
|
|
||||||
result_path = OUT / "results.csv"
|
|
||||||
run_log = OUT / "counter.log"
|
|
||||||
command = ["taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--",
|
|
||||||
str(binary), str(input_path), str(result_path)]
|
|
||||||
with run_log.open("w", encoding="utf-8") as log:
|
|
||||||
result = subprocess.run(command, cwd=ROOT, stdout=log, stderr=subprocess.STDOUT,
|
|
||||||
check=False, timeout=1740)
|
|
||||||
if result.returncode:
|
|
||||||
raise SystemExit(f"counter failed: {run_log}; exit={result.returncode}")
|
|
||||||
print(f"[L129Precount] segments={[len(x) for x in passages]} "
|
|
||||||
f"profile_tiles={len(tiles)} input={input_path.relative_to(ROOT)} "
|
|
||||||
f"results={result_path.relative_to(ROOT)}")
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
raise SystemExit(main())
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
# L129 — tunnel reach
|
|
||||||
|
|
||||||
**Decision: no-go for performance.** The 2 m candidate passed the geometry checks, but it was slower than both timing references and failed every UE movement comparison. The count pass also found a units mismatch in v225's reach bounds, so the requested physical reach cannot be cut cheaply against the source as it stands.
|
|
||||||
|
|
||||||
## What the reach includes
|
|
||||||
|
|
||||||
The 4.0 m term is the signed-distance influence cutoff outside the bore. The bound adds 0.21 m for wall relief and reserves 0.125 m for the 0.50 m smooth corner (`width/6` is about 0.083 m). The plain shell is 0.75 m thick, so its minimum reach with relief is 0.96 m. The larger term wins: `r + max(R + 0.21 + 0.125, 0.75 + 0.21) + 0.05 m`. At `R=4 m` and the maximum `r=3.5 m`, that is 7.885 m.
|
|
||||||
|
|
||||||
The mouth blend is 5 m **along the route**, not an added radial reach. The open-air half-pipe's side wall is 1 m high; its rounded crest uses the same reach. L129 leaves the 0.75 m shell rule, smooth floor `h(s)`, rounded crest, and grade limit unchanged. The highest audited grade was 10.695°.
|
|
||||||
|
|
||||||
## Counts before the build
|
|
||||||
|
|
||||||
Counts cover the four owner strata at LOD0–2, with 993 route segments. “Pairs” are route-segment/sample checks; “support” is unique per-passage samples inside the distance cutoff. The v225 model's 29.87M pairs is close to the measured source profile's 29.41M.
|
|
||||||
|
|
||||||
| Reach and bounds | Pairs (M) | Support samples (M) | Overlap pairs (M) | Feature / proof-active tiles |
|
|
||||||
|---|---:|---:|---:|---:|
|
|
||||||
| v225 as coded, nominal 4 m | 29.87 | 8.57 | 20.90 | 721 / 677 |
|
|
||||||
| 4 m, physical bounds | 124.97 | 11.72 | 46.64 | 826 / 791 |
|
|
||||||
| 3 m, physical bounds | 87.06 | 8.84 | 30.42 | 787 / 764 |
|
|
||||||
| 2 m, physical bounds | 56.86 | 6.32 | 18.48 | 755 / 729 |
|
|
||||||
| 1.5 m, physical bounds | 44.74 | 5.21 | 13.93 | 743 / 718 |
|
|
||||||
|
|
||||||
Against a correctly bounded 4 m model, 2 m removes 54.5% of pairs and 60.4% of overlap pairs; 71 feature tiles and 62 proof-active tiles become free. Against the v225-as-coded count model, however, physical 2 m adds 90.3% of raw pairs and leaves 34 more feature tiles and 52 more proof-active tiles. Physical 1.5 m still adds 49.8% of pairs and leaves 22 more feature tiles and 41 more proof-active tiles. So the smaller reach does **not** unlock proofs or tile skips versus the shipped source.
|
|
||||||
|
|
||||||
The cause is in `BuildPassageSpatialIndices`: positions are converted to core voxels before the reach is added, but v225 adds the metre value directly. At 0.25 m per core voxel, the nominal 4.335 m bound is only 1.084 m per axis; the sweep cutoff itself remains 4 m. L129 converts the smaller physical bounds to core voxels. That makes its broadphase boxes larger than v225's, even though its actual influence cutoff is smaller. The extra segment/sample checks erase the predicted saving. The 2 m setting was selected from the pre-build counts and is the only reach fully timed.
|
|
||||||
|
|
||||||
## Timing and quality
|
|
||||||
|
|
||||||
Five interleaved L80 runs per W8/W12 cell were completed on a quiet machine (load 0.71, CPU idle 97.3%). L125 is the `b96dd73` source. Every near-ready cell and every whole-view cell was slower than L109 and b96dd73:
|
|
||||||
|
|
||||||
| Stratum / workers | Near vs L109 / base | Whole view vs L109 / base |
|
|
||||||
|---|---:|---:|
|
|
||||||
| S0 W8 | +11.1% / +9.3% | +7.5% / +7.2% |
|
|
||||||
| S0 W12 | +11.2% / +6.6% | +5.5% / +3.3% |
|
|
||||||
| S1 W8 | +16.7% / +7.8% | +8.7% / +5.3% |
|
|
||||||
| S1 W12 | +17.9% / +9.9% | +9.5% / +5.6% |
|
|
||||||
| S2 W8 | +12.8% / +8.4% | +5.3% / +5.2% |
|
|
||||||
| S2 W12 | +17.1% / +9.1% | +10.3% / +5.7% |
|
|
||||||
| S3 W8 | +13.4% / +4.9% | +6.3% / +2.8% |
|
|
||||||
| S3 W12 | +18.2% / +6.9% | +8.9% / +4.2% |
|
|
||||||
|
|
||||||
Five UE runs at 30 m/s also missed the b96dd73 gate: near coverage 38.05% vs 40.22% (−2.17 points), far holes 4.03% vs 3.46% (+0.58 points), tick p99 11.54 vs 10.80 ms (+0.74 ms), and worst tick 14.12 vs 13.27 ms (+0.85 ms). The Linux UE host build passed after timing with `-NoUBA -MaxParallelActions=4`; Unreal was not run under `prlimit`.
|
|
||||||
|
|
||||||
Fast verification passed (259 checks; 5 historical diagnostics), walkability passed at 21,425/21,425, all three passage grades stayed below 15°, and the seam audit passed 4 joins / 4,900 samples with no mismatches. Clang and GCC hashes matched for W1/W8/W12 across all three tested owner layouts (18 cases). Evaluator version 226 and three canonical owner hash baselines were added.
|
|
||||||
|
|
||||||
The 23 L125 pose captures and six paired mouth close-ups are verified. All before/after PNGs are pixel-identical; these views show no visible change. The floor probe peaked at 7.9 mm, above a strict “few millimetres” reading.
|
|
||||||
|
|
||||||
## Captures and records
|
|
||||||
|
|
||||||
- [L125 poses: before / L129 comparison](captures/COMPARE.html)
|
|
||||||
- [Mouth close-ups: before / L129 comparison](captures/L129-mouth/COMPARE.html)
|
|
||||||
- [L80 timing results](../../../../Saved/Linux/l129/timing/summary.json)
|
|
||||||
- [UE movement results](../../../../Saved/Linux/l129/movement/summary.json)
|
|
||||||
- [Pre-build count results](../../../../Saved/Linux/l129/precount/results.csv)
|
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
"""Render the 23 L125 camera poses with the L129 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/l129/captures"
|
|
||||||
BASELINE_INDEX = (ROOT / "Standalone/Research/WorldAssemblerM3/Linux125"
|
|
||||||
/ "captures/L125/capture-index.json")
|
|
||||||
LAYOUT = ROOT / "Saved/Linux/l129/hashes/owner4-surface-world-w12-clang.layout.json"
|
|
||||||
CLANG = ROOT / os.environ.get("L129_CAPTURE_CLANG",
|
|
||||||
"Saved/Linux/l129/bin/VoxelForgeCoreHeadless-l129-clang")
|
|
||||||
RENDERER = ROOT / os.environ.get("L129_CAPTURE_RENDERER",
|
|
||||||
"Saved/Linux/l129/bin/VoxelForgeOffscreenCapture-l129-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 = {"L129": CLANG}
|
|
||||||
HELPERS.RENDERERS = {"L129": RENDERER}
|
|
||||||
|
|
||||||
|
|
||||||
def main() -> int:
|
|
||||||
if any(not path.is_file() for path in (BASELINE_INDEX, LAYOUT, CLANG, RENDERER)):
|
|
||||||
raise SystemExit("missing L125 camera set, L129 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("L129", view, layout)
|
|
||||||
row["variant"] = "L129-v226"
|
|
||||||
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"L129 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 L125 views, captured {len(rows)}")
|
|
||||||
index = CAPTURES / "L129" / "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 = ["<!doctype html><meta charset='utf-8'>",
|
|
||||||
"<title>L125 / L129 tunnel capture comparison</title>",
|
|
||||||
"<style>body{font:14px system-ui;margin:24px;background:#17191d;color:#eee}"
|
|
||||||
"section{margin:28px 0}h2{font-size:18px}div{display:grid;"
|
|
||||||
"grid-template-columns:1fr 1fr;gap:12px}img{width:100%;height:auto}"
|
|
||||||
"p{color:#bbb}</style>", "<h1>L125 / L129 v226: identical views</h1>"]
|
|
||||||
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/Linux125"
|
|
||||||
/ old["capture"], CAPTURES)
|
|
||||||
new_path = os.path.relpath(RESEARCH / row["capture"], CAPTURES)
|
|
||||||
html.extend(["<section>", f"<h2>{row['passage']} — {row['station']}</h2>",
|
|
||||||
f"<p>{row['kind']} · L125 {old['pixel_quality_status']} · "
|
|
||||||
f"L129 {row['pixel_quality_status']}</p>", "<div>",
|
|
||||||
f"<figure><figcaption>L125</figcaption><img src='{old_path}'></figure>",
|
|
||||||
f"<figure><figcaption>L129 v226</figcaption><img src='{new_path}'></figure>",
|
|
||||||
"</div>", "</section>"])
|
|
||||||
(CAPTURES / "COMPARE.html").write_text("\n".join(html) + "\n", encoding="utf-8")
|
|
||||||
print(f"[L129Captures] rendered={len(rows)} views index={index.relative_to(ROOT)}",
|
|
||||||
flush=True)
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
raise SystemExit(main())
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
#!/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("L129_PROBE_DIR", "Saved/Linux/l129/density-probe")
|
|
||||||
BINARY = ROOT / os.environ.get("L129_PROBE_BINARY",
|
|
||||||
"Saved/Linux/l129/bin/VoxelForgeCoreHeadless-l129-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"[L129DensityProbe] exit={result.returncode} stations={len(summary)} "
|
|
||||||
f"log={log.relative_to(ROOT)}", flush=True)
|
|
||||||
return result.returncode
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
raise SystemExit(main())
|
|
||||||
@@ -1,119 +0,0 @@
|
|||||||
#!/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("L129_HASH_DIR", "Saved/Linux/l129/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("L129_HASH_CLANG",
|
|
||||||
"Saved/Linux/l129/bin/VoxelForgeCoreHeadless-l129-clang"),
|
|
||||||
"gcc": ROOT / os.environ.get("L129_HASH_GCC",
|
|
||||||
"Saved/Linux/l129/bin/VoxelForgeCoreHeadless-l129-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("[L129HashRun] " + 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 L129 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-v226.baseline"),
|
|
||||||
("owner2", "surface-world", 1,
|
|
||||||
"owner-hash-surface-world-style1-v226.baseline"),
|
|
||||||
("owner2", "floating-islands", 2,
|
|
||||||
"owner-hash-floating-islands-style2-v226.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("[L129HashSummary] " + json.dumps(groups, sort_keys=True), flush=True)
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
raise SystemExit(main())
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
"""Render matching baseline and L129 close views of each tunnel mouth."""
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
import hashlib
|
|
||||||
import importlib.util
|
|
||||||
import json
|
|
||||||
import os
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
ROOT = Path(__file__).resolve().parents[4]
|
|
||||||
RESEARCH = Path(__file__).resolve().parent
|
|
||||||
CAPTURES = RESEARCH / "captures/L129-mouth"
|
|
||||||
SAVED = ROOT / "Saved/Linux/l129/captures/mouth-closeups"
|
|
||||||
BASE_LAYOUT = ROOT / "Saved/Linux/l125/hashes/owner4-surface-world-w12-clang.layout.json"
|
|
||||||
AFTER_LAYOUT = ROOT / "Saved/Linux/l129/hashes/owner4-surface-world-w12-clang.layout.json"
|
|
||||||
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 verified 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 = {
|
|
||||||
"before": ROOT / "Saved/Linux/l125/bin/VoxelForgeCoreHeadless-l125-clang",
|
|
||||||
"after": ROOT / "Saved/Linux/l129/bin/VoxelForgeCoreHeadless-l129-clang",
|
|
||||||
}
|
|
||||||
HELPERS.RENDERERS = {
|
|
||||||
"before": ROOT / "Saved/Linux/l125/bin/VoxelForgeOffscreenCapture-l125-clang",
|
|
||||||
"after": ROOT / "Saved/Linux/l129/bin/VoxelForgeOffscreenCapture-l129-clang",
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def main() -> int:
|
|
||||||
required = [BASE_LAYOUT, AFTER_LAYOUT, *HELPERS.BINARIES.values(),
|
|
||||||
*HELPERS.RENDERERS.values()]
|
|
||||||
if any(not path.is_file() for path in required):
|
|
||||||
raise SystemExit("missing baseline/candidate layout or capture binary")
|
|
||||||
before_layout = json.loads(BASE_LAYOUT.read_text(encoding="utf-8"))
|
|
||||||
after_layout = json.loads(AFTER_LAYOUT.read_text(encoding="utf-8"))
|
|
||||||
if before_layout["passages"] != after_layout["passages"]:
|
|
||||||
raise RuntimeError("baseline and candidate passage routes differ")
|
|
||||||
|
|
||||||
views = [view for view in HELPERS.make_views(before_layout, [],
|
|
||||||
use_derived_shape=True, use_spline=True, include_open_air=False)
|
|
||||||
if view["kind"] == "mouth"]
|
|
||||||
if len(views) != 2 * len(before_layout["passages"]):
|
|
||||||
raise RuntimeError("unexpected mouth camera count")
|
|
||||||
|
|
||||||
rows = []
|
|
||||||
CAPTURES.mkdir(parents=True, exist_ok=True)
|
|
||||||
SAVED.mkdir(parents=True, exist_ok=True)
|
|
||||||
for view in views:
|
|
||||||
for variant, layout in (("before", before_layout), ("after", after_layout)):
|
|
||||||
row = HELPERS.capture(variant, view, layout)
|
|
||||||
row["variant"] = "L125-v225" if variant == "before" else "L129-v226"
|
|
||||||
row["view"] = view["name"]
|
|
||||||
image = ROOT / "Standalone/Research/WorldAssemblerM3/Linux129" / row["capture"]
|
|
||||||
row["image_sha256"] = hashlib.sha256(image.read_bytes()).hexdigest()
|
|
||||||
rows.append(row)
|
|
||||||
|
|
||||||
index = CAPTURES / "capture-index.json"
|
|
||||||
index.write_text(json.dumps({"captures": rows}, indent=2) + "\n", encoding="utf-8")
|
|
||||||
old_rows = {row["view"]: row for row in rows if row["variant"] == "L125-v225"}
|
|
||||||
new_rows = {row["view"]: row for row in rows if row["variant"] == "L129-v226"}
|
|
||||||
html = ["<!doctype html><meta charset='utf-8'>",
|
|
||||||
"<title>L125 / L129 mouth close-ups</title>",
|
|
||||||
"<style>body{font:14px system-ui;margin:24px;background:#17191d;color:#eee}"
|
|
||||||
"section{margin:28px 0}div{display:grid;grid-template-columns:1fr 1fr;gap:12px}"
|
|
||||||
"img{width:100%;height:auto}p{color:#bbb}</style>",
|
|
||||||
"<h1>L125 v225 / L129 v226 tunnel mouths</h1>"]
|
|
||||||
for name in old_rows:
|
|
||||||
old, new = old_rows[name], new_rows[name]
|
|
||||||
old_path = os.path.relpath(RESEARCH / old["capture"], CAPTURES)
|
|
||||||
new_path = os.path.relpath(RESEARCH / new["capture"], CAPTURES)
|
|
||||||
equality = "pixel-identical" if old["image_sha256"] == new["image_sha256"] else "pixels differ"
|
|
||||||
html.extend(["<section>", f"<h2>{old['passage']} — {old['station']}</h2>",
|
|
||||||
f"<p>{equality}; {old['pixel_quality_status']} / {new['pixel_quality_status']}</p>",
|
|
||||||
"<div>", f"<figure><figcaption>L125 v225</figcaption><img src='{old_path}'></figure>",
|
|
||||||
f"<figure><figcaption>L129 v226</figcaption><img src='{new_path}'></figure>",
|
|
||||||
"</div>", "</section>"])
|
|
||||||
(CAPTURES / "COMPARE.html").write_text("\n".join(html) + "\n", encoding="utf-8")
|
|
||||||
print(f"[L129MouthCaptures] views={len(views)} paired={len(rows)//2} "
|
|
||||||
f"index={index.relative_to(ROOT)}", flush=True)
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
raise SystemExit(main())
|
|
||||||
@@ -1,136 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
"""Five interleaved L80 readiness runs for L109, L125 and L129."""
|
|
||||||
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("L129_TIMING_DIR", "Saved/Linux/l129/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",
|
|
||||||
"L129": ROOT / os.environ.get("L129_CANDIDATE_BINARY",
|
|
||||||
"Saved/Linux/l129/bin/VoxelForgeCoreHeadless-l129-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("[L129TimingRun] " + 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/L129 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"[L129TimingGate] 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", "L129")
|
|
||||||
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"L129_vs_{comparison}_{key}_delta_pct"] = round(
|
|
||||||
100.0 * (medians["L129"][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())
|
|
||||||
@@ -1,257 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
"""Five 30 m/s UE runs for the L129 tunnel reach candidate."""
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
import argparse
|
|
||||||
import json
|
|
||||||
import math
|
|
||||||
import statistics
|
|
||||||
import subprocess
|
|
||||||
import time
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
ROOT = Path(__file__).resolve().parents[4]
|
|
||||||
HOST = Path("/home/jahni/VFHost")
|
|
||||||
EDITOR = Path("/home/jahni/UnrealEngine/Engine/Binaries/Linux/UnrealEditor-Cmd")
|
|
||||||
SPAWN_TN_M = (19.166015625, -14.2001953125, -753.3740234375)
|
|
||||||
SPAWN_FI_M = (25.8369140625, 3.19921875, -737.0)
|
|
||||||
|
|
||||||
|
|
||||||
def percentile(values: list[float], fraction: float) -> float | None:
|
|
||||||
if not values:
|
|
||||||
return None
|
|
||||||
ordered = sorted(values)
|
|
||||||
return ordered[max(0, min(len(ordered) - 1, math.ceil(len(ordered) * fraction) - 1))]
|
|
||||||
|
|
||||||
|
|
||||||
def read_events(path: Path) -> list[dict]:
|
|
||||||
rows = []
|
|
||||||
if path.is_file():
|
|
||||||
for line in path.read_text(encoding="utf-8", errors="replace").splitlines():
|
|
||||||
if not line.startswith("{"):
|
|
||||||
continue
|
|
||||||
try:
|
|
||||||
rows.append(json.loads(line))
|
|
||||||
except json.JSONDecodeError:
|
|
||||||
pass
|
|
||||||
return rows
|
|
||||||
|
|
||||||
|
|
||||||
def run(scenario: str, condition: str, repetition: int, turn: bool = False) -> dict:
|
|
||||||
lookahead = int(condition in ("lookahead", "turn_lookahead"))
|
|
||||||
if scenario == "movement":
|
|
||||||
speed, start, duration, exit_s, slot, spawn = (
|
|
||||||
3000.0, 6.0, 12.0, 23.0, 0, SPAWN_TN_M)
|
|
||||||
else:
|
|
||||||
speed, start, duration, exit_s, slot, spawn = (
|
|
||||||
140.0, 20.0, 12.0, 37.0, 1, SPAWN_FI_M)
|
|
||||||
|
|
||||||
label = f"{scenario}-{condition}-r{repetition}"
|
|
||||||
output_group = "turn" if turn else scenario
|
|
||||||
out = ROOT / "Saved/Linux/l129" / output_group / condition / "unreal"
|
|
||||||
host_out = HOST / "Plugins/VoxelForge/Saved/Linux/l129" / output_group / condition
|
|
||||||
host_saved = HOST / "Saved/Linux/l129"
|
|
||||||
trace = out / f"{label}.trace.jsonl"
|
|
||||||
abslog = out / f"{label}.log"
|
|
||||||
stdout = out / f"{label}.stdout.log"
|
|
||||||
export = host_out / "output" / label
|
|
||||||
userdir = host_saved / "user" / label
|
|
||||||
zendata = host_saved / "zen" / label
|
|
||||||
ddc = host_saved / "DDC"
|
|
||||||
for path in (out, export, userdir, zendata, ddc):
|
|
||||||
path.mkdir(parents=True, exist_ok=True)
|
|
||||||
trace.unlink(missing_ok=True)
|
|
||||||
spawn_cm = ",".join(f"{value * 100.0:.3f}" for value in spawn)
|
|
||||||
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={slot}", "-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={export}", "-voxel.StreamingCoarseFirst=1",
|
|
||||||
"-voxel.StreamingDynamicNearReserve=1", "-voxel.StreamingLegacyPendingResultCap=0",
|
|
||||||
"-voxel.CoreRegionConcurrentAdmission=1", "-voxel.StreamingResultBacklogCap=256",
|
|
||||||
"-voxel.StreamingReadyQueueDepth=8", "-voxel.StreamingBackgroundWorkerCap=1",
|
|
||||||
"-voxel.CoreColumnCacheDirectMapped=0", "-voxel.StreamingFarApplySupplement=1",
|
|
||||||
"-voxel.CoreMCGradientMemoization=1", "-voxel.StreamingCollisionLookahead=1",
|
|
||||||
f"-voxel.CoreRegionLookahead={lookahead}", "-voxel.TestMove=1",
|
|
||||||
f"-voxel.TestMoveSpeedCmPerSecond={speed:.1f}",
|
|
||||||
f"-voxel.TestMoveStartSeconds={start:.1f}",
|
|
||||||
f"-voxel.TestMoveDurationSeconds={duration:.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 turn:
|
|
||||||
command.extend(["-voxel.TestMoveTurnAfterSeconds=6.0",
|
|
||||||
"-voxel.TestMoveTurnDirection=0,1,0"])
|
|
||||||
started = time.monotonic()
|
|
||||||
wrapped = ["taskset", "-c", "0-11", "timeout", "1740s", *command]
|
|
||||||
with stdout.open("w", encoding="utf-8") as stream:
|
|
||||||
process = subprocess.run(wrapped, cwd=ROOT, stdout=stream,
|
|
||||||
stderr=subprocess.STDOUT, check=False, timeout=1740)
|
|
||||||
events = read_events(trace)
|
|
||||||
samples = [event for event in events if event.get("type") == "streaming_sample"]
|
|
||||||
moving = [event for event in samples if float(event.get("speed_cm_s", 0.0)) >= 50.0]
|
|
||||||
stop_event = next((event for event in events
|
|
||||||
if event.get("type") == "streaming_test_move_stopped"), {})
|
|
||||||
stop_s = float(stop_event.get("t_s", 0.0))
|
|
||||||
move_start = min((float(event.get("t_s", 0.0)) for event in moving), default=float("inf"))
|
|
||||||
dwell = [event for event in samples if float(event.get("t_s", 0.0)) >= stop_s
|
|
||||||
and float(event.get("speed_cm_s", 0.0)) < 50.0]
|
|
||||||
backend = next((event for event in events if event.get("type") == "worker_backend_config"), {})
|
|
||||||
cap = next((event for event in events if event.get("type") == "streaming_worker_cap_readback"), {})
|
|
||||||
if process.returncode or len(moving) < 40 or len(dwell) < 16:
|
|
||||||
raise RuntimeError(f"incomplete UE run {label}: exit={process.returncode}, "
|
|
||||||
f"move={len(moving)}, dwell={len(dwell)}, trace={trace}")
|
|
||||||
if (int(backend.get("streaming_far_apply_supplement", -1)) != 1
|
|
||||||
or int(cap.get("streaming_background_worker_cap", -1)) != 1
|
|
||||||
or int(backend.get("effective_tile_slots", -1)) != 8):
|
|
||||||
raise RuntimeError(f"configuration readback mismatch: {backend}; {cap}")
|
|
||||||
|
|
||||||
moving_rows = []
|
|
||||||
for event in moving:
|
|
||||||
desired = event.get("desired_by_lod", [0] * 9)
|
|
||||||
resident = event.get("resident_by_lod", [0] * 9)
|
|
||||||
covered = event.get("covered_by_lod", resident)
|
|
||||||
moving_rows.append({
|
|
||||||
"near_ready_pct": 100.0 * sum(resident[:3]) / max(1, sum(desired[:3])),
|
|
||||||
"lod0_ready_pct": 100.0 * resident[0] / max(1, desired[0]),
|
|
||||||
"lod1_ready_pct": 100.0 * resident[1] / max(1, desired[1]),
|
|
||||||
"lod2_ready_pct": 100.0 * resident[2] / max(1, desired[2]),
|
|
||||||
"far_hole_pct": 100.0 * (sum(desired[3:]) - sum(covered[3:]))
|
|
||||||
/ max(1, sum(desired[3:])),
|
|
||||||
})
|
|
||||||
work = [event for event in events if event.get("type") == "game_thread_work_frame"
|
|
||||||
and move_start <= float(event.get("t_s", 0.0)) < stop_s]
|
|
||||||
ticks = [float(event.get("tick_ms", 0.0)) for event in work]
|
|
||||||
updates = [float(event.get("update_chunks_ms", 0.0)) for event in work]
|
|
||||||
arrival = [event for event in samples if float(event.get("t_s", 0.0)) < start
|
|
||||||
and float(event.get("speed_cm_s", 0.0)) < 50.0]
|
|
||||||
|
|
||||||
def settled(event: dict, end: int) -> bool:
|
|
||||||
desired = event.get("desired_by_lod", [0] * 9)
|
|
||||||
actual = event.get("settled_by_lod", [0] * 9)
|
|
||||||
return sum(desired[:end]) > 0 and sum(actual[:end]) >= sum(desired[:end])
|
|
||||||
|
|
||||||
def far_holes(event: dict) -> float | None:
|
|
||||||
desired = event.get("desired_by_lod", [0] * 9)[3:]
|
|
||||||
covered = event.get("covered_by_lod", [0] * 9)[3:]
|
|
||||||
return 100.0 * (sum(desired) - sum(covered)) / sum(desired) if sum(desired) else None
|
|
||||||
|
|
||||||
near_settled = next((event for event in arrival if settled(event, 3)), None)
|
|
||||||
whole_settled = next((event for event in arrival if settled(event, 9)), None)
|
|
||||||
far_clear = next((event for event in arrival if far_holes(event) == 0.0), None)
|
|
||||||
compile_done = [event for event in events if event.get("type") == "core_region_compile_complete"
|
|
||||||
and move_start <= float(event.get("t_s", 0.0)) < stop_s]
|
|
||||||
compile_requests = [event for event in events
|
|
||||||
if event.get("type") == "core_region_compile_request"
|
|
||||||
and move_start <= float(event.get("t_s", 0.0)) < stop_s]
|
|
||||||
lookahead_turns = [event for event in events
|
|
||||||
if event.get("type") == "core_region_lookahead_turn"]
|
|
||||||
row = {
|
|
||||||
"scenario": scenario, "condition": condition, "repetition": repetition,
|
|
||||||
"speed_mps": speed / 100.0, "core_region_lookahead": lookahead,
|
|
||||||
"exit_code": process.returncode, "wall_s": round(time.monotonic() - started, 3),
|
|
||||||
"moving_samples": len(moving), "dwell_samples": len(dwell),
|
|
||||||
"near_ready_moving_mean_pct": statistics.mean(r["near_ready_pct"] for r in moving_rows),
|
|
||||||
"lod0_ready_moving_mean_pct": statistics.mean(r["lod0_ready_pct"] for r in moving_rows),
|
|
||||||
"lod1_ready_moving_mean_pct": statistics.mean(r["lod1_ready_pct"] for r in moving_rows),
|
|
||||||
"lod2_ready_moving_mean_pct": statistics.mean(r["lod2_ready_pct"] for r in moving_rows),
|
|
||||||
"far_holes_moving_mean_pct": statistics.mean(r["far_hole_pct"] for r in moving_rows),
|
|
||||||
"game_thread_tick_p99_ms": percentile(ticks, 0.99),
|
|
||||||
"game_thread_tick_max_ms": max(ticks, default=None),
|
|
||||||
"stream_update_p99_ms": percentile(updates, 0.99),
|
|
||||||
"stream_update_max_ms": max(updates, default=None),
|
|
||||||
"lod02_settled_t_s": float(near_settled["t_s"]) if near_settled else None,
|
|
||||||
"whole_view_settled_t_s": float(whole_settled["t_s"]) if whole_settled else None,
|
|
||||||
"far_clear_t_s": float(far_clear["t_s"]) if far_clear else None,
|
|
||||||
"far_holes_at_pre_move_pct": far_holes(arrival[-1]) if arrival else None,
|
|
||||||
"pending_gate_p50_ms": percentile(
|
|
||||||
[float(e.get("pending_gate_elapsed_ms", 0.0)) for e in compile_done], 0.50),
|
|
||||||
"compile_queue_p95_ms": percentile(
|
|
||||||
[float(e.get("compile_queue_ms", 0.0)) for e in compile_done], 0.95),
|
|
||||||
"compile_task_p95_ms": percentile(
|
|
||||||
[float(e.get("compile_task_ms", 0.0)) for e in compile_done], 0.95),
|
|
||||||
"compiled_tiles_total": sum(int(e.get("compiled_tiles", 0)) for e in compile_done),
|
|
||||||
"lookahead_tiles_peak": max((int(e.get("lookahead_region_tiles", 0))
|
|
||||||
for e in compile_requests), default=0),
|
|
||||||
"wasted_prefetch_tiles": sum(int(e.get("wasted_prefetch_tiles", 0))
|
|
||||||
for e in compile_done),
|
|
||||||
"lookahead_turn_events": lookahead_turns,
|
|
||||||
"compile_completion_count": len(compile_done),
|
|
||||||
"trace": str(trace.relative_to(ROOT)), "log": str(abslog.relative_to(ROOT)),
|
|
||||||
}
|
|
||||||
with (ROOT / "Saved/Linux/l129" / "runs.jsonl").open("a", encoding="utf-8") as stream:
|
|
||||||
stream.write(json.dumps(row, sort_keys=True) + "\n")
|
|
||||||
print("[L129Pair] " + json.dumps(row, sort_keys=True), flush=True)
|
|
||||||
return row
|
|
||||||
|
|
||||||
|
|
||||||
def pairs_for(runs: list[dict], scenario: str) -> list[dict]:
|
|
||||||
pairs = []
|
|
||||||
for repetition in range(1, 6):
|
|
||||||
baseline = next(row for row in runs if row["scenario"] == scenario
|
|
||||||
and row["condition"] == "baseline" and row["repetition"] == repetition)
|
|
||||||
candidate = next(row for row in runs if row["scenario"] == scenario
|
|
||||||
and row["condition"] == "lookahead" and row["repetition"] == repetition)
|
|
||||||
pairs.append({"repetition": repetition,
|
|
||||||
"near_ready_delta_pct": candidate["near_ready_moving_mean_pct"]
|
|
||||||
- baseline["near_ready_moving_mean_pct"],
|
|
||||||
"far_holes_delta_pct": candidate["far_holes_moving_mean_pct"]
|
|
||||||
- baseline["far_holes_moving_mean_pct"],
|
|
||||||
"tick_p99_delta_ms": candidate["game_thread_tick_p99_ms"]
|
|
||||||
- baseline["game_thread_tick_p99_ms"],
|
|
||||||
"tick_max_delta_ms": candidate["game_thread_tick_max_ms"]
|
|
||||||
- baseline["game_thread_tick_max_ms"]})
|
|
||||||
return pairs
|
|
||||||
|
|
||||||
|
|
||||||
def main() -> int:
|
|
||||||
parser = argparse.ArgumentParser()
|
|
||||||
parser.add_argument("--scenario", choices=("movement",), default="movement")
|
|
||||||
args = parser.parse_args()
|
|
||||||
if not EDITOR.is_file():
|
|
||||||
raise SystemExit(f"missing Unreal editor: {EDITOR}")
|
|
||||||
root_out = ROOT / "Saved/Linux/l129" / args.scenario
|
|
||||||
root_out.mkdir(parents=True, exist_ok=True)
|
|
||||||
(ROOT / "Saved/Linux/l129").mkdir(parents=True, exist_ok=True)
|
|
||||||
runs = []
|
|
||||||
for repetition in range(1, 6):
|
|
||||||
runs.append(run(args.scenario, "candidate", repetition))
|
|
||||||
(root_out / "runs-partial.json").write_text(
|
|
||||||
json.dumps(runs, indent=2) + "\n", encoding="utf-8")
|
|
||||||
baseline_path = ROOT / "Saved/Linux/l127/ue/movement-pairs-summary.json"
|
|
||||||
baseline = json.loads(baseline_path.read_text(encoding="utf-8"))["summary"]["merge"]["metrics"]
|
|
||||||
metric_names = ("near_ready_moving_mean_pct", "far_holes_moving_mean_pct",
|
|
||||||
"game_thread_tick_p99_ms", "game_thread_tick_max_ms")
|
|
||||||
candidate = {name: statistics.median(row[name] for row in runs) for name in metric_names}
|
|
||||||
reference = {name: baseline[name]["median"] for name in metric_names}
|
|
||||||
deltas = {name: candidate[name] - reference[name] for name in metric_names}
|
|
||||||
bar_pass = (candidate["near_ready_moving_mean_pct"] > reference["near_ready_moving_mean_pct"]
|
|
||||||
and candidate["far_holes_moving_mean_pct"] <= reference["far_holes_moving_mean_pct"]
|
|
||||||
and candidate["game_thread_tick_p99_ms"] <= reference["game_thread_tick_p99_ms"]
|
|
||||||
and candidate["game_thread_tick_max_ms"] <= reference["game_thread_tick_max_ms"])
|
|
||||||
summary = {
|
|
||||||
"design": "L129 R=2.0 m passage influence; five runs at 30 m/s.",
|
|
||||||
"scenario": args.scenario, "runs": runs,
|
|
||||||
"baseline": {"commit": "b96dd73", "source_summary": str(baseline_path),
|
|
||||||
"metrics": reference},
|
|
||||||
"candidate_medians": candidate, "deltas": deltas,
|
|
||||||
"bar_pass": bar_pass,
|
|
||||||
}
|
|
||||||
(root_out / "summary.json").write_text(json.dumps(summary, indent=2) + "\n",
|
|
||||||
encoding="utf-8")
|
|
||||||
print("[L129MovementSummary] " + json.dumps(summary, sort_keys=True), flush=True)
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
raise SystemExit(main())
|
|
||||||
@@ -1,188 +0,0 @@
|
|||||||
<!doctype html><meta charset='utf-8'>
|
|
||||||
<title>L125 / L129 tunnel capture comparison</title>
|
|
||||||
<style>body{font:14px system-ui;margin:24px;background:#17191d;color:#eee}section{margin:28px 0}h2{font-size:18px}div{display:grid;grid-template-columns:1fr 1fr;gap:12px}img{width:100%;height:auto}p{color:#bbb}</style>
|
|
||||||
<h1>L125 / L129 v226: identical views</h1>
|
|
||||||
<section>
|
|
||||||
<h2>passage/0-1/0 — rock-floor/401.7m</h2>
|
|
||||||
<p>rock-floor-close · L125 pass · L129 pass</p>
|
|
||||||
<div>
|
|
||||||
<figure><figcaption>L125</figcaption><img src='../../Linux125/captures/L125/passage-0-1-0-rock-floor-station-1.png'></figure>
|
|
||||||
<figure><figcaption>L129 v226</figcaption><img src='L129/passage-0-1-0-rock-floor-station-1.png'></figure>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<h2>passage/0-1/0 — rock-floor/792.8m</h2>
|
|
||||||
<p>rock-floor-close · L125 pass · L129 pass</p>
|
|
||||||
<div>
|
|
||||||
<figure><figcaption>L125</figcaption><img src='../../Linux125/captures/L125/passage-0-1-0-rock-floor-station-2.png'></figure>
|
|
||||||
<figure><figcaption>L129 v226</figcaption><img src='L129/passage-0-1-0-rock-floor-station-2.png'></figure>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<h2>passage/0-1/0 — rock-floor/1634.5m</h2>
|
|
||||||
<p>rock-floor-close · L125 pass · L129 pass</p>
|
|
||||||
<div>
|
|
||||||
<figure><figcaption>L125</figcaption><img src='../../Linux125/captures/L125/passage-0-1-0-rock-floor-station-3.png'></figure>
|
|
||||||
<figure><figcaption>L129 v226</figcaption><img src='L129/passage-0-1-0-rock-floor-station-3.png'></figure>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<h2>passage/1-2/0 — rock-floor/27.0m</h2>
|
|
||||||
<p>rock-floor-close · L125 pass · L129 pass</p>
|
|
||||||
<div>
|
|
||||||
<figure><figcaption>L125</figcaption><img src='../../Linux125/captures/L125/passage-1-2-0-rock-floor-station-1.png'></figure>
|
|
||||||
<figure><figcaption>L129 v226</figcaption><img src='L129/passage-1-2-0-rock-floor-station-1.png'></figure>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<h2>passage/1-2/0 — rock-floor/52.9m</h2>
|
|
||||||
<p>rock-floor-close · L125 pass · L129 pass</p>
|
|
||||||
<div>
|
|
||||||
<figure><figcaption>L125</figcaption><img src='../../Linux125/captures/L125/passage-1-2-0-rock-floor-station-2.png'></figure>
|
|
||||||
<figure><figcaption>L129 v226</figcaption><img src='L129/passage-1-2-0-rock-floor-station-2.png'></figure>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<h2>passage/1-2/0 — rock-floor/78.9m</h2>
|
|
||||||
<p>rock-floor-close · L125 pass · L129 pass</p>
|
|
||||||
<div>
|
|
||||||
<figure><figcaption>L125</figcaption><img src='../../Linux125/captures/L125/passage-1-2-0-rock-floor-station-3.png'></figure>
|
|
||||||
<figure><figcaption>L129 v226</figcaption><img src='L129/passage-1-2-0-rock-floor-station-3.png'></figure>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<h2>passage/2-3/0 — rock-floor/323.4m</h2>
|
|
||||||
<p>rock-floor-close · L125 low_contrast_geometry_visible · L129 low_contrast_geometry_visible</p>
|
|
||||||
<div>
|
|
||||||
<figure><figcaption>L125</figcaption><img src='../../Linux125/captures/L125/passage-2-3-0-rock-floor-station-1.png'></figure>
|
|
||||||
<figure><figcaption>L129 v226</figcaption><img src='L129/passage-2-3-0-rock-floor-station-1.png'></figure>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<h2>passage/2-3/0 — rock-floor/333.4m</h2>
|
|
||||||
<p>rock-floor-close · L125 pass · L129 pass</p>
|
|
||||||
<div>
|
|
||||||
<figure><figcaption>L125</figcaption><img src='../../Linux125/captures/L125/passage-2-3-0-rock-floor-station-2.png'></figure>
|
|
||||||
<figure><figcaption>L129 v226</figcaption><img src='L129/passage-2-3-0-rock-floor-station-2.png'></figure>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<h2>passage/2-3/0 — rock-floor/343.4m</h2>
|
|
||||||
<p>rock-floor-close · L125 pass · L129 pass</p>
|
|
||||||
<div>
|
|
||||||
<figure><figcaption>L125</figcaption><img src='../../Linux125/captures/L125/passage-2-3-0-rock-floor-station-3.png'></figure>
|
|
||||||
<figure><figcaption>L129 v226</figcaption><img src='L129/passage-2-3-0-rock-floor-station-3.png'></figure>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<h2>passage/0-1/0 — section-1/4m-outside</h2>
|
|
||||||
<p>open-air-close · L125 pass · L129 pass</p>
|
|
||||||
<div>
|
|
||||||
<figure><figcaption>L125</figcaption><img src='../../Linux125/captures/L125/passage-0-1-0-openair-1-4m-outside.png'></figure>
|
|
||||||
<figure><figcaption>L129 v226</figcaption><img src='L129/passage-0-1-0-openair-1-4m-outside.png'></figure>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<h2>passage/0-1/0 — section-1/4m-interior-wall</h2>
|
|
||||||
<p>open-air-close · L125 low_contrast_geometry_visible · L129 low_contrast_geometry_visible</p>
|
|
||||||
<div>
|
|
||||||
<figure><figcaption>L125</figcaption><img src='../../Linux125/captures/L125/passage-0-1-0-openair-1-4m-interior-wall.png'></figure>
|
|
||||||
<figure><figcaption>L129 v226</figcaption><img src='L129/passage-0-1-0-openair-1-4m-interior-wall.png'></figure>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<h2>passage/0-1/0 — section-2/4m-outside</h2>
|
|
||||||
<p>open-air-close · L125 pass · L129 pass</p>
|
|
||||||
<div>
|
|
||||||
<figure><figcaption>L125</figcaption><img src='../../Linux125/captures/L125/passage-0-1-0-openair-2-4m-outside.png'></figure>
|
|
||||||
<figure><figcaption>L129 v226</figcaption><img src='L129/passage-0-1-0-openair-2-4m-outside.png'></figure>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<h2>passage/0-1/0 — section-2/4m-interior-wall</h2>
|
|
||||||
<p>open-air-close · L125 pass · L129 pass</p>
|
|
||||||
<div>
|
|
||||||
<figure><figcaption>L125</figcaption><img src='../../Linux125/captures/L125/passage-0-1-0-openair-2-4m-interior-wall.png'></figure>
|
|
||||||
<figure><figcaption>L129 v226</figcaption><img src='L129/passage-0-1-0-openair-2-4m-interior-wall.png'></figure>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<h2>passage/0-1/0 — section-3/4m-outside</h2>
|
|
||||||
<p>open-air-close · L125 pass · L129 pass</p>
|
|
||||||
<div>
|
|
||||||
<figure><figcaption>L125</figcaption><img src='../../Linux125/captures/L125/passage-0-1-0-openair-3-4m-outside.png'></figure>
|
|
||||||
<figure><figcaption>L129 v226</figcaption><img src='L129/passage-0-1-0-openair-3-4m-outside.png'></figure>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<h2>passage/0-1/0 — section-3/4m-interior-wall</h2>
|
|
||||||
<p>open-air-close · L125 pass · L129 pass</p>
|
|
||||||
<div>
|
|
||||||
<figure><figcaption>L125</figcaption><img src='../../Linux125/captures/L125/passage-0-1-0-openair-3-4m-interior-wall.png'></figure>
|
|
||||||
<figure><figcaption>L129 v226</figcaption><img src='L129/passage-0-1-0-openair-3-4m-interior-wall.png'></figure>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<h2>passage/1-2/0 — section-1/4m-outside</h2>
|
|
||||||
<p>open-air-close · L125 pass · L129 pass</p>
|
|
||||||
<div>
|
|
||||||
<figure><figcaption>L125</figcaption><img src='../../Linux125/captures/L125/passage-1-2-0-openair-1-4m-outside.png'></figure>
|
|
||||||
<figure><figcaption>L129 v226</figcaption><img src='L129/passage-1-2-0-openair-1-4m-outside.png'></figure>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<h2>passage/1-2/0 — section-1/4m-interior-wall</h2>
|
|
||||||
<p>open-air-close · L125 pass · L129 pass</p>
|
|
||||||
<div>
|
|
||||||
<figure><figcaption>L125</figcaption><img src='../../Linux125/captures/L125/passage-1-2-0-openair-1-4m-interior-wall.png'></figure>
|
|
||||||
<figure><figcaption>L129 v226</figcaption><img src='L129/passage-1-2-0-openair-1-4m-interior-wall.png'></figure>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<h2>passage/1-2/0 — section-2/4m-outside</h2>
|
|
||||||
<p>open-air-close · L125 pass · L129 pass</p>
|
|
||||||
<div>
|
|
||||||
<figure><figcaption>L125</figcaption><img src='../../Linux125/captures/L125/passage-1-2-0-openair-2-4m-outside.png'></figure>
|
|
||||||
<figure><figcaption>L129 v226</figcaption><img src='L129/passage-1-2-0-openair-2-4m-outside.png'></figure>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<h2>passage/1-2/0 — section-2/4m-interior-wall</h2>
|
|
||||||
<p>open-air-close · L125 pass · L129 pass</p>
|
|
||||||
<div>
|
|
||||||
<figure><figcaption>L125</figcaption><img src='../../Linux125/captures/L125/passage-1-2-0-openair-2-4m-interior-wall.png'></figure>
|
|
||||||
<figure><figcaption>L129 v226</figcaption><img src='L129/passage-1-2-0-openair-2-4m-interior-wall.png'></figure>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<h2>passage/2-3/0 — section-1/4m-outside</h2>
|
|
||||||
<p>open-air-close · L125 low_contrast_geometry_visible · L129 low_contrast_geometry_visible</p>
|
|
||||||
<div>
|
|
||||||
<figure><figcaption>L125</figcaption><img src='../../Linux125/captures/L125/passage-2-3-0-openair-1-4m-outside.png'></figure>
|
|
||||||
<figure><figcaption>L129 v226</figcaption><img src='L129/passage-2-3-0-openair-1-4m-outside.png'></figure>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<h2>passage/2-3/0 — section-1/4m-interior-wall</h2>
|
|
||||||
<p>open-air-close · L125 low_contrast_geometry_visible · L129 low_contrast_geometry_visible</p>
|
|
||||||
<div>
|
|
||||||
<figure><figcaption>L125</figcaption><img src='../../Linux125/captures/L125/passage-2-3-0-openair-1-4m-interior-wall.png'></figure>
|
|
||||||
<figure><figcaption>L129 v226</figcaption><img src='L129/passage-2-3-0-openair-1-4m-interior-wall.png'></figure>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<h2>passage/2-3/0 — section-2/4m-outside</h2>
|
|
||||||
<p>open-air-close · L125 pass · L129 pass</p>
|
|
||||||
<div>
|
|
||||||
<figure><figcaption>L125</figcaption><img src='../../Linux125/captures/L125/passage-2-3-0-openair-2-4m-outside.png'></figure>
|
|
||||||
<figure><figcaption>L129 v226</figcaption><img src='L129/passage-2-3-0-openair-2-4m-outside.png'></figure>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<h2>passage/2-3/0 — section-2/4m-interior-wall</h2>
|
|
||||||
<p>open-air-close · L125 pass · L129 pass</p>
|
|
||||||
<div>
|
|
||||||
<figure><figcaption>L125</figcaption><img src='../../Linux125/captures/L125/passage-2-3-0-openair-2-4m-interior-wall.png'></figure>
|
|
||||||
<figure><figcaption>L129 v226</figcaption><img src='L129/passage-2-3-0-openair-2-4m-interior-wall.png'></figure>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
<!doctype html><meta charset='utf-8'>
|
|
||||||
<title>L125 / L129 mouth close-ups</title>
|
|
||||||
<style>body{font:14px system-ui;margin:24px;background:#17191d;color:#eee}section{margin:28px 0}div{display:grid;grid-template-columns:1fr 1fr;gap:12px}img{width:100%;height:auto}p{color:#bbb}</style>
|
|
||||||
<h1>L125 v225 / L129 v226 tunnel mouths</h1>
|
|
||||||
<section>
|
|
||||||
<h2>passage/0-1/0 — upper-mouth</h2>
|
|
||||||
<p>pixel-identical; pass / pass</p>
|
|
||||||
<div>
|
|
||||||
<figure><figcaption>L125 v225</figcaption><img src='before/passage-0-1-0-upper-mouth.png'></figure>
|
|
||||||
<figure><figcaption>L129 v226</figcaption><img src='after/passage-0-1-0-upper-mouth.png'></figure>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<h2>passage/0-1/0 — lower-mouth</h2>
|
|
||||||
<p>pixel-identical; pass / pass</p>
|
|
||||||
<div>
|
|
||||||
<figure><figcaption>L125 v225</figcaption><img src='before/passage-0-1-0-lower-mouth.png'></figure>
|
|
||||||
<figure><figcaption>L129 v226</figcaption><img src='after/passage-0-1-0-lower-mouth.png'></figure>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<h2>passage/1-2/0 — upper-mouth</h2>
|
|
||||||
<p>pixel-identical; pass / pass</p>
|
|
||||||
<div>
|
|
||||||
<figure><figcaption>L125 v225</figcaption><img src='before/passage-1-2-0-upper-mouth.png'></figure>
|
|
||||||
<figure><figcaption>L129 v226</figcaption><img src='after/passage-1-2-0-upper-mouth.png'></figure>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<h2>passage/1-2/0 — lower-mouth</h2>
|
|
||||||
<p>pixel-identical; pass / pass</p>
|
|
||||||
<div>
|
|
||||||
<figure><figcaption>L125 v225</figcaption><img src='before/passage-1-2-0-lower-mouth.png'></figure>
|
|
||||||
<figure><figcaption>L129 v226</figcaption><img src='after/passage-1-2-0-lower-mouth.png'></figure>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<h2>passage/2-3/0 — upper-mouth</h2>
|
|
||||||
<p>pixel-identical; pass / pass</p>
|
|
||||||
<div>
|
|
||||||
<figure><figcaption>L125 v225</figcaption><img src='before/passage-2-3-0-upper-mouth.png'></figure>
|
|
||||||
<figure><figcaption>L129 v226</figcaption><img src='after/passage-2-3-0-upper-mouth.png'></figure>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<h2>passage/2-3/0 — lower-mouth</h2>
|
|
||||||
<p>pixel-identical; low_contrast_geometry_visible / low_contrast_geometry_visible</p>
|
|
||||||
<div>
|
|
||||||
<figure><figcaption>L125 v225</figcaption><img src='before/passage-2-3-0-lower-mouth.png'></figure>
|
|
||||||
<figure><figcaption>L129 v226</figcaption><img src='after/passage-2-3-0-lower-mouth.png'></figure>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
Before Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 225 KiB |
|
Before Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 187 KiB |
|
Before Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 225 KiB |
|
Before Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 187 KiB |
|
Before Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 44 KiB |
@@ -1,676 +0,0 @@
|
|||||||
{
|
|
||||||
"captures": [
|
|
||||||
{
|
|
||||||
"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": "L125-v225",
|
|
||||||
"capture": "captures/L129-mouth/before/passage-0-1-0-upper-mouth.png",
|
|
||||||
"scene": "Saved/Linux/l129/captures/mouth-closeups/before/passage-0-1-0-upper-mouth.vfmesh",
|
|
||||||
"drawn_triangles": 243380,
|
|
||||||
"source_triangles": 287904,
|
|
||||||
"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/l129/captures/mouth-closeups/before/passage-0-1-0-upper-mouth-mesh.log",
|
|
||||||
"Saved/Linux/l129/captures/mouth-closeups/before/passage-0-1-0-upper-mouth-render.log",
|
|
||||||
"Saved/Linux/l129/captures/mouth-closeups/before/passage-0-1-0-upper-mouth-quality.log"
|
|
||||||
],
|
|
||||||
"view": "passage-0-1-0-upper-mouth",
|
|
||||||
"image_sha256": "20a56bb0419cc9c0ccb6a3c3f6a79e7f1614d095a8b233ecc65dc836fee9eb3b"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"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": "L129-v226",
|
|
||||||
"capture": "captures/L129-mouth/after/passage-0-1-0-upper-mouth.png",
|
|
||||||
"scene": "Saved/Linux/l129/captures/mouth-closeups/after/passage-0-1-0-upper-mouth.vfmesh",
|
|
||||||
"drawn_triangles": 243380,
|
|
||||||
"source_triangles": 287904,
|
|
||||||
"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/l129/captures/mouth-closeups/after/passage-0-1-0-upper-mouth-mesh.log",
|
|
||||||
"Saved/Linux/l129/captures/mouth-closeups/after/passage-0-1-0-upper-mouth-render.log",
|
|
||||||
"Saved/Linux/l129/captures/mouth-closeups/after/passage-0-1-0-upper-mouth-quality.log"
|
|
||||||
],
|
|
||||||
"view": "passage-0-1-0-upper-mouth",
|
|
||||||
"image_sha256": "20a56bb0419cc9c0ccb6a3c3f6a79e7f1614d095a8b233ecc65dc836fee9eb3b"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"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": "L125-v225",
|
|
||||||
"capture": "captures/L129-mouth/before/passage-0-1-0-lower-mouth.png",
|
|
||||||
"scene": "Saved/Linux/l129/captures/mouth-closeups/before/passage-0-1-0-lower-mouth.vfmesh",
|
|
||||||
"drawn_triangles": 549170,
|
|
||||||
"source_triangles": 582732,
|
|
||||||
"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/l129/captures/mouth-closeups/before/passage-0-1-0-lower-mouth-mesh.log",
|
|
||||||
"Saved/Linux/l129/captures/mouth-closeups/before/passage-0-1-0-lower-mouth-render.log",
|
|
||||||
"Saved/Linux/l129/captures/mouth-closeups/before/passage-0-1-0-lower-mouth-quality.log"
|
|
||||||
],
|
|
||||||
"view": "passage-0-1-0-lower-mouth",
|
|
||||||
"image_sha256": "01e5f52b7c9080cb34ed9fb92b60360426ef21bc8934309542cd8736a116fc29"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"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": "L129-v226",
|
|
||||||
"capture": "captures/L129-mouth/after/passage-0-1-0-lower-mouth.png",
|
|
||||||
"scene": "Saved/Linux/l129/captures/mouth-closeups/after/passage-0-1-0-lower-mouth.vfmesh",
|
|
||||||
"drawn_triangles": 549170,
|
|
||||||
"source_triangles": 582732,
|
|
||||||
"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/l129/captures/mouth-closeups/after/passage-0-1-0-lower-mouth-mesh.log",
|
|
||||||
"Saved/Linux/l129/captures/mouth-closeups/after/passage-0-1-0-lower-mouth-render.log",
|
|
||||||
"Saved/Linux/l129/captures/mouth-closeups/after/passage-0-1-0-lower-mouth-quality.log"
|
|
||||||
],
|
|
||||||
"view": "passage-0-1-0-lower-mouth",
|
|
||||||
"image_sha256": "01e5f52b7c9080cb34ed9fb92b60360426ef21bc8934309542cd8736a116fc29"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"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": "L125-v225",
|
|
||||||
"capture": "captures/L129-mouth/before/passage-1-2-0-upper-mouth.png",
|
|
||||||
"scene": "Saved/Linux/l129/captures/mouth-closeups/before/passage-1-2-0-upper-mouth.vfmesh",
|
|
||||||
"drawn_triangles": 593026,
|
|
||||||
"source_triangles": 638590,
|
|
||||||
"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.39180762797774,
|
|
||||||
-15.509524798921928,
|
|
||||||
-731.7810546875
|
|
||||||
],
|
|
||||||
"target_actual_m": [
|
|
||||||
17.28788584589878,
|
|
||||||
-13.618271096312476,
|
|
||||||
-731.8810546875
|
|
||||||
],
|
|
||||||
"logs": [
|
|
||||||
"Saved/Linux/l129/captures/mouth-closeups/before/passage-1-2-0-upper-mouth-mesh.log",
|
|
||||||
"Saved/Linux/l129/captures/mouth-closeups/before/passage-1-2-0-upper-mouth-render.log",
|
|
||||||
"Saved/Linux/l129/captures/mouth-closeups/before/passage-1-2-0-upper-mouth-quality.log"
|
|
||||||
],
|
|
||||||
"view": "passage-1-2-0-upper-mouth",
|
|
||||||
"image_sha256": "8314a919e0c4b16390622371be96c89459ddef922c20711db281c55227e29de2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"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": "L129-v226",
|
|
||||||
"capture": "captures/L129-mouth/after/passage-1-2-0-upper-mouth.png",
|
|
||||||
"scene": "Saved/Linux/l129/captures/mouth-closeups/after/passage-1-2-0-upper-mouth.vfmesh",
|
|
||||||
"drawn_triangles": 593026,
|
|
||||||
"source_triangles": 638590,
|
|
||||||
"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.39180762797774,
|
|
||||||
-15.509524798921928,
|
|
||||||
-731.7810546875
|
|
||||||
],
|
|
||||||
"target_actual_m": [
|
|
||||||
17.28788584589878,
|
|
||||||
-13.618271096312476,
|
|
||||||
-731.8810546875
|
|
||||||
],
|
|
||||||
"logs": [
|
|
||||||
"Saved/Linux/l129/captures/mouth-closeups/after/passage-1-2-0-upper-mouth-mesh.log",
|
|
||||||
"Saved/Linux/l129/captures/mouth-closeups/after/passage-1-2-0-upper-mouth-render.log",
|
|
||||||
"Saved/Linux/l129/captures/mouth-closeups/after/passage-1-2-0-upper-mouth-quality.log"
|
|
||||||
],
|
|
||||||
"view": "passage-1-2-0-upper-mouth",
|
|
||||||
"image_sha256": "8314a919e0c4b16390622371be96c89459ddef922c20711db281c55227e29de2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"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": "L125-v225",
|
|
||||||
"capture": "captures/L129-mouth/before/passage-1-2-0-lower-mouth.png",
|
|
||||||
"scene": "Saved/Linux/l129/captures/mouth-closeups/before/passage-1-2-0-lower-mouth.vfmesh",
|
|
||||||
"drawn_triangles": 544808,
|
|
||||||
"source_triangles": 576830,
|
|
||||||
"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/l129/captures/mouth-closeups/before/passage-1-2-0-lower-mouth-mesh.log",
|
|
||||||
"Saved/Linux/l129/captures/mouth-closeups/before/passage-1-2-0-lower-mouth-render.log",
|
|
||||||
"Saved/Linux/l129/captures/mouth-closeups/before/passage-1-2-0-lower-mouth-quality.log"
|
|
||||||
],
|
|
||||||
"view": "passage-1-2-0-lower-mouth",
|
|
||||||
"image_sha256": "dc1e5b79bb9afa6e1aa66edac7e0d84e1161ece0147b1ea58e4e60b93dca399b"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"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": "L129-v226",
|
|
||||||
"capture": "captures/L129-mouth/after/passage-1-2-0-lower-mouth.png",
|
|
||||||
"scene": "Saved/Linux/l129/captures/mouth-closeups/after/passage-1-2-0-lower-mouth.vfmesh",
|
|
||||||
"drawn_triangles": 544808,
|
|
||||||
"source_triangles": 576830,
|
|
||||||
"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/l129/captures/mouth-closeups/after/passage-1-2-0-lower-mouth-mesh.log",
|
|
||||||
"Saved/Linux/l129/captures/mouth-closeups/after/passage-1-2-0-lower-mouth-render.log",
|
|
||||||
"Saved/Linux/l129/captures/mouth-closeups/after/passage-1-2-0-lower-mouth-quality.log"
|
|
||||||
],
|
|
||||||
"view": "passage-1-2-0-lower-mouth",
|
|
||||||
"image_sha256": "dc1e5b79bb9afa6e1aa66edac7e0d84e1161ece0147b1ea58e4e60b93dca399b"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"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": "L125-v225",
|
|
||||||
"capture": "captures/L129-mouth/before/passage-2-3-0-upper-mouth.png",
|
|
||||||
"scene": "Saved/Linux/l129/captures/mouth-closeups/before/passage-2-3-0-upper-mouth.vfmesh",
|
|
||||||
"drawn_triangles": 59554,
|
|
||||||
"source_triangles": 71494,
|
|
||||||
"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/l129/captures/mouth-closeups/before/passage-2-3-0-upper-mouth-mesh.log",
|
|
||||||
"Saved/Linux/l129/captures/mouth-closeups/before/passage-2-3-0-upper-mouth-render.log",
|
|
||||||
"Saved/Linux/l129/captures/mouth-closeups/before/passage-2-3-0-upper-mouth-quality.log"
|
|
||||||
],
|
|
||||||
"view": "passage-2-3-0-upper-mouth",
|
|
||||||
"image_sha256": "954c7be05d77c4ccf5d3a7a486cc7cd1e32f108120e02daac2bb2cf18ed2a325"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"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": "L129-v226",
|
|
||||||
"capture": "captures/L129-mouth/after/passage-2-3-0-upper-mouth.png",
|
|
||||||
"scene": "Saved/Linux/l129/captures/mouth-closeups/after/passage-2-3-0-upper-mouth.vfmesh",
|
|
||||||
"drawn_triangles": 59554,
|
|
||||||
"source_triangles": 71494,
|
|
||||||
"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/l129/captures/mouth-closeups/after/passage-2-3-0-upper-mouth-mesh.log",
|
|
||||||
"Saved/Linux/l129/captures/mouth-closeups/after/passage-2-3-0-upper-mouth-render.log",
|
|
||||||
"Saved/Linux/l129/captures/mouth-closeups/after/passage-2-3-0-upper-mouth-quality.log"
|
|
||||||
],
|
|
||||||
"view": "passage-2-3-0-upper-mouth",
|
|
||||||
"image_sha256": "954c7be05d77c4ccf5d3a7a486cc7cd1e32f108120e02daac2bb2cf18ed2a325"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"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": "L125-v225",
|
|
||||||
"capture": "captures/L129-mouth/before/passage-2-3-0-lower-mouth.png",
|
|
||||||
"scene": "Saved/Linux/l129/captures/mouth-closeups/before/passage-2-3-0-lower-mouth.vfmesh",
|
|
||||||
"drawn_triangles": 293832,
|
|
||||||
"source_triangles": 314658,
|
|
||||||
"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/l129/captures/mouth-closeups/before/passage-2-3-0-lower-mouth-mesh.log",
|
|
||||||
"Saved/Linux/l129/captures/mouth-closeups/before/passage-2-3-0-lower-mouth-render.log",
|
|
||||||
"Saved/Linux/l129/captures/mouth-closeups/before/passage-2-3-0-lower-mouth-quality.log"
|
|
||||||
],
|
|
||||||
"view": "passage-2-3-0-lower-mouth",
|
|
||||||
"image_sha256": "295bc7662d9b699212110c61e60c7bd19e99d13ebe94d41201fa93e109bf707e"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"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": "L129-v226",
|
|
||||||
"capture": "captures/L129-mouth/after/passage-2-3-0-lower-mouth.png",
|
|
||||||
"scene": "Saved/Linux/l129/captures/mouth-closeups/after/passage-2-3-0-lower-mouth.vfmesh",
|
|
||||||
"drawn_triangles": 293832,
|
|
||||||
"source_triangles": 314658,
|
|
||||||
"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/l129/captures/mouth-closeups/after/passage-2-3-0-lower-mouth-mesh.log",
|
|
||||||
"Saved/Linux/l129/captures/mouth-closeups/after/passage-2-3-0-lower-mouth-render.log",
|
|
||||||
"Saved/Linux/l129/captures/mouth-closeups/after/passage-2-3-0-lower-mouth-quality.log"
|
|
||||||
],
|
|
||||||
"view": "passage-2-3-0-lower-mouth",
|
|
||||||
"image_sha256": "295bc7662d9b699212110c61e60c7bd19e99d13ebe94d41201fa93e109bf707e"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,174 +0,0 @@
|
|||||||
diff --git a/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h b/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h
|
|
||||||
index dc4ca32..aac34ff 100644
|
|
||||||
--- a/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h
|
|
||||||
+++ b/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h
|
|
||||||
@@ -494,7 +494,8 @@ namespace VoxelForgeCore
|
|
||||||
// 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;
|
|
||||||
+ // Version 226 bounds smooth-passage influence in physical metres and narrows its reach.
|
|
||||||
+ inline constexpr std::uint32_t WorldAssemblyEvaluatorVersion = 226;
|
|
||||||
|
|
||||||
enum class FieldChannel : std::uint32_t
|
|
||||||
{
|
|
||||||
diff --git a/Standalone/Core/src/ShapeWorldInternal.h b/Standalone/Core/src/ShapeWorldInternal.h
|
|
||||||
index 517f375..dc258a1 100644
|
|
||||||
--- a/Standalone/Core/src/ShapeWorldInternal.h
|
|
||||||
+++ b/Standalone/Core/src/ShapeWorldInternal.h
|
|
||||||
@@ -72,11 +72,11 @@ static bool VF_IsL98PassagePrepareTraceEnabled()
|
|
||||||
return bEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static double VF_L93PassageCarveReachMetres()
|
|
||||||
+static double VF_L129PassageCarveReachMetres()
|
|
||||||
{
|
|
||||||
- // The generated world uses a fixed bounded tube influence. An explicit diagnostic
|
|
||||||
- // option can still select the legacy point-evaluation path for comparisons.
|
|
||||||
- return 4.0;
|
|
||||||
+ // Keep the sweep cutoff and its spatial bounds on one physical reach. Diagnostic
|
|
||||||
+ // comparisons can still select another bounded reach or the point-evaluation path.
|
|
||||||
+ return 2.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum class EPassageDensityQueryCaller : std::size_t
|
|
||||||
@@ -306,7 +306,7 @@ public:
|
|
||||||
profileStats_(profileStats),profileLod_(profileLod),
|
|
||||||
passageCarveReachMetres_(std::isfinite(passageCarveReachMetres)
|
|
||||||
&&passageCarveReachMetres>=0.0?passageCarveReachMetres
|
|
||||||
- :VF_L93PassageCarveReachMetres())
|
|
||||||
+ :VF_L129PassageCarveReachMetres())
|
|
||||||
{
|
|
||||||
mayContainResolvedBoundaryBand_=shape.ResolvedBoundaryBandsIntersectSubvoxelRange(
|
|
||||||
minimumSubvoxels_[2],maximumSubvoxels_[2]);
|
|
||||||
@@ -4813,11 +4813,14 @@ private:
|
|
||||||
constexpr double Q=static_cast<double>(VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel);
|
|
||||||
constexpr double PassageShellMetres=0.75;
|
|
||||||
constexpr double ReliefMetres=0.21;
|
|
||||||
- constexpr double SweepReachMetres=4.0;
|
|
||||||
+ const double SweepReachMetres=VF_L129PassageCarveReachMetres();
|
|
||||||
constexpr double CornerBlendMetres=0.50;
|
|
||||||
constexpr std::size_t CandidateFineSamplesPerSpan=5;
|
|
||||||
+ const double qPerMetre=Q*1000000.0/
|
|
||||||
+ std::max<std::uint32_t>(1,ResolvedLayout->coreVoxelSizeMicrometres);
|
|
||||||
const double requiredReach=std::max(SweepReachMetres+ReliefMetres
|
|
||||||
+CornerBlendMetres*0.25,PassageShellMetres+ReliefMetres);
|
|
||||||
+ const double requiredReachCoreVoxels=requiredReach*qPerMetre/Q;
|
|
||||||
for(std::size_t passageIndex=0;passageIndex<ResolvedLayout->passages.size();
|
|
||||||
++passageIndex)
|
|
||||||
{
|
|
||||||
@@ -4854,7 +4857,7 @@ private:
|
|
||||||
routeMinimum[axis]=std::min(routeMinimum[axis],localMinimum[axis]);
|
|
||||||
routeMaximum[axis]=std::max(routeMaximum[axis],localMaximum[axis]);
|
|
||||||
}
|
|
||||||
- const double localExtent=requiredReach
|
|
||||||
+ const double localExtent=requiredReachCoreVoxels
|
|
||||||
+std::max(prepared.radiusA,prepared.radiusB)/Q+0.01;
|
|
||||||
FPassageProofBound proof;
|
|
||||||
for(std::size_t axis=0;axis<3;++axis)
|
|
||||||
@@ -4872,7 +4875,8 @@ private:
|
|
||||||
std::ceil((localMaximum[axis]+localExtent)*Q));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
- const double routeExtent=maximumRadiusSubvoxels/Q+requiredReach+0.01;
|
|
||||||
+ const double routeExtent=maximumRadiusSubvoxels/Q
|
|
||||||
+ +requiredReachCoreVoxels+0.01;
|
|
||||||
const double tileExtent=routeExtent;
|
|
||||||
std::array<std::int64_t,3> featureMinimum{},featureMaximum{};
|
|
||||||
for(std::size_t axis=0;axis<3;++axis)
|
|
||||||
@@ -11442,7 +11446,7 @@ inline void FStandaloneShapeWorld::FScopedPassageTileQueries::prepareSweptTubeBa
|
|
||||||
const FIntVector& origin,std::int32_t step,std::int32_t cells,std::uint32_t seed)
|
|
||||||
{
|
|
||||||
constexpr std::int64_t Q=VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel;
|
|
||||||
- constexpr double InfluenceMetres=4.0;
|
|
||||||
+ const double InfluenceMetres=VF_L129PassageCarveReachMetres();
|
|
||||||
constexpr double OpenAirSideWallHeightMetres=1.0;
|
|
||||||
if(!shape_||step<=0||cells<=0||!std::isfinite(passageCarveReachMetres_)
|
|
||||||
||std::abs(passageCarveReachMetres_-InfluenceMetres)>1.0e-9)return;
|
|
||||||
diff --git a/Standalone/Tools/verify/baselines/README.md b/Standalone/Tools/verify/baselines/README.md
|
|
||||||
index 45fbb9f..fc7a59a 100644
|
|
||||||
--- a/Standalone/Tools/verify/baselines/README.md
|
|
||||||
+++ b/Standalone/Tools/verify/baselines/README.md
|
|
||||||
@@ -4,7 +4,7 @@ These inputs are byte-for-byte copies of the historical files consumed by the
|
|
||||||
verification gates. The gates now read this tracked directory instead of
|
|
||||||
`Saved/Linux`, which is generated and is not present in a fresh checkout.
|
|
||||||
|
|
||||||
-- `owner-hash/`: L46, L52 and L53 diagnostics plus the pinned v212/v214 owner hash baselines.
|
|
||||||
+- `owner-hash/`: L46, L52 and L53 diagnostics plus the pinned v212/v214 and L129 v226 owner hash baselines.
|
|
||||||
- `historical-controls/`: L35, L36 and L38 regression-control logs.
|
|
||||||
- `fixtures/`: Linux25 owner JSON inputs and L33 style-override fixtures.
|
|
||||||
- `landmarks/`: L45–L48 landmark mesh and layout controls.
|
|
||||||
diff --git a/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-floating-islands-style2-v226.baseline b/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-floating-islands-style2-v226.baseline
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000..9d3b87b
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-floating-islands-style2-v226.baseline
|
|
||||||
@@ -0,0 +1,12 @@
|
|
||||||
+[PipelineFullDetailHash] tiles=960 density=0x91931a57a067fd92 mesh=0xa818654be89790ac payload=0x370ff80451105a39 topology=0x06e507557aa70173
|
|
||||||
+[PipelineWholeViewHash] tiles=2370 density=0x1573b570e1cbbf7e mesh=0xd88bf8bcf69ce1ce payload=0x347541780c9d8d71 topology=0x6b8ff8640be6e9d4
|
|
||||||
+[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=0x600ce5633a8f9e83 mesh=0xcd40f163b4cf3e0e payload=0xbe81dc276737a33a topology=0x942806963fedb92d
|
|
||||||
+[PipelineLODHash] lod=3 tiles=208 density=0xf778be0581c49ed8 mesh=0x9aacf9e2a23034f8 payload=0xc1d4a985f2db3df5 topology=0xcdfdb412d3784023
|
|
||||||
+[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-v226.baseline b/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-owner4-surface-world-style1-v226.baseline
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000..128c807
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-owner4-surface-world-style1-v226.baseline
|
|
||||||
@@ -0,0 +1,12 @@
|
|
||||||
+[PipelineFullDetailHash] tiles=960 density=0xe1aa01ac806a84fb mesh=0x453624e695910639 payload=0x2f5793602ea13144 topology=0x31a43376cb129e55
|
|
||||||
+[PipelineWholeViewHash] tiles=2578 density=0xb82dc1dcdadda8ff mesh=0xe74e85bf3cb0909b payload=0x40bc3871dd9dccbe topology=0x855e712b549606c3
|
|
||||||
+[PipelineLODHash] lod=0 tiles=512 density=0x8119a4f12c4661f4 mesh=0xc074e3705293bef2 payload=0x36c965f6b43875ea topology=0x38bed0df168486d0
|
|
||||||
+[PipelineLODHash] lod=1 tiles=448 density=0x6270dd0856c53432 mesh=0xa803bb427deeba9a payload=0xf4718f1ce85d4f4f topology=0x7b770585aafd8174
|
|
||||||
+[PipelineLODHash] lod=2 tiles=320 density=0xf774df80811a61c1 mesh=0xb223f0f68d0310f8 payload=0x6c3fd8c4aa100ee9 topology=0x923485084c866600
|
|
||||||
+[PipelineLODHash] lod=3 tiles=272 density=0x62088ea9f38d2ed0 mesh=0x19bb327ba4ba3287 payload=0xd04c1223d50da0ea topology=0xf3817d1351cc89c5
|
|
||||||
+[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-v226.baseline b/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-surface-world-style1-v226.baseline
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000..49f85bb
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/Standalone/Tools/verify/baselines/owner-hash/canonical/owner-hash-surface-world-style1-v226.baseline
|
|
||||||
@@ -0,0 +1,12 @@
|
|
||||||
+[PipelineFullDetailHash] tiles=960 density=0xace56c8f205238ad mesh=0xa9c603a1248de6b8 payload=0xea55f1f4fcc6a894 topology=0x5ea7bc78a1b678ae
|
|
||||||
+[PipelineWholeViewHash] tiles=2370 density=0x637fdf29ccba949b mesh=0xb02cf034b0c9e375 payload=0x74240706eac0c770 topology=0xe607e19fd4684210
|
|
||||||
+[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=0x353ee7ab408a9da1 mesh=0x8d355a8d598d56d5 payload=0x458f26e32d815635 topology=0x2e89b3cba09efcfe
|
|
||||||
+[PipelineLODHash] lod=3 tiles=208 density=0xfe4f53b3ec010392 mesh=0xbd04d2da98d5b2e0 payload=0x10627f36d82200e8 topology=0xd625f3434ac0a893
|
|
||||||
+[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 5fc1584..70f6a69 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-v225.baseline",
|
|
||||||
- "L125-v225-stamped-passage-sweep")
|
|
||||||
+ return (BASELINES / "owner-hash/canonical/owner-hash-surface-world-style1-v226.baseline",
|
|
||||||
+ "L129-v226-physical-passage-reach")
|
|
||||||
if recipe == "floating-islands" and style == 2:
|
|
||||||
- return (BASELINES / "owner-hash/canonical/owner-hash-floating-islands-style2-v225.baseline",
|
|
||||||
- "L125-v225-stamped-passage-sweep")
|
|
||||||
+ return (BASELINES / "owner-hash/canonical/owner-hash-floating-islands-style2-v226.baseline",
|
|
||||||
+ "L129-v226-physical-passage-reach")
|
|
||||||
raise VerificationFailure(f"no pinned owner hash baseline for {recipe} style {style}")
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
# Linux130 — passage reach
|
||||||
|
|
||||||
|
On `wip/l130-reach-units` from `b96dd73`, passage influence is now **1.0533 m**: 0.75 m shell + 0.21 m relief + 0.50 m smooth-max support (`width/6`) + 0.01 m margin. One metres-to-core-voxels conversion feeds proof, feature, fallback and off-grid bounds; the sweep cutoff uses the same metre value. The dead 4 m cutoff is removed. Evaluator version is 227.
|
||||||
|
|
||||||
|
The debug shell/crest audit sampled 25,728 points, including 5 mm inside and outside the reach; 18,993 had sign-relevant passage contribution. Proof and feature bounds missed none. The nine-station floor probe still peaks at **7.884 mm**, matching L125. The 23 L125 views and six L129 mouth close-ups are byte-identical. Fast verification, walkability and shell audits pass; the seam audit found 0 mismatches across 4 pairs / 4,900 shared samples.
|
||||||
|
|
||||||
|
Clang/GCC W1/W8/W12 hashes agree across all 18 runs. Versus v225, hashes changed for owner4 full-detail, whole-view and LOD0–3; owner2 surface-world and floating-islands whole-view and LOD2–3. Exact-query hashes stayed unchanged. The v227 canonical baselines are recorded; changed hashes reflect the shorter density influence halo, while sampled sign-relevant bounds and captured surfaces remain covered.
|
||||||
|
|
||||||
|
L80 timing used 10 interleaved pairs per stratum/worker count. Across the eight case medians, the weighted deltas were +0.33% for LOD0–2 and +0.31% whole-view. Across 80 paired runs, mean deltas were +0.26% (95% interval −0.44% to +0.96%) and +0.47% (−0.06% to +1.00%); both intervals include zero. No measurable timing change; UE movement was skipped. The Linux UE host build succeeded in 76.30 s with `-NoUBA -MaxParallelActions=4`, without `prlimit`. `ARCHITECTURE.md` and `CODEMAP.md` had no note for this optimized influence reach, so they were unchanged.
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Run Clang/GCC owner hashes at W1/W8/W12 and compare with b96dd73."""
|
||||||
|
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/l130/hashes"
|
||||||
|
BASELINE = json.loads((ROOT / "Saved/Linux/l125/hashes/summary.json").read_text())
|
||||||
|
DATASETS = {
|
||||||
|
"owner4": ROOT / "Standalone/data/owner_world.json",
|
||||||
|
"owner2": ROOT / "Standalone/data/regression/owner_world_2strate_l61.json",
|
||||||
|
}
|
||||||
|
RECIPES = {"owner4": ("surface-world",),
|
||||||
|
"owner2": ("surface-world", "floating-islands")}
|
||||||
|
BINARIES = {
|
||||||
|
"clang": ROOT / "Saved/Linux/l130/bin/VoxelForgeCoreHeadless-l130-clang",
|
||||||
|
"gcc": ROOT / "Saved/Linux/l130/bin/VoxelForgeCoreHeadless-l130-gcc",
|
||||||
|
}
|
||||||
|
HASH_RE = re.compile(r"^\[Pipeline(?:FullDetailHash|WholeViewHash|LODHash|ExactQueryHash)\].*$", re.M)
|
||||||
|
STAMP_RE = 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_RE.findall(output)
|
||||||
|
if result.returncode or len(hashes) != 12:
|
||||||
|
raise SystemExit(f"hash run failed: {label}; exit={result.returncode} "
|
||||||
|
f"hashes={len(hashes)} log={log}")
|
||||||
|
stamp = STAMP_RE.search(output)
|
||||||
|
row = {"dataset": dataset, "recipe": recipe, "workers": workers,
|
||||||
|
"compiler": compiler, "exit_code": result.returncode, "hashes": hashes,
|
||||||
|
"source_stamp": stamp.group(1) if stamp else None,
|
||||||
|
"elapsed_s": round(time.monotonic() - started, 3),
|
||||||
|
"log": str(log.relative_to(ROOT))}
|
||||||
|
print("[L130HashRun] " + 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 L130 hash input")
|
||||||
|
old = {(row["dataset"], row["recipe"], row["workers"], row["compiler"]): row
|
||||||
|
for row in BASELINE["runs"]}
|
||||||
|
rows = []
|
||||||
|
for dataset, recipes in RECIPES.items():
|
||||||
|
for recipe in 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, recipes in RECIPES.items():
|
||||||
|
for recipe in recipes:
|
||||||
|
group = [row for row in rows if row["dataset"] == dataset
|
||||||
|
and row["recipe"] == recipe]
|
||||||
|
key = f"{dataset}/{recipe}"
|
||||||
|
stable = all(row["hashes"] == group[0]["hashes"] for row in group)
|
||||||
|
baseline = old[(dataset, recipe, 12, "clang")]["hashes"]
|
||||||
|
changed = [i for i, (before, after) in enumerate(zip(baseline,
|
||||||
|
group[0]["hashes"])) if before != after]
|
||||||
|
groups[key] = {"all_workers_and_compilers_match": stable,
|
||||||
|
"matches_b96dd73_v225": not changed,
|
||||||
|
"changed_hash_rows_from_v225": changed,
|
||||||
|
"source_stamps": sorted({row["source_stamp"] for row in group})}
|
||||||
|
if not stable:
|
||||||
|
raise SystemExit(f"worker/compiler hash mismatch: {key}")
|
||||||
|
(OUT / "summary.json").write_text(
|
||||||
|
json.dumps({"baseline_source": "b96dd73", "runs": rows,
|
||||||
|
"groups": groups}, indent=2) + "\n", encoding="utf-8")
|
||||||
|
print("[L130HashSummary] " + json.dumps(groups, sort_keys=True), flush=True)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
raise SystemExit(main())
|
||||||
@@ -0,0 +1,136 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Render the six L129 b96dd73 mouth views against the L130 meshes."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import hashlib
|
||||||
|
import html
|
||||||
|
import json
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
import time
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[4]
|
||||||
|
SOURCE = ROOT / "Saved/Linux/l129/captures/mouth-closeups/before"
|
||||||
|
SAVED = ROOT / "Saved/Linux/l130/captures/mouth-closeups"
|
||||||
|
CAPTURES = ROOT / "Standalone/Research/WorldAssemblerM3/Linux130/captures/mouth-closeups"
|
||||||
|
DATA = ROOT / "Standalone/data/owner_world.json"
|
||||||
|
HEADLESS = ROOT / "Saved/Linux/l130/bin/VoxelForgeCoreHeadless-l130-clang"
|
||||||
|
RENDERER = ROOT / "Saved/Linux/l130/bin/VoxelForgeOffscreenCapture-l130-clang"
|
||||||
|
HEADLESS_CONFIG = re.compile(
|
||||||
|
r"^\[HeadlessConfig\].*?camera_m=\(([^)]*)\) camera_rotation_deg=\(([^)]*)\)", re.M)
|
||||||
|
SCENE = re.compile(r"^\[OffscreenScene\].*?height_center_m=(-?[\d.]+)", re.M)
|
||||||
|
DRAWN = re.compile(r"drawn_triangles=(\d+)")
|
||||||
|
|
||||||
|
|
||||||
|
def wrapped(command: list[str]) -> list[str]:
|
||||||
|
return ["taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--",
|
||||||
|
"timeout", "1740s", *map(str, command)]
|
||||||
|
|
||||||
|
|
||||||
|
def run(label: str, command: list[str], log: Path) -> str:
|
||||||
|
started = time.monotonic()
|
||||||
|
log.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
with log.open("w", encoding="utf-8") as output:
|
||||||
|
result = subprocess.run(wrapped(command), cwd=ROOT, stdout=output,
|
||||||
|
stderr=subprocess.STDOUT, check=False, timeout=1740)
|
||||||
|
content = log.read_text(encoding="utf-8", errors="replace")
|
||||||
|
if result.returncode:
|
||||||
|
raise SystemExit(f"{label} failed exit={result.returncode}: {log}")
|
||||||
|
print(f"[L130MouthProcess] {label} elapsed_s={time.monotonic()-started:.2f}",
|
||||||
|
flush=True)
|
||||||
|
return content
|
||||||
|
|
||||||
|
|
||||||
|
def parse_vector(text: str) -> tuple[float, ...]:
|
||||||
|
return tuple(float(value) for value in text.split(","))
|
||||||
|
|
||||||
|
|
||||||
|
def sha256(path: Path) -> str:
|
||||||
|
return hashlib.sha256(path.read_bytes()).hexdigest()
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
if any(not path.is_file() for path in (DATA, HEADLESS, RENDERER)):
|
||||||
|
raise SystemExit("missing L130 mouth capture input")
|
||||||
|
(CAPTURES / "b96dd73").mkdir(parents=True, exist_ok=True)
|
||||||
|
(CAPTURES / "L130").mkdir(parents=True, exist_ok=True)
|
||||||
|
rows = []
|
||||||
|
for source_log in sorted(SOURCE.glob("*-mouth-mesh.log")):
|
||||||
|
name = source_log.name.removesuffix("-mesh.log")
|
||||||
|
source_render = SOURCE / f"{name}-render.log"
|
||||||
|
baseline_mesh = SOURCE / f"{name}.vfmesh"
|
||||||
|
if not all(path.is_file() for path in (source_render, baseline_mesh)):
|
||||||
|
raise SystemExit(f"missing b96dd73 source artifact for {name}")
|
||||||
|
config = HEADLESS_CONFIG.search(source_log.read_text())
|
||||||
|
scene = SCENE.search(source_render.read_text())
|
||||||
|
if config is None or scene is None:
|
||||||
|
raise SystemExit(f"missing camera metadata for {name}")
|
||||||
|
camera = parse_vector(config.group(1))
|
||||||
|
yaw, pitch = parse_vector(config.group(2))
|
||||||
|
height_center = float(scene.group(1))
|
||||||
|
camera_arg = ",".join(f"{value:.6f}" for value in (*camera, yaw, pitch))
|
||||||
|
candidate_mesh = SAVED / "L130" / f"{name}.vfmesh"
|
||||||
|
candidate_mesh.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
run(f"{name}-mesh", [HEADLESS, 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={camera_arg}",
|
||||||
|
"--render-distance-chunks=1", f"--mesh-export={candidate_mesh}"],
|
||||||
|
SAVED / "L130" / f"{name}-mesh.log")
|
||||||
|
if not candidate_mesh.is_file() or candidate_mesh.stat().st_size == 0:
|
||||||
|
raise SystemExit(f"empty L130 mesh for {name}")
|
||||||
|
|
||||||
|
render_args = ["--size=1920x1080",
|
||||||
|
f"--camera-m={','.join(f'{value:.6f}' for value in camera)}",
|
||||||
|
f"--yaw-deg={yaw:.6f}", f"--pitch-deg={pitch:.6f}",
|
||||||
|
"--shade=readable", "--headlamp=on", "--height-tint=on",
|
||||||
|
f"--height-center-m={height_center:.6f}", "--height-range-m=32"]
|
||||||
|
images = {}
|
||||||
|
draw_counts = {}
|
||||||
|
for variant, mesh in (("b96dd73", baseline_mesh), ("L130", candidate_mesh)):
|
||||||
|
image = CAPTURES / variant / f"{name}.png"
|
||||||
|
render_log = SAVED / variant / f"{name}-render.log"
|
||||||
|
content = run(f"{name}-{variant}-render",
|
||||||
|
[RENDERER, mesh, image, *render_args], render_log)
|
||||||
|
drawn = DRAWN.search(content)
|
||||||
|
if drawn is None or int(drawn.group(1)) <= 0 or not image.is_file():
|
||||||
|
raise SystemExit(f"render has no visible triangles for {name}/{variant}")
|
||||||
|
images[variant] = image
|
||||||
|
draw_counts[variant] = int(drawn.group(1))
|
||||||
|
equal = images["b96dd73"].read_bytes() == images["L130"].read_bytes()
|
||||||
|
row = {"name": name, "camera_m": camera, "yaw_deg": yaw,
|
||||||
|
"pitch_deg": pitch, "height_center_m": height_center,
|
||||||
|
"source_mesh": str(baseline_mesh.relative_to(ROOT)),
|
||||||
|
"candidate_mesh": str(candidate_mesh.relative_to(ROOT)),
|
||||||
|
"baseline_png": str(images["b96dd73"].relative_to(ROOT)),
|
||||||
|
"candidate_png": str(images["L130"].relative_to(ROOT)),
|
||||||
|
"baseline_sha256": sha256(images["b96dd73"]),
|
||||||
|
"candidate_sha256": sha256(images["L130"]),
|
||||||
|
"byte_identical": equal, "drawn_triangles": draw_counts}
|
||||||
|
rows.append(row)
|
||||||
|
print(f"[L130MouthCompare] {name} byte_identical={equal} "
|
||||||
|
f"sha256={row['candidate_sha256']}", flush=True)
|
||||||
|
|
||||||
|
if len(rows) != 6:
|
||||||
|
raise SystemExit(f"expected six L129 mouth views, found {len(rows)}")
|
||||||
|
(CAPTURES / "summary.json").write_text(json.dumps(rows, indent=2) + "\n")
|
||||||
|
sections = []
|
||||||
|
for row in rows:
|
||||||
|
name = html.escape(row["name"])
|
||||||
|
sections.append(f"<section><h2>{name}</h2><p>byte identical: "
|
||||||
|
f"{str(row['byte_identical']).lower()}</p><div>"
|
||||||
|
f"<figure><figcaption>b96dd73 source mesh</figcaption><img src='b96dd73/{name}.png'></figure>"
|
||||||
|
f"<figure><figcaption>L130 reach units</figcaption><img src='L130/{name}.png'></figure>"
|
||||||
|
"</div></section>")
|
||||||
|
page = ("<!doctype html><meta charset='utf-8'><title>L130 mouth closeups</title>"
|
||||||
|
"<style>body{font:14px system-ui;margin:24px;background:#17191d;color:#eee}"
|
||||||
|
"section{margin:28px 0}div{display:grid;grid-template-columns:1fr 1fr;gap:12px}"
|
||||||
|
"img{width:100%;height:auto}p{color:#bbb}</style>"
|
||||||
|
"<h1>L129 mouth closeups: b96dd73 vs L130</h1>" + "\n".join(sections))
|
||||||
|
(CAPTURES / "COMPARE.html").write_text(page)
|
||||||
|
return 0 if all(row["byte_identical"] for row in rows) else 1
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
raise SystemExit(main())
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Render the 23 L125 camera poses with the L130 evaluator and compare them."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import html
|
||||||
|
import importlib.util
|
||||||
|
import json
|
||||||
|
import shutil
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[4]
|
||||||
|
RESEARCH = Path(__file__).resolve().parent
|
||||||
|
CAPTURES = RESEARCH / "captures"
|
||||||
|
SAVED = ROOT / "Saved/Linux/l130/captures"
|
||||||
|
BASELINE_INDEX = (ROOT / "Standalone/Research/WorldAssemblerM3/Linux119"
|
||||||
|
/ "captures/L119/capture-index.json")
|
||||||
|
REFERENCE = ROOT / "Standalone/Research/WorldAssemblerM3/Linux125/captures/L125"
|
||||||
|
LAYOUT = ROOT / "Saved/Linux/l130/hashes/owner4-surface-world-w12-clang.layout.json"
|
||||||
|
HEADLESS = ROOT / "Saved/Linux/l130/bin/VoxelForgeCoreHeadless-l130-clang"
|
||||||
|
RENDERER = ROOT / "Saved/Linux/l130/bin/VoxelForgeOffscreenCapture-l130-clang"
|
||||||
|
HELPER_PATH = ROOT / "Standalone/Research/WorldAssemblerM3/Linux113/RunL113Captures.py"
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
if any(not path.is_file() for path in
|
||||||
|
(BASELINE_INDEX, REFERENCE / "passage-0-1-0-rock-floor-station-1.png",
|
||||||
|
LAYOUT, HEADLESS, RENDERER)):
|
||||||
|
raise SystemExit("missing pose, layout, or L130 capture input")
|
||||||
|
spec = importlib.util.spec_from_file_location("l125_capture_runner",
|
||||||
|
ROOT / "Standalone/Research/WorldAssemblerM3/Linux125/RunL125Captures.py")
|
||||||
|
if spec is None or spec.loader is None:
|
||||||
|
raise SystemExit("cannot load the verified L125 pose set")
|
||||||
|
runner = importlib.util.module_from_spec(spec)
|
||||||
|
spec.loader.exec_module(runner)
|
||||||
|
runner.RESEARCH = RESEARCH
|
||||||
|
runner.CAPTURES = CAPTURES
|
||||||
|
runner.SAVED = SAVED
|
||||||
|
runner.LAYOUT = LAYOUT
|
||||||
|
runner.CLANG = HEADLESS
|
||||||
|
runner.RENDERER = RENDERER
|
||||||
|
runner.HELPERS.RESEARCH = RESEARCH
|
||||||
|
runner.HELPERS.CAPTURES = CAPTURES
|
||||||
|
runner.HELPERS.SAVED = SAVED
|
||||||
|
runner.HELPERS.BINARIES = {"L125": HEADLESS}
|
||||||
|
runner.HELPERS.RENDERERS = {"L125": RENDERER}
|
||||||
|
if runner.main() != 0:
|
||||||
|
raise SystemExit("L130 pose generation failed")
|
||||||
|
|
||||||
|
new_captures = CAPTURES / "L125"
|
||||||
|
new_saved = SAVED / "L125"
|
||||||
|
index_path = new_captures / "capture-index.json"
|
||||||
|
data = json.loads(index_path.read_text())
|
||||||
|
if len(data["captures"]) != 23:
|
||||||
|
raise SystemExit(f"expected 23 poses, found {len(data['captures'])}")
|
||||||
|
identical = 0
|
||||||
|
sections = []
|
||||||
|
for row in data["captures"]:
|
||||||
|
name = row["name"]
|
||||||
|
old_image = REFERENCE / f"{name}.png"
|
||||||
|
new_image = new_captures / f"{name}.png"
|
||||||
|
if not old_image.is_file() or not new_image.is_file():
|
||||||
|
raise SystemExit(f"missing comparison image for {name}")
|
||||||
|
same = old_image.read_bytes() == new_image.read_bytes()
|
||||||
|
identical += int(same)
|
||||||
|
row["variant"] = "L130-v227"
|
||||||
|
row["capture"] = row["capture"].replace("captures/L125/", "captures/L130/")
|
||||||
|
row["scene"] = row["scene"].replace("captures/L125/", "captures/L130/")
|
||||||
|
row["logs"] = [path.replace("captures/L125/", "captures/L130/")
|
||||||
|
for path in row.get("logs", [])]
|
||||||
|
sections.append(f"<section><h2>{html.escape(row['passage'])} — "
|
||||||
|
f"{html.escape(row.get('station', ''))}</h2><p>{html.escape(row['kind'])} · "
|
||||||
|
f"byte identical: {str(same).lower()}</p><div>"
|
||||||
|
f"<figure><figcaption>L125 v225</figcaption><img src='../../Linux125/captures/L125/{html.escape(name)}.png'></figure>"
|
||||||
|
f"<figure><figcaption>L130 v227</figcaption><img src='L130/{html.escape(name)}.png'></figure>"
|
||||||
|
"</div></section>")
|
||||||
|
if identical != 23:
|
||||||
|
raise SystemExit(f"only {identical}/23 L125 pose captures are byte-identical")
|
||||||
|
|
||||||
|
index_path.write_text(json.dumps(data, indent=2) + "\n")
|
||||||
|
old_captures, old_saved = CAPTURES / "L130", SAVED / "L130"
|
||||||
|
if old_captures.exists():
|
||||||
|
shutil.rmtree(old_captures)
|
||||||
|
if old_saved.exists():
|
||||||
|
shutil.rmtree(old_saved)
|
||||||
|
new_captures.rename(old_captures)
|
||||||
|
new_saved.rename(old_saved)
|
||||||
|
page = ("<!doctype html><meta charset='utf-8'><title>L130 passage captures</title>"
|
||||||
|
"<style>body{font:14px system-ui;margin:24px;background:#17191d;color:#eee}"
|
||||||
|
"section{margin:28px 0}div{display:grid;grid-template-columns:1fr 1fr;gap:12px}"
|
||||||
|
"img{width:100%;height:auto}p{color:#bbb}</style>"
|
||||||
|
"<h1>L125 v225 vs L130 v227: passage captures</h1>" + "\n".join(sections))
|
||||||
|
(CAPTURES / "COMPARE.html").write_text(page)
|
||||||
|
print(f"[L130PoseCapture] poses=23 byte_identical={identical}/23", flush=True)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
raise SystemExit(main())
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Five interleaved L80 near-ready runs per stratum/worker vs b96dd73."""
|
||||||
|
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/l130/timing"
|
||||||
|
PASS_ID = int(os.environ.get("VOXELFORGE_L130_TIMING_PASS", "1"))
|
||||||
|
REPLICATE_FIRST = (PASS_ID - 1) * 5 + 1
|
||||||
|
DATA = ROOT / "Standalone/data/owner_world.json"
|
||||||
|
BINARIES = {
|
||||||
|
"b96dd73": ROOT / "Saved/Linux/l125/bin/VoxelForgeCoreHeadless-l125-clang",
|
||||||
|
"L130": ROOT / "Saved/Linux/l130/bin/VoxelForgeCoreHeadless-l130-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 = re.compile(r"^\[StreamPipeline\] (.*)$", re.M)
|
||||||
|
FIELDS_RE = re.compile(r"([a-zA-Z0-9_]+)=([^ ]+)")
|
||||||
|
NEAR_RE = 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)
|
||||||
|
pass_suffix = "" if PASS_ID == 1 else f"-p{PASS_ID}"
|
||||||
|
label = f"s{strate}-w{workers}-{version}-{phase}{replicate}-l130-v227{pass_suffix}"
|
||||||
|
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, near = PIPELINE_RE.search(content), NEAR_RE.search(content)
|
||||||
|
if result.returncode or pipeline is None or near is None:
|
||||||
|
raise SystemExit(f"timing run failed: {log}; exit={result.returncode}")
|
||||||
|
fields = dict(FIELDS_RE.findall(pipeline.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.group(3)),
|
||||||
|
"whole_view_ready_s": float(fields["whole_view_ready"].removesuffix("s")),
|
||||||
|
"log": str(log.relative_to(ROOT))}
|
||||||
|
print("[L130TimingRun] " + json.dumps(row, sort_keys=True), flush=True)
|
||||||
|
return row
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
if any(not path.is_file() for path in (DATA, *BINARIES.values())):
|
||||||
|
raise SystemExit("missing L130 timing input")
|
||||||
|
OUT.mkdir(parents=True, exist_ok=True)
|
||||||
|
load_1m = __import__("os").getloadavg()[0]
|
||||||
|
def cpu_idle(interval: float = 2.0) -> float:
|
||||||
|
def totals() -> tuple[int, int]:
|
||||||
|
fields = Path("/proc/stat").read_text().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 = totals()
|
||||||
|
time.sleep(interval)
|
||||||
|
after = totals()
|
||||||
|
return 100.0 * (after[1] - before[1]) / max(1, after[0] - before[0])
|
||||||
|
idle = cpu_idle()
|
||||||
|
pass_suffix = "" if PASS_ID == 1 else f"-p{PASS_ID}"
|
||||||
|
(OUT / f"machine-load-v227{pass_suffix}-before.txt").write_text(
|
||||||
|
f"1-minute load: {load_1m:.2f}\n2-second CPU idle: {idle:.1f}%\n")
|
||||||
|
print(f"[L130TimingGate] load_1m={load_1m:.2f} cpu_idle_2s={idle:.1f}%",
|
||||||
|
flush=True)
|
||||||
|
if load_1m >= 0.9 or idle < 97.0:
|
||||||
|
raise SystemExit("timing refused: machine is above the quiet-load gate")
|
||||||
|
|
||||||
|
rows = []
|
||||||
|
for strate in range(4):
|
||||||
|
for workers in (8, 12):
|
||||||
|
for version in BINARIES:
|
||||||
|
run(strate, workers, version, "warmup", 0)
|
||||||
|
for replicate in range(REPLICATE_FIRST, REPLICATE_FIRST + 5):
|
||||||
|
order = tuple(BINARIES) if replicate % 2 else tuple(reversed(BINARIES))
|
||||||
|
for version in order:
|
||||||
|
rows.append(run(strate, workers, version, "measured", replicate))
|
||||||
|
(OUT / f"runs-v227{pass_suffix}-partial.json").write_text(
|
||||||
|
json.dumps(rows, indent=2) + "\n", encoding="utf-8")
|
||||||
|
prior_runs = []
|
||||||
|
if PASS_ID > 1:
|
||||||
|
previous = OUT / ("v227-summary.json" if PASS_ID == 2
|
||||||
|
else "v227-combined-summary.json")
|
||||||
|
if previous.is_file():
|
||||||
|
prior_runs = json.loads(previous.read_text(encoding="utf-8")).get("runs", [])
|
||||||
|
all_rows = prior_runs + rows
|
||||||
|
measured_rows = [row for row in all_rows if row["phase"] == "measured"]
|
||||||
|
summary = []
|
||||||
|
for strate in range(4):
|
||||||
|
for workers in (8, 12):
|
||||||
|
group_size = sum(row["strate"] == strate and row["workers"] == workers
|
||||||
|
for row in measured_rows) // 2
|
||||||
|
item = {"strate": strate, "workers": workers,
|
||||||
|
"replicates_per_version": group_size}
|
||||||
|
medians = {}
|
||||||
|
for version in BINARIES:
|
||||||
|
group = [row for row in measured_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 key in ("lod02_ready_s", "whole_view_ready_s"):
|
||||||
|
item[f"L130_vs_b96dd73_{key}_delta_pct"] = round(
|
||||||
|
100.0*(medians["L130"][key]/medians["b96dd73"][key]-1.0), 2)
|
||||||
|
summary.append(item)
|
||||||
|
summary_path = OUT / ("v227-summary.json" if PASS_ID == 1
|
||||||
|
else f"v227-combined-summary.json")
|
||||||
|
summary_path.write_text(json.dumps(
|
||||||
|
{"runs": all_rows, "summary": summary}, indent=2) + "\n", encoding="utf-8")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
raise SystemExit(main())
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<!doctype html><meta charset='utf-8'><title>L130 passage captures</title><style>body{font:14px system-ui;margin:24px;background:#17191d;color:#eee}section{margin:28px 0}div{display:grid;grid-template-columns:1fr 1fr;gap:12px}img{width:100%;height:auto}p{color:#bbb}</style><h1>L125 v225 vs L130 v227: passage captures</h1><section><h2>passage/0-1/0 — rock-floor/401.7m</h2><p>rock-floor-close · byte identical: true</p><div><figure><figcaption>L125 v225</figcaption><img src='../../Linux125/captures/L125/passage-0-1-0-rock-floor-station-1.png'></figure><figure><figcaption>L130 v227</figcaption><img src='L130/passage-0-1-0-rock-floor-station-1.png'></figure></div></section>
|
||||||
|
<section><h2>passage/0-1/0 — rock-floor/792.8m</h2><p>rock-floor-close · byte identical: true</p><div><figure><figcaption>L125 v225</figcaption><img src='../../Linux125/captures/L125/passage-0-1-0-rock-floor-station-2.png'></figure><figure><figcaption>L130 v227</figcaption><img src='L130/passage-0-1-0-rock-floor-station-2.png'></figure></div></section>
|
||||||
|
<section><h2>passage/0-1/0 — rock-floor/1634.5m</h2><p>rock-floor-close · byte identical: true</p><div><figure><figcaption>L125 v225</figcaption><img src='../../Linux125/captures/L125/passage-0-1-0-rock-floor-station-3.png'></figure><figure><figcaption>L130 v227</figcaption><img src='L130/passage-0-1-0-rock-floor-station-3.png'></figure></div></section>
|
||||||
|
<section><h2>passage/1-2/0 — rock-floor/27.0m</h2><p>rock-floor-close · byte identical: true</p><div><figure><figcaption>L125 v225</figcaption><img src='../../Linux125/captures/L125/passage-1-2-0-rock-floor-station-1.png'></figure><figure><figcaption>L130 v227</figcaption><img src='L130/passage-1-2-0-rock-floor-station-1.png'></figure></div></section>
|
||||||
|
<section><h2>passage/1-2/0 — rock-floor/52.9m</h2><p>rock-floor-close · byte identical: true</p><div><figure><figcaption>L125 v225</figcaption><img src='../../Linux125/captures/L125/passage-1-2-0-rock-floor-station-2.png'></figure><figure><figcaption>L130 v227</figcaption><img src='L130/passage-1-2-0-rock-floor-station-2.png'></figure></div></section>
|
||||||
|
<section><h2>passage/1-2/0 — rock-floor/78.9m</h2><p>rock-floor-close · byte identical: true</p><div><figure><figcaption>L125 v225</figcaption><img src='../../Linux125/captures/L125/passage-1-2-0-rock-floor-station-3.png'></figure><figure><figcaption>L130 v227</figcaption><img src='L130/passage-1-2-0-rock-floor-station-3.png'></figure></div></section>
|
||||||
|
<section><h2>passage/2-3/0 — rock-floor/323.4m</h2><p>rock-floor-close · byte identical: true</p><div><figure><figcaption>L125 v225</figcaption><img src='../../Linux125/captures/L125/passage-2-3-0-rock-floor-station-1.png'></figure><figure><figcaption>L130 v227</figcaption><img src='L130/passage-2-3-0-rock-floor-station-1.png'></figure></div></section>
|
||||||
|
<section><h2>passage/2-3/0 — rock-floor/333.4m</h2><p>rock-floor-close · byte identical: true</p><div><figure><figcaption>L125 v225</figcaption><img src='../../Linux125/captures/L125/passage-2-3-0-rock-floor-station-2.png'></figure><figure><figcaption>L130 v227</figcaption><img src='L130/passage-2-3-0-rock-floor-station-2.png'></figure></div></section>
|
||||||
|
<section><h2>passage/2-3/0 — rock-floor/343.4m</h2><p>rock-floor-close · byte identical: true</p><div><figure><figcaption>L125 v225</figcaption><img src='../../Linux125/captures/L125/passage-2-3-0-rock-floor-station-3.png'></figure><figure><figcaption>L130 v227</figcaption><img src='L130/passage-2-3-0-rock-floor-station-3.png'></figure></div></section>
|
||||||
|
<section><h2>passage/0-1/0 — section-1/4m-outside</h2><p>open-air-close · byte identical: true</p><div><figure><figcaption>L125 v225</figcaption><img src='../../Linux125/captures/L125/passage-0-1-0-openair-1-4m-outside.png'></figure><figure><figcaption>L130 v227</figcaption><img src='L130/passage-0-1-0-openair-1-4m-outside.png'></figure></div></section>
|
||||||
|
<section><h2>passage/0-1/0 — section-1/4m-interior-wall</h2><p>open-air-close · byte identical: true</p><div><figure><figcaption>L125 v225</figcaption><img src='../../Linux125/captures/L125/passage-0-1-0-openair-1-4m-interior-wall.png'></figure><figure><figcaption>L130 v227</figcaption><img src='L130/passage-0-1-0-openair-1-4m-interior-wall.png'></figure></div></section>
|
||||||
|
<section><h2>passage/0-1/0 — section-2/4m-outside</h2><p>open-air-close · byte identical: true</p><div><figure><figcaption>L125 v225</figcaption><img src='../../Linux125/captures/L125/passage-0-1-0-openair-2-4m-outside.png'></figure><figure><figcaption>L130 v227</figcaption><img src='L130/passage-0-1-0-openair-2-4m-outside.png'></figure></div></section>
|
||||||
|
<section><h2>passage/0-1/0 — section-2/4m-interior-wall</h2><p>open-air-close · byte identical: true</p><div><figure><figcaption>L125 v225</figcaption><img src='../../Linux125/captures/L125/passage-0-1-0-openair-2-4m-interior-wall.png'></figure><figure><figcaption>L130 v227</figcaption><img src='L130/passage-0-1-0-openair-2-4m-interior-wall.png'></figure></div></section>
|
||||||
|
<section><h2>passage/0-1/0 — section-3/4m-outside</h2><p>open-air-close · byte identical: true</p><div><figure><figcaption>L125 v225</figcaption><img src='../../Linux125/captures/L125/passage-0-1-0-openair-3-4m-outside.png'></figure><figure><figcaption>L130 v227</figcaption><img src='L130/passage-0-1-0-openair-3-4m-outside.png'></figure></div></section>
|
||||||
|
<section><h2>passage/0-1/0 — section-3/4m-interior-wall</h2><p>open-air-close · byte identical: true</p><div><figure><figcaption>L125 v225</figcaption><img src='../../Linux125/captures/L125/passage-0-1-0-openair-3-4m-interior-wall.png'></figure><figure><figcaption>L130 v227</figcaption><img src='L130/passage-0-1-0-openair-3-4m-interior-wall.png'></figure></div></section>
|
||||||
|
<section><h2>passage/1-2/0 — section-1/4m-outside</h2><p>open-air-close · byte identical: true</p><div><figure><figcaption>L125 v225</figcaption><img src='../../Linux125/captures/L125/passage-1-2-0-openair-1-4m-outside.png'></figure><figure><figcaption>L130 v227</figcaption><img src='L130/passage-1-2-0-openair-1-4m-outside.png'></figure></div></section>
|
||||||
|
<section><h2>passage/1-2/0 — section-1/4m-interior-wall</h2><p>open-air-close · byte identical: true</p><div><figure><figcaption>L125 v225</figcaption><img src='../../Linux125/captures/L125/passage-1-2-0-openair-1-4m-interior-wall.png'></figure><figure><figcaption>L130 v227</figcaption><img src='L130/passage-1-2-0-openair-1-4m-interior-wall.png'></figure></div></section>
|
||||||
|
<section><h2>passage/1-2/0 — section-2/4m-outside</h2><p>open-air-close · byte identical: true</p><div><figure><figcaption>L125 v225</figcaption><img src='../../Linux125/captures/L125/passage-1-2-0-openair-2-4m-outside.png'></figure><figure><figcaption>L130 v227</figcaption><img src='L130/passage-1-2-0-openair-2-4m-outside.png'></figure></div></section>
|
||||||
|
<section><h2>passage/1-2/0 — section-2/4m-interior-wall</h2><p>open-air-close · byte identical: true</p><div><figure><figcaption>L125 v225</figcaption><img src='../../Linux125/captures/L125/passage-1-2-0-openair-2-4m-interior-wall.png'></figure><figure><figcaption>L130 v227</figcaption><img src='L130/passage-1-2-0-openair-2-4m-interior-wall.png'></figure></div></section>
|
||||||
|
<section><h2>passage/2-3/0 — section-1/4m-outside</h2><p>open-air-close · byte identical: true</p><div><figure><figcaption>L125 v225</figcaption><img src='../../Linux125/captures/L125/passage-2-3-0-openair-1-4m-outside.png'></figure><figure><figcaption>L130 v227</figcaption><img src='L130/passage-2-3-0-openair-1-4m-outside.png'></figure></div></section>
|
||||||
|
<section><h2>passage/2-3/0 — section-1/4m-interior-wall</h2><p>open-air-close · byte identical: true</p><div><figure><figcaption>L125 v225</figcaption><img src='../../Linux125/captures/L125/passage-2-3-0-openair-1-4m-interior-wall.png'></figure><figure><figcaption>L130 v227</figcaption><img src='L130/passage-2-3-0-openair-1-4m-interior-wall.png'></figure></div></section>
|
||||||
|
<section><h2>passage/2-3/0 — section-2/4m-outside</h2><p>open-air-close · byte identical: true</p><div><figure><figcaption>L125 v225</figcaption><img src='../../Linux125/captures/L125/passage-2-3-0-openair-2-4m-outside.png'></figure><figure><figcaption>L130 v227</figcaption><img src='L130/passage-2-3-0-openair-2-4m-outside.png'></figure></div></section>
|
||||||
|
<section><h2>passage/2-3/0 — section-2/4m-interior-wall</h2><p>open-air-close · byte identical: true</p><div><figure><figcaption>L125 v225</figcaption><img src='../../Linux125/captures/L125/passage-2-3-0-openair-2-4m-interior-wall.png'></figure><figure><figcaption>L130 v227</figcaption><img src='L130/passage-2-3-0-openair-2-4m-interior-wall.png'></figure></div></section>
|
||||||
@@ -28,9 +28,9 @@
|
|||||||
"route_length_m": 2026.6238040154117,
|
"route_length_m": 2026.6238040154117,
|
||||||
"planned_floor_m": -445.66373993191075,
|
"planned_floor_m": -445.66373993191075,
|
||||||
"planned_grade_deg": 10.372328677972732,
|
"planned_grade_deg": 10.372328677972732,
|
||||||
"variant": "L129-v226",
|
"variant": "L130-v227",
|
||||||
"capture": "captures/L129/passage-0-1-0-rock-floor-station-1.png",
|
"capture": "captures/L130/passage-0-1-0-rock-floor-station-1.png",
|
||||||
"scene": "Saved/Linux/l129/captures/L129/passage-0-1-0-rock-floor-station-1.vfmesh",
|
"scene": "Saved/Linux/l130/captures/L130/passage-0-1-0-rock-floor-station-1.vfmesh",
|
||||||
"drawn_triangles": 122294,
|
"drawn_triangles": 122294,
|
||||||
"source_triangles": 146798,
|
"source_triangles": 146798,
|
||||||
"verified": true,
|
"verified": true,
|
||||||
@@ -54,9 +54,9 @@
|
|||||||
-445.66373993191075
|
-445.66373993191075
|
||||||
],
|
],
|
||||||
"logs": [
|
"logs": [
|
||||||
"Saved/Linux/l129/captures/L129/passage-0-1-0-rock-floor-station-1-mesh.log",
|
"Saved/Linux/l130/captures/L130/passage-0-1-0-rock-floor-station-1-mesh.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-0-1-0-rock-floor-station-1-render.log",
|
"Saved/Linux/l130/captures/L130/passage-0-1-0-rock-floor-station-1-render.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-0-1-0-rock-floor-station-1-quality.log"
|
"Saved/Linux/l130/captures/L130/passage-0-1-0-rock-floor-station-1-quality.log"
|
||||||
],
|
],
|
||||||
"floor_anchor_position_m": [
|
"floor_anchor_position_m": [
|
||||||
-7.026885053959959,
|
-7.026885053959959,
|
||||||
@@ -100,9 +100,9 @@
|
|||||||
"route_length_m": 2026.6238040154117,
|
"route_length_m": 2026.6238040154117,
|
||||||
"planned_floor_m": -516.0616688299093,
|
"planned_floor_m": -516.0616688299093,
|
||||||
"planned_grade_deg": 10.367725129664787,
|
"planned_grade_deg": 10.367725129664787,
|
||||||
"variant": "L129-v226",
|
"variant": "L130-v227",
|
||||||
"capture": "captures/L129/passage-0-1-0-rock-floor-station-2.png",
|
"capture": "captures/L130/passage-0-1-0-rock-floor-station-2.png",
|
||||||
"scene": "Saved/Linux/l129/captures/L129/passage-0-1-0-rock-floor-station-2.vfmesh",
|
"scene": "Saved/Linux/l130/captures/L130/passage-0-1-0-rock-floor-station-2.vfmesh",
|
||||||
"drawn_triangles": 586092,
|
"drawn_triangles": 586092,
|
||||||
"source_triangles": 626196,
|
"source_triangles": 626196,
|
||||||
"verified": true,
|
"verified": true,
|
||||||
@@ -126,9 +126,9 @@
|
|||||||
-516.0616688299093
|
-516.0616688299093
|
||||||
],
|
],
|
||||||
"logs": [
|
"logs": [
|
||||||
"Saved/Linux/l129/captures/L129/passage-0-1-0-rock-floor-station-2-mesh.log",
|
"Saved/Linux/l130/captures/L130/passage-0-1-0-rock-floor-station-2-mesh.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-0-1-0-rock-floor-station-2-render.log",
|
"Saved/Linux/l130/captures/L130/passage-0-1-0-rock-floor-station-2-render.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-0-1-0-rock-floor-station-2-quality.log"
|
"Saved/Linux/l130/captures/L130/passage-0-1-0-rock-floor-station-2-quality.log"
|
||||||
],
|
],
|
||||||
"floor_anchor_position_m": [
|
"floor_anchor_position_m": [
|
||||||
-2.471476828908,
|
-2.471476828908,
|
||||||
@@ -172,9 +172,9 @@
|
|||||||
"route_length_m": 2026.6238040154117,
|
"route_length_m": 2026.6238040154117,
|
||||||
"planned_floor_m": -667.5348848643227,
|
"planned_floor_m": -667.5348848643227,
|
||||||
"planned_grade_deg": 10.360515186362372,
|
"planned_grade_deg": 10.360515186362372,
|
||||||
"variant": "L129-v226",
|
"variant": "L130-v227",
|
||||||
"capture": "captures/L129/passage-0-1-0-rock-floor-station-3.png",
|
"capture": "captures/L130/passage-0-1-0-rock-floor-station-3.png",
|
||||||
"scene": "Saved/Linux/l129/captures/L129/passage-0-1-0-rock-floor-station-3.vfmesh",
|
"scene": "Saved/Linux/l130/captures/L130/passage-0-1-0-rock-floor-station-3.vfmesh",
|
||||||
"drawn_triangles": 137288,
|
"drawn_triangles": 137288,
|
||||||
"source_triangles": 166736,
|
"source_triangles": 166736,
|
||||||
"verified": true,
|
"verified": true,
|
||||||
@@ -198,9 +198,9 @@
|
|||||||
-667.5348848643227
|
-667.5348848643227
|
||||||
],
|
],
|
||||||
"logs": [
|
"logs": [
|
||||||
"Saved/Linux/l129/captures/L129/passage-0-1-0-rock-floor-station-3-mesh.log",
|
"Saved/Linux/l130/captures/L130/passage-0-1-0-rock-floor-station-3-mesh.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-0-1-0-rock-floor-station-3-render.log",
|
"Saved/Linux/l130/captures/L130/passage-0-1-0-rock-floor-station-3-render.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-0-1-0-rock-floor-station-3-quality.log"
|
"Saved/Linux/l130/captures/L130/passage-0-1-0-rock-floor-station-3-quality.log"
|
||||||
],
|
],
|
||||||
"floor_anchor_position_m": [
|
"floor_anchor_position_m": [
|
||||||
17.33622182815858,
|
17.33622182815858,
|
||||||
@@ -244,9 +244,9 @@
|
|||||||
"route_length_m": 114.99063175809309,
|
"route_length_m": 114.99063175809309,
|
||||||
"planned_floor_m": -738.1970266319915,
|
"planned_floor_m": -738.1970266319915,
|
||||||
"planned_grade_deg": 10.657740387934142,
|
"planned_grade_deg": 10.657740387934142,
|
||||||
"variant": "L129-v226",
|
"variant": "L130-v227",
|
||||||
"capture": "captures/L129/passage-1-2-0-rock-floor-station-1.png",
|
"capture": "captures/L130/passage-1-2-0-rock-floor-station-1.png",
|
||||||
"scene": "Saved/Linux/l129/captures/L129/passage-1-2-0-rock-floor-station-1.vfmesh",
|
"scene": "Saved/Linux/l130/captures/L130/passage-1-2-0-rock-floor-station-1.vfmesh",
|
||||||
"drawn_triangles": 652056,
|
"drawn_triangles": 652056,
|
||||||
"source_triangles": 719660,
|
"source_triangles": 719660,
|
||||||
"verified": true,
|
"verified": true,
|
||||||
@@ -270,9 +270,9 @@
|
|||||||
-738.1970266319915
|
-738.1970266319915
|
||||||
],
|
],
|
||||||
"logs": [
|
"logs": [
|
||||||
"Saved/Linux/l129/captures/L129/passage-1-2-0-rock-floor-station-1-mesh.log",
|
"Saved/Linux/l130/captures/L130/passage-1-2-0-rock-floor-station-1-mesh.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-1-2-0-rock-floor-station-1-render.log",
|
"Saved/Linux/l130/captures/L130/passage-1-2-0-rock-floor-station-1-render.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-1-2-0-rock-floor-station-1-quality.log"
|
"Saved/Linux/l130/captures/L130/passage-1-2-0-rock-floor-station-1-quality.log"
|
||||||
],
|
],
|
||||||
"floor_anchor_position_m": [
|
"floor_anchor_position_m": [
|
||||||
15.354124807038394,
|
15.354124807038394,
|
||||||
@@ -316,9 +316,9 @@
|
|||||||
"route_length_m": 114.99063175809309,
|
"route_length_m": 114.99063175809309,
|
||||||
"planned_floor_m": -742.995373541633,
|
"planned_floor_m": -742.995373541633,
|
||||||
"planned_grade_deg": 10.645569354114926,
|
"planned_grade_deg": 10.645569354114926,
|
||||||
"variant": "L129-v226",
|
"variant": "L130-v227",
|
||||||
"capture": "captures/L129/passage-1-2-0-rock-floor-station-2.png",
|
"capture": "captures/L130/passage-1-2-0-rock-floor-station-2.png",
|
||||||
"scene": "Saved/Linux/l129/captures/L129/passage-1-2-0-rock-floor-station-2.vfmesh",
|
"scene": "Saved/Linux/l130/captures/L130/passage-1-2-0-rock-floor-station-2.vfmesh",
|
||||||
"drawn_triangles": 636162,
|
"drawn_triangles": 636162,
|
||||||
"source_triangles": 700558,
|
"source_triangles": 700558,
|
||||||
"verified": true,
|
"verified": true,
|
||||||
@@ -342,9 +342,9 @@
|
|||||||
-742.995373541633
|
-742.995373541633
|
||||||
],
|
],
|
||||||
"logs": [
|
"logs": [
|
||||||
"Saved/Linux/l129/captures/L129/passage-1-2-0-rock-floor-station-2-mesh.log",
|
"Saved/Linux/l130/captures/L130/passage-1-2-0-rock-floor-station-2-mesh.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-1-2-0-rock-floor-station-2-render.log",
|
"Saved/Linux/l130/captures/L130/passage-1-2-0-rock-floor-station-2-render.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-1-2-0-rock-floor-station-2-quality.log"
|
"Saved/Linux/l130/captures/L130/passage-1-2-0-rock-floor-station-2-quality.log"
|
||||||
],
|
],
|
||||||
"floor_anchor_position_m": [
|
"floor_anchor_position_m": [
|
||||||
-4.766428465537912,
|
-4.766428465537912,
|
||||||
@@ -388,9 +388,9 @@
|
|||||||
"route_length_m": 114.99063175809309,
|
"route_length_m": 114.99063175809309,
|
||||||
"planned_floor_m": -747.7963166548619,
|
"planned_floor_m": -747.7963166548619,
|
||||||
"planned_grade_deg": 10.659092990906162,
|
"planned_grade_deg": 10.659092990906162,
|
||||||
"variant": "L129-v226",
|
"variant": "L130-v227",
|
||||||
"capture": "captures/L129/passage-1-2-0-rock-floor-station-3.png",
|
"capture": "captures/L130/passage-1-2-0-rock-floor-station-3.png",
|
||||||
"scene": "Saved/Linux/l129/captures/L129/passage-1-2-0-rock-floor-station-3.vfmesh",
|
"scene": "Saved/Linux/l130/captures/L130/passage-1-2-0-rock-floor-station-3.vfmesh",
|
||||||
"drawn_triangles": 580472,
|
"drawn_triangles": 580472,
|
||||||
"source_triangles": 639376,
|
"source_triangles": 639376,
|
||||||
"verified": true,
|
"verified": true,
|
||||||
@@ -414,9 +414,9 @@
|
|||||||
-747.7963166548619
|
-747.7963166548619
|
||||||
],
|
],
|
||||||
"logs": [
|
"logs": [
|
||||||
"Saved/Linux/l129/captures/L129/passage-1-2-0-rock-floor-station-3-mesh.log",
|
"Saved/Linux/l130/captures/L130/passage-1-2-0-rock-floor-station-3-mesh.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-1-2-0-rock-floor-station-3-render.log",
|
"Saved/Linux/l130/captures/L130/passage-1-2-0-rock-floor-station-3-render.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-1-2-0-rock-floor-station-3-quality.log"
|
"Saved/Linux/l130/captures/L130/passage-1-2-0-rock-floor-station-3-quality.log"
|
||||||
],
|
],
|
||||||
"floor_anchor_position_m": [
|
"floor_anchor_position_m": [
|
||||||
-12.283352972838873,
|
-12.283352972838873,
|
||||||
@@ -460,9 +460,9 @@
|
|||||||
"route_length_m": 494.0722798830563,
|
"route_length_m": 494.0722798830563,
|
||||||
"planned_floor_m": -871.0755965556104,
|
"planned_floor_m": -871.0755965556104,
|
||||||
"planned_grade_deg": 10.274530613220444,
|
"planned_grade_deg": 10.274530613220444,
|
||||||
"variant": "L129-v226",
|
"variant": "L130-v227",
|
||||||
"capture": "captures/L129/passage-2-3-0-rock-floor-station-1.png",
|
"capture": "captures/L130/passage-2-3-0-rock-floor-station-1.png",
|
||||||
"scene": "Saved/Linux/l129/captures/L129/passage-2-3-0-rock-floor-station-1.vfmesh",
|
"scene": "Saved/Linux/l130/captures/L130/passage-2-3-0-rock-floor-station-1.vfmesh",
|
||||||
"drawn_triangles": 474964,
|
"drawn_triangles": 474964,
|
||||||
"source_triangles": 502362,
|
"source_triangles": 502362,
|
||||||
"verified": true,
|
"verified": true,
|
||||||
@@ -486,9 +486,9 @@
|
|||||||
-871.0755965556104
|
-871.0755965556104
|
||||||
],
|
],
|
||||||
"logs": [
|
"logs": [
|
||||||
"Saved/Linux/l129/captures/L129/passage-2-3-0-rock-floor-station-1-mesh.log",
|
"Saved/Linux/l130/captures/L130/passage-2-3-0-rock-floor-station-1-mesh.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-2-3-0-rock-floor-station-1-render.log",
|
"Saved/Linux/l130/captures/L130/passage-2-3-0-rock-floor-station-1-render.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-2-3-0-rock-floor-station-1-quality.log"
|
"Saved/Linux/l130/captures/L130/passage-2-3-0-rock-floor-station-1-quality.log"
|
||||||
],
|
],
|
||||||
"floor_anchor_position_m": [
|
"floor_anchor_position_m": [
|
||||||
9.103799793973732,
|
9.103799793973732,
|
||||||
@@ -532,9 +532,9 @@
|
|||||||
"route_length_m": 494.0722798830563,
|
"route_length_m": 494.0722798830563,
|
||||||
"planned_floor_m": -872.8561420785873,
|
"planned_floor_m": -872.8561420785873,
|
||||||
"planned_grade_deg": 10.266334408339132,
|
"planned_grade_deg": 10.266334408339132,
|
||||||
"variant": "L129-v226",
|
"variant": "L130-v227",
|
||||||
"capture": "captures/L129/passage-2-3-0-rock-floor-station-2.png",
|
"capture": "captures/L130/passage-2-3-0-rock-floor-station-2.png",
|
||||||
"scene": "Saved/Linux/l129/captures/L129/passage-2-3-0-rock-floor-station-2.vfmesh",
|
"scene": "Saved/Linux/l130/captures/L130/passage-2-3-0-rock-floor-station-2.vfmesh",
|
||||||
"drawn_triangles": 494504,
|
"drawn_triangles": 494504,
|
||||||
"source_triangles": 524342,
|
"source_triangles": 524342,
|
||||||
"verified": true,
|
"verified": true,
|
||||||
@@ -558,9 +558,9 @@
|
|||||||
-872.8561420785873
|
-872.8561420785873
|
||||||
],
|
],
|
||||||
"logs": [
|
"logs": [
|
||||||
"Saved/Linux/l129/captures/L129/passage-2-3-0-rock-floor-station-2-mesh.log",
|
"Saved/Linux/l130/captures/L130/passage-2-3-0-rock-floor-station-2-mesh.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-2-3-0-rock-floor-station-2-render.log",
|
"Saved/Linux/l130/captures/L130/passage-2-3-0-rock-floor-station-2-render.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-2-3-0-rock-floor-station-2-quality.log"
|
"Saved/Linux/l130/captures/L130/passage-2-3-0-rock-floor-station-2-quality.log"
|
||||||
],
|
],
|
||||||
"floor_anchor_position_m": [
|
"floor_anchor_position_m": [
|
||||||
15.204108325185125,
|
15.204108325185125,
|
||||||
@@ -604,9 +604,9 @@
|
|||||||
"route_length_m": 494.0722798830563,
|
"route_length_m": 494.0722798830563,
|
||||||
"planned_floor_m": -874.6379150751349,
|
"planned_floor_m": -874.6379150751349,
|
||||||
"planned_grade_deg": 10.259484647608062,
|
"planned_grade_deg": 10.259484647608062,
|
||||||
"variant": "L129-v226",
|
"variant": "L130-v227",
|
||||||
"capture": "captures/L129/passage-2-3-0-rock-floor-station-3.png",
|
"capture": "captures/L130/passage-2-3-0-rock-floor-station-3.png",
|
||||||
"scene": "Saved/Linux/l129/captures/L129/passage-2-3-0-rock-floor-station-3.vfmesh",
|
"scene": "Saved/Linux/l130/captures/L130/passage-2-3-0-rock-floor-station-3.vfmesh",
|
||||||
"drawn_triangles": 485356,
|
"drawn_triangles": 485356,
|
||||||
"source_triangles": 512664,
|
"source_triangles": 512664,
|
||||||
"verified": true,
|
"verified": true,
|
||||||
@@ -630,9 +630,9 @@
|
|||||||
-874.6379150751349
|
-874.6379150751349
|
||||||
],
|
],
|
||||||
"logs": [
|
"logs": [
|
||||||
"Saved/Linux/l129/captures/L129/passage-2-3-0-rock-floor-station-3-mesh.log",
|
"Saved/Linux/l130/captures/L130/passage-2-3-0-rock-floor-station-3-mesh.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-2-3-0-rock-floor-station-3-render.log",
|
"Saved/Linux/l130/captures/L130/passage-2-3-0-rock-floor-station-3-render.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-2-3-0-rock-floor-station-3-quality.log"
|
"Saved/Linux/l130/captures/L130/passage-2-3-0-rock-floor-station-3-quality.log"
|
||||||
],
|
],
|
||||||
"floor_anchor_position_m": [
|
"floor_anchor_position_m": [
|
||||||
15.464091528009144,
|
15.464091528009144,
|
||||||
@@ -682,9 +682,9 @@
|
|||||||
"route_distance_m": 8.3545,
|
"route_distance_m": 8.3545,
|
||||||
"requested_route_distance_m": 8.3545,
|
"requested_route_distance_m": 8.3545,
|
||||||
"route_length_m": 2026.6238040154117,
|
"route_length_m": 2026.6238040154117,
|
||||||
"variant": "L129-v226",
|
"variant": "L130-v227",
|
||||||
"capture": "captures/L129/passage-0-1-0-openair-1-4m-outside.png",
|
"capture": "captures/L130/passage-0-1-0-openair-1-4m-outside.png",
|
||||||
"scene": "Saved/Linux/l129/captures/L129/passage-0-1-0-openair-1-4m-outside.vfmesh",
|
"scene": "Saved/Linux/l130/captures/L130/passage-0-1-0-openair-1-4m-outside.vfmesh",
|
||||||
"drawn_triangles": 275333,
|
"drawn_triangles": 275333,
|
||||||
"source_triangles": 327745,
|
"source_triangles": 327745,
|
||||||
"verified": true,
|
"verified": true,
|
||||||
@@ -708,9 +708,9 @@
|
|||||||
-373.75
|
-373.75
|
||||||
],
|
],
|
||||||
"logs": [
|
"logs": [
|
||||||
"Saved/Linux/l129/captures/L129/passage-0-1-0-openair-1-4m-outside-mesh.log",
|
"Saved/Linux/l130/captures/L130/passage-0-1-0-openair-1-4m-outside-mesh.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-0-1-0-openair-1-4m-outside-render.log",
|
"Saved/Linux/l130/captures/L130/passage-0-1-0-openair-1-4m-outside-render.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-0-1-0-openair-1-4m-outside-quality.log"
|
"Saved/Linux/l130/captures/L130/passage-0-1-0-openair-1-4m-outside-quality.log"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -747,9 +747,9 @@
|
|||||||
"route_distance_m": 8.3545,
|
"route_distance_m": 8.3545,
|
||||||
"requested_route_distance_m": 8.3545,
|
"requested_route_distance_m": 8.3545,
|
||||||
"route_length_m": 2026.6238040154117,
|
"route_length_m": 2026.6238040154117,
|
||||||
"variant": "L129-v226",
|
"variant": "L130-v227",
|
||||||
"capture": "captures/L129/passage-0-1-0-openair-1-4m-interior-wall.png",
|
"capture": "captures/L130/passage-0-1-0-openair-1-4m-interior-wall.png",
|
||||||
"scene": "Saved/Linux/l129/captures/L129/passage-0-1-0-openair-1-4m-interior-wall.vfmesh",
|
"scene": "Saved/Linux/l130/captures/L130/passage-0-1-0-openair-1-4m-interior-wall.vfmesh",
|
||||||
"drawn_triangles": 308012,
|
"drawn_triangles": 308012,
|
||||||
"source_triangles": 368124,
|
"source_triangles": 368124,
|
||||||
"verified": true,
|
"verified": true,
|
||||||
@@ -773,9 +773,9 @@
|
|||||||
-373.75
|
-373.75
|
||||||
],
|
],
|
||||||
"logs": [
|
"logs": [
|
||||||
"Saved/Linux/l129/captures/L129/passage-0-1-0-openair-1-4m-interior-wall-mesh.log",
|
"Saved/Linux/l130/captures/L130/passage-0-1-0-openair-1-4m-interior-wall-mesh.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-0-1-0-openair-1-4m-interior-wall-render.log",
|
"Saved/Linux/l130/captures/L130/passage-0-1-0-openair-1-4m-interior-wall-render.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-0-1-0-openair-1-4m-interior-wall-quality.log"
|
"Saved/Linux/l130/captures/L130/passage-0-1-0-openair-1-4m-interior-wall-quality.log"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -812,9 +812,9 @@
|
|||||||
"route_distance_m": 14.4925,
|
"route_distance_m": 14.4925,
|
||||||
"requested_route_distance_m": 14.4925,
|
"requested_route_distance_m": 14.4925,
|
||||||
"route_length_m": 2026.6238040154117,
|
"route_length_m": 2026.6238040154117,
|
||||||
"variant": "L129-v226",
|
"variant": "L130-v227",
|
||||||
"capture": "captures/L129/passage-0-1-0-openair-2-4m-outside.png",
|
"capture": "captures/L130/passage-0-1-0-openair-2-4m-outside.png",
|
||||||
"scene": "Saved/Linux/l129/captures/L129/passage-0-1-0-openair-2-4m-outside.vfmesh",
|
"scene": "Saved/Linux/l130/captures/L130/passage-0-1-0-openair-2-4m-outside.vfmesh",
|
||||||
"drawn_triangles": 275333,
|
"drawn_triangles": 275333,
|
||||||
"source_triangles": 327745,
|
"source_triangles": 327745,
|
||||||
"verified": true,
|
"verified": true,
|
||||||
@@ -838,9 +838,9 @@
|
|||||||
-376.0
|
-376.0
|
||||||
],
|
],
|
||||||
"logs": [
|
"logs": [
|
||||||
"Saved/Linux/l129/captures/L129/passage-0-1-0-openair-2-4m-outside-mesh.log",
|
"Saved/Linux/l130/captures/L130/passage-0-1-0-openair-2-4m-outside-mesh.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-0-1-0-openair-2-4m-outside-render.log",
|
"Saved/Linux/l130/captures/L130/passage-0-1-0-openair-2-4m-outside-render.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-0-1-0-openair-2-4m-outside-quality.log"
|
"Saved/Linux/l130/captures/L130/passage-0-1-0-openair-2-4m-outside-quality.log"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -877,9 +877,9 @@
|
|||||||
"route_distance_m": 14.4925,
|
"route_distance_m": 14.4925,
|
||||||
"requested_route_distance_m": 14.4925,
|
"requested_route_distance_m": 14.4925,
|
||||||
"route_length_m": 2026.6238040154117,
|
"route_length_m": 2026.6238040154117,
|
||||||
"variant": "L129-v226",
|
"variant": "L130-v227",
|
||||||
"capture": "captures/L129/passage-0-1-0-openair-2-4m-interior-wall.png",
|
"capture": "captures/L130/passage-0-1-0-openair-2-4m-interior-wall.png",
|
||||||
"scene": "Saved/Linux/l129/captures/L129/passage-0-1-0-openair-2-4m-interior-wall.vfmesh",
|
"scene": "Saved/Linux/l130/captures/L130/passage-0-1-0-openair-2-4m-interior-wall.vfmesh",
|
||||||
"drawn_triangles": 345026,
|
"drawn_triangles": 345026,
|
||||||
"source_triangles": 414658,
|
"source_triangles": 414658,
|
||||||
"verified": true,
|
"verified": true,
|
||||||
@@ -903,9 +903,9 @@
|
|||||||
-376.0
|
-376.0
|
||||||
],
|
],
|
||||||
"logs": [
|
"logs": [
|
||||||
"Saved/Linux/l129/captures/L129/passage-0-1-0-openair-2-4m-interior-wall-mesh.log",
|
"Saved/Linux/l130/captures/L130/passage-0-1-0-openair-2-4m-interior-wall-mesh.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-0-1-0-openair-2-4m-interior-wall-render.log",
|
"Saved/Linux/l130/captures/L130/passage-0-1-0-openair-2-4m-interior-wall-render.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-0-1-0-openair-2-4m-interior-wall-quality.log"
|
"Saved/Linux/l130/captures/L130/passage-0-1-0-openair-2-4m-interior-wall-quality.log"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -942,9 +942,9 @@
|
|||||||
"route_distance_m": 1265.3425000000002,
|
"route_distance_m": 1265.3425000000002,
|
||||||
"requested_route_distance_m": 1265.3425000000002,
|
"requested_route_distance_m": 1265.3425000000002,
|
||||||
"route_length_m": 2026.6238040154117,
|
"route_length_m": 2026.6238040154117,
|
||||||
"variant": "L129-v226",
|
"variant": "L130-v227",
|
||||||
"capture": "captures/L129/passage-0-1-0-openair-3-4m-outside.png",
|
"capture": "captures/L130/passage-0-1-0-openair-3-4m-outside.png",
|
||||||
"scene": "Saved/Linux/l129/captures/L129/passage-0-1-0-openair-3-4m-outside.vfmesh",
|
"scene": "Saved/Linux/l130/captures/L130/passage-0-1-0-openair-3-4m-outside.vfmesh",
|
||||||
"drawn_triangles": 149234,
|
"drawn_triangles": 149234,
|
||||||
"source_triangles": 181128,
|
"source_triangles": 181128,
|
||||||
"verified": true,
|
"verified": true,
|
||||||
@@ -968,9 +968,9 @@
|
|||||||
-600.5734332352072
|
-600.5734332352072
|
||||||
],
|
],
|
||||||
"logs": [
|
"logs": [
|
||||||
"Saved/Linux/l129/captures/L129/passage-0-1-0-openair-3-4m-outside-mesh.log",
|
"Saved/Linux/l130/captures/L130/passage-0-1-0-openair-3-4m-outside-mesh.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-0-1-0-openair-3-4m-outside-render.log",
|
"Saved/Linux/l130/captures/L130/passage-0-1-0-openair-3-4m-outside-render.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-0-1-0-openair-3-4m-outside-quality.log"
|
"Saved/Linux/l130/captures/L130/passage-0-1-0-openair-3-4m-outside-quality.log"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1007,9 +1007,9 @@
|
|||||||
"route_distance_m": 1265.3425000000002,
|
"route_distance_m": 1265.3425000000002,
|
||||||
"requested_route_distance_m": 1265.3425000000002,
|
"requested_route_distance_m": 1265.3425000000002,
|
||||||
"route_length_m": 2026.6238040154117,
|
"route_length_m": 2026.6238040154117,
|
||||||
"variant": "L129-v226",
|
"variant": "L130-v227",
|
||||||
"capture": "captures/L129/passage-0-1-0-openair-3-4m-interior-wall.png",
|
"capture": "captures/L130/passage-0-1-0-openair-3-4m-interior-wall.png",
|
||||||
"scene": "Saved/Linux/l129/captures/L129/passage-0-1-0-openair-3-4m-interior-wall.vfmesh",
|
"scene": "Saved/Linux/l130/captures/L130/passage-0-1-0-openair-3-4m-interior-wall.vfmesh",
|
||||||
"drawn_triangles": 148100,
|
"drawn_triangles": 148100,
|
||||||
"source_triangles": 180244,
|
"source_triangles": 180244,
|
||||||
"verified": true,
|
"verified": true,
|
||||||
@@ -1033,9 +1033,9 @@
|
|||||||
-600.6947104389109
|
-600.6947104389109
|
||||||
],
|
],
|
||||||
"logs": [
|
"logs": [
|
||||||
"Saved/Linux/l129/captures/L129/passage-0-1-0-openair-3-4m-interior-wall-mesh.log",
|
"Saved/Linux/l130/captures/L130/passage-0-1-0-openair-3-4m-interior-wall-mesh.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-0-1-0-openair-3-4m-interior-wall-render.log",
|
"Saved/Linux/l130/captures/L130/passage-0-1-0-openair-3-4m-interior-wall-render.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-0-1-0-openair-3-4m-interior-wall-quality.log"
|
"Saved/Linux/l130/captures/L130/passage-0-1-0-openair-3-4m-interior-wall-quality.log"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1072,9 +1072,9 @@
|
|||||||
"route_distance_m": 83.504,
|
"route_distance_m": 83.504,
|
||||||
"requested_route_distance_m": 83.504,
|
"requested_route_distance_m": 83.504,
|
||||||
"route_length_m": 114.99063175809309,
|
"route_length_m": 114.99063175809309,
|
||||||
"variant": "L129-v226",
|
"variant": "L130-v227",
|
||||||
"capture": "captures/L129/passage-1-2-0-openair-1-4m-outside.png",
|
"capture": "captures/L130/passage-1-2-0-openair-1-4m-outside.png",
|
||||||
"scene": "Saved/Linux/l129/captures/L129/passage-1-2-0-openair-1-4m-outside.vfmesh",
|
"scene": "Saved/Linux/l130/captures/L130/passage-1-2-0-openair-1-4m-outside.vfmesh",
|
||||||
"drawn_triangles": 620814,
|
"drawn_triangles": 620814,
|
||||||
"source_triangles": 684776,
|
"source_triangles": 684776,
|
||||||
"verified": true,
|
"verified": true,
|
||||||
@@ -1098,9 +1098,9 @@
|
|||||||
-747.5006103515625
|
-747.5006103515625
|
||||||
],
|
],
|
||||||
"logs": [
|
"logs": [
|
||||||
"Saved/Linux/l129/captures/L129/passage-1-2-0-openair-1-4m-outside-mesh.log",
|
"Saved/Linux/l130/captures/L130/passage-1-2-0-openair-1-4m-outside-mesh.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-1-2-0-openair-1-4m-outside-render.log",
|
"Saved/Linux/l130/captures/L130/passage-1-2-0-openair-1-4m-outside-render.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-1-2-0-openair-1-4m-outside-quality.log"
|
"Saved/Linux/l130/captures/L130/passage-1-2-0-openair-1-4m-outside-quality.log"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1137,9 +1137,9 @@
|
|||||||
"route_distance_m": 83.504,
|
"route_distance_m": 83.504,
|
||||||
"requested_route_distance_m": 83.504,
|
"requested_route_distance_m": 83.504,
|
||||||
"route_length_m": 114.99063175809309,
|
"route_length_m": 114.99063175809309,
|
||||||
"variant": "L129-v226",
|
"variant": "L130-v227",
|
||||||
"capture": "captures/L129/passage-1-2-0-openair-1-4m-interior-wall.png",
|
"capture": "captures/L130/passage-1-2-0-openair-1-4m-interior-wall.png",
|
||||||
"scene": "Saved/Linux/l129/captures/L129/passage-1-2-0-openair-1-4m-interior-wall.vfmesh",
|
"scene": "Saved/Linux/l130/captures/L130/passage-1-2-0-openair-1-4m-interior-wall.vfmesh",
|
||||||
"drawn_triangles": 609757,
|
"drawn_triangles": 609757,
|
||||||
"source_triangles": 668131,
|
"source_triangles": 668131,
|
||||||
"verified": true,
|
"verified": true,
|
||||||
@@ -1163,9 +1163,9 @@
|
|||||||
-748.1744141343152
|
-748.1744141343152
|
||||||
],
|
],
|
||||||
"logs": [
|
"logs": [
|
||||||
"Saved/Linux/l129/captures/L129/passage-1-2-0-openair-1-4m-interior-wall-mesh.log",
|
"Saved/Linux/l130/captures/L130/passage-1-2-0-openair-1-4m-interior-wall-mesh.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-1-2-0-openair-1-4m-interior-wall-render.log",
|
"Saved/Linux/l130/captures/L130/passage-1-2-0-openair-1-4m-interior-wall-render.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-1-2-0-openair-1-4m-interior-wall-quality.log"
|
"Saved/Linux/l130/captures/L130/passage-1-2-0-openair-1-4m-interior-wall-quality.log"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1202,9 +1202,9 @@
|
|||||||
"route_distance_m": 104.362,
|
"route_distance_m": 104.362,
|
||||||
"requested_route_distance_m": 104.362,
|
"requested_route_distance_m": 104.362,
|
||||||
"route_length_m": 114.99063175809309,
|
"route_length_m": 114.99063175809309,
|
||||||
"variant": "L129-v226",
|
"variant": "L130-v227",
|
||||||
"capture": "captures/L129/passage-1-2-0-openair-2-4m-outside.png",
|
"capture": "captures/L130/passage-1-2-0-openair-2-4m-outside.png",
|
||||||
"scene": "Saved/Linux/l129/captures/L129/passage-1-2-0-openair-2-4m-outside.vfmesh",
|
"scene": "Saved/Linux/l130/captures/L130/passage-1-2-0-openair-2-4m-outside.vfmesh",
|
||||||
"drawn_triangles": 584542,
|
"drawn_triangles": 584542,
|
||||||
"source_triangles": 637002,
|
"source_triangles": 637002,
|
||||||
"verified": true,
|
"verified": true,
|
||||||
@@ -1228,9 +1228,9 @@
|
|||||||
-752.0293187551489
|
-752.0293187551489
|
||||||
],
|
],
|
||||||
"logs": [
|
"logs": [
|
||||||
"Saved/Linux/l129/captures/L129/passage-1-2-0-openair-2-4m-outside-mesh.log",
|
"Saved/Linux/l130/captures/L130/passage-1-2-0-openair-2-4m-outside-mesh.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-1-2-0-openair-2-4m-outside-render.log",
|
"Saved/Linux/l130/captures/L130/passage-1-2-0-openair-2-4m-outside-render.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-1-2-0-openair-2-4m-outside-quality.log"
|
"Saved/Linux/l130/captures/L130/passage-1-2-0-openair-2-4m-outside-quality.log"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1267,9 +1267,9 @@
|
|||||||
"route_distance_m": 104.362,
|
"route_distance_m": 104.362,
|
||||||
"requested_route_distance_m": 104.362,
|
"requested_route_distance_m": 104.362,
|
||||||
"route_length_m": 114.99063175809309,
|
"route_length_m": 114.99063175809309,
|
||||||
"variant": "L129-v226",
|
"variant": "L130-v227",
|
||||||
"capture": "captures/L129/passage-1-2-0-openair-2-4m-interior-wall.png",
|
"capture": "captures/L130/passage-1-2-0-openair-2-4m-interior-wall.png",
|
||||||
"scene": "Saved/Linux/l129/captures/L129/passage-1-2-0-openair-2-4m-interior-wall.vfmesh",
|
"scene": "Saved/Linux/l130/captures/L130/passage-1-2-0-openair-2-4m-interior-wall.vfmesh",
|
||||||
"drawn_triangles": 572258,
|
"drawn_triangles": 572258,
|
||||||
"source_triangles": 618646,
|
"source_triangles": 618646,
|
||||||
"verified": true,
|
"verified": true,
|
||||||
@@ -1293,9 +1293,9 @@
|
|||||||
-752.0074179101423
|
-752.0074179101423
|
||||||
],
|
],
|
||||||
"logs": [
|
"logs": [
|
||||||
"Saved/Linux/l129/captures/L129/passage-1-2-0-openair-2-4m-interior-wall-mesh.log",
|
"Saved/Linux/l130/captures/L130/passage-1-2-0-openair-2-4m-interior-wall-mesh.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-1-2-0-openair-2-4m-interior-wall-render.log",
|
"Saved/Linux/l130/captures/L130/passage-1-2-0-openair-2-4m-interior-wall-render.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-1-2-0-openair-2-4m-interior-wall-quality.log"
|
"Saved/Linux/l130/captures/L130/passage-1-2-0-openair-2-4m-interior-wall-quality.log"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1332,9 +1332,9 @@
|
|||||||
"route_distance_m": 16.616500000000002,
|
"route_distance_m": 16.616500000000002,
|
||||||
"requested_route_distance_m": 16.616500000000002,
|
"requested_route_distance_m": 16.616500000000002,
|
||||||
"route_length_m": 494.0722798830563,
|
"route_length_m": 494.0722798830563,
|
||||||
"variant": "L129-v226",
|
"variant": "L130-v227",
|
||||||
"capture": "captures/L129/passage-2-3-0-openair-1-4m-outside.png",
|
"capture": "captures/L130/passage-2-3-0-openair-1-4m-outside.png",
|
||||||
"scene": "Saved/Linux/l129/captures/L129/passage-2-3-0-openair-1-4m-outside.vfmesh",
|
"scene": "Saved/Linux/l130/captures/L130/passage-2-3-0-openair-1-4m-outside.vfmesh",
|
||||||
"drawn_triangles": 104612,
|
"drawn_triangles": 104612,
|
||||||
"source_triangles": 129326,
|
"source_triangles": 129326,
|
||||||
"verified": true,
|
"verified": true,
|
||||||
@@ -1358,9 +1358,9 @@
|
|||||||
-816.1078690565205
|
-816.1078690565205
|
||||||
],
|
],
|
||||||
"logs": [
|
"logs": [
|
||||||
"Saved/Linux/l129/captures/L129/passage-2-3-0-openair-1-4m-outside-mesh.log",
|
"Saved/Linux/l130/captures/L130/passage-2-3-0-openair-1-4m-outside-mesh.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-2-3-0-openair-1-4m-outside-render.log",
|
"Saved/Linux/l130/captures/L130/passage-2-3-0-openair-1-4m-outside-render.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-2-3-0-openair-1-4m-outside-quality.log"
|
"Saved/Linux/l130/captures/L130/passage-2-3-0-openair-1-4m-outside-quality.log"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1397,9 +1397,9 @@
|
|||||||
"route_distance_m": 16.616500000000002,
|
"route_distance_m": 16.616500000000002,
|
||||||
"requested_route_distance_m": 16.616500000000002,
|
"requested_route_distance_m": 16.616500000000002,
|
||||||
"route_length_m": 494.0722798830563,
|
"route_length_m": 494.0722798830563,
|
||||||
"variant": "L129-v226",
|
"variant": "L130-v227",
|
||||||
"capture": "captures/L129/passage-2-3-0-openair-1-4m-interior-wall.png",
|
"capture": "captures/L130/passage-2-3-0-openair-1-4m-interior-wall.png",
|
||||||
"scene": "Saved/Linux/l129/captures/L129/passage-2-3-0-openair-1-4m-interior-wall.vfmesh",
|
"scene": "Saved/Linux/l130/captures/L130/passage-2-3-0-openair-1-4m-interior-wall.vfmesh",
|
||||||
"drawn_triangles": 94962,
|
"drawn_triangles": 94962,
|
||||||
"source_triangles": 118028,
|
"source_triangles": 118028,
|
||||||
"verified": true,
|
"verified": true,
|
||||||
@@ -1423,9 +1423,9 @@
|
|||||||
-815.6327986602337
|
-815.6327986602337
|
||||||
],
|
],
|
||||||
"logs": [
|
"logs": [
|
||||||
"Saved/Linux/l129/captures/L129/passage-2-3-0-openair-1-4m-interior-wall-mesh.log",
|
"Saved/Linux/l130/captures/L130/passage-2-3-0-openair-1-4m-interior-wall-mesh.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-2-3-0-openair-1-4m-interior-wall-render.log",
|
"Saved/Linux/l130/captures/L130/passage-2-3-0-openair-1-4m-interior-wall-render.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-2-3-0-openair-1-4m-interior-wall-quality.log"
|
"Saved/Linux/l130/captures/L130/passage-2-3-0-openair-1-4m-interior-wall-quality.log"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1462,9 +1462,9 @@
|
|||||||
"route_distance_m": 374.929,
|
"route_distance_m": 374.929,
|
||||||
"requested_route_distance_m": 374.929,
|
"requested_route_distance_m": 374.929,
|
||||||
"route_length_m": 494.0722798830563,
|
"route_length_m": 494.0722798830563,
|
||||||
"variant": "L129-v226",
|
"variant": "L130-v227",
|
||||||
"capture": "captures/L129/passage-2-3-0-openair-2-4m-outside.png",
|
"capture": "captures/L130/passage-2-3-0-openair-2-4m-outside.png",
|
||||||
"scene": "Saved/Linux/l129/captures/L129/passage-2-3-0-openair-2-4m-outside.vfmesh",
|
"scene": "Saved/Linux/l130/captures/L130/passage-2-3-0-openair-2-4m-outside.vfmesh",
|
||||||
"drawn_triangles": 475860,
|
"drawn_triangles": 475860,
|
||||||
"source_triangles": 504244,
|
"source_triangles": 504244,
|
||||||
"verified": true,
|
"verified": true,
|
||||||
@@ -1488,9 +1488,9 @@
|
|||||||
-879.7662205769708
|
-879.7662205769708
|
||||||
],
|
],
|
||||||
"logs": [
|
"logs": [
|
||||||
"Saved/Linux/l129/captures/L129/passage-2-3-0-openair-2-4m-outside-mesh.log",
|
"Saved/Linux/l130/captures/L130/passage-2-3-0-openair-2-4m-outside-mesh.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-2-3-0-openair-2-4m-outside-render.log",
|
"Saved/Linux/l130/captures/L130/passage-2-3-0-openair-2-4m-outside-render.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-2-3-0-openair-2-4m-outside-quality.log"
|
"Saved/Linux/l130/captures/L130/passage-2-3-0-openair-2-4m-outside-quality.log"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1527,9 +1527,9 @@
|
|||||||
"route_distance_m": 374.929,
|
"route_distance_m": 374.929,
|
||||||
"requested_route_distance_m": 374.929,
|
"requested_route_distance_m": 374.929,
|
||||||
"route_length_m": 494.0722798830563,
|
"route_length_m": 494.0722798830563,
|
||||||
"variant": "L129-v226",
|
"variant": "L130-v227",
|
||||||
"capture": "captures/L129/passage-2-3-0-openair-2-4m-interior-wall.png",
|
"capture": "captures/L130/passage-2-3-0-openair-2-4m-interior-wall.png",
|
||||||
"scene": "Saved/Linux/l129/captures/L129/passage-2-3-0-openair-2-4m-interior-wall.vfmesh",
|
"scene": "Saved/Linux/l130/captures/L130/passage-2-3-0-openair-2-4m-interior-wall.vfmesh",
|
||||||
"drawn_triangles": 486480,
|
"drawn_triangles": 486480,
|
||||||
"source_triangles": 513552,
|
"source_triangles": 513552,
|
||||||
"verified": true,
|
"verified": true,
|
||||||
@@ -1553,9 +1553,9 @@
|
|||||||
-879.75
|
-879.75
|
||||||
],
|
],
|
||||||
"logs": [
|
"logs": [
|
||||||
"Saved/Linux/l129/captures/L129/passage-2-3-0-openair-2-4m-interior-wall-mesh.log",
|
"Saved/Linux/l130/captures/L130/passage-2-3-0-openair-2-4m-interior-wall-mesh.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-2-3-0-openair-2-4m-interior-wall-render.log",
|
"Saved/Linux/l130/captures/L130/passage-2-3-0-openair-2-4m-interior-wall-render.log",
|
||||||
"Saved/Linux/l129/captures/L129/passage-2-3-0-openair-2-4m-interior-wall-quality.log"
|
"Saved/Linux/l130/captures/L130/passage-2-3-0-openair-2-4m-interior-wall-quality.log"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<!doctype html><meta charset='utf-8'><title>L130 mouth closeups</title><style>body{font:14px system-ui;margin:24px;background:#17191d;color:#eee}section{margin:28px 0}div{display:grid;grid-template-columns:1fr 1fr;gap:12px}img{width:100%;height:auto}p{color:#bbb}</style><h1>L129 mouth closeups: b96dd73 vs L130</h1><section><h2>passage-0-1-0-lower-mouth</h2><p>byte identical: true</p><div><figure><figcaption>b96dd73 source mesh</figcaption><img src='b96dd73/passage-0-1-0-lower-mouth.png'></figure><figure><figcaption>L130 reach units</figcaption><img src='L130/passage-0-1-0-lower-mouth.png'></figure></div></section>
|
||||||
|
<section><h2>passage-0-1-0-upper-mouth</h2><p>byte identical: true</p><div><figure><figcaption>b96dd73 source mesh</figcaption><img src='b96dd73/passage-0-1-0-upper-mouth.png'></figure><figure><figcaption>L130 reach units</figcaption><img src='L130/passage-0-1-0-upper-mouth.png'></figure></div></section>
|
||||||
|
<section><h2>passage-1-2-0-lower-mouth</h2><p>byte identical: true</p><div><figure><figcaption>b96dd73 source mesh</figcaption><img src='b96dd73/passage-1-2-0-lower-mouth.png'></figure><figure><figcaption>L130 reach units</figcaption><img src='L130/passage-1-2-0-lower-mouth.png'></figure></div></section>
|
||||||
|
<section><h2>passage-1-2-0-upper-mouth</h2><p>byte identical: true</p><div><figure><figcaption>b96dd73 source mesh</figcaption><img src='b96dd73/passage-1-2-0-upper-mouth.png'></figure><figure><figcaption>L130 reach units</figcaption><img src='L130/passage-1-2-0-upper-mouth.png'></figure></div></section>
|
||||||
|
<section><h2>passage-2-3-0-lower-mouth</h2><p>byte identical: true</p><div><figure><figcaption>b96dd73 source mesh</figcaption><img src='b96dd73/passage-2-3-0-lower-mouth.png'></figure><figure><figcaption>L130 reach units</figcaption><img src='L130/passage-2-3-0-lower-mouth.png'></figure></div></section>
|
||||||
|
<section><h2>passage-2-3-0-upper-mouth</h2><p>byte identical: true</p><div><figure><figcaption>b96dd73 source mesh</figcaption><img src='b96dd73/passage-2-3-0-upper-mouth.png'></figure><figure><figcaption>L130 reach units</figcaption><img src='L130/passage-2-3-0-upper-mouth.png'></figure></div></section>
|
||||||
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 225 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 187 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 225 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 187 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 44 KiB |
@@ -0,0 +1,134 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "passage-0-1-0-lower-mouth",
|
||||||
|
"camera_m": [
|
||||||
|
32.688347,
|
||||||
|
9.553723,
|
||||||
|
-735.48053
|
||||||
|
],
|
||||||
|
"yaw_deg": -132.845,
|
||||||
|
"pitch_deg": -6.052,
|
||||||
|
"height_center_m": -736.267,
|
||||||
|
"source_mesh": "Saved/Linux/l129/captures/mouth-closeups/before/passage-0-1-0-lower-mouth.vfmesh",
|
||||||
|
"candidate_mesh": "Saved/Linux/l130/captures/mouth-closeups/L130/passage-0-1-0-lower-mouth.vfmesh",
|
||||||
|
"baseline_png": "Standalone/Research/WorldAssemblerM3/Linux130/captures/mouth-closeups/b96dd73/passage-0-1-0-lower-mouth.png",
|
||||||
|
"candidate_png": "Standalone/Research/WorldAssemblerM3/Linux130/captures/mouth-closeups/L130/passage-0-1-0-lower-mouth.png",
|
||||||
|
"baseline_sha256": "aff7310b94e1b57e9cd1e42d3294e10964aed4a56e74bec8c1cdc0a5b2bffa98",
|
||||||
|
"candidate_sha256": "aff7310b94e1b57e9cd1e42d3294e10964aed4a56e74bec8c1cdc0a5b2bffa98",
|
||||||
|
"byte_identical": true,
|
||||||
|
"drawn_triangles": {
|
||||||
|
"b96dd73": 549170,
|
||||||
|
"L130": 549170
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "passage-0-1-0-upper-mouth",
|
||||||
|
"camera_m": [
|
||||||
|
8.324777,
|
||||||
|
20.450708,
|
||||||
|
-371.84259
|
||||||
|
],
|
||||||
|
"yaw_deg": -175.826,
|
||||||
|
"pitch_deg": -0.889,
|
||||||
|
"height_center_m": -372.122,
|
||||||
|
"source_mesh": "Saved/Linux/l129/captures/mouth-closeups/before/passage-0-1-0-upper-mouth.vfmesh",
|
||||||
|
"candidate_mesh": "Saved/Linux/l130/captures/mouth-closeups/L130/passage-0-1-0-upper-mouth.vfmesh",
|
||||||
|
"baseline_png": "Standalone/Research/WorldAssemblerM3/Linux130/captures/mouth-closeups/b96dd73/passage-0-1-0-upper-mouth.png",
|
||||||
|
"candidate_png": "Standalone/Research/WorldAssemblerM3/Linux130/captures/mouth-closeups/L130/passage-0-1-0-upper-mouth.png",
|
||||||
|
"baseline_sha256": "76dbb3263eb4f2018d13496f42b6eff7eb875e2029358776e22337aea8893a6d",
|
||||||
|
"candidate_sha256": "76dbb3263eb4f2018d13496f42b6eff7eb875e2029358776e22337aea8893a6d",
|
||||||
|
"byte_identical": true,
|
||||||
|
"drawn_triangles": {
|
||||||
|
"b96dd73": 243380,
|
||||||
|
"L130": 243380
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "passage-1-2-0-lower-mouth",
|
||||||
|
"camera_m": [
|
||||||
|
27.129938,
|
||||||
|
-19.07345,
|
||||||
|
-751.877197
|
||||||
|
],
|
||||||
|
"yaw_deg": -58.537,
|
||||||
|
"pitch_deg": -5.944,
|
||||||
|
"height_center_m": -751.734,
|
||||||
|
"source_mesh": "Saved/Linux/l129/captures/mouth-closeups/before/passage-1-2-0-lower-mouth.vfmesh",
|
||||||
|
"candidate_mesh": "Saved/Linux/l130/captures/mouth-closeups/L130/passage-1-2-0-lower-mouth.vfmesh",
|
||||||
|
"baseline_png": "Standalone/Research/WorldAssemblerM3/Linux130/captures/mouth-closeups/b96dd73/passage-1-2-0-lower-mouth.png",
|
||||||
|
"candidate_png": "Standalone/Research/WorldAssemblerM3/Linux130/captures/mouth-closeups/L130/passage-1-2-0-lower-mouth.png",
|
||||||
|
"baseline_sha256": "1c193b6fcb65b98b1c721704990392dc816486639e047b53bb72b4a17d89ae4c",
|
||||||
|
"candidate_sha256": "1c193b6fcb65b98b1c721704990392dc816486639e047b53bb72b4a17d89ae4c",
|
||||||
|
"byte_identical": true,
|
||||||
|
"drawn_triangles": {
|
||||||
|
"b96dd73": 544808,
|
||||||
|
"L130": 544808
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "passage-1-2-0-upper-mouth",
|
||||||
|
"camera_m": [
|
||||||
|
23.391808,
|
||||||
|
-15.509525,
|
||||||
|
-731.781067
|
||||||
|
],
|
||||||
|
"yaw_deg": -72.785,
|
||||||
|
"pitch_deg": -0.897,
|
||||||
|
"height_center_m": -730.561,
|
||||||
|
"source_mesh": "Saved/Linux/l129/captures/mouth-closeups/before/passage-1-2-0-upper-mouth.vfmesh",
|
||||||
|
"candidate_mesh": "Saved/Linux/l130/captures/mouth-closeups/L130/passage-1-2-0-upper-mouth.vfmesh",
|
||||||
|
"baseline_png": "Standalone/Research/WorldAssemblerM3/Linux130/captures/mouth-closeups/b96dd73/passage-1-2-0-upper-mouth.png",
|
||||||
|
"candidate_png": "Standalone/Research/WorldAssemblerM3/Linux130/captures/mouth-closeups/L130/passage-1-2-0-upper-mouth.png",
|
||||||
|
"baseline_sha256": "28576cefb1b59601d2e68981a7b77fc28a1d667c58ab27292deac0acd9deb338",
|
||||||
|
"candidate_sha256": "28576cefb1b59601d2e68981a7b77fc28a1d667c58ab27292deac0acd9deb338",
|
||||||
|
"byte_identical": true,
|
||||||
|
"drawn_triangles": {
|
||||||
|
"b96dd73": 593026,
|
||||||
|
"L130": 593026
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "passage-2-3-0-lower-mouth",
|
||||||
|
"camera_m": [
|
||||||
|
-28.589163,
|
||||||
|
-1.226313,
|
||||||
|
-898.811707
|
||||||
|
],
|
||||||
|
"yaw_deg": 114.256,
|
||||||
|
"pitch_deg": -6.159,
|
||||||
|
"height_center_m": -898.713,
|
||||||
|
"source_mesh": "Saved/Linux/l129/captures/mouth-closeups/before/passage-2-3-0-lower-mouth.vfmesh",
|
||||||
|
"candidate_mesh": "Saved/Linux/l130/captures/mouth-closeups/L130/passage-2-3-0-lower-mouth.vfmesh",
|
||||||
|
"baseline_png": "Standalone/Research/WorldAssemblerM3/Linux130/captures/mouth-closeups/b96dd73/passage-2-3-0-lower-mouth.png",
|
||||||
|
"candidate_png": "Standalone/Research/WorldAssemblerM3/Linux130/captures/mouth-closeups/L130/passage-2-3-0-lower-mouth.png",
|
||||||
|
"baseline_sha256": "58cd3ea88c754afab20d1cdcaf5f0edf676f0303d9f392d3632a6f2257205766",
|
||||||
|
"candidate_sha256": "58cd3ea88c754afab20d1cdcaf5f0edf676f0303d9f392d3632a6f2257205766",
|
||||||
|
"byte_identical": true,
|
||||||
|
"drawn_triangles": {
|
||||||
|
"b96dd73": 293832,
|
||||||
|
"L130": 293832
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "passage-2-3-0-upper-mouth",
|
||||||
|
"camera_m": [
|
||||||
|
-24.455027,
|
||||||
|
-5.631774,
|
||||||
|
-811.975403
|
||||||
|
],
|
||||||
|
"yaw_deg": 82.691,
|
||||||
|
"pitch_deg": -0.896,
|
||||||
|
"height_center_m": -810.755,
|
||||||
|
"source_mesh": "Saved/Linux/l129/captures/mouth-closeups/before/passage-2-3-0-upper-mouth.vfmesh",
|
||||||
|
"candidate_mesh": "Saved/Linux/l130/captures/mouth-closeups/L130/passage-2-3-0-upper-mouth.vfmesh",
|
||||||
|
"baseline_png": "Standalone/Research/WorldAssemblerM3/Linux130/captures/mouth-closeups/b96dd73/passage-2-3-0-upper-mouth.png",
|
||||||
|
"candidate_png": "Standalone/Research/WorldAssemblerM3/Linux130/captures/mouth-closeups/L130/passage-2-3-0-upper-mouth.png",
|
||||||
|
"baseline_sha256": "6b903c68fac1a20783185afbac8cdad717c6e9374e665e3618e118c5a6aadf51",
|
||||||
|
"candidate_sha256": "6b903c68fac1a20783185afbac8cdad717c6e9374e665e3618e118c5a6aadf51",
|
||||||
|
"byte_identical": true,
|
||||||
|
"drawn_triangles": {
|
||||||
|
"b96dd73": 59554,
|
||||||
|
"L130": 59554
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
[PipelineFullDetailHash] tiles=960 density=0x91931a57a067fd92 mesh=0xa818654be89790ac payload=0x370ff80451105a39 topology=0x06e507557aa70173
|
||||||
|
[PipelineWholeViewHash] tiles=2370 density=0xf4d3d09d3f31d9bc mesh=0x520f545165440f40 payload=0x6a45502e6bb7ae01 topology=0x8f7d03ba1e2000f3
|
||||||
|
[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=0x7640a0646ee5ac17 mesh=0x9b63c5aa29160969 payload=0x91cd7ca9a828149b topology=0xcb558843c345a327
|
||||||
|
[PipelineLODHash] lod=3 tiles=208 density=0xdd07fe8f31ede73a mesh=0xfaa2f90438226625 payload=0x86904d144f5db47c topology=0xcfd10c90d38f3fca
|
||||||
|
[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
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
[PipelineFullDetailHash] tiles=960 density=0x11802e529414a62a mesh=0xee7dab071f572c46 payload=0x824a7c07f3cd3f8f topology=0x14a372c4f0003a9b
|
||||||
|
[PipelineWholeViewHash] tiles=2578 density=0x077534532d13b549 mesh=0x0932314a7475fed4 payload=0x6c2bfa3e4a72f8dc topology=0x7e6b3b76ed31bd0f
|
||||||
|
[PipelineLODHash] lod=0 tiles=512 density=0xf8cbb499fca6f62b mesh=0xf3b8e097407eb9e1 payload=0xeef6bfe266279de5 topology=0x79c5ed3811360d1e
|
||||||
|
[PipelineLODHash] lod=1 tiles=448 density=0x7d95c955a8433cac mesh=0xa803bb427deeba9a payload=0xf4718f1ce85d4f4f topology=0x7b770585aafd8174
|
||||||
|
[PipelineLODHash] lod=2 tiles=320 density=0x1c9445d15cce0de3 mesh=0x4da3bcf40eb6d137 payload=0x561116e3bbf34b8e topology=0x5e0e5a961bea641e
|
||||||
|
[PipelineLODHash] lod=3 tiles=272 density=0xe505981dea225509 mesh=0x1b13027b94137ad0 payload=0x3f93cd2fda3fef1c topology=0x8e160cd2f5ab0805
|
||||||
|
[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
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
[PipelineFullDetailHash] tiles=960 density=0xace56c8f205238ad mesh=0xa9c603a1248de6b8 payload=0xea55f1f4fcc6a894 topology=0x5ea7bc78a1b678ae
|
||||||
|
[PipelineWholeViewHash] tiles=2370 density=0x03331b1721d89092 mesh=0x1fa61520dc6c6d7b payload=0xe5c306e087381056 topology=0xef499f11d87ca569
|
||||||
|
[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=0x8581c27a6966cccd mesh=0x610a6eb3ef75fe11 payload=0xdecaf47d125efd5c topology=0xa5ea883ebeb628e4
|
||||||
|
[PipelineLODHash] lod=3 tiles=208 density=0x5d87341a6428ea0b mesh=0x662096703512f5e2 payload=0x5703acca3ad9c2c7 topology=0xc8fb411f09c46f60
|
||||||
|
[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
|
||||||
@@ -122,11 +122,11 @@ RECIPE_RE = re.compile(
|
|||||||
|
|
||||||
def owner_hash_baseline(recipe: str, style: int) -> tuple[Path, str]:
|
def owner_hash_baseline(recipe: str, style: int) -> tuple[Path, str]:
|
||||||
if recipe == "surface-world" and style == 1:
|
if recipe == "surface-world" and style == 1:
|
||||||
return (BASELINES / "owner-hash/canonical/owner-hash-surface-world-style1-v225.baseline",
|
return (BASELINES / "owner-hash/canonical/owner-hash-surface-world-style1-v227.baseline",
|
||||||
"L125-v225-stamped-passage-sweep")
|
"L130-v227-reach-units")
|
||||||
if recipe == "floating-islands" and style == 2:
|
if recipe == "floating-islands" and style == 2:
|
||||||
return (BASELINES / "owner-hash/canonical/owner-hash-floating-islands-style2-v225.baseline",
|
return (BASELINES / "owner-hash/canonical/owner-hash-floating-islands-style2-v227.baseline",
|
||||||
"L125-v225-stamped-passage-sweep")
|
"L130-v227-reach-units")
|
||||||
raise VerificationFailure(f"no pinned owner hash baseline for {recipe} style {style}")
|
raise VerificationFailure(f"no pinned owner hash baseline for {recipe} style {style}")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||