Skip to content

Commit ef0557e

Browse files
authored
Cached 2D & 3D arrow clouds (#5088)
Grunt work to make arrow clouds go through the cached APIs. #### Performance comparison Using the clock example, with the minutes hand set to `-inf:+inf`. main: ![image](https://github.com/rerun-io/rerun/assets/2910679/e8a9edee-6d50-40eb-bf13-5b29616656e3) now: ![image](https://github.com/rerun-io/rerun/assets/2910679/f1763543-a279-4903-a339-701dec949a09) --- TODO: - [x] self-review - [x] check doc examples still work - [x] arrow2d_simple - [x] arrow3d_simple - [x] perf comparison ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5088/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5088/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5088/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5088) - [Docs preview](https://rerun.io/preview/1f35dde2aa51f7817fd38afcf4bfe5ac04d2f6b8/docs) <!--DOCS-PREVIEW--> - [Examples preview](https://rerun.io/preview/1f35dde2aa51f7817fd38afcf4bfe5ac04d2f6b8/examples) <!--EXAMPLES-PREVIEW--> - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)
1 parent 79d8021 commit ef0557e

2 files changed

Lines changed: 216 additions & 104 deletions

File tree

crates/re_space_view_spatial/src/visualizers/arrows2d.rs

Lines changed: 108 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,23 @@
11
use re_entity_db::{EntityPath, InstancePathHash};
2-
use re_query::{ArchetypeView, QueryError};
3-
use re_renderer::renderer::LineStripFlags;
2+
use re_renderer::{renderer::LineStripFlags, PickingLayerInstanceId};
43
use re_types::{
54
archetypes::Arrows2D,
6-
components::{Position2D, Text, Vector2D},
5+
components::{ClassId, Color, InstanceKey, KeypointId, Position2D, Radius, Text, Vector2D},
76
};
87
use re_viewer_context::{
98
ApplicableEntities, IdentifiedViewSystem, ResolvedAnnotationInfos,
109
SpaceViewSystemExecutionError, ViewContextCollection, ViewQuery, ViewerContext,
1110
VisualizableEntities, VisualizableFilterContext, VisualizerQueryInfo, VisualizerSystem,
1211
};
1312

14-
use super::{picking_id_from_instance_key, process_annotations, SpatialViewVisualizerData};
13+
use super::{
14+
process_annotation_and_keypoint_slices, process_color_slice, process_radius_slice,
15+
SpatialViewVisualizerData,
16+
};
1517
use crate::{
1618
contexts::{EntityDepthOffsets, SpatialSceneEntityContext},
1719
view_kind::SpatialSpaceViewKind,
18-
visualizers::{
19-
entity_iterator::process_archetype_views, filter_visualizable_2d_entities, process_colors,
20-
process_radii, UiLabel, UiLabelTarget,
21-
},
20+
visualizers::{filter_visualizable_2d_entities, UiLabel, UiLabelTarget},
2221
};
2322

2423
pub struct Arrows2DVisualizer {
@@ -38,17 +37,19 @@ impl Default for Arrows2DVisualizer {
3837

3938
impl Arrows2DVisualizer {
4039
fn process_labels<'a>(
41-
arch_view: &'a ArchetypeView<Arrows2D>,
40+
vectors: &'a [Vector2D],
41+
origins: impl Iterator<Item = Option<Position2D>> + 'a,
42+
labels: &'a [Option<Text>],
4243
instance_path_hashes: &'a [InstancePathHash],
4344
colors: &'a [egui::Color32],
4445
annotation_infos: &'a ResolvedAnnotationInfos,
4546
world_from_obj: glam::Affine3A,
46-
) -> Result<impl Iterator<Item = UiLabel> + 'a, QueryError> {
47-
let labels = itertools::izip!(
47+
) -> impl Iterator<Item = UiLabel> + 'a {
48+
itertools::izip!(
4849
annotation_infos.iter(),
49-
arch_view.iter_required_component::<Vector2D>()?,
50-
arch_view.iter_optional_component::<Position2D>()?,
51-
arch_view.iter_optional_component::<Text>()?,
50+
vectors,
51+
origins,
52+
labels,
5253
colors,
5354
instance_path_hashes,
5455
)
@@ -73,43 +74,60 @@ impl Arrows2DVisualizer {
7374
_ => None,
7475
}
7576
},
76-
);
77-
Ok(labels)
77+
)
7878
}
7979

