wip: L174 Design50 steps 0-2 in progress (interrupted for a power cut)
Audits collect gates and run seams (landing discs + end runs, LOD0/1), tagged uncapped failures, separate exempt counts, self-overlap census; level end runs; overlap/turn constraints. Partial sweep: end runs pass 3/3 per seed; 1-2 end-turn violations per seed; 50-110k tagged seam mismatches per seed (real vs audit artefact not yet decided). Not verified; resume L174. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1
This commit is contained in:
1 parent
b09728354d
commit
dee53c8d2a
9 files changed
+2155
-257
No files matched your search
@@ -327,6 +327,9 @@ namespace VoxelForgeCore
|
|||||||
// boundary-face bit mask (bit order: -X,+X,-Y,+Y,-Z,+Z).
|
// boundary-face bit mask (bit order: -X,+X,-Y,+Y,-Z,+Z).
|
||||||
std::vector<std::uint8_t> skirtFaceMasks;
|
std::vector<std::uint8_t> skirtFaceMasks;
|
||||||
std::vector<float> debugDensitySamples;
|
std::vector<float> debugDensitySamples;
|
||||||
|
std::array<std::int32_t,3> debugDensityOriginVoxels{};
|
||||||
|
std::array<std::int32_t,3> debugDensityDimensions{};
|
||||||
|
std::int32_t debugDensityStepVoxels = 0;
|
||||||
MeshGroups groups;
|
MeshGroups groups;
|
||||||
TileGenerationStats diagnostics;
|
TileGenerationStats diagnostics;
|
||||||
std::uint64_t densitySampleCount = 0;
|
std::uint64_t densitySampleCount = 0;
|
||||||
@@ -512,7 +515,8 @@ namespace VoxelForgeCore
|
|||||||
// boundary-blended host rock from widening the authored passage wall.
|
// boundary-blended host rock from widening the authored passage wall.
|
||||||
// v238 plans one resolved passage spline with explicit landing chambers.
|
// v238 plans one resolved passage spline with explicit landing chambers.
|
||||||
// v239 plans their floor planes as the passage's continuous floor profile.
|
// v239 plans their floor planes as the passage's continuous floor profile.
|
||||||
inline constexpr std::uint32_t WorldAssemblyEvaluatorVersion = 239;
|
// v240 adds level end runs and rejects passage tube overlaps and hairpins.
|
||||||
|
inline constexpr std::uint32_t WorldAssemblyEvaluatorVersion = 240;
|
||||||
|
|
||||||
enum class FieldChannel : std::uint32_t
|
enum class FieldChannel : std::uint32_t
|
||||||
{
|
{
|
||||||
@@ -1336,6 +1340,69 @@ namespace VoxelForgeCore
|
|||||||
std::int64_t clearHeightSubvoxels = 0;
|
std::int64_t clearHeightSubvoxels = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline std::int64_t ResolvedLayoutPassageLandingDiscRadiusSubvoxels(
|
||||||
|
std::int64_t mouthRadiusSubvoxels,
|
||||||
|
std::uint32_t coreVoxelSizeMicrometres) noexcept
|
||||||
|
{
|
||||||
|
if(coreVoxelSizeMicrometres==0)return 0;
|
||||||
|
const std::int64_t qPerMetre=static_cast<std::int64_t>(std::llround(
|
||||||
|
static_cast<double>(WorldAssemblySubvoxelsPerVoxel)*1000000.0
|
||||||
|
/coreVoxelSizeMicrometres));
|
||||||
|
return std::max<std::int64_t>(3*qPerMetre,
|
||||||
|
mouthRadiusSubvoxels+qPerMetre);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool IsInsideResolvedLayoutPassageLandingDiscV1(
|
||||||
|
const std::array<std::int64_t,2>& centerSubvoxels,
|
||||||
|
std::int64_t radiusSubvoxels,double xSubvoxels,double ySubvoxels) noexcept
|
||||||
|
{
|
||||||
|
if(radiusSubvoxels<=0)return false;
|
||||||
|
const double dx=xSubvoxels-static_cast<double>(centerSubvoxels[0]);
|
||||||
|
const double dy=ySubvoxels-static_cast<double>(centerSubvoxels[1]);
|
||||||
|
const double radius=static_cast<double>(radiusSubvoxels);
|
||||||
|
return dx*dx+dy*dy<=radius*radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool IsInsideResolvedLayoutPassageLandingRimV1(
|
||||||
|
const std::array<std::int64_t,2>& centerSubvoxels,
|
||||||
|
std::int64_t radiusSubvoxels,std::int64_t halfWidthSubvoxels,
|
||||||
|
double xSubvoxels,double ySubvoxels) noexcept
|
||||||
|
{
|
||||||
|
if(radiusSubvoxels<=0||halfWidthSubvoxels<0)return false;
|
||||||
|
const double dx=xSubvoxels-static_cast<double>(centerSubvoxels[0]);
|
||||||
|
const double dy=ySubvoxels-static_cast<double>(centerSubvoxels[1]);
|
||||||
|
return std::abs(std::hypot(dx,dy)-static_cast<double>(radiusSubvoxels))
|
||||||
|
<=static_cast<double>(halfWidthSubvoxels);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shared landing-volume predicate for planners, the passage composer, and audits.
|
||||||
|
// Query coordinates use the same world subvoxel units as the resolved passage.
|
||||||
|
inline double ResolvedLayoutPassageLandingFloorAtXYSubvoxels(
|
||||||
|
const ResolvedLayoutPassageLandingChamberV1& chamber,
|
||||||
|
double xSubvoxels,double ySubvoxels) noexcept
|
||||||
|
{
|
||||||
|
return static_cast<double>(chamber.floorCenterSubvoxels[2])
|
||||||
|
+static_cast<double>(chamber.floorGradientQ16[0])/65536.0
|
||||||
|
*(xSubvoxels-static_cast<double>(chamber.floorCenterSubvoxels[0]))
|
||||||
|
+static_cast<double>(chamber.floorGradientQ16[1])/65536.0
|
||||||
|
*(ySubvoxels-static_cast<double>(chamber.floorCenterSubvoxels[1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool IsInsideResolvedLayoutPassageLandingChamberV1(
|
||||||
|
const ResolvedLayoutPassageLandingChamberV1& chamber,
|
||||||
|
double xSubvoxels,double ySubvoxels,double zSubvoxels) noexcept
|
||||||
|
{
|
||||||
|
if(chamber.radiusSubvoxels<=0||chamber.clearHeightSubvoxels<=0)return false;
|
||||||
|
const double dx=xSubvoxels-static_cast<double>(chamber.floorCenterSubvoxels[0]);
|
||||||
|
const double dy=ySubvoxels-static_cast<double>(chamber.floorCenterSubvoxels[1]);
|
||||||
|
const double radius=static_cast<double>(chamber.radiusSubvoxels);
|
||||||
|
const double floor=ResolvedLayoutPassageLandingFloorAtXYSubvoxels(
|
||||||
|
chamber,xSubvoxels,ySubvoxels);
|
||||||
|
return dx*dx+dy*dy<=radius*radius
|
||||||
|
&&zSubvoxels>=floor
|
||||||
|
&&zSubvoxels<=floor+static_cast<double>(chamber.clearHeightSubvoxels);
|
||||||
|
}
|
||||||
|
|
||||||
struct ResolvedLayoutPassageV1
|
struct ResolvedLayoutPassageV1
|
||||||
{
|
{
|
||||||
std::string stableId;
|
std::string stableId;
|
||||||
@@ -1348,6 +1415,8 @@ namespace VoxelForgeCore
|
|||||||
std::array<std::int64_t, 3> lowerMouthSubvoxels{};
|
std::array<std::int64_t, 3> lowerMouthSubvoxels{};
|
||||||
std::int64_t mouthRadiusSubvoxels = 0;
|
std::int64_t mouthRadiusSubvoxels = 0;
|
||||||
std::int64_t midRadiusSubvoxels = 0;
|
std::int64_t midRadiusSubvoxels = 0;
|
||||||
|
// Planned flat distance from each landing, at least R+1 m.
|
||||||
|
std::int64_t endRunSubvoxels = 0;
|
||||||
// Derived from the mouth binding; the main descent is monotone through this point.
|
// Derived from the mouth binding; the main descent is monotone through this point.
|
||||||
std::size_t lowerMouthControlIndex = 0;
|
std::size_t lowerMouthControlIndex = 0;
|
||||||
ResolvedLayoutPassageLandingChamberV1 upperLandingChamber;
|
ResolvedLayoutPassageLandingChamberV1 upperLandingChamber;
|
||||||
@@ -1380,6 +1449,47 @@ namespace VoxelForgeCore
|
|||||||
std::int64_t cascadeLedgeSubvoxels = 0;
|
std::int64_t cascadeLedgeSubvoxels = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ResolvedLayoutPassageSelfOverlapAuditV1
|
||||||
|
{
|
||||||
|
std::uint64_t segmentPairs = 0;
|
||||||
|
std::uint64_t measuredSegmentPairs = 0;
|
||||||
|
std::uint64_t localExemptSegmentPairs = 0;
|
||||||
|
std::uint64_t overlappingSegmentPairs = 0;
|
||||||
|
std::uint64_t firstOverlapSegmentA = 0;
|
||||||
|
std::uint64_t firstOverlapSegmentB = 0;
|
||||||
|
std::uint64_t firstLandingColumnSegment = 0;
|
||||||
|
bool firstLandingColumnIsLower = false;
|
||||||
|
std::uint64_t landingColumnViolations = 0;
|
||||||
|
double maximumEndTurnDegrees = 0.0;
|
||||||
|
std::uint32_t endTurnViolations = 0;
|
||||||
|
double minimumClearanceMetres = 0.0;
|
||||||
|
bool hasOverlapLocation = false;
|
||||||
|
bool hasMeasuredCoverage = false;
|
||||||
|
bool passed = false;
|
||||||
|
};
|
||||||
|
VFCORE_API ResolvedLayoutPassageSelfOverlapAuditV1
|
||||||
|
AuditResolvedLayoutPassageSelfOverlapV1(
|
||||||
|
const ResolvedLayoutPassageV1& passage,
|
||||||
|
std::uint32_t coreVoxelSizeMicrometres);
|
||||||
|
|
||||||
|
struct ResolvedLayoutPassageEndRunAuditV1
|
||||||
|
{
|
||||||
|
double requiredEndRunMetres = 0.0;
|
||||||
|
double measuredStartMetres = 0.0;
|
||||||
|
double measuredEndMetres = 0.0;
|
||||||
|
double startMaximumFloorDeviationMetres = 0.0;
|
||||||
|
double endMaximumFloorDeviationMetres = 0.0;
|
||||||
|
double startMaximumGradeDegrees = 0.0;
|
||||||
|
double endMaximumGradeDegrees = 0.0;
|
||||||
|
bool hasMeasuredCoverage = false;
|
||||||
|
bool passed = false;
|
||||||
|
};
|
||||||
|
VFCORE_API ResolvedLayoutPassageEndRunAuditV1
|
||||||
|
AuditResolvedLayoutPassageEndRunsV1(
|
||||||
|
const ResolvedLayoutPassageV1& passage,
|
||||||
|
std::uint32_t coreVoxelSizeMicrometres,
|
||||||
|
std::int64_t endRunSubvoxels = 0);
|
||||||
|
|
||||||
struct VFCORE_API ResolvedLayoutSnapshotV3
|
struct VFCORE_API ResolvedLayoutSnapshotV3
|
||||||
{
|
{
|
||||||
std::uint32_t schemaVersion = ResolvedLayoutSchemaVersionV3;
|
std::uint32_t schemaVersion = ResolvedLayoutSchemaVersionV3;
|
||||||
|
|||||||
File diff suppressed because it is too large.
Load diff
@@ -2890,6 +2890,7 @@ namespace VoxelForgeCore
|
|||||||
const auto MarchingCubesStart=std::chrono::steady_clock::now();
|
const auto MarchingCubesStart=std::chrono::steady_clock::now();
|
||||||
FVoxelUniformBlockProofAuditStats BlockProofAudit;
|
FVoxelUniformBlockProofAuditStats BlockProofAudit;
|
||||||
FVoxelMeshData mesh;
|
FVoxelMeshData mesh;
|
||||||
|
FIntVector DebugDensityOrigin,DebugDensityDimensions;
|
||||||
{
|
{
|
||||||
FStandaloneShapeWorld::FScopedStampSamplingStep stampSamplingStep(MeshStep);
|
FStandaloneShapeWorld::FScopedStampSamplingStep stampSamplingStep(MeshStep);
|
||||||
mesh=mesher.GenerateMesh(origin,MeshStep,MeshCells,nullptr,
|
mesh=mesher.GenerateMesh(origin,MeshStep,MeshCells,nullptr,
|
||||||
@@ -2897,7 +2898,9 @@ namespace VoxelForgeCore
|
|||||||
(options.hashDensity||options.captureDensitySamples)?&densityValues:nullptr,
|
(options.hashDensity||options.captureDensitySamples)?&densityValues:nullptr,
|
||||||
options.profileMesherStages?&McStageTimings:nullptr,
|
options.profileMesherStages?&McStageTimings:nullptr,
|
||||||
options.auditUniformBlockProofs?&BlockProofAudit:nullptr,
|
options.auditUniformBlockProofs?&BlockProofAudit:nullptr,
|
||||||
options.forceFullDensityCapture);
|
options.forceFullDensityCapture,
|
||||||
|
options.captureDensitySamples?&DebugDensityOrigin:nullptr,
|
||||||
|
options.captureDensitySamples?&DebugDensityDimensions:nullptr);
|
||||||
}
|
}
|
||||||
passageFeatureScope.copySweptTubeRuntimeCounts();
|
passageFeatureScope.copySweptTubeRuntimeCounts();
|
||||||
if(options.auditUniformBlockProofs)
|
if(options.auditUniformBlockProofs)
|
||||||
@@ -3222,7 +3225,15 @@ namespace VoxelForgeCore
|
|||||||
std::chrono::steady_clock::now()-materialQueryStart).count():0.0;
|
std::chrono::steady_clock::now()-materialQueryStart).count():0.0;
|
||||||
out.indices.reserve(static_cast<std::size_t>(mesh.Triangles.Num()));
|
out.indices.reserve(static_cast<std::size_t>(mesh.Triangles.Num()));
|
||||||
for(const int32 index:mesh.Triangles)out.indices.push_back(static_cast<std::uint32_t>(index));
|
for(const int32 index:mesh.Triangles)out.indices.push_back(static_cast<std::uint32_t>(index));
|
||||||
if(options.captureDensitySamples)out.debugDensitySamples=std::move(densityValues);
|
if(options.captureDensitySamples)
|
||||||
|
{
|
||||||
|
out.debugDensitySamples=std::move(densityValues);
|
||||||
|
out.debugDensityOriginVoxels={DebugDensityOrigin.X,DebugDensityOrigin.Y,
|
||||||
|
DebugDensityOrigin.Z};
|
||||||
|
out.debugDensityDimensions={DebugDensityDimensions.X,
|
||||||
|
DebugDensityDimensions.Y,DebugDensityDimensions.Z};
|
||||||
|
out.debugDensityStepVoxels=MeshStep;
|
||||||
|
}
|
||||||
if(options.hashDensity)
|
if(options.hashDensity)
|
||||||
{
|
{
|
||||||
std::uint64_t densityHash=14695981039346656037ull;
|
std::uint64_t densityHash=14695981039346656037ull;
|
||||||
|
|||||||
@@ -0,0 +1,104 @@
|
|||||||
|
# Design50 — why the tunnel landings fail, and the plan (review 2026-11-03)
|
||||||
|
|
||||||
|
A read-only review (Claude Opus 5.5, extra-high effort) of `wip/combined-cave` (b097283), with the L133–L173 history and
|
||||||
|
the L173 logs. The orchestrator verified R6 and R7a in the code.
|
||||||
|
|
||||||
|
**Headline:** one wrong assumption, that a tunnel end is a separate 2-D "landing chamber" owned by the tube, the layer
|
||||||
|
and the audits at once. The plan replaces it with a level end run of the same spline plus the Design49 stamp,
|
||||||
|
applied last.
|
||||||
|
|
||||||
|
## Root causes
|
||||||
|
|
||||||
|
- **R1:** the chamber plane and the tube's 1-D h(s) disagree off the centreline (up to 1.3 m at the 7.5 m rim on FI).
|
||||||
|
- **R2:** the departure tube descends from the disc centre and undercuts its own landing. Unsupported samples: upper
|
||||||
|
chambers 316, lower 0 (L173); L159 upper pads 96/96 failing, lower 2/96.
|
||||||
|
- **R3:** the passage composer overrides the host:
|
||||||
|
- a forced-solid chamber floor slab (`ShapeWorldInternal.h` ~1665);
|
||||||
|
- shell walls filled over host air (~1869–1898);
|
||||||
|
- per-layer corridor exemptions only (Surface World, planned tunnels);
|
||||||
|
- the liminal route stamp re-applied after the carve (~1997, the L146 refill).
|
||||||
|
- **R4:** planner self-overlap. The FI helix pitch (3.2–3.9 m) is less than the bore height (~5.8 m), with 2,738
|
||||||
|
overlapping control-point pairs. Upper and lower mouths share XY, so 32/32 final junctions turn 107–178°
|
||||||
|
(curl-back).
|
||||||
|
- **R5:** the passage picks the landing height, not the layer. FI departures land inside the FI→TN transition band.
|
||||||
|
- **R6 (bug, verified):** `floorProfileIncludesLandingChambers` (set for every passage) makes
|
||||||
|
`PassageFlatFloorCenterZSubvoxels` return early, skipping both blends.
|
||||||
|
- **R7 (audits):**
|
||||||
|
- (a) **verified:** the composed audit returns 10 before the seam audit, so seams were never measured;
|
||||||
|
- (b) audits re-model chambers (L159's interior-air 0/16 was a phantom);
|
||||||
|
- (c) exempt probes count as supported; zero-coverage gates pass;
|
||||||
|
- (d) only 8 failures are printed;
|
||||||
|
- (e) the TN and VS sweeps are the same 4-strata world.
|
||||||
|
|
||||||
|
## Model
|
||||||
|
|
||||||
|
1. **One spline, one floor:** h(s) is level and straight for the first and last a ≥ R+1 m.
|
||||||
|
2. **The landing = the end run:** a flat disc radius R at P = h(end); the descent starts outside the disc.
|
||||||
|
3. **One composition order:** layer content (including liminal decks) → bore carve (air only, plus a floor shell under
|
||||||
|
the bore where the host is air) → Design49 clamp stamp last, masked by the bore → edits. No walls or roofs over
|
||||||
|
host air; no corridor exemptions.
|
||||||
|
4. **Who sets P:** fixed-ground layers (SW, FI, liminal) propose the site and P; for carved layers (TN, VS) the passage
|
||||||
|
picks P and the cave planner connects.
|
||||||
|
|
||||||
|
**Keep:**
|
||||||
|
- the spline, h(s) and the grade audit;
|
||||||
|
- the interior-air gate;
|
||||||
|
- cave binding to the end anchors;
|
||||||
|
- the L148 envelope, the L156 band fit and the L130 bounds;
|
||||||
|
- `l159-pad-stamp.patch` (stamp, bounds, LandingPadAudit plus 4 controls).
|
||||||
|
|
||||||
|
**Delete:**
|
||||||
|
- the chamber records and their composition, and the slab return;
|
||||||
|
- the corridor exemptions and the shell-over-air fills;
|
||||||
|
- the flag and both floor blends;
|
||||||
|
- the SW plane fit;
|
||||||
|
- the chamber audits.
|
||||||
|
|
||||||
|
## Steps
|
||||||
|
|
||||||
|
- **0:** audits that measure:
|
||||||
|
- collect gates, exit at the end;
|
||||||
|
- seams over discs and end runs at LOD0/1;
|
||||||
|
- tagged failing samples, with no 8-sample cap;
|
||||||
|
- exempt probes counted separately, with a coverage minimum;
|
||||||
|
- a self-overlap census;
|
||||||
|
- Core-exported predicates.
|
||||||
|
- **1:** level end runs.
|
||||||
|
- **2:** no self-overlap or hairpins:
|
||||||
|
- pitch ≥ bore height + 2 shells + margin;
|
||||||
|
- lower mouth on the ring;
|
||||||
|
- end turns ≤ 60°;
|
||||||
|
- the helix kept out of the landing columns.
|
||||||
|
- **3:** the composer and the audits together, with the stamp last.
|
||||||
|
- **4:** site selection for fixed-ground layers.
|
||||||
|
- **5:** verify (fast tier; TN/VS/native-FI sweeps 16/16; versioned hashes; Clang/GCC W1/W8/W12; captures).
|
||||||
|
|
||||||
|
**Owner look decisions:**
|
||||||
|
- the disc radius, the end-run length, the cone angle (12°) and reach (8 m);
|
||||||
|
- no walls on open-air landings;
|
||||||
|
- headroom underground;
|
||||||
|
- whether a FI landing may float or must sit on an island;
|
||||||
|
- wider spirals (~6 m or more);
|
||||||
|
- landings may move.
|
||||||
|
|
||||||
|
## Owner decisions (2026-11-03)
|
||||||
|
|
||||||
|
- Open-air landings: **no walls**.
|
||||||
|
- Floating Islands landings: **add a landing island to the FI plan** at each tunnel end: top at P, footprint wider
|
||||||
|
than the pad, normal island shaping at the edges. It's planned from the seed before generation, and the FI route
|
||||||
|
connects to it. (Not pathfinding the tunnel to an existing island.)
|
||||||
|
|
||||||
|
## Owner decision: uniform layer planners (2026-11-03)
|
||||||
|
|
||||||
|
- **Planning side: a `LayerPlanner` parent with one child per layer type:**
|
||||||
|
- `Plan(seed, settings)`;
|
||||||
|
- `OnTunnelArrival(end)`, the landing hook: nothing (stamp only), a plan record (FI landing island, liminal walkway,
|
||||||
|
cave connection), or a content request for Unreal;
|
||||||
|
- `ProvideRouteAnchors()`;
|
||||||
|
- `MakeDrawer()`.
|
||||||
|
|
||||||
|
Planning runs once per world, so virtual dispatch costs nothing there.
|
||||||
|
- **Drawing side:** keep the `std::variant` adapters with a shared `densityAt` shape (no virtual call per sample;
|
||||||
|
`ShapeWorldInternal.h` ~121), and choose the drawer once per tile.
|
||||||
|
- **Migration:** one planner at a time; owner canonical hashes identical after each move (refactor only); the landing
|
||||||
|
hook then implements step 4.
|
||||||
@@ -0,0 +1,225 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Capture composed passage, route, shell, and seam attribution for seeds 0..15."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import json
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[4]
|
||||||
|
DEFAULT_BIN = ROOT / "Standalone/bin/linux/VoxelForgeCoreHeadless-l174-step0-clang"
|
||||||
|
DATA = ROOT / "Standalone/data/owner_world.json"
|
||||||
|
STAMP_TOOL = ROOT / "Standalone/Tools/verify/source_stamp.py"
|
||||||
|
STAMP_RE = re.compile(r"^\[VoxelForgeSourceStamp\] sha256=([0-9a-f]+)$", re.M)
|
||||||
|
|
||||||
|
GATES = {
|
||||||
|
"passages": r"^\[ResolvedPassageAuditSummary\].*status=PASS$",
|
||||||
|
"seams": r"^\[PassageTileSeamAudit\].*status=PASS$",
|
||||||
|
"shell": r"^\[PassageShellAuditSummary\].*status=PASS$",
|
||||||
|
"naturalness": r"^\[PassageNaturalnessSummary\].*status=PASS$",
|
||||||
|
"mouth_profile": r"^\[PassageMouthProfileSummary\].*status=PASS$",
|
||||||
|
"ripple": r"^\[PassageRippleAuditSummary\].*status=PASS$",
|
||||||
|
"passage_interior": r"^\[PassageInteriorCapsuleAuditSummary\].*status=PASS$",
|
||||||
|
"self_overlap": r"^\[PassageTubeSelfOverlapAuditSummary\].*status=PASS$",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def evaluate(content: str, expected_stamp: str, layout_path: Path,
|
||||||
|
require_end_runs: bool = False) -> tuple[dict, dict, str | None]:
|
||||||
|
stamp = STAMP_RE.search(content)
|
||||||
|
checks = {name: re.search(pattern, content, re.M) is not None
|
||||||
|
for name, pattern in GATES.items()}
|
||||||
|
if require_end_runs:
|
||||||
|
checks["end_runs"] = re.search(
|
||||||
|
r"^\[PassageEndRunAuditSummary\].*status=PASS$", content, re.M) is not None
|
||||||
|
checks["source_stamp"] = stamp is not None and stamp.group(1) == expected_stamp
|
||||||
|
for kind, strate in (("tunnel_network", 2), ("vertical_shafts", 3)):
|
||||||
|
route = re.compile(
|
||||||
|
rf"^\[ResolvedStrateRouteAudit\] strate={strate} .*unsupported=0 "
|
||||||
|
rf"grade_failures=0 .*status=PASS$", re.M)
|
||||||
|
checks[f"{kind}_route"] = route.search(content) is not None
|
||||||
|
checks[f"{kind}_blocked_route_control"] = re.search(
|
||||||
|
rf"^\[{kind.title().replace('_', '')}BlockedRouteControl\].*"
|
||||||
|
r"expected=FAIL status=PASS$", content, re.M) is not None
|
||||||
|
checks["passage_count"] = len(re.findall(
|
||||||
|
r"^\[ResolvedPassageAudit\] .*walkability=PASS$", content, re.M)) == 3
|
||||||
|
checks["negative_controls"] = (
|
||||||
|
len(re.findall(r"^\[ResolvedPassageInteriorNegativeControl\].*"
|
||||||
|
r"detected=true status=PASS$", content, re.M)) == 3
|
||||||
|
and len(re.findall(r"^\[ResolvedPassageBlockedControl\].*detected=true$",
|
||||||
|
content, re.M)) == 3
|
||||||
|
)
|
||||||
|
attribution = {
|
||||||
|
"seam_samples_by_tag": {
|
||||||
|
tag: len(re.findall(rf"^\[PassageTileSeamSample\] tag={re.escape(tag)} ",
|
||||||
|
content, re.M))
|
||||||
|
for tag in ("disc", "rim", "end run", "body", "route")
|
||||||
|
},
|
||||||
|
"landing_support_failures_upper": len(re.findall(
|
||||||
|
r"^\[PassageLandingSupportFailure\].*side=upper", content, re.M)),
|
||||||
|
"landing_support_failures_lower": len(re.findall(
|
||||||
|
r"^\[PassageLandingSupportFailure\].*side=lower", content, re.M)),
|
||||||
|
"unsupported_walk_samples": len(re.findall(
|
||||||
|
r"^\[ResolvedWalkDispatch\] kind=unsupported", content, re.M)),
|
||||||
|
"shell_floor_samples": len(re.findall(
|
||||||
|
r"^\[PassageShellAuditSample\]", content, re.M)),
|
||||||
|
"shell_wall_samples": len(re.findall(
|
||||||
|
r"^\[PassageShellAuditSample\].*kind=wall_missing", content, re.M)),
|
||||||
|
"tube_self_overlap_rows": len(re.findall(
|
||||||
|
r"^\[PassageTubeSelfOverlapAudit\]", content, re.M)),
|
||||||
|
"tube_self_overlap_pairs": sum(int(value) for value in re.findall(
|
||||||
|
r"^\[PassageTubeSelfOverlapAudit\].*overlap_pairs=(\d+)",
|
||||||
|
content, re.M)),
|
||||||
|
"tube_end_turn_violations": sum(int(value) for value in re.findall(
|
||||||
|
r"^\[PassageTubeSelfOverlapAudit\].*end_turn_violations=(\d+)",
|
||||||
|
content, re.M)),
|
||||||
|
"tube_landing_column_violations": sum(int(value) for value in re.findall(
|
||||||
|
r"^\[PassageTubeSelfOverlapAudit\].*landing_column_violations=(\d+)",
|
||||||
|
content, re.M)),
|
||||||
|
"end_run_failures": len(re.findall(
|
||||||
|
r"^\[PassageEndRunAudit\].*status=FAIL$", content, re.M)),
|
||||||
|
"end_run_measured": len(re.findall(
|
||||||
|
r"^\[PassageEndRunAudit\].*measured_start_m=(?!0\.000)"
|
||||||
|
r".*measured_end_m=(?!0\.000)", content, re.M)),
|
||||||
|
}
|
||||||
|
seam_summary = re.search(r"^\[PassageTileSeamAudit\].*$", content, re.M)
|
||||||
|
if seam_summary:
|
||||||
|
for key in ("candidates", "examined", "pairs", "lod0_pairs", "lod0_samples",
|
||||||
|
"lod1_pairs", "lod1_samples", "landing_discs", "end_runs",
|
||||||
|
"lod0_disc_samples", "lod1_disc_samples", "lod0_rim_samples",
|
||||||
|
"lod1_rim_samples", "lod0_end_run_samples",
|
||||||
|
"lod1_end_run_samples", "exempt_pairs", "mismatches"):
|
||||||
|
match = re.search(rf"\b{key}=(\d+)", seam_summary.group(0))
|
||||||
|
attribution[f"seam_{key}"] = int(match.group(1)) if match else None
|
||||||
|
for key in ("landing_discs", "end_runs"):
|
||||||
|
match = re.search(rf"\b{key}=(\d+)/(\d+)", seam_summary.group(0))
|
||||||
|
if match:
|
||||||
|
attribution[f"seam_{key}_covered"] = int(match.group(1))
|
||||||
|
attribution[f"seam_{key}_required"] = int(match.group(2))
|
||||||
|
attribution["seam_uncovered_disc_regions"] = len(re.findall(
|
||||||
|
r"^\[PassageTileSeamCoverage\].*\bdisc_status=FAIL\b", content, re.M))
|
||||||
|
attribution["seam_uncovered_end_run_regions"] = len(re.findall(
|
||||||
|
r"^\[PassageTileSeamCoverage\].*\bend_run_status=FAIL\b", content, re.M))
|
||||||
|
attribution["seam_uncovered_regions"] = (
|
||||||
|
attribution["seam_uncovered_disc_regions"]
|
||||||
|
+attribution["seam_uncovered_end_run_regions"])
|
||||||
|
passage_summary = re.search(r"^\[ResolvedPassageAuditSummary\].*$", content, re.M)
|
||||||
|
if passage_summary:
|
||||||
|
for key in ("support_probes", "exempt_support_probes", "unsupported"):
|
||||||
|
match = re.search(rf"\b{key}=(\d+)", passage_summary.group(0))
|
||||||
|
if match:
|
||||||
|
attribution[key] = int(match.group(1))
|
||||||
|
identity = None
|
||||||
|
try:
|
||||||
|
if layout_path.is_file():
|
||||||
|
identity = json.loads(layout_path.read_text(encoding="utf-8")).get(
|
||||||
|
"stable_identity")
|
||||||
|
except (OSError, json.JSONDecodeError):
|
||||||
|
pass
|
||||||
|
checks["layout_output"] = identity is not None
|
||||||
|
return checks, attribution, identity
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
parser = argparse.ArgumentParser(description=__doc__)
|
||||||
|
parser.add_argument("--binary", type=Path, default=DEFAULT_BIN)
|
||||||
|
parser.add_argument("--out", type=Path,
|
||||||
|
default=ROOT / "Saved/Linux/l174/rebaseline-l173/seeds")
|
||||||
|
parser.add_argument("--seed-start", type=int, default=0)
|
||||||
|
parser.add_argument("--seed-stop", type=int, default=16,
|
||||||
|
help="exclusive seed bound")
|
||||||
|
parser.add_argument("--expected-stamp", type=str,
|
||||||
|
help="source stamp embedded in an earlier binary")
|
||||||
|
parser.add_argument("--require-end-runs", action="store_true",
|
||||||
|
help="require the L174 end-run audit (use for post-Step-1 sweeps)")
|
||||||
|
parser.add_argument("--no-resume", action="store_true",
|
||||||
|
help="rerun even when both the log and layout already exist")
|
||||||
|
args = parser.parse_args()
|
||||||
|
if not args.binary.is_file() or not DATA.is_file():
|
||||||
|
raise SystemExit(f"missing binary or owner fixture: {args.binary}")
|
||||||
|
args.binary = args.binary.resolve()
|
||||||
|
args.out = args.out.resolve()
|
||||||
|
args.out.mkdir(parents=True, exist_ok=True)
|
||||||
|
stamp = args.expected_stamp or subprocess.check_output(
|
||||||
|
[sys.executable, str(STAMP_TOOL), "stamp", "--root", str(ROOT)], text=True).strip()
|
||||||
|
results = []
|
||||||
|
partial = args.out / "runs-partial.json"
|
||||||
|
for seed in range(args.seed_start, args.seed_stop):
|
||||||
|
log = args.out / f"seed{seed}.log"
|
||||||
|
layout = args.out / f"seed{seed}.layout.json"
|
||||||
|
exit_path = args.out / f"seed{seed}.exit"
|
||||||
|
command = [
|
||||||
|
"taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--",
|
||||||
|
"timeout", "1740s", str(args.binary), str(DATA),
|
||||||
|
"--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline",
|
||||||
|
"--workers=8", "--clip-radius=3", "--max-clip-level=8", "--max-level=0",
|
||||||
|
"--force-generate", f"--seed={seed}", "--recipe=surface-world",
|
||||||
|
"--density-dispatch-report", "--audit-resolved-layout-passages",
|
||||||
|
"--audit-passage-tile-seams", f"--resolved-layout-output={layout}",
|
||||||
|
]
|
||||||
|
started = time.monotonic()
|
||||||
|
resumed = False
|
||||||
|
if not args.no_resume and log.is_file() and layout.is_file():
|
||||||
|
content = log.read_text(encoding="utf-8", errors="replace")
|
||||||
|
if exit_path.is_file():
|
||||||
|
code: int | str = int(exit_path.read_text().strip())
|
||||||
|
elif ("[PipelineExactQueryHash]" in content
|
||||||
|
and "[ResolvedPassageAuditSummary]" in content):
|
||||||
|
code = 10 if re.search(r"^\[[^]]*(?:Summary|Audit)\].*status=FAIL$",
|
||||||
|
content, re.M) else 0
|
||||||
|
else:
|
||||||
|
code = "NO_EXIT_RECORD"
|
||||||
|
resumed = code != "NO_EXIT_RECORD"
|
||||||
|
if not resumed:
|
||||||
|
try:
|
||||||
|
with log.open("w", encoding="utf-8") as output:
|
||||||
|
proc = subprocess.run(command, cwd=ROOT, stdout=output,
|
||||||
|
stderr=subprocess.STDOUT, check=False, timeout=1740)
|
||||||
|
code = proc.returncode
|
||||||
|
except subprocess.TimeoutExpired:
|
||||||
|
code = "OUTER_TIMEOUT"
|
||||||
|
if isinstance(code, int):
|
||||||
|
exit_path.write_text(str(code) + "\n", encoding="utf-8")
|
||||||
|
content = log.read_text(encoding="utf-8", errors="replace") if log.exists() else ""
|
||||||
|
checks, attribution, identity = evaluate(
|
||||||
|
content, stamp, layout, args.require_end_runs)
|
||||||
|
passed = code == 0 and all(checks.values())
|
||||||
|
failed = [name for name, ok in checks.items() if not ok]
|
||||||
|
row = {
|
||||||
|
"seed": seed,
|
||||||
|
"verdict": "PASS" if passed else "FAIL",
|
||||||
|
"exit": code,
|
||||||
|
"failed_gates": failed,
|
||||||
|
"checks": checks,
|
||||||
|
"attribution": attribution,
|
||||||
|
"source_stamp": stamp,
|
||||||
|
"layout_identity": identity,
|
||||||
|
"elapsed_s": round(time.monotonic() - started, 3),
|
||||||
|
"log": str(log.relative_to(ROOT)),
|
||||||
|
"layout": str(layout.relative_to(ROOT)),
|
||||||
|
"resumed": resumed,
|
||||||
|
}
|
||||||
|
results.append(row)
|
||||||
|
partial.write_text(json.dumps(results, indent=2) + "\n", encoding="utf-8")
|
||||||
|
print("[L174CaveSeedSweep] " + json.dumps(row, sort_keys=True), flush=True)
|
||||||
|
summary = {
|
||||||
|
"source_stamp": stamp,
|
||||||
|
"seeds": list(range(args.seed_start, args.seed_stop)),
|
||||||
|
"passed": sum(row["verdict"] == "PASS" for row in results),
|
||||||
|
"failed": sum(row["verdict"] != "PASS" for row in results),
|
||||||
|
"results": results,
|
||||||
|
}
|
||||||
|
(args.out / "summary.json").write_text(
|
||||||
|
json.dumps(summary, indent=2) + "\n", encoding="utf-8")
|
||||||
|
print(f"[L174CaveSeedSweepSummary] passed={summary['passed']}/{len(results)} "
|
||||||
|
f"failed={summary['failed']}", flush=True)
|
||||||
|
return 0 if summary["failed"] == 0 else 1
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
raise SystemExit(main())
|
||||||
@@ -60,6 +60,7 @@ namespace
|
|||||||
bool AuditBasePageEquivalence=false;
|
bool AuditBasePageEquivalence=false;
|
||||||
bool AuditRouteParity=false;
|
bool AuditRouteParity=false;
|
||||||
bool AuditPassageTileSeams=false;
|
bool AuditPassageTileSeams=false;
|
||||||
|
bool InjectPassageSeamMismatch=false;
|
||||||
bool AuditPassageSourceClamp=false;
|
bool AuditPassageSourceClamp=false;
|
||||||
bool AuditPassageCarveReach=false;
|
bool AuditPassageCarveReach=false;
|
||||||
bool RegionCrossing=false;
|
bool RegionCrossing=false;
|
||||||
@@ -1476,7 +1477,8 @@ namespace
|
|||||||
" --shape-helper-limit=8|12 (default 8; shape build A/B)\n"
|
" --shape-helper-limit=8|12 (default 8; shape build A/B)\n"
|
||||||
" --audit-base-page-equivalence (hash one tile through both shape routes)\n"
|
" --audit-base-page-equivalence (hash one tile through both shape routes)\n"
|
||||||
" --audit-route-parity (compare page, native-only, exact-query and mesh routes)\n"
|
" --audit-route-parity (compare page, native-only, exact-query and mesh routes)\n"
|
||||||
" --audit-passage-tile-seams (compare shared LOD0 density samples in adjacent route tiles)\n"
|
" --audit-passage-tile-seams (compare shared LOD0/1 density samples across passage regions)\n"
|
||||||
|
" --inject-passage-seam-mismatch (negative control for seam gate)\n"
|
||||||
" --audit-passage-source-clamp (compare passage source floors 2,3,4,6 over all near tiles)\n"
|
" --audit-passage-source-clamp (compare passage source floors 2,3,4,6 over all near tiles)\n"
|
||||||
" --audit-passage-carve-reach (compare post-composer reaches 1.5,2,2.5,4 m over all near tiles)\n"
|
" --audit-passage-carve-reach (compare post-composer reaches 1.5,2,2.5,4 m over all near tiles)\n"
|
||||||
" --audit-tile-shape-readiness (run a deliberately mis-marked tile against the native-only guard)\n"
|
" --audit-tile-shape-readiness (run a deliberately mis-marked tile against the native-only guard)\n"
|
||||||
@@ -1568,6 +1570,8 @@ namespace
|
|||||||
else if(arg=="--audit-base-page-equivalence")options.AuditBasePageEquivalence=true;
|
else if(arg=="--audit-base-page-equivalence")options.AuditBasePageEquivalence=true;
|
||||||
else if(arg=="--audit-route-parity")options.AuditRouteParity=true;
|
else if(arg=="--audit-route-parity")options.AuditRouteParity=true;
|
||||||
else if(arg=="--audit-passage-tile-seams")options.AuditPassageTileSeams=true;
|
else if(arg=="--audit-passage-tile-seams")options.AuditPassageTileSeams=true;
|
||||||
|
else if(arg=="--inject-passage-seam-mismatch")
|
||||||
|
{options.AuditPassageTileSeams=true;options.InjectPassageSeamMismatch=true;}
|
||||||
else if(arg=="--audit-passage-source-clamp")options.AuditPassageSourceClamp=true;
|
else if(arg=="--audit-passage-source-clamp")options.AuditPassageSourceClamp=true;
|
||||||
else if(arg=="--audit-passage-carve-reach")options.AuditPassageCarveReach=true;
|
else if(arg=="--audit-passage-carve-reach")options.AuditPassageCarveReach=true;
|
||||||
else if(arg=="--region-crossing")options.RegionCrossing=true;
|
else if(arg=="--region-crossing")options.RegionCrossing=true;
|
||||||
@@ -1742,6 +1746,7 @@ int main(int argc,char** argv)
|
|||||||
const auto coldStart=Clock::now();
|
const auto coldStart=Clock::now();
|
||||||
FOptions options;
|
FOptions options;
|
||||||
if(!ParseOptions(argc,argv,options))return 2;
|
if(!ParseOptions(argc,argv,options))return 2;
|
||||||
|
bool preflightGateFailure=false;
|
||||||
if(options.TlsProbeRequested)
|
if(options.TlsProbeRequested)
|
||||||
return StandaloneTlsProbe::Run(options.TlsProbeWorkers,options.TlsProbeTouch);
|
return StandaloneTlsProbe::Run(options.TlsProbeWorkers,options.TlsProbeTouch);
|
||||||
std::printf("[HeadlessConfig] data=%s workers=%d clip_radius=%d max_clip_level=%d max_level=%d hash=%s hash_uniform_skips=%s column_overlap=%s force_generate=%s recipe=%s lattice_strate=%d shared_column_cache=%s camera_step_m=(%.3f,%.3f,%.3f) camera_override=%s camera_m=(%.6f,%.6f,%.6f) camera_rotation_deg=(%.3f,%.3f) seed_override=%s render_distance_override=%s\n",
|
std::printf("[HeadlessConfig] data=%s workers=%d clip_radius=%d max_clip_level=%d max_level=%d hash=%s hash_uniform_skips=%s column_overlap=%s force_generate=%s recipe=%s lattice_strate=%d shared_column_cache=%s camera_step_m=(%.3f,%.3f,%.3f) camera_override=%s camera_m=(%.6f,%.6f,%.6f) camera_rotation_deg=(%.3f,%.3f) seed_override=%s render_distance_override=%s\n",
|
||||||
@@ -2392,24 +2397,24 @@ int main(int argc,char** argv)
|
|||||||
if(actualRecipe!=requestedRecipe)
|
if(actualRecipe!=requestedRecipe)
|
||||||
{std::fprintf(stderr,"Requested recipe %.*s resolved to %.*s\n",
|
{std::fprintf(stderr,"Requested recipe %.*s resolved to %.*s\n",
|
||||||
static_cast<int>(requestedRecipe.size()),requestedRecipe.data(),
|
static_cast<int>(requestedRecipe.size()),requestedRecipe.data(),
|
||||||
static_cast<int>(actualRecipe.size()),actualRecipe.data());return 2;}
|
static_cast<int>(actualRecipe.size()),actualRecipe.data());preflightGateFailure=true;}
|
||||||
std::printf("[ResolvedLayoutCompatibility] accepted=%s issues=%zu error=%s\n",
|
std::printf("[ResolvedLayoutCompatibility] accepted=%s issues=%zu error=%s\n",
|
||||||
compatibilityAccepted?"true":"false",compatibilityIssues.size(),compatibilityError.c_str());
|
compatibilityAccepted?"true":"false",compatibilityIssues.size(),compatibilityError.c_str());
|
||||||
for(const auto& issue:compatibilityIssues)
|
for(const auto& issue:compatibilityIssues)
|
||||||
std::printf("[ResolvedLayoutCompatibilityIssue] code=%s detail=%s\n",
|
std::printf("[ResolvedLayoutCompatibilityIssue] code=%s detail=%s\n",
|
||||||
issue.code.c_str(),issue.detail.c_str());
|
issue.code.c_str(),issue.detail.c_str());
|
||||||
if(!compatibilityAccepted)
|
if(!compatibilityAccepted)
|
||||||
{std::fprintf(stderr,"Resolved-layout compatibility validation failed: %s\n",compatibilityError.c_str());return 2;}
|
{std::fprintf(stderr,"Resolved-layout compatibility validation failed: %s\n",compatibilityError.c_str());preflightGateFailure=true;}
|
||||||
std::printf("[ResolvedLayoutStrict] accepted=%s issues=%zu error=%s\n",
|
std::printf("[ResolvedLayoutStrict] accepted=%s issues=%zu error=%s\n",
|
||||||
strictAccepted?"true":"false",strictIssues.size(),strictError.c_str());
|
strictAccepted?"true":"false",strictIssues.size(),strictError.c_str());
|
||||||
for(const auto& issue:strictIssues)
|
for(const auto& issue:strictIssues)
|
||||||
std::printf("[ResolvedLayoutStrictIssue] code=%s detail=%s\n",issue.code.c_str(),issue.detail.c_str());
|
std::printf("[ResolvedLayoutStrictIssue] code=%s detail=%s\n",issue.code.c_str(),issue.detail.c_str());
|
||||||
if(!strictAccepted)
|
if(!strictAccepted)
|
||||||
{std::fprintf(stderr,"Resolved-layout strict validation failed: %s\n",strictError.c_str());return 2;}
|
{std::fprintf(stderr,"Resolved-layout strict validation failed: %s\n",strictError.c_str());preflightGateFailure=true;}
|
||||||
std::printf("[ResolvedLayoutValidatorControls] rejected=%u/%u status=%s\n",
|
std::printf("[ResolvedLayoutValidatorControls] rejected=%u/%u status=%s\n",
|
||||||
controls.controlsRejectedAsExpected,controls.controlsRun,controls.passed?"PASS":"FAIL");
|
controls.controlsRejectedAsExpected,controls.controlsRun,controls.passed?"PASS":"FAIL");
|
||||||
if(!controls.passed)
|
if(!controls.passed)
|
||||||
{for(const auto& failure:controls.failures)std::printf("[ResolvedLayoutValidatorControlFailure] %s %s\n",failure.code.c_str(),failure.detail.c_str());return 2;}
|
{for(const auto& failure:controls.failures)std::printf("[ResolvedLayoutValidatorControlFailure] %s %s\n",failure.code.c_str(),failure.detail.c_str());preflightGateFailure=true;}
|
||||||
if(options.DensityDispatchReport)
|
if(options.DensityDispatchReport)
|
||||||
{
|
{
|
||||||
const auto& slots=ownerWorld->Manager->GetLayout();
|
const auto& slots=ownerWorld->Manager->GetLayout();
|
||||||
@@ -2577,7 +2582,7 @@ int main(int argc,char** argv)
|
|||||||
plan->route.size(),MaximumRouteZ,CeilingFace-MaximumRouteZ,
|
plan->route.size(),MaximumRouteZ,CeilingFace-MaximumRouteZ,
|
||||||
MaximumRouteZ<CeilingFace?"PASS":"COLLISION");
|
MaximumRouteZ<CeilingFace?"PASS":"COLLISION");
|
||||||
}
|
}
|
||||||
if(options.ResolvedLayoutOnly)return 0;
|
if(options.ResolvedLayoutOnly)return preflightGateFailure?2:0;
|
||||||
}
|
}
|
||||||
if(options.AutoSurfaceCamera)
|
if(options.AutoSurfaceCamera)
|
||||||
{
|
{
|
||||||
@@ -2667,7 +2672,7 @@ int main(int argc,char** argv)
|
|||||||
?FVector(options.CameraStepMeters.X*1000000.0f/std::max<std::uint32_t>(1,ownerWorld->CoreVoxelSizeMicrons),
|
?FVector(options.CameraStepMeters.X*1000000.0f/std::max<std::uint32_t>(1,ownerWorld->CoreVoxelSizeMicrons),
|
||||||
options.CameraStepMeters.Y*1000000.0f/std::max<std::uint32_t>(1,ownerWorld->CoreVoxelSizeMicrons),
|
options.CameraStepMeters.Y*1000000.0f/std::max<std::uint32_t>(1,ownerWorld->CoreVoxelSizeMicrons),
|
||||||
options.CameraStepMeters.Z*1000000.0f/std::max<std::uint32_t>(1,ownerWorld->CoreVoxelSizeMicrons)):FVector::ZeroVector;
|
options.CameraStepMeters.Z*1000000.0f/std::max<std::uint32_t>(1,ownerWorld->CoreVoxelSizeMicrons)):FVector::ZeroVector;
|
||||||
return StandaloneStreamBenchmark::RunPipelinedStreamingBenchmark(ownerWorld,snapshot,
|
const int pipelineResult=StandaloneStreamBenchmark::RunPipelinedStreamingBenchmark(ownerWorld,snapshot,
|
||||||
cameraVoxels,options.WorkerCount,options.MaxLevel,VoxelForgeCore::DetailVariant::coherent,
|
cameraVoxels,options.WorkerCount,options.MaxLevel,VoxelForgeCore::DetailVariant::coherent,
|
||||||
scheduler,options.StreamHash,false,false,false,false,coldStart,
|
scheduler,options.StreamHash,false,false,false,false,coldStart,
|
||||||
options.ProfileColumnOverlap,options.FarHorizonLOD8InteriorStepVoxels,
|
options.ProfileColumnOverlap,options.FarHorizonLOD8InteriorStepVoxels,
|
||||||
@@ -2690,6 +2695,8 @@ int main(int argc,char** argv)
|
|||||||
options.MovingCameraSpeedMetersPerSecond,options.MovingCameraDurationSeconds,
|
options.MovingCameraSpeedMetersPerSecond,options.MovingCameraDurationSeconds,
|
||||||
options.MovingCameraDwellSeconds,options.ColdWorkerTimeline,
|
options.MovingCameraDwellSeconds,options.ColdWorkerTimeline,
|
||||||
options.AuditPassageSourceClamp,options.AuditPassageCarveReach,
|
options.AuditPassageSourceClamp,options.AuditPassageCarveReach,
|
||||||
options.AuditPassageTileSeams,options.AuditLiminalRoadWalk,
|
options.AuditPassageTileSeams,options.InjectPassageSeamMismatch,
|
||||||
|
options.AuditLiminalRoadWalk,
|
||||||
options.LiminalStampWalkAuditPath);
|
options.LiminalStampWalkAuditPath);
|
||||||
|
return pipelineResult!=0?pipelineResult:(preflightGateFailure?2:0);
|
||||||
}
|
}
|
||||||
File diff suppressed because it is too large.
Load diff
@@ -202,7 +202,9 @@ FVoxelMeshData UVoxelMarchingCubesMesher::GenerateMesh(FIntVector OriginVoxels,
|
|||||||
std::vector<float>* OutDebugDensitySamples,
|
std::vector<float>* OutDebugDensitySamples,
|
||||||
FVoxelMarchingCubesStageTimings* OutStageTimings,
|
FVoxelMarchingCubesStageTimings* OutStageTimings,
|
||||||
FVoxelUniformBlockProofAuditStats* OutBlockProofAudit,
|
FVoxelUniformBlockProofAuditStats* OutBlockProofAudit,
|
||||||
bool bForceFullDensityCapture)
|
bool bForceFullDensityCapture,
|
||||||
|
FIntVector* OutDebugDensityOriginVoxels,
|
||||||
|
FIntVector* OutDebugDensityDimensions)
|
||||||
{
|
{
|
||||||
TRACE_CPUPROFILER_EVENT_SCOPE(VoxelForge_MesherGenerateMesh);
|
TRACE_CPUPROFILER_EVENT_SCOPE(VoxelForge_MesherGenerateMesh);
|
||||||
FStandaloneShapeWorld::FScopedPassageDensityQueryCaller densityQueryCaller(
|
FStandaloneShapeWorld::FScopedPassageDensityQueryCaller densityQueryCaller(
|
||||||
@@ -215,6 +217,8 @@ FVoxelMeshData UVoxelMarchingCubesMesher::GenerateMesh(FIntVector OriginVoxels,
|
|||||||
if (OutStageTimings) { *OutStageTimings = FVoxelMarchingCubesStageTimings{}; }
|
if (OutStageTimings) { *OutStageTimings = FVoxelMarchingCubesStageTimings{}; }
|
||||||
if (OutBlockProofAudit) { *OutBlockProofAudit = FVoxelUniformBlockProofAuditStats{}; }
|
if (OutBlockProofAudit) { *OutBlockProofAudit = FVoxelUniformBlockProofAuditStats{}; }
|
||||||
if (OutDebugDensitySamples) { OutDebugDensitySamples->clear(); }
|
if (OutDebugDensitySamples) { OutDebugDensitySamples->clear(); }
|
||||||
|
if (OutDebugDensityOriginVoxels) *OutDebugDensityOriginVoxels=FIntVector::ZeroValue;
|
||||||
|
if (OutDebugDensityDimensions) *OutDebugDensityDimensions=FIntVector::ZeroValue;
|
||||||
if (!Generator) return MeshData;
|
if (!Generator) return MeshData;
|
||||||
const bool bEmitUV = !bStandaloneSkipUvAndColors && !bStandaloneSkipUV;
|
const bool bEmitUV = !bStandaloneSkipUvAndColors && !bStandaloneSkipUV;
|
||||||
const bool bEmitColors = !bStandaloneSkipUvAndColors && !bStandaloneSkipColors;
|
const bool bEmitColors = !bStandaloneSkipUvAndColors && !bStandaloneSkipColors;
|
||||||
@@ -640,6 +644,14 @@ FVoxelMeshData UVoxelMarchingCubesMesher::GenerateMesh(FIntVector OriginVoxels,
|
|||||||
}
|
}
|
||||||
const int32 GzLo = CzLo - 1; // coins CzLo..CzHi+1, gradients ±1
|
const int32 GzLo = CzLo - 1; // coins CzLo..CzHi+1, gradients ±1
|
||||||
const int32 GzHi = CzHi + 2; // (== -1..GridDim sans bande)
|
const int32 GzHi = CzHi + 2; // (== -1..GridDim sans bande)
|
||||||
|
if(OutDebugDensitySamples)
|
||||||
|
{
|
||||||
|
if(OutDebugDensityOriginVoxels)
|
||||||
|
*OutDebugDensityOriginVoxels=OriginVoxels
|
||||||
|
+FIntVector(-Step,-Step,GzLo*Step);
|
||||||
|
if(OutDebugDensityDimensions)
|
||||||
|
*OutDebugDensityDimensions=FIntVector(MDim,MDim,GzHi-GzLo+1);
|
||||||
|
}
|
||||||
|
|
||||||
MesherSetupTimer.End();
|
MesherSetupTimer.End();
|
||||||
|
|
||||||
|
|||||||
@@ -171,7 +171,9 @@ public:
|
|||||||
std::vector<float>* OutDebugDensitySamples = nullptr,
|
std::vector<float>* OutDebugDensitySamples = nullptr,
|
||||||
FVoxelMarchingCubesStageTimings* OutStageTimings = nullptr,
|
FVoxelMarchingCubesStageTimings* OutStageTimings = nullptr,
|
||||||
FVoxelUniformBlockProofAuditStats* OutBlockProofAudit = nullptr,
|
FVoxelUniformBlockProofAuditStats* OutBlockProofAudit = nullptr,
|
||||||
bool bForceFullDensityCapture = false);
|
bool bForceFullDensityCapture = false,
|
||||||
|
FIntVector* OutDebugDensityOriginVoxels = nullptr,
|
||||||
|
FIntVector* OutDebugDensityDimensions = nullptr);
|
||||||
|
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
// SERVICES (injectés par AVoxelWorld)
|
// SERVICES (injectés par AVoxelWorld)
|
||||||
|
|||||||
Reference in new issue
Block a user