Skip to main content

viewport_lib/renderer/picking/
mod.rs

1use super::*;
2
3mod helpers;
4use helpers::*;
5mod gpu;
6mod point;
7mod rect;
8
9impl ViewportRenderer {
10    /// Copy this frame's pickable items into the CPU pick caches so `pick()` and
11    /// `pick_rect()` can run later (e.g. on a mouse click) without the scene data.
12    ///
13    /// Called from `prepare()` only when the CPU pick cache is enabled. The mesh
14    /// entry is cheap (it holds a `mesh_id`), but the data primitives carry inline
15    /// geometry, so this is the per-frame cost that `set_cpu_pick_cache` controls.
16    pub(crate) fn cache_pick_items(&mut self, frame: &FrameData) {
17        let surfaces = match &frame.scene.surfaces {
18            SurfaceSubmission::Flat(items) => items.as_ref(),
19        };
20        // Opaque volume meshes appear as boundary SceneRenderItems for face/vertex
21        // picking; cell-level remapping is driven from `pick_volume_mesh_items`.
22        self.pick_scene_items = surfaces
23            .iter()
24            .cloned()
25            .chain(
26                frame
27                    .scene
28                    .volume_meshes
29                    .iter()
30                    .filter(|item| item.transparency.is_none())
31                    .map(|item| item.to_render_item()),
32            )
33            .collect();
34        self.pick_point_cloud_items = frame.scene.point_clouds.clone();
35        self.pick_splat_items = frame.scene.gaussian_splats.clone();
36        self.pick_volume_items = frame.scene.volumes.clone();
37        self.pick_scatter_volume_items = frame.scene.scatter_volumes.clone();
38        self.pick_volume_mesh_items = frame.scene.volume_meshes.clone();
39        self.pick_polyline_items = frame.scene.polylines.clone();
40        self.pick_glyph_items = frame.scene.glyphs.clone();
41        self.pick_tensor_glyph_items = frame.scene.tensor_glyphs.clone();
42        self.pick_sprite_items = frame.scene.sprite_items.clone();
43        self.pick_streamtube_items = frame.scene.streamtube_items.clone();
44        self.pick_tube_items = frame.scene.tube_items.clone();
45        self.pick_ribbon_items = frame.scene.ribbon_items.clone();
46        self.pick_image_slice_items = frame.scene.image_slices.clone();
47        self.pick_volume_surface_slice_items = frame.scene.volume_surface_slices.clone();
48        self.pick_screen_image_items = frame.scene.screen_images.clone();
49        self.pick_decal_items = frame.scene.decals.clone();
50    }
51
52    /// Empty the CPU pick caches populated by `cache_pick_items`, freeing their
53    /// memory when the cache is turned off.
54    pub(crate) fn clear_pick_cache(&mut self) {
55        self.pick_scene_items = Vec::new();
56        self.pick_point_cloud_items = Vec::new();
57        self.pick_splat_items = Vec::new();
58        self.pick_volume_items = Vec::new();
59        self.pick_scatter_volume_items = Vec::new();
60        self.pick_volume_mesh_items = Vec::new();
61        self.pick_polyline_items = Vec::new();
62        self.pick_glyph_items = Vec::new();
63        self.pick_tensor_glyph_items = Vec::new();
64        self.pick_sprite_items = Vec::new();
65        self.pick_streamtube_items = Vec::new();
66        self.pick_tube_items = Vec::new();
67        self.pick_ribbon_items = Vec::new();
68        self.pick_image_slice_items = Vec::new();
69        self.pick_volume_surface_slice_items = Vec::new();
70        self.pick_screen_image_items = Vec::new();
71        self.pick_decal_items = Vec::new();
72    }
73}
74
75// ---------------------------------------------------------------------------
76// PickRectResult
77// ---------------------------------------------------------------------------
78
79/// Result of a [`ViewportRenderer::pick_rect`] call.
80#[derive(Clone, Debug, Default)]
81pub struct PickRectResult {
82    /// IDs of whole items that have geometry inside the pick rect.
83    ///
84    /// Populated when [`crate::interaction::select::pick_mask::PickMask::OBJECT`] is set.
85    pub objects: Vec<u64>,
86    /// Sub-elements inside the pick rect as `(item_id, sub_object)` pairs.
87    ///
88    /// Populated when any sub-element bit is set in the mask. All entries
89    /// belong to the same geometric dimension when the mask is
90    /// dimension-homogeneous (the common case).
91    pub elements: Vec<(u64, crate::interaction::select::sub_object::SubObjectRef)>,
92}
93
94impl PickRectResult {
95    /// Returns `true` when no objects or elements were found.
96    pub fn is_empty(&self) -> bool {
97        self.objects.is_empty() && self.elements.is_empty()
98    }
99}