polyscope_render/
point_cloud_render.rs1use glam::{Vec3, Vec4};
4use wgpu::util::DeviceExt;
5
6pub struct PointCloudRenderData {
8 pub position_buffer: wgpu::Buffer,
10 pub color_buffer: wgpu::Buffer,
12 pub uniform_buffer: wgpu::Buffer,
14 pub bind_group: wgpu::BindGroup,
16 pub num_points: u32,
18}
19
20#[repr(C)]
22#[derive(Debug, Clone, Copy, bytemuck::Pod, bytemuck::Zeroable)]
23#[allow(clippy::pub_underscore_fields)]
24pub struct PointUniforms {
25 pub model_matrix: [[f32; 4]; 4],
26 pub point_radius: f32,
27 pub use_per_point_color: u32,
28 pub _padding: [f32; 2],
29 pub base_color: [f32; 4],
30}
31
32impl Default for PointUniforms {
33 fn default() -> Self {
34 Self {
35 model_matrix: [
36 [1.0, 0.0, 0.0, 0.0],
37 [0.0, 1.0, 0.0, 0.0],
38 [0.0, 0.0, 1.0, 0.0],
39 [0.0, 0.0, 0.0, 1.0],
40 ],
41 point_radius: 0.01,
42 use_per_point_color: 0,
43 _padding: [0.0; 2],
44 base_color: [0.2, 0.5, 0.8, 1.0], }
46 }
47}
48
49impl PointCloudRenderData {
50 #[must_use]
52 pub fn new(
53 device: &wgpu::Device,
54 bind_group_layout: &wgpu::BindGroupLayout,
55 camera_buffer: &wgpu::Buffer,
56 positions: &[Vec3],
57 colors: Option<&[Vec4]>,
58 ) -> Self {
59 let num_points = positions.len() as u32;
60
61 let position_data: Vec<f32> = positions
63 .iter()
64 .flat_map(|p| [p.x, p.y, p.z, 0.0]) .collect();
66 let position_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
67 label: Some("point positions"),
68 contents: bytemuck::cast_slice(&position_data),
69 usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST,
70 });
71
72 let color_data: Vec<f32> = if let Some(colors) = colors {
74 colors.iter().flat_map(glam::Vec4::to_array).collect()
75 } else {
76 vec![1.0; positions.len() * 4]
77 };
78 let color_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
79 label: Some("point colors"),
80 contents: bytemuck::cast_slice(&color_data),
81 usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST,
82 });
83
84 let uniforms = PointUniforms::default();
86 let uniform_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
87 label: Some("point uniforms"),
88 contents: bytemuck::cast_slice(&[uniforms]),
89 usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
90 });
91
92 let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
94 label: Some("point cloud bind group"),
95 layout: bind_group_layout,
96 entries: &[
97 wgpu::BindGroupEntry {
98 binding: 0,
99 resource: camera_buffer.as_entire_binding(),
100 },
101 wgpu::BindGroupEntry {
102 binding: 1,
103 resource: uniform_buffer.as_entire_binding(),
104 },
105 wgpu::BindGroupEntry {
106 binding: 2,
107 resource: position_buffer.as_entire_binding(),
108 },
109 wgpu::BindGroupEntry {
110 binding: 3,
111 resource: color_buffer.as_entire_binding(),
112 },
113 ],
114 });
115
116 Self {
117 position_buffer,
118 color_buffer,
119 uniform_buffer,
120 bind_group,
121 num_points,
122 }
123 }
124
125 pub fn update_colors(&self, queue: &wgpu::Queue, colors: &[Vec4]) {
127 let color_data: Vec<f32> = colors.iter().flat_map(glam::Vec4::to_array).collect();
128 queue.write_buffer(&self.color_buffer, 0, bytemuck::cast_slice(&color_data));
129 }
130
131 pub fn update_uniforms(&self, queue: &wgpu::Queue, uniforms: &PointUniforms) {
133 queue.write_buffer(&self.uniform_buffer, 0, bytemuck::cast_slice(&[*uniforms]));
134 }
135}