Skip to main content

qualia_core_db/render/
projection.rs

1//! Unified manifold projection (Phase 1.4, `RENDERER_IMPLEMENTATION_PLAN.md`) — **one projection,
2//! many views**.
3//!
4//! The renderer's foundation is the 10D tensor manifold. A node's *place* is decided once, by the
5//! semantic-motor map `10D → 3D world` (the same map `projector.wgsl` applies on the GPU;
6//! [`crate::render::pga`] is its parity-tested CPU oracle). Every "view" — the 3D scene, the 2D
7//! canvas — is then a projection of that **same** world point onto a target, not an independent
8//! re-computation. This module is the single entry point that makes that explicit:
9//!
10//!   * [`manifold_world`] — the shared step: `Tensor10D → [x,y,z]` world.
11//!   * [`project`] — that world point as the requested [`ProjectionTarget`] (3D volume, or its 2D
12//!     planar shadow). One call, selectable view.
13//!
14//! The 3D *scene* additionally applies the orbit camera ([`crate::render::camera`]) on top of the
15//! world point; the 2D *canvas* uses the planar shadow directly. Both start from one `project`.
16
17use crate::render::pga::{sandwich_point, semantic_motor_intrinsic};
18use crate::render::telemetry::STANDPOINT_SPECTATOR;
19use crate::tensor::Tensor10D;
20
21/// Which view of the shared manifold world point to produce.
22#[derive(Clone, Copy, Debug, PartialEq, Eq)]
23pub enum ProjectionTarget {
24    /// 2D canvas: the orthographic shadow of the world point on the `z = 0` plane.
25    Plane2D,
26    /// 3D scene: the world point itself (the orbit camera is applied downstream).
27    Volume3D,
28}
29
30/// The shared projection step — a 10D tensor node to its 3D world position via the semantic-motor
31/// manifold map. `time` drives the animated bands (`v`/`q`); a spectator standpoint with full
32/// epistemic aperture is used (view-neutral). This is the parity-tested oracle of `projector.wgsl`.
33#[inline]
34pub fn manifold_world(t: &Tensor10D, time: f32) -> [f32; 3] {
35    let local = [t.x, t.y, t.z];
36    let motor = semantic_motor_intrinsic(
37        t.v,
38        t.w,
39        t.q,
40        t.sigma,
41        time,
42        t.alpha,
43        local,
44        STANDPOINT_SPECTATOR,
45        1.0,
46    );
47    sandwich_point(motor, local)
48}
49
50/// One projection, many views: project a 10D node through the shared manifold map, then select the
51/// view. `Volume3D` yields the 3D world point; `Plane2D` yields its 2D shadow (`z` zeroed). The two
52/// agree on `(x, y)` by construction — they are the *same* manifold point seen two ways.
53#[inline]
54pub fn project(t: &Tensor10D, time: f32, target: ProjectionTarget) -> [f32; 3] {
55    let world = manifold_world(t, time);
56    match target {
57        ProjectionTarget::Volume3D => world,
58        ProjectionTarget::Plane2D => [world[0], world[1], 0.0],
59    }
60}
61
62#[cfg(test)]
63mod tests {
64    use super::*;
65
66    fn node() -> Tensor10D {
67        Tensor10D {
68            q: 0.4,
69            v: 1.5,
70            w: 2.0,
71            x: 0.3,
72            y: -0.2,
73            z: 0.5,
74            t: 0.5,
75            alpha: 0.9,
76            mu: 0.0,
77            sigma: 0.25,
78        }
79    }
80
81    #[test]
82    fn one_projection_many_views() {
83        let t = node();
84        let time = 0.7;
85        let v3 = project(&t, time, ProjectionTarget::Volume3D);
86        let v2 = project(&t, time, ProjectionTarget::Plane2D);
87        // Both views are the SAME manifold world point: the 2D plane view is the (x,y) shadow of
88        // the 3D volume view, and the 3D view is exactly the shared step.
89        assert!((v2[0] - v3[0]).abs() < 1e-6);
90        assert!((v2[1] - v3[1]).abs() < 1e-6);
91        assert_eq!(v2[2], 0.0);
92        assert_eq!(v3, manifold_world(&t, time));
93    }
94
95    #[test]
96    fn euclidean_node_projects_to_itself() {
97        // v=0 (Euclidean), w=0, q=0 → identity motor → world == local, independent of time.
98        let t = Tensor10D {
99            q: 0.0,
100            v: 0.0,
101            w: 0.0,
102            x: 0.2,
103            y: -0.4,
104            z: 0.1,
105            sigma: 0.0,
106            alpha: 1.0,
107            ..node()
108        };
109        let w = manifold_world(&t, 1.23);
110        assert!((w[0] - 0.2).abs() < 1e-6);
111        assert!((w[1] + 0.4).abs() < 1e-6);
112        assert!((w[2] - 0.1).abs() < 1e-6);
113    }
114
115    #[test]
116    fn projection_is_deterministic() {
117        let t = node();
118        assert_eq!(
119            project(&t, 2.5, ProjectionTarget::Volume3D),
120            project(&t, 2.5, ProjectionTarget::Volume3D)
121        );
122    }
123}