facett-map3d/examples/selftest.rs
//! **facett-map3d headless render SELF-TEST** (EMIT-DOCTRINE, the canonical
//! GPU-fallback case).
//!
//! A 3D GPU render cannot be observed from a return value, so this self-test
//! renders the extruded 3D map (the znippy-rabbit synthetic fixture) to an
//! **offscreen wgpu framebuffer** (egui_kittest's wgpu backend), then measures
//! three real, independent signals:
//!
//! * `triangles` — the extruded mesh's triangle count (`state_json`),
//! * `tiles` — the footprint count it extruded (`state_json`), and
//! * `lit_px` — the number of **lit** framebuffer pixels (pixels far from the
//! modal background colour — the proof the lit solid actually rasterised).
//!
//! `ok = (triangles > 0 && tiles > 0 && lit_px > 0)`, and the result is EMITTED as
//! one functional-status row:
//! `functional_status("facett-map3d", "3d_map_rendered", ok, &detail)`
//!
//! The emit **and** the expensive detail-building are gated behind
//! `#[cfg(feature = "testmatrix")]`, so a release build (feature OFF) strips both
//! and carries no `nornir-testmatrix` edge.
//!
//! Run: `cargo run -p facett-map3d --example selftest --features testmatrix`
use egui_kittest::Harness;
use facett_core::Facet;
use facett_map3d::Map3D;
/// Count **lit** pixels: those whose colour is far from the modal (≈background)
/// colour. A lit, depth-shaded 3D solid fills a visible region with many such
/// pixels; a blank pane has ~none. (Same modal-distance metric facett-map /
/// facett-graph3d's render proofs use, but reported as an absolute pixel count.)
fn lit_pixels(img: &image::RgbaImage) -> usize {
let mut hist = std::collections::HashMap::<u32, u32>::new();
for p in img.pixels() {
let key = ((p.0[0] as u32 >> 3) << 10) | ((p.0[1] as u32 >> 3) << 5) | (p.0[2] as u32 >> 3);
*hist.entry(key).or_default() += 1;
}
let (modal, _) = hist.iter().max_by_key(|(_, c)| **c).map(|(k, c)| (*k, *c)).unwrap();
let (mr, mg, mb) = (((modal >> 10) & 0x1f) as i32, ((modal >> 5) & 0x1f) as i32, (modal & 0x1f) as i32);
let mut lit = 0usize;
for p in img.pixels() {
let (r, g, b) = ((p.0[0] >> 3) as i32, (p.0[1] >> 3) as i32, (p.0[2] >> 3) as i32);
if (r - mr).abs() + (g - mg).abs() + (b - mb).abs() > 3 {
lit += 1;
}
}
lit
}
fn main() {
// The synthetic znippy-rabbit 3D skyline at a fixed clock → deterministic spin.
let probe = Map3D::synthetic("map3d-selftest").with_clock(1.2);
let state = probe.state_json();
let triangles = state["triangles"].as_u64().unwrap_or(0) as usize;
let tiles = state["tiles"].as_u64().unwrap_or(0) as usize;
// Render offscreen on a real wgpu framebuffer.
let mut view = Map3D::synthetic("map3d-selftest").with_clock(1.2);
let mut harness = Harness::builder().with_size(egui::vec2(640.0, 640.0)).build_ui(move |ui| {
facett_core::set_theme(ui.ctx(), facett_core::Theme::sci_fi());
view.ui(ui);
});
harness.run_steps(3);
let img = harness.render().expect("wgpu render produced an image");
let lit_px = lit_pixels(&img);
let ok = triangles > 0 && tiles > 0 && lit_px > 0;
eprintln!("[map3d-selftest] triangles={triangles} tiles={tiles} lit_px={lit_px} ok={ok}");
// EMIT-DOCTRINE: a 3D render is not observable from a return value, so emit the
// measured render as a functional-status row. Both the emit AND the expensive
// detail string are gated behind `testmatrix` → stripped in release.
#[cfg(feature = "testmatrix")]
{
let total_px = (img.width() * img.height()) as usize;
let detail = format!(
"triangles={triangles} tiles={tiles} lit_px={lit_px}/{total_px} ratio={:.4}",
lit_px as f64 / total_px as f64
);
facett_core::testmatrix::emit("facett-map3d", "3d_map_rendered", ok, &detail);
eprintln!("[map3d-selftest] emitted functional row: 3d_map_rendered ok={ok} ({detail})");
}
if !ok {
eprintln!("[map3d-selftest] FAILED: the 3D map did not render real lit geometry");
std::process::exit(1);
}
}