@@ -445,6 +445,59 @@ pub fn certify_batch_simd(
445445 }
446446}
447447
448+ // ════════════════════════════════════════════════════════════════════════════
449+ // P4 — Blender/CAD mesh-depth anchor (render-depth plan § "Blender/CAD relevance")
450+ // ════════════════════════════════════════════════════════════════════════════
451+
452+ /// Alignment report between an exact mesh/CAD depth and a 3DGS splat's
453+ /// certified depth interval. Realizes the plan's claim: *"CAD mesh says the
454+ /// wall is here; the 3DGS scan says the visual surface is here; the
455+ /// certificate reports whether the visual skin aligns within tolerance."*
456+ ///
457+ /// `#[repr(C)]` for `lance-graph` ingestion.
458+ #[ repr( C ) ]
459+ #[ derive( Clone , Copy , Debug , PartialEq ) ]
460+ pub struct MeshAlignment {
461+ /// Exact mesh/CAD depth (camera-space), the anchor.
462+ pub mesh_depth : f32 ,
463+ /// 3DGS splat centre depth (camera-space).
464+ pub splat_depth : f32 ,
465+ /// `splat_depth - mesh_depth` (signed).
466+ pub depth_delta : f32 ,
467+ /// Mesh depth lies inside the certified `[min_depth, max_depth]` interval.
468+ pub within_interval : bool ,
469+ /// `|depth_delta| ≤ tolerance`.
470+ pub within_tolerance : bool ,
471+ /// `|depth_delta|` in units of the interval half-width (k·σ_z) — "how many
472+ /// sigmas the visual skin is off the CAD surface".
473+ pub normalized_error : f32 ,
474+ /// Overall: aligned if the mesh is inside the interval or within tolerance.
475+ pub aligned : bool ,
476+ }
477+
478+ /// Compare an exact mesh depth against a splat's certified depth interval.
479+ ///
480+ /// `mesh_depth` and `splat_depth` are camera-space depths; `cert` is the
481+ /// splat's [`RenderDepthCertificate`]; `tolerance` is the world-space depth
482+ /// slack the caller accepts for "the scan skin sits on the CAD surface".
483+ pub fn mesh_alignment (
484+ mesh_depth : f32 , splat_depth : f32 , cert : & RenderDepthCertificate , tolerance : f32 ,
485+ ) -> MeshAlignment {
486+ let depth_delta = splat_depth - mesh_depth;
487+ let within_interval = mesh_depth >= cert. min_depth && mesh_depth <= cert. max_depth ;
488+ let within_tolerance = depth_delta. abs ( ) <= tolerance;
489+ let normalized_error = depth_delta. abs ( ) / cert. covariance_depth_error . max ( 1e-6 ) ;
490+ MeshAlignment {
491+ mesh_depth,
492+ splat_depth,
493+ depth_delta,
494+ within_interval,
495+ within_tolerance,
496+ normalized_error,
497+ aligned : within_interval || within_tolerance,
498+ }
499+ }
500+
448501/// Zeroed certificate for culled slots (shared by scalar + SIMD batch paths).
449502const ZERO_CERT : RenderDepthCertificate = RenderDepthCertificate {
450503 min_depth : 0.0 ,
@@ -712,4 +765,72 @@ mod tests {
712765 }
713766 assert ! ( culled > 0 , "test should exercise at least one culled slot" ) ;
714767 }
768+
769+ // ── P4: mesh-anchor alignment + first demo ────────────────────────────────
770+
771+ #[ test]
772+ fn mesh_alignment_within_interval_is_aligned ( ) {
773+ // depth=10, cov_zz=0.25, k=2 → interval [9, 11].
774+ let params = DepthCertParams { k_sigma : 2.0 , ..Default :: default ( ) } ;
775+ let cert = certify_depth_scalar ( 10.0 , 0.25 , 5.0 , & params) ;
776+ let a = mesh_alignment ( 10.0 , 10.0 , & cert, 0.01 ) ;
777+ assert ! ( a. within_interval && a. aligned, "{a:?}" ) ;
778+ assert ! ( approx( a. normalized_error, 0.0 , 1e-6 ) ) ;
779+ assert ! ( approx( a. depth_delta, 0.0 , 1e-6 ) ) ;
780+ }
781+
782+ #[ test]
783+ fn mesh_alignment_outside_interval_but_within_tolerance_is_aligned ( ) {
784+ let params = DepthCertParams { k_sigma : 2.0 , ..Default :: default ( ) } ;
785+ let cert = certify_depth_scalar ( 10.0 , 0.25 , 5.0 , & params) ; // [9, 11]
786+ // mesh at 8.5 is outside [9,11] but a generous 2.0 tolerance accepts it.
787+ let a = mesh_alignment ( 8.5 , 10.0 , & cert, 2.0 ) ;
788+ assert ! ( !a. within_interval) ;
789+ assert ! ( a. within_tolerance) ;
790+ assert ! ( a. aligned) ;
791+ }
792+
793+ #[ test]
794+ fn mesh_alignment_far_is_not_aligned_and_many_sigma ( ) {
795+ let params = DepthCertParams { k_sigma : 2.0 , ..Default :: default ( ) } ;
796+ let cert = certify_depth_scalar ( 10.0 , 0.25 , 5.0 , & params) ; // half-width 1.0
797+ let a = mesh_alignment ( 11.5 , 10.0 , & cert, 0.01 ) ;
798+ assert ! ( !a. aligned && !a. within_interval && !a. within_tolerance, "{a:?}" ) ;
799+ assert ! ( approx( a. normalized_error, 1.5 , 1e-5 ) , "1.5σ off, got {}" , a. normalized_error) ;
800+ }
801+
802+ /// Plan § "First demo": one camera, one mesh plane, one splat block near it
803+ /// → project → certify depth interval → report alignment / pass-fail.
804+ #[ test]
805+ fn first_demo_mesh_plane_splat_alignment ( ) {
806+ let cam = Camera :: identity_at_origin ( 256 , 256 ) ;
807+ let mesh_depth = 5.0 ; // CAD plane at camera-space z = 5
808+
809+ // One splat sitting on the plane.
810+ let mut batch = GaussianBatch :: with_capacity ( 1 ) ;
811+ let mut g = Gaussian3D :: unit ( ) ;
812+ g. mean = [ 0.0 , 0.0 , 5.0 ] ;
813+ g. scale = [ 0.2 , 0.2 , 0.2 ] ;
814+ g. quat = [ 1.0 , 0.0 , 0.0 , 0.0 ] ;
815+ g. opacity = 1.0 ;
816+ batch. push ( g) ;
817+
818+ let mut proj = ProjectedBatch :: with_capacity ( batch. capacity ) ;
819+ project_batch ( & batch, & cam, & mut proj) ;
820+ assert_eq ! ( proj. valid[ 0 ] , 1 , "demo splat must be visible" ) ;
821+
822+ let mut dv = vec ! [ 0.0f32 ; batch. len] ;
823+ camera_depth_variance_batch ( & batch, & cam, & mut dv) ;
824+ let params = DepthCertParams { k_sigma : 3.0 , ..Default :: default ( ) } ;
825+ let cert = certify_depth_scalar ( proj. depth [ 0 ] , dv[ 0 ] , proj. radius [ 0 ] , & params) ;
826+
827+ // Scan skin sits on the CAD plane → aligned, mesh inside interval.
828+ let on = mesh_alignment ( mesh_depth, proj. depth [ 0 ] , & cert, 0.05 ) ;
829+ assert ! ( on. aligned && on. within_interval, "splat on plane should align: {on:?}" ) ;
830+
831+ // CAD wall 15 units behind the scan surface → not aligned, many σ off.
832+ let off = mesh_alignment ( 20.0 , proj. depth [ 0 ] , & cert, 0.05 ) ;
833+ assert ! ( !off. aligned && !off. within_interval, "distant mesh must not align: {off:?}" ) ;
834+ assert ! ( off. normalized_error > 1.0 , "should be many σ off, got {}" , off. normalized_error) ;
835+ }
715836}
0 commit comments