wip(assembler): round S3 -- far ground from the native heightfield; LOD7/8 tiles 36-66% cheaper
Far-shell repair (81-96% of S2's LOD7/8 tile time) is skipped for certified SurfaceWorld tiles; ground and cap come from the shared planar heightfield. Near LOD0-3 hashes equal S2; far recipe version 1 salts LOD5+ identities. Cold first view 6.6 -> 3.4 s (aim 1.57 s). Not a visual sign-off: distant cap shows floating pieces, sprint streaming arrives late. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MmSoF64BbRFmk9C3p1VsBJ
This commit is contained in:
1 parent
6ddb834b1c
commit
d0f97bf79a
26 files changed
+976
-30
No files matched your search
@@ -15147,14 +15147,244 @@ bool RunCoreOffActorTest(const FExploreArguments& Arguments, FString& OutError)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RunCoreFarHorizonAgreementAudit(VoxelForgeCore::World& World,
|
||||
const std::vector<VoxelForgeCore::TileKey>& Keys,
|
||||
const VoxelForgeCore::WorldAssemblyManifest& Assembly,FString& OutError)
|
||||
{
|
||||
constexpr std::int64_t SubvoxelsPerVoxel=VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel;
|
||||
constexpr double ToleranceCm=2.0;
|
||||
constexpr double NegativeDatumOffsetCm=100.0;
|
||||
const double VoxelSizeCm=static_cast<double>(World.configuration().voxelSizeMicrons)/10000.0;
|
||||
using FXYKey=std::pair<std::int64_t,std::int64_t>;
|
||||
struct FGroundVertices { std::map<FXYKey,std::vector<std::int64_t>> ByXY; };
|
||||
const auto GatherGroundVertices=[&](const VoxelForgeCore::TileMesh& Mesh)
|
||||
{
|
||||
FGroundVertices Out;
|
||||
constexpr std::int64_t GridPeriod=128*SubvoxelsPerVoxel;
|
||||
for(const VoxelForgeCore::MeshVertex& Vertex:Mesh.vertices)
|
||||
{
|
||||
if(Vertex.normal.z<0.35)continue;
|
||||
const auto X=static_cast<std::int64_t>(std::llround(
|
||||
Vertex.position.x/VoxelSizeCm*SubvoxelsPerVoxel));
|
||||
const auto Y=static_cast<std::int64_t>(std::llround(
|
||||
Vertex.position.y/VoxelSizeCm*SubvoxelsPerVoxel));
|
||||
if(X%GridPeriod!=0||Y%GridPeriod!=0)continue;
|
||||
const auto Z=static_cast<std::int64_t>(std::llround(
|
||||
Vertex.position.z/VoxelSizeCm*SubvoxelsPerVoxel));
|
||||
Out.ByXY[{X,Y}].push_back(Z);
|
||||
}
|
||||
return Out;
|
||||
};
|
||||
const auto TileBounds=[](const VoxelForgeCore::TileKey& Key)
|
||||
{
|
||||
const std::int64_t Extent=static_cast<std::int64_t>(32)<<Key.lod;
|
||||
const std::int64_t X=static_cast<std::int64_t>(Key.coordinate.x)*Extent;
|
||||
const std::int64_t Y=static_cast<std::int64_t>(Key.coordinate.y)*Extent;
|
||||
const std::int64_t Z=static_cast<std::int64_t>(Key.coordinate.z)*Extent;
|
||||
return std::array<std::int64_t,6>{X,Y,Z,X+Extent,Y+Extent,Z+Extent};
|
||||
};
|
||||
struct FSample { std::int64_t X=0,Y=0,ProfileGround=0,Far7=0,Far8=0; };
|
||||
std::vector<FSample> Samples;
|
||||
std::string CoreError;
|
||||
VoxelForgeCore::TileGenerationOptions Options;
|
||||
Options.hashDensity=true;
|
||||
for(const auto& Key7:Keys)
|
||||
{
|
||||
if(Key7.lod!=7)continue;
|
||||
const auto Bounds7=TileBounds(Key7);
|
||||
for(const auto& Key8:Keys)
|
||||
{
|
||||
if(Key8.lod!=8)continue;
|
||||
const auto Bounds8=TileBounds(Key8);
|
||||
bool bTouches=true;
|
||||
for(int Axis=0;Axis<3;++Axis)
|
||||
bTouches=bTouches&&Bounds7[Axis]<=Bounds8[Axis+3]&&Bounds8[Axis]<=Bounds7[Axis+3];
|
||||
if(!bTouches)continue;
|
||||
const auto Mesh7=World.generateTile(Key7,Options,CoreError);
|
||||
const auto Mesh8=World.generateTile(Key8,Options,CoreError);
|
||||
if(!Mesh7||!Mesh8)
|
||||
{
|
||||
OutError=FString::Printf(TEXT("Far-horizon agreement tile generation failed: %s"),
|
||||
UTF8_TO_TCHAR(CoreError.c_str()));
|
||||
return false;
|
||||
}
|
||||
const FGroundVertices Ground7=GatherGroundVertices(*Mesh7);
|
||||
const FGroundVertices Ground8=GatherGroundVertices(*Mesh8);
|
||||
std::vector<FSample> PairSamples;
|
||||
for(const auto& Plan:Assembly.plan.strates)
|
||||
{
|
||||
const VoxelForgeCore::Heightfield2D Field(Assembly.recipe,Plan);
|
||||
if(!Field.isValid())continue;
|
||||
for(const auto& Pair:Ground7.ByXY)
|
||||
{
|
||||
const auto Other=Ground8.ByXY.find(Pair.first);
|
||||
if(Other==Ground8.ByXY.end())continue;
|
||||
const auto Column=Field.point(Pair.first.first,Pair.first.second,0);
|
||||
const std::int64_t Ground=Column.groundHeightSubvoxels;
|
||||
const std::int64_t Cap=Column.capHeightSubvoxels;
|
||||
if(Ground>=Cap)continue;
|
||||
const double GroundVoxel=static_cast<double>(Ground)/SubvoxelsPerVoxel;
|
||||
if(GroundVoxel<Bounds7[2]||GroundVoxel>Bounds7[5]
|
||||
||GroundVoxel<Bounds8[2]||GroundVoxel>Bounds8[5])continue;
|
||||
const auto Nearest=[Ground](const std::vector<std::int64_t>& Values)
|
||||
->std::optional<std::int64_t>
|
||||
{
|
||||
if(Values.empty())return std::nullopt;
|
||||
return *std::min_element(Values.begin(),Values.end(),[Ground](auto A,auto B)
|
||||
{return std::abs(A-Ground)<std::abs(B-Ground);});
|
||||
};
|
||||
const auto Z7=Nearest(Pair.second),Z8=Nearest(Other->second);
|
||||
if(Z7&&Z8)PairSamples.push_back({Pair.first.first,Pair.first.second,Ground,*Z7,*Z8});
|
||||
}
|
||||
if(PairSamples.size()>=64)break;
|
||||
}
|
||||
if(PairSamples.size()>Samples.size())Samples=std::move(PairSamples);
|
||||
if(Samples.size()>=64)break;
|
||||
}
|
||||
if(Samples.size()>=64)break;
|
||||
}
|
||||
bool bUsedWalkRouteGrid=false;
|
||||
if(Samples.size()<64)
|
||||
{
|
||||
Samples.clear();
|
||||
for(const auto& Plan:Assembly.plan.strates)
|
||||
{
|
||||
const VoxelForgeCore::Heightfield2D Field(Assembly.recipe,Plan);
|
||||
if(!Field.isValid())continue;
|
||||
std::int64_t RouteXSub=0,RouteYSub=0;
|
||||
if(!Plan.route.empty())
|
||||
{
|
||||
RouteXSub=Plan.route.front().positionSubvoxels[0];
|
||||
RouteYSub=Plan.route.front().positionSubvoxels[1];
|
||||
}
|
||||
constexpr std::int64_t GridPeriod=128*SubvoxelsPerVoxel;
|
||||
const std::int64_t XSub=static_cast<std::int64_t>(std::llround(
|
||||
static_cast<double>(RouteXSub)/GridPeriod))*GridPeriod;
|
||||
const std::int64_t YSub=static_cast<std::int64_t>(std::llround(
|
||||
static_cast<double>(RouteYSub)/GridPeriod))*GridPeriod;
|
||||
const auto WalkColumn=Field.point(XSub,YSub,0);
|
||||
if(WalkColumn.groundHeightSubvoxels>=WalkColumn.capHeightSubvoxels)continue;
|
||||
const std::int64_t XVoxel=XSub/SubvoxelsPerVoxel,YVoxel=YSub/SubvoxelsPerVoxel;
|
||||
const std::int64_t WalkGroundVoxel=WalkColumn.groundHeightSubvoxels/SubvoxelsPerVoxel;
|
||||
const auto MakeKey=[](std::int64_t X,std::int64_t Y,std::int64_t Z,std::int64_t Extent,int32 LOD)
|
||||
{
|
||||
VoxelForgeCore::TileKey Key;
|
||||
Key.coordinate={static_cast<int32>(std::floor(static_cast<double>(X)/Extent)),
|
||||
static_cast<int32>(std::floor(static_cast<double>(Y)/Extent)),
|
||||
static_cast<int32>(std::floor(static_cast<double>(Z)/Extent))};
|
||||
Key.lod=LOD;
|
||||
return Key;
|
||||
};
|
||||
const VoxelForgeCore::TileKey Key7=MakeKey(XVoxel,YVoxel,WalkGroundVoxel,4096,7);
|
||||
const VoxelForgeCore::TileKey Key8=MakeKey(XVoxel,YVoxel,WalkGroundVoxel,8192,8);
|
||||
const auto Mesh7=World.generateTile(Key7,Options,CoreError);
|
||||
const auto Mesh8=World.generateTile(Key8,Options,CoreError);
|
||||
if(!Mesh7||!Mesh8)
|
||||
{
|
||||
OutError=FString::Printf(TEXT("Walk-route far-horizon tile generation failed: %s"),
|
||||
UTF8_TO_TCHAR(CoreError.c_str()));
|
||||
return false;
|
||||
}
|
||||
const FGroundVertices Ground7=GatherGroundVertices(*Mesh7);
|
||||
const FGroundVertices Ground8=GatherGroundVertices(*Mesh8);
|
||||
for(const auto& Pair:Ground7.ByXY)
|
||||
{
|
||||
const auto Other=Ground8.ByXY.find(Pair.first);
|
||||
if(Other==Ground8.ByXY.end())continue;
|
||||
const auto Column=Field.point(Pair.first.first,Pair.first.second,0);
|
||||
const std::int64_t Ground=Column.groundHeightSubvoxels;
|
||||
if(Ground>=Column.capHeightSubvoxels)continue;
|
||||
const auto Bounds7=TileBounds(Key7),Bounds8=TileBounds(Key8);
|
||||
const double GroundVoxel=static_cast<double>(Ground)/SubvoxelsPerVoxel;
|
||||
if(GroundVoxel<Bounds7[2]||GroundVoxel>Bounds7[5]
|
||||
||GroundVoxel<Bounds8[2]||GroundVoxel>Bounds8[5])continue;
|
||||
const auto Nearest=[Ground](const std::vector<std::int64_t>& Values)
|
||||
->std::optional<std::int64_t>
|
||||
{
|
||||
if(Values.empty())return std::nullopt;
|
||||
return *std::min_element(Values.begin(),Values.end(),[Ground](auto A,auto B)
|
||||
{return std::abs(A-Ground)<std::abs(B-Ground);});
|
||||
};
|
||||
const auto Z7=Nearest(Pair.second),Z8=Nearest(Other->second);
|
||||
if(Z7&&Z8)
|
||||
Samples.push_back({Pair.first.first,Pair.first.second,Ground,*Z7,*Z8});
|
||||
if(Samples.size()>=256)break;
|
||||
}
|
||||
if(Samples.size()>=64){bUsedWalkRouteGrid=true;break;}
|
||||
Samples.clear();
|
||||
}
|
||||
}
|
||||
if(Samples.size()<64)
|
||||
{OutError=TEXT("Far-horizon agreement audit found fewer than 64 shared LOD7/8 surface points around the staged walk route.");return false;}
|
||||
|
||||
const auto FindNearRoot=[&](std::int64_t XSub,std::int64_t YSub,double GroundVoxel,double& OutVoxel)
|
||||
{
|
||||
const double X=static_cast<double>(XSub)/SubvoxelsPerVoxel;
|
||||
const double Y=static_cast<double>(YSub)/SubvoxelsPerVoxel;
|
||||
for(double Radius=4.0;Radius<=4096.0;Radius*=2.0)
|
||||
{
|
||||
double Lo=GroundVoxel-Radius,Hi=GroundVoxel+Radius;
|
||||
if(!(World.densityAt({X,Y,Lo})<0.0f&&World.densityAt({X,Y,Hi})>=0.0f))continue;
|
||||
for(int Iteration=0;Iteration<14;++Iteration)
|
||||
{
|
||||
const double Mid=(Lo+Hi)*0.5;
|
||||
if(World.densityAt({X,Y,Mid})<0.0f)Lo=Mid;else Hi=Mid;
|
||||
}
|
||||
OutVoxel=(Lo+Hi)*0.5;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
double MaximumFar7ErrorCm=0.0,MaximumFar8ErrorCm=0.0,MaximumCrossLodErrorCm=0.0;
|
||||
double MaximumNegativeControlErrorCm=0.0;
|
||||
std::size_t Compared=0;
|
||||
const std::size_t SampleStride=std::max<std::size_t>(1,(Samples.size()+127)/128);
|
||||
for(std::size_t Index=0;Index<Samples.size();Index+=SampleStride)
|
||||
{
|
||||
const auto& Sample=Samples[Index];
|
||||
double NearVoxel=0.0;
|
||||
if(!FindNearRoot(Sample.X,Sample.Y,
|
||||
static_cast<double>(Sample.ProfileGround)/SubvoxelsPerVoxel,NearVoxel))continue;
|
||||
const double Far7Cm=static_cast<double>(Sample.Far7)/SubvoxelsPerVoxel*VoxelSizeCm;
|
||||
const double Far8Cm=static_cast<double>(Sample.Far8)/SubvoxelsPerVoxel*VoxelSizeCm;
|
||||
const double NearCm=NearVoxel*VoxelSizeCm;
|
||||
MaximumFar7ErrorCm=std::max(MaximumFar7ErrorCm,std::abs(Far7Cm-NearCm));
|
||||
MaximumFar8ErrorCm=std::max(MaximumFar8ErrorCm,std::abs(Far8Cm-NearCm));
|
||||
MaximumCrossLodErrorCm=std::max(MaximumCrossLodErrorCm,std::abs(Far7Cm-Far8Cm));
|
||||
MaximumNegativeControlErrorCm=std::max(MaximumNegativeControlErrorCm,
|
||||
std::abs((Far8Cm+NegativeDatumOffsetCm)-NearCm));
|
||||
++Compared;
|
||||
}
|
||||
const bool bNegativeControlDetected=Compared>0&&MaximumNegativeControlErrorCm>ToleranceCm;
|
||||
if(Compared<32||MaximumFar7ErrorCm>ToleranceCm||MaximumFar8ErrorCm>ToleranceCm
|
||||
||MaximumCrossLodErrorCm>ToleranceCm||!bNegativeControlDetected)
|
||||
{
|
||||
OutError=FString::Printf(TEXT("Far-horizon agreement failed: points=%llu far7_cm=%.4f far8_cm=%.4f cross_lod_cm=%.4f tolerance_cm=%.2f negative_control_cm=%.4f detected=%d."),
|
||||
static_cast<unsigned long long>(Compared),MaximumFar7ErrorCm,MaximumFar8ErrorCm,
|
||||
MaximumCrossLodErrorCm,ToleranceCm,MaximumNegativeControlErrorCm,bNegativeControlDetected?1:0);
|
||||
return false;
|
||||
}
|
||||
UE_LOG(LogTemp,Display,
|
||||
TEXT("[VoxelForgeFarHorizonAgreement] status=PASS lod_pair=7/8 shared_points=%llu source=%s max_far7_near_cm=%.4f max_far8_near_cm=%.4f max_cross_lod_cm=%.4f tolerance_cm=%.2f near_source=exact_density_root negative_control=100cm_datum_offset max_error_cm=%.4f detected=1"),
|
||||
static_cast<unsigned long long>(Compared),
|
||||
bUsedWalkRouteGrid?TEXT("staged_walk_route_grid"):TEXT("desired_tile_overlap"),
|
||||
MaximumFar7ErrorCm,MaximumFar8ErrorCm,MaximumCrossLodErrorCm,
|
||||
ToleranceCm,MaximumNegativeControlErrorCm);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Paired engine timings include preparation and derived shells, with canonical output hashes.
|
||||
// Mesures moteur appariees : preparation et coques derivees incluses, avec hashes canoniques.
|
||||
bool RunCoreSharedFeatureCostAudit(VoxelForgeCore::World& World,
|
||||
const std::vector<VoxelForgeCore::TileKey>& Keys,const TCHAR* Label,FString& OutError)
|
||||
const std::vector<VoxelForgeCore::TileKey>& Keys,const TCHAR* Label,
|
||||
const VoxelForgeCore::WorldAssemblyManifest* Assembly,FString& OutError)
|
||||
{
|
||||
for (const int32 LOD : {0,1,7,8})
|
||||
{
|
||||
TArray<double> FullTimes,CandidateTimes,FullShellTimes,CandidateShellTimes,ListTimes;
|
||||
TArray<double> UnknownBoxes,FieldCalls,ColumnMisses,StratumShellTimes,ConnectorShellTimes;
|
||||
TArray<double> ClassificationTimes,ColumnComputeTimes,MeshingTimes,HorizonTimes,RepairSkipped;
|
||||
TArray<double> StratumFieldCalls,ConnectorFieldCalls,ShellTriangles,GroundTriangles,GroundRemoved,CapTriangles;
|
||||
for (const auto& Key : Keys)
|
||||
{
|
||||
if (Key.lod!=LOD || FullTimes.Num()>=8) continue;
|
||||
@@ -15182,15 +15412,37 @@ bool RunCoreSharedFeatureCostAudit(VoxelForgeCore::World& World,
|
||||
FullShellTimes.Add(Full->diagnostics.farShellMilliseconds);
|
||||
CandidateShellTimes.Add(Candidate->diagnostics.farShellMilliseconds);
|
||||
ListTimes.Add(Candidate->diagnostics.featureListMilliseconds);
|
||||
UnknownBoxes.Add(static_cast<double>(Full->diagnostics.unknownBoxes));
|
||||
FieldCalls.Add(static_cast<double>(Full->diagnostics.fieldCalls));
|
||||
ColumnMisses.Add(static_cast<double>(Full->diagnostics.columnCacheMisses));
|
||||
ClassificationTimes.Add(Full->diagnostics.classificationMilliseconds);
|
||||
ColumnComputeTimes.Add(Full->diagnostics.columnComputeMilliseconds);
|
||||
MeshingTimes.Add(Full->diagnostics.meshingMilliseconds);
|
||||
HorizonTimes.Add(Full->diagnostics.farHorizonMilliseconds);
|
||||
RepairSkipped.Add(Full->diagnostics.farShellRepairSkipped?1.0:0.0);
|
||||
StratumShellTimes.Add(Full->diagnostics.farStratumShellMilliseconds);
|
||||
ConnectorShellTimes.Add(Full->diagnostics.farConnectorShellMilliseconds);
|
||||
StratumFieldCalls.Add(static_cast<double>(Full->diagnostics.farStratumFieldCalls));
|
||||
ConnectorFieldCalls.Add(static_cast<double>(Full->diagnostics.farConnectorFieldCalls));
|
||||
ShellTriangles.Add(static_cast<double>(Full->diagnostics.farShellTrianglesAdded));
|
||||
GroundTriangles.Add(static_cast<double>(Full->diagnostics.horizonGroundTriangles));
|
||||
GroundRemoved.Add(static_cast<double>(Full->diagnostics.horizonGroundTrianglesRemoved));
|
||||
CapTriangles.Add(static_cast<double>(Full->diagnostics.horizonCapTriangles));
|
||||
}
|
||||
const auto P95=[](TArray<double> Values)
|
||||
{ Values.Sort(); return Values.IsEmpty() ? 0.0 : Values[FMath::Clamp(
|
||||
FMath::CeilToInt(Values.Num()*0.95f)-1,0,Values.Num()-1)]; };
|
||||
UE_LOG(LogTemp,Display,
|
||||
TEXT("[VoxelForgeSharedFeatureCost] label=%s lod=%d tiles=%d hashes_identical=1 full_p95_ms=%.5f candidate_p95_ms=%.5f list_p95_ms=%.5f full_shell_p95_ms=%.5f candidate_shell_p95_ms=%.5f"),
|
||||
TEXT("[VoxelForgeSharedFeatureCost] label=%s lod=%d tiles=%d hashes_identical=1 full_p95_ms=%.5f candidate_p95_ms=%.5f list_p95_ms=%.5f classification_p95_ms=%.5f column_compute_p95_ms=%.5f meshing_p95_ms=%.5f horizon_p95_ms=%.5f full_shell_p95_ms=%.5f candidate_shell_p95_ms=%.5f repair_skipped_p95=%.0f unknown_boxes_p95=%.0f field_calls_p95=%.0f column_misses_p95=%.0f stratum_shell_p95_ms=%.5f stratum_field_calls_p95=%.0f connector_shell_p95_ms=%.5f connector_field_calls_p95=%.0f shell_triangles_p95=%.0f horizon_ground_triangles_p95=%.0f horizon_ground_removed_p95=%.0f horizon_cap_triangles_p95=%.0f"),
|
||||
Label,LOD,FullTimes.Num(),P95(FullTimes),P95(CandidateTimes),P95(ListTimes),
|
||||
P95(FullShellTimes),P95(CandidateShellTimes));
|
||||
P95(ClassificationTimes),P95(ColumnComputeTimes),P95(MeshingTimes),P95(HorizonTimes),
|
||||
P95(FullShellTimes),P95(CandidateShellTimes),P95(RepairSkipped),P95(UnknownBoxes),P95(FieldCalls),
|
||||
P95(ColumnMisses),P95(StratumShellTimes),P95(StratumFieldCalls),
|
||||
P95(ConnectorShellTimes),P95(ConnectorFieldCalls),P95(ShellTriangles),
|
||||
P95(GroundTriangles),P95(GroundRemoved),P95(CapTriangles));
|
||||
}
|
||||
if(Assembly!=nullptr&&!Assembly->plan.strates.empty()
|
||||
&&!RunCoreFarHorizonAgreementAudit(World,Keys,*Assembly,OutError))return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -15429,7 +15681,8 @@ bool RunCoreFloatingIslandActorIntegrationTest(
|
||||
return false;
|
||||
}
|
||||
ReferenceWorld.retainTileRegions(Desired);
|
||||
if (!RunCoreSharedFeatureCostAudit(ReferenceWorld,Desired,TEXT("islands"),OutError)) return false;
|
||||
if (!RunCoreSharedFeatureCostAudit(ReferenceWorld,Desired,TEXT("islands"),
|
||||
&NativeAssembly,OutError)) return false;
|
||||
VoxelForgeCore::TileGenerationOptions Options;
|
||||
Options.hashDensity = true;
|
||||
std::vector<FStandaloneCoreAdapterTileHashes> AggregateRows;
|
||||
@@ -16838,7 +17091,8 @@ bool RunCoreWorldActorIntegrationTest(const FExploreArguments& Arguments, FStrin
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!RunCoreSharedFeatureCostAudit(ReferenceWorld,Desired,TEXT("surface"),OutError)) return false;
|
||||
if (!RunCoreSharedFeatureCostAudit(ReferenceWorld,Desired,TEXT("surface"),
|
||||
Assembly,OutError)) return false;
|
||||
if (FParse::Param(FCommandLine::Get(),TEXT("corefeatureauditonly")))
|
||||
{
|
||||
UE_LOG(LogTemp,Display,TEXT("[VoxelForgeSharedFeatureCost] pass complete=1 warmed_routes=1"));
|
||||
|
||||
Reference in new issue
Block a user