80-
fn process_arch_view(
80+
fn process_data(
8181
&mut self,
8282
query: &ViewQuery<'_>,
83-
arch_view: &ArchetypeView<Arrows2D>,
83+
data: &Arrows2DComponentData<'_>,
8484
ent_path: &EntityPath,
8585
ent_context: &SpatialSceneEntityContext<'_>,
86-
) -> Result<(), QueryError> {
87-
let annotation_infos =
88-
process_annotations::<Vector2D, Arrows2D>(query, arch_view, &ent_context.annotations)?;
86+
) {
87+
let (annotation_infos, _) = process_annotation_and_keypoint_slices(
88+
query.latest_at,
89+
data.instance_keys,
90+
data.keypoint_ids,
91+
data.class_ids,
92+
data.vectors.iter().map(|_| glam::Vec3::ZERO),
93+
&ent_context.annotations,
94+
);
95+
96+
let radii = process_radius_slice(data.radii, data.vectors.len(), ent_path);
97+
let colors = process_color_slice(data.colors, ent_path, &annotation_infos);
98+
let origins = || {
99+
data.origins.map_or_else(
100+
|| itertools::Either::Left(std::iter::repeat(Some(Position2D::ZERO))),
101+
|origins| itertools::Either::Right(origins.iter().copied()),
102+
)
103+
};
89104

90-
let colors = process_colors(arch_view, ent_path, &annotation_infos)?;
91-
let radii = process_radii(arch_view, ent_path)?;
105+
if data.instance_keys.len() <= self.max_labels {
106+
re_tracing::profile_scope!("labels");
92107

93-
if arch_view.num_instances() <= self.max_labels {
94108
// Max labels is small enough that we can afford iterating on the colors again.
95-
let colors =
96-
process_colors(arch_view, ent_path, &annotation_infos)?.collect::<Vec<_>>();
109+
let colors = process_color_slice(data.colors, ent_path, &annotation_infos);
97110

98111
let instance_path_hashes_for_picking = {
99112
re_tracing::profile_scope!("instance_hashes");
100-
arch_view
101-
.iter_instance_keys()
113+
data.instance_keys
114+
.iter()
115+
.copied()
102116
.map(|instance_key| InstancePathHash::instance(ent_path, instance_key))
103117
.collect::<Vec<_>>()
104118
};
105119

106-
self.data.ui_labels.extend(Self::process_labels(
107-
arch_view,
108-
&instance_path_hashes_for_picking,
109-
&colors,
110-
&annotation_infos,
111-
ent_context.world_from_entity,
112-
)?);
120+
if let Some(labels) = data.labels {
121+
self.data.ui_labels.extend(Self::process_labels(
122+
data.vectors,
123+
origins(),
124+
labels,
125+
&instance_path_hashes_for_picking,
126+
&colors,
127+
&annotation_infos,
128+
ent_context.world_from_entity,
129+
));
130+
}
113131
}
114132

115133
let mut line_builder = ent_context.shared_render_builders.lines();
@@ -119,17 +137,10 @@ impl Arrows2DVisualizer {
119137
.outline_mask_ids(ent_context.highlight.overall)
120138
.picking_object_id(re_renderer::PickingLayerObjectId(ent_path.hash64()));
121139

122-
let instance_keys = arch_view.iter_instance_keys();
123-
let pick_ids = arch_view
124-
.iter_instance_keys()
125-
.map(picking_id_from_instance_key);
126-
let vectors = arch_view.iter_required_component::<Vector2D>()?;
127-
let origins = arch_view.iter_optional_component::<Position2D>()?;
128-
129140
let mut bounding_box = macaw::BoundingBox::nothing();
130141

131-
for (instance_key, vector, origin, radius, color, pick_id) in
132-
itertools::izip!(instance_keys, vectors, origins, radii, colors, pick_ids)
142+
for (instance_key, vector, origin, radius, color) in
143+
itertools::izip!(data.instance_keys, data.vectors, origins(), radii, colors,)
133144
{
134145
let vector: glam::Vec2 = vector.0.into();
135146
let origin: glam::Vec2 = origin.unwrap_or(Position2D::ZERO).0.into();
@@ -144,9 +155,9 @@ impl Arrows2DVisualizer {
144155
| LineStripFlags::FLAG_CAP_START_ROUND
145156
| LineStripFlags::FLAG_CAP_START_EXTEND_OUTWARDS,
146157
)
147-
.picking_instance_id(pick_id);
158+
.picking_instance_id(PickingLayerInstanceId(instance_key.0));
148159

149-
if let Some(outline_mask_ids) = ent_context.highlight.instances.get(&instance_key) {
160+
if let Some(outline_mask_ids) = ent_context.highlight.instances.get(instance_key) {
150161
segment.outline_mask_ids(*outline_mask_ids);
151162
}
152163

@@ -156,11 +167,22 @@ impl Arrows2DVisualizer {
156167

157168
self.data
158169
.add_bounding_box(ent_path.hash(), bounding_box, ent_context.world_from_entity);
159-
160-
Ok(())
161170
}
162171
}
163172

173+
// ---
174+
175+
struct Arrows2DComponentData<'a> {
176+
pub instance_keys: &'a [InstanceKey],
177+
pub vectors: &'a [Vector2D],
178+
pub origins: Option<&'a [Option<Position2D>]>,
179+
pub colors: Option<&'a [Option<Color>]>,
180+
pub radii: Option<&'a [Option<Radius>]>,
181+
pub labels: Option<&'a [Option<Text>]>,
182+
pub keypoint_ids: Option<&'a [Option<KeypointId>]>,
183+
pub class_ids: Option<&'a [Option<ClassId>]>,
184+
}
185+
164186
impl IdentifiedViewSystem for Arrows2DVisualizer {
165187
fn identifier() -> re_viewer_context::ViewSystemIdentifier {
166188
"Arrows2D".into()
@@ -187,13 +209,47 @@ impl VisualizerSystem for Arrows2DVisualizer {
187209
query: &ViewQuery<'_>,
188210
view_ctx: &ViewContextCollection,
189211
) -> Result<Vec<re_renderer::QueueableDrawData>, SpaceViewSystemExecutionError> {
190-
process_archetype_views::<Arrows2DVisualizer, Arrows2D, { Arrows2D::NUM_COMPONENTS }, _>(
212+
super::entity_iterator::process_archetype_pov1_comp6::<
213+
Arrows2DVisualizer,
214+
Arrows2D,
215+
Vector2D,
216+
Position2D,
217+
Color,
218+
Radius,
219+
Text,
220+
KeypointId,
221+
ClassId,
222+
_,
223+
>(
191224
ctx,
192225
query,
193226
view_ctx,
194-
view_ctx.get::<EntityDepthOffsets>()?.lines2d,
195-
|_ctx, ent_path, _ent_props, arch_view, ent_context| {
196-
self.process_arch_view(query, &arch_view, ent_path, ent_context)
227+
view_ctx.get::<EntityDepthOffsets>()?.points,
228+
|_ctx,
229+
ent_path,
230+
_ent_props,
231+
ent_context,
232+
(_time, _row_id),
233+
instance_keys,
234+
vectors,
235+
origins,
236+
colors,
237+
radii,
238+
labels,
239+
keypoint_ids,
240+
class_ids| {
241+
let data = Arrows2DComponentData {
242+
instance_keys,
243+
vectors,
244+
origins,
245+
colors,
246+
radii,
247+
labels,
248+
keypoint_ids,
249+
class_ids,
250+
};
251+
self.process_data(query, &data, ent_path, ent_context);
252+
Ok(())
197253
},
198254
)?;
199255

0 commit comments

Comments
 (0)