diff --git a/coordination/claims/M00-QAR-CAMERA-POSE-EVIDENCE-001.md b/coordination/claims/M00-QAR-CAMERA-POSE-EVIDENCE-001.md new file mode 100644 index 0000000..e64f6fa --- /dev/null +++ b/coordination/claims/M00-QAR-CAMERA-POSE-EVIDENCE-001.md @@ -0,0 +1,78 @@ +# M00-QAR-CAMERA-POSE-EVIDENCE-001 — Goldshire camera pose evidence + + + +## Ownership + +- Target: M00 +- Program: QAR +- Owner/Agent ID: sindo-main-codex +- Branch: `work/sindo-main-codex/m00-camera-pose-evidence` +- Lease expires UTC: 2026-07-14 +- Integrator: milestone integrator + +## Outcome + +Produce coarse-to-fine yaw/pitch evidence for the build 12340 Goldshire Inn reference and classify whether framing dominates the paired-image gap. + +## Non-goals + +- Changing manifest camera defaults before human approval. +- Treating minimum perceptual error as proof of exact camera parity. +- Committing proprietary reference images or generated candidates. + +## Paths + +- Exclusive: camera-pose evidence record +- Shared/hotspots: renderer baseline and module fidelity findings +- Generated/ignored: all sweep PNGs and JSON under `user://` + +## Contracts and data + +- Public API/events: none +- Schema/format version: unchanged +- Migration/compatibility: none +- Consumers: M00 fidelity review + +## Dependencies + +- Requires: merged camera-pose sweep and local build 12340 reference +- Blocks: classification of the Goldshire WMO paired gap +- External state: `sources/OpenWCReferenceCheckpoints/goldshire_inn_large_wmo.jpg` + +## Verification + +- Commands: coarse and fine real sweeps, ranking inspection, repository gates +- Fixtures: private Goldshire Inn build 12340 screenshot +- Fidelity evidence: ranked mean perceptual error and changed-pixel ratio +- Performance budget: offline diagnostic only + +## Documentation deliverables + +- Inline public API docs: unchanged +- Module specification: fidelity finding and remaining risk +- Data-flow diagram: unchanged +- Sequence/state/dependency diagrams: unchanged +- Source map/status updates: baseline evidence + +## Simplicity and naming + +- Important names introduced: none +- Simplest considered solution: use the merged bounded grid runner +- Rejected complexity/abstractions: optimizer or renderer changes +- Unavoidable complexity and justification: real images must be rendered for each candidate +- Measured optimization evidence: single pass per candidate + +## Status + +- State: ready-for-review +- Done: private reference dimensions verified; coarse, extended and limit sweeps completed; representative candidates inspected; runner failure handling hardened +- Next: investigate Goldshire Inn spatial/placement composition separately; do not change manifest yaw/pitch from this metric +- Blocked by: + +## Handoff + +- Commit: this work-package commit +- Results: zero offset mean error 0.099632; coarse best (-10,-20) 0.077575; metric decreased monotonically to (0,-60) 0.063574/changed ratio 0.549556, while visual inspection showed only grass and no inn +- Remaining risks: full-frame color error cannot register a missing landmark; WMO placement/streaming at this checkpoint remains unresolved +- Documentation updated: `docs/CAMERA_POSE_SWEEP.md`, `docs/modules/world-renderer.md` diff --git a/docs/CAMERA_POSE_SWEEP.md b/docs/CAMERA_POSE_SWEEP.md index 84e3a97..fe253ca 100644 --- a/docs/CAMERA_POSE_SWEEP.md +++ b/docs/CAMERA_POSE_SWEEP.md @@ -14,10 +14,11 @@ This offline M00 diagnostic recovers reproducible checkpoint framing when an ori -Checkpoint elwynn_adt_boundary ` -YawOffsets -15,-10,-5,0,5,10,15 ` -PitchOffsets -10,-5,0,5,10 ` + -ViewportWidth 1280 -ViewportHeight 960 ` -WaitSeconds 2 ``` -Each candidate receives its own output directory and comparison report. `ranking.json` sorts candidates by mean perceptual error and then changed-pixel ratio. Use `-PlanOnly` to validate the Cartesian grid and output paths without rendering. Run a coarse grid first, then a finer grid around the best candidate. +Each candidate receives its own output directory and comparison report. The viewport must exactly match the reference image dimensions; the runner fails on `size_mismatch` instead of inventing a score. `ranking.json` sorts candidates by mean perceptual error and then changed-pixel ratio. Use `-PlanOnly` to validate the Cartesian grid and output paths without rendering. Run a coarse grid first, then a finer grid around the best candidate. ```mermaid flowchart LR @@ -37,3 +38,11 @@ The smallest error is a candidate, not automatic fidelity approval. Geometry, ma ## Verification The headless capture dry-run must report requested yaw and pitch offsets. Comparator `--self-test` covers paired metrics. Sweep `-PlanOnly` covers deterministic grid expansion and output naming without requiring a display. A real ranked sweep requires a display and a private build 12340 reference image. + +## Goldshire Inn evidence — 2026-07-12 + +The private `2560x1440` build 12340 `goldshire_inn_large_wmo` reference was evaluated at FOV 62 degrees. A coarse 5x5 grid over yaw/pitch `[-20, -10, 0, 10, 20]` reduced mean error from `0.099632` at `(0, 0)` to `0.077575` at `(-10, -20)`. Extending pitch produced `0.070901` at `(0, -40)` and `0.063574` at `(0, -60)` with changed-pixel ratio `0.549556`. + +This is not a camera-pose solution. Human inspection shows the original-client reference centered on the Goldshire Inn, while the zero-offset OpenWC candidate contains forest/roads and no inn; negative pitch increasingly fills the frame with grass. The monotonically improving full-frame metric rewards similar green color coverage rather than landmark alignment. Therefore the manifest pose is unchanged and this checkpoint remains spatial/placement-composition evidence. A future registration metric must use approved landmark or region masks before it can select camera pose automatically. + +During this run the sweep orchestration was hardened in two ways: expected comparator exit code `1` is now collected through an explicit child process, and viewport dimensions are explicit. A reference/candidate `size_mismatch` now fails before ranking instead of producing an empty metric. diff --git a/docs/modules/world-renderer.md b/docs/modules/world-renderer.md index 466145c..2634ffc 100644 --- a/docs/modules/world-renderer.md +++ b/docs/modules/world-renderer.md @@ -230,6 +230,7 @@ Exact exported settings and cache versions remain documented in [`../../RENDER.m - Camera-occluder probe не нашёл camera containment в пяти точках; paired mismatch локализован прежде всего в manual look direction/target/FOV calibration, с явным ограничением по RID-only geometry. - Empirical FOV sweep выявил, что checkpoint camera должна явно вызывать `make_current()`; после исправления projection ranking остаётся inconclusive из-за неизвестного manual yaw/pitch/framing reference. - Camera-pose sweep can now rank bounded yaw/pitch grids without changing manifest defaults; perceptual ranking remains diagnostic and requires human framing approval. +- Goldshire Inn pose evidence has no landmark-aligned optimum: full-frame error decreases as negative pitch replaces the missing inn composition with grass. The checkpoint remains a spatial/placement gap, not a validated camera offset. - D3D12 descriptor issues remain; the capture-path anonymous `RefCounted` shutdown leak is regression-covered by a clean verbose dry-run, while other RID/resource diagnostics still require independent evidence. - M2/WMO/material/particle/ribbon/portal parity incomplete. - Public API is mostly exported configuration rather than stable contracts. diff --git a/tools/sweep_render_checkpoint_camera_pose.ps1 b/tools/sweep_render_checkpoint_camera_pose.ps1 index 0e38fe6..8ee2fd0 100644 --- a/tools/sweep_render_checkpoint_camera_pose.ps1 +++ b/tools/sweep_render_checkpoint_camera_pose.ps1 @@ -9,6 +9,8 @@ param( [double[]]$YawOffsets = @(-10.0, 0.0, 10.0), [double[]]$PitchOffsets = @(-10.0, 0.0, 10.0), [double]$CameraFov = 62.0, + [int]$ViewportWidth = 1280, + [int]$ViewportHeight = 900, [double]$WaitSeconds = 2.0, [double]$MeasureSeconds = 0.1, [switch]$PlanOnly @@ -62,19 +64,26 @@ try { continue } - & $GodotPath --path . --script res://src/tools/capture_render_checkpoints.gd -- ` - --output $candidateOutput --only $Checkpoint --single-pass ` - --camera-fov $cameraFovText ` - --camera-yaw-offset $yawText --camera-pitch-offset $pitchText ` - --wait $waitSecondsText --measure $measureSecondsText - if ($LASTEXITCODE -ne 0) { + $captureArguments = @( + "--path", ".", "--script", "res://src/tools/capture_render_checkpoints.gd", "--", + "--output", $candidateOutput, "--only", $Checkpoint, "--single-pass", + "--camera-fov", $cameraFovText, + "--camera-yaw-offset", $yawText, "--camera-pitch-offset", $pitchText, + "--viewport-width", $ViewportWidth, "--viewport-height", $ViewportHeight, + "--wait", $waitSecondsText, "--measure", $measureSecondsText + ) + $captureProcess = Start-Process -FilePath $GodotPath -ArgumentList $captureArguments -Wait -PassThru + if ($captureProcess.ExitCode -ne 0) { throw "Capture failed for yaw=$yawText pitch=$pitchText" } - & $GodotPath --headless --path . --script res://src/tools/compare_render_checkpoints.gd -- ` - --reference $ReferenceDirectory --candidate $candidateOutput ` - --only $Checkpoint --output $comparisonReport - if ($LASTEXITCODE -notin @(0, 1)) { + $comparisonArguments = @( + "--headless", "--path", ".", "--script", "res://src/tools/compare_render_checkpoints.gd", "--", + "--reference", $ReferenceDirectory, "--candidate", $candidateOutput, + "--only", $Checkpoint, "--output", $comparisonReport + ) + $comparisonProcess = Start-Process -FilePath $GodotPath -ArgumentList $comparisonArguments -Wait -PassThru -NoNewWindow + if ($comparisonProcess.ExitCode -notin @(0, 1)) { throw "Comparison failed for yaw=$yawText pitch=$pitchText" } @@ -82,8 +91,13 @@ try { if ($comparison.compared_count -lt 1) { throw "No paired image was compared for yaw=$yawText pitch=$pitchText" } - $meanError = ($comparison.results | Measure-Object -Property mean_perceptual_error -Average).Average - $changedRatio = ($comparison.results | Measure-Object -Property changed_pixel_ratio -Average).Average + $metricResults = @($comparison.results | Where-Object { $null -ne $_.mean_perceptual_error }) + if ($metricResults.Count -ne $comparison.compared_count) { + $statuses = ($comparison.results.status | Sort-Object -Unique) -join "," + throw "Comparison produced no numeric metric for yaw=$yawText pitch=$pitchText statuses=$statuses" + } + $meanError = ($metricResults | Measure-Object -Property mean_perceptual_error -Average).Average + $changedRatio = ($metricResults | Measure-Object -Property changed_pixel_ratio -Average).Average $ranking.Add([pscustomobject]@{ yaw_offset_degrees = $yawOffset pitch_offset_degrees = $pitchOffset @@ -106,6 +120,7 @@ try { schema_version = 1 checkpoint = $Checkpoint reference_directory = [IO.Path]::GetFullPath($ReferenceDirectory) + viewport = @($ViewportWidth, $ViewportHeight) candidates = $rankedCandidates } New-Item -ItemType Directory -Force -Path $absoluteOutput | Out-Null