Skip to main content

loam_render/passes/
point.rs

1use std::cell::RefCell;
2use std::rc::Rc;
3
4use glam::Vec2;
5use loam_math::{EuclideanR3, Projection};
6use loam_runtime::{Eye, PointRecord};
7use loam_shape::PointMesh;
8use wgpu::{CommandEncoder, Device, Queue};
9
10use crate::device::GpuContext;
11use crate::pass::{FrameFormat, FramePass, FrameTarget, PassStage};
12use crate::{DepthConvention, DepthMode, PointRasterNode};
13
14struct State {
15    eye: Eye,
16    mesh: PointMesh<3>,
17    uploaded: bool,
18    uploads: u64,
19    node: Option<PointRasterNode>,
20    device: Option<Device>,
21    queue: Option<Queue>,
22}
23
24#[derive(Clone)]
25pub struct PointPass {
26    name: &'static str,
27    shared: Rc<RefCell<State>>,
28}
29
30impl PointPass {
31    pub fn new(name: &'static str) -> Self {
32        Self {
33            name,
34            shared: Rc::new(RefCell::new(State {
35                eye: Eye::default(),
36                mesh: PointMesh::default(),
37                uploaded: false,
38                uploads: 0,
39                node: None,
40                device: None,
41                queue: None,
42            })),
43        }
44    }
45
46    pub fn publish(&self, eye: &Eye, points: &[PointRecord]) {
47        let mut state = self.shared.borrow_mut();
48        state.eye = *eye;
49        let mesh = &state.mesh;
50        let same = mesh.positions.len() == points.len()
51            && mesh.colors.len() == points.len()
52            && mesh.sizes.len() == points.len()
53            && points.iter().enumerate().all(|(index, point)| {
54                mesh.positions[index] == point.position
55                    && mesh.colors[index] == point.color
56                    && mesh.sizes[index] == point.radius_px
57            });
58        state.uploaded &= same;
59        let mesh = &mut state.mesh;
60        mesh.positions.clear();
61        mesh.colors.clear();
62        mesh.sizes.clear();
63        for point in points {
64            mesh.positions.push(point.position);
65            mesh.colors.push(point.color);
66            mesh.sizes.push(point.radius_px);
67        }
68    }
69
70    pub fn point_count(&self) -> usize {
71        self.shared.borrow().mesh.positions.len()
72    }
73
74    pub fn uploads(&self) -> u64 {
75        self.shared.borrow().uploads
76    }
77}
78
79impl FramePass for PointPass {
80    fn name(&self) -> &'static str {
81        self.name
82    }
83
84    fn stage(&self) -> PassStage {
85        PassStage::Scene
86    }
87
88    fn record(
89        &mut self,
90        encoder: &mut CommandEncoder,
91        target: &FrameTarget<'_>,
92    ) -> anyhow::Result<()> {
93        let mut state = self.shared.borrow_mut();
94        let State {
95            eye,
96            mesh,
97            uploaded,
98            uploads,
99            node,
100            device,
101            queue,
102            ..
103        } = &mut *state;
104        let (Some(node), Some(device), Some(queue)) =
105            (node.as_mut(), device.as_ref(), queue.as_ref())
106        else {
107            return Ok(());
108        };
109        node.set_camera(
110            queue,
111            crate::view::root_view_projection(eye),
112            Vec2::new(target.size.0 as f32, target.size.1 as f32),
113        );
114        if !*uploaded {
115            node.upload::<EuclideanR3, 3>(device, queue, mesh, &Projection::Identity);
116            *uploaded = true;
117            *uploads += 1;
118        }
119        node.record(encoder, target.color, None, None);
120        Ok(())
121    }
122
123    fn attach(&mut self, gpu: &GpuContext, frame: FrameFormat) -> anyhow::Result<()> {
124        let mut state = self.shared.borrow_mut();
125        state.node = Some(PointRasterNode::new(
126            &gpu.device,
127            frame.color,
128            DepthMode::Off,
129            DepthConvention::ReversedZ,
130        ));
131        state.device = Some(gpu.device.clone());
132        state.queue = Some(gpu.queue.clone());
133        state.uploaded = false;
134        Ok(())
135    }
136}