From 70aa6f315dd8edaba3d373c8ac07a82934c21284 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Wed, 31 May 2023 18:47:45 +0200 Subject: [PATCH 01/39] introduce scene context, abandon scene some of the tuple conversions --- .../re_space_view_text/src/scene_element.rs | 9 +- .../src/space_view_class.rs | 14 +- .../src/scene_element.rs | 15 +- .../src/space_view_class.rs | 15 +- crates/re_viewer_context/src/lib.rs | 6 +- .../re_viewer_context/src/space_view/mod.rs | 7 +- .../re_viewer_context/src/space_view/scene.rs | 196 ++++++++++++++++++ .../src/space_view/scene_element_impl.rs | 15 +- .../src/space_view/scene_element_list.rs | 86 -------- .../src/space_view/space_view_class.rs | 50 +---- .../src/space_view/space_view_class_impl.rs | 27 +-- 11 files changed, 262 insertions(+), 178 deletions(-) create mode 100644 crates/re_viewer_context/src/space_view/scene.rs delete mode 100644 crates/re_viewer_context/src/space_view/scene_element_list.rs diff --git a/crates/re_space_view_text/src/scene_element.rs b/crates/re_space_view_text/src/scene_element.rs index 138534829baa..f9f151c64be2 100644 --- a/crates/re_space_view_text/src/scene_element.rs +++ b/crates/re_space_view_text/src/scene_element.rs @@ -2,7 +2,9 @@ use re_arrow_store::TimeRange; use re_data_store::EntityPath; use re_log_types::{Component as _, InstanceKey, RowId}; use re_query::{range_entity_with_primary, QueryError}; -use re_viewer_context::{ArchetypeDefinition, SceneElementImpl, SceneQuery, ViewerContext}; +use re_viewer_context::{ + ArchetypeDefinition, SceneContextCollection, SceneElementImpl, SceneQuery, ViewerContext, +}; use super::space_view_class::TextSpaceViewState; @@ -41,6 +43,7 @@ impl SceneElementImpl for SceneText { ctx: &mut ViewerContext<'_>, query: &SceneQuery<'_>, state: &TextSpaceViewState, + _contexts: &SceneContextCollection, ) { let store = &ctx.store_db.entity_db.data_store; @@ -99,8 +102,4 @@ impl SceneElementImpl for SceneText { } } } - - fn as_any(&self) -> &dyn std::any::Any { - self - } } diff --git a/crates/re_space_view_text/src/space_view_class.rs b/crates/re_space_view_text/src/space_view_class.rs index 51c69377b65a..47d2228a9159 100644 --- a/crates/re_space_view_text/src/space_view_class.rs +++ b/crates/re_space_view_text/src/space_view_class.rs @@ -3,7 +3,8 @@ use std::collections::BTreeMap; use re_data_ui::item_ui; use re_log_types::{EntityPath, TimePoint, Timeline}; use re_viewer_context::{ - level_to_rich_text, SpaceViewClassImpl, SpaceViewClassName, SpaceViewState, ViewerContext, + level_to_rich_text, Scene, SpaceViewClassImpl, SpaceViewClassName, SpaceViewState, + ViewerContext, }; use super::scene_element::{SceneText, TextEntry}; @@ -37,6 +38,7 @@ pub struct TextSpaceView; impl SpaceViewClassImpl for TextSpaceView { type State = TextSpaceViewState; + type SceneContextTuple = (); type SceneElementTuple = (SceneText,); fn name(&self) -> SpaceViewClassName { @@ -106,9 +108,15 @@ impl SpaceViewClassImpl for TextSpaceView { ctx: &mut ViewerContext<'_>, ui: &mut egui::Ui, state: &mut Self::State, - scene_elements: Self::SceneElementTuple, + scene: Scene, ) { - let scene = scene_elements.0; + let scene = match scene.elements.get::() { + Ok(scene) => scene, + Err(err) => { + re_log::error_once!("Failed to get text scene element {err}"); + return; + } + }; egui::Frame { inner_margin: re_ui::ReUi::view_padding().into(), diff --git a/crates/re_space_view_text_box/src/scene_element.rs b/crates/re_space_view_text_box/src/scene_element.rs index 0010adf47ecd..5caa0e789a7f 100644 --- a/crates/re_space_view_text_box/src/scene_element.rs +++ b/crates/re_space_view_text_box/src/scene_element.rs @@ -2,9 +2,11 @@ use re_arrow_store::LatestAtQuery; use re_components::Component; use re_query::{query_entity_with_primary, QueryError}; use re_viewer_context::{ - ArchetypeDefinition, SceneElement, SceneQuery, SpaceViewState, ViewerContext, + ArchetypeDefinition, SceneContextCollection, SceneElementImpl, SceneQuery, ViewerContext, }; +use crate::space_view_class::TextBoxSpaceViewState; + // --- #[derive(Debug, Clone)] @@ -18,7 +20,9 @@ pub struct SceneTextBox { pub text_entries: Vec, } -impl SceneElement for SceneTextBox { +impl SceneElementImpl for SceneTextBox { + type State = TextBoxSpaceViewState; + fn archetype(&self) -> ArchetypeDefinition { vec1::vec1![re_components::TextBox::name()] } @@ -27,7 +31,8 @@ impl SceneElement for SceneTextBox { &mut self, ctx: &mut ViewerContext<'_>, query: &SceneQuery<'_>, - _state: &dyn SpaceViewState, + _space_view_state: &Self::State, + _contexts: &SceneContextCollection, ) { let store = &ctx.store_db.entity_db.data_store; @@ -52,8 +57,4 @@ impl SceneElement for SceneTextBox { } } } - - fn into_any(self: Box) -> Box { - self - } } diff --git a/crates/re_space_view_text_box/src/space_view_class.rs b/crates/re_space_view_text_box/src/space_view_class.rs index 94420fb673e3..528866e6a78c 100644 --- a/crates/re_space_view_text_box/src/space_view_class.rs +++ b/crates/re_space_view_text_box/src/space_view_class.rs @@ -1,5 +1,7 @@ use egui::Label; -use re_viewer_context::{SpaceViewClassImpl, SpaceViewClassName, SpaceViewState, ViewerContext}; +use re_viewer_context::{ + Scene, SpaceViewClassImpl, SpaceViewClassName, SpaceViewState, ViewerContext, +}; use super::scene_element::SceneTextBox; @@ -35,6 +37,7 @@ pub struct TextBoxSpaceView; impl SpaceViewClassImpl for TextBoxSpaceView { type State = TextBoxSpaceViewState; type SceneElementTuple = (SceneTextBox,); + type SceneContextTuple = (); fn name(&self) -> SpaceViewClassName { "Text Box".into() @@ -70,9 +73,15 @@ impl SpaceViewClassImpl for TextBoxSpaceView { _ctx: &mut ViewerContext<'_>, ui: &mut egui::Ui, state: &mut Self::State, - scene_elements: Self::SceneElementTuple, + scene: Scene, ) { - let scene = scene_elements.0; + let scene = match scene.elements.get::() { + Ok(scene) => scene, + Err(err) => { + re_log::error_once!("Failed to get text box scene element {err}"); + return; + } + }; egui::Frame { inner_margin: re_ui::ReUi::view_padding().into(), diff --git a/crates/re_viewer_context/src/lib.rs b/crates/re_viewer_context/src/lib.rs index 8a2d16935c87..ea3c91b3f0a4 100644 --- a/crates/re_viewer_context/src/lib.rs +++ b/crates/re_viewer_context/src/lib.rs @@ -32,9 +32,9 @@ pub use selection_state::{ HoverHighlight, HoveredSpace, InteractionHighlight, SelectionHighlight, SelectionState, }; pub use space_view::{ - ArchetypeDefinition, EmptySpaceViewState, Scene, SceneElement, SceneElementImpl, - SpaceViewClass, SpaceViewClassImpl, SpaceViewClassName, SpaceViewClassRegistry, - SpaceViewClassRegistryError, SpaceViewState, + ArchetypeDefinition, EmptySpaceViewState, Scene, SceneContext, SceneContextCollection, + SceneElement, SceneElementCollection, SceneElementImpl, SpaceViewClass, SpaceViewClassImpl, + SpaceViewClassName, SpaceViewClassRegistry, SpaceViewClassRegistryError, SpaceViewState, }; pub use tensor::{TensorDecodeCache, TensorStats, TensorStatsCache}; pub use time_control::{Looping, PlayState, TimeControl, TimeView}; diff --git a/crates/re_viewer_context/src/space_view/mod.rs b/crates/re_viewer_context/src/space_view/mod.rs index f31fd553b7b0..cbd760b1b73a 100644 --- a/crates/re_viewer_context/src/space_view/mod.rs +++ b/crates/re_viewer_context/src/space_view/mod.rs @@ -3,15 +3,18 @@ //! Defines a framework & utilities for defining classes of space views in the Rerun viewer. //! Does not implement any concrete space view. +mod scene; mod scene_element_impl; -mod scene_element_list; mod space_view_class; mod space_view_class_impl; mod space_view_class_registry; +pub use scene::{ + Scene, SceneContext, SceneContextCollection, SceneElement, SceneElementCollection, +}; pub use scene_element_impl::SceneElementImpl; pub use space_view_class::{ - ArchetypeDefinition, Scene, SceneElement, SpaceViewClass, SpaceViewClassName, SpaceViewState, + ArchetypeDefinition, SpaceViewClass, SpaceViewClassName, SpaceViewState, }; pub use space_view_class_impl::{EmptySpaceViewState, SpaceViewClassImpl}; pub use space_view_class_registry::{SpaceViewClassRegistry, SpaceViewClassRegistryError}; diff --git a/crates/re_viewer_context/src/space_view/scene.rs b/crates/re_viewer_context/src/space_view/scene.rs new file mode 100644 index 000000000000..414c44afb543 --- /dev/null +++ b/crates/re_viewer_context/src/space_view/scene.rs @@ -0,0 +1,196 @@ +use std::any::Any; + +use ahash::HashMap; + +use crate::{ArchetypeDefinition, SceneQuery, SpaceViewState, ViewerContext}; + +#[derive(Debug, thiserror::Error)] +pub enum SceneItemCollectionLookupError { + #[error("Type not found in collection")] + TypeNotFound, + + #[error("Failed to downcast type.")] + DowncastFailure, +} + +// TODO(andreas): Use tinyvec for these. + +/// Collection of scene contexts. +/// +/// New type pattern to support adding From impls. +pub struct SceneContextCollection(HashMap>); + +impl SceneContextCollection { + pub fn get(&self) -> Result<&T, SceneItemCollectionLookupError> { + self.0 + .get(&std::any::TypeId::of::()) + .ok_or(SceneItemCollectionLookupError::TypeNotFound)? + .as_any() + .downcast_ref::() + .ok_or(SceneItemCollectionLookupError::DowncastFailure) + } + + pub fn get_mut(&mut self) -> Result<&mut T, SceneItemCollectionLookupError> { + self.0 + .get_mut(&std::any::TypeId::of::()) + .ok_or(SceneItemCollectionLookupError::TypeNotFound)? + .as_any_mut() + .downcast_mut::() + .ok_or(SceneItemCollectionLookupError::DowncastFailure) + } +} + +macro_rules! scene_context_collection_from_tuple { + ($($idx:tt => $name:ident),*) => { + impl<$($name: SceneContext),*> From<($($name,)*)> for SceneContextCollection { + #[allow(unused_mut)] + fn from(_value: ($($name,)*)) -> Self { + let mut map = HashMap::>::default(); + $( + map.insert(std::any::TypeId::of::<$name>(), Box::new(_value.$idx)); + )* + Self(map) + } + } + }; +} + +scene_context_collection_from_tuple!(); +scene_context_collection_from_tuple!(0 => T0); +scene_context_collection_from_tuple!(0 => T0, 1 => T1); +scene_context_collection_from_tuple!(0 => T0, 1 => T1, 2 => T2); +scene_context_collection_from_tuple!(0 => T0, 1 => T1, 2 => T2, 3 => T3); +scene_context_collection_from_tuple!(0 => T0, 1 => T1, 2 => T2, 3 => T3, 4 => T4); + +/// Collections of scene elements. +/// +/// New type pattern to support adding From impls. +pub struct SceneElementCollection(HashMap>); + +impl SceneElementCollection { + pub fn get(&self) -> Result<&T, SceneItemCollectionLookupError> { + self.0 + .get(&std::any::TypeId::of::()) + .ok_or(SceneItemCollectionLookupError::TypeNotFound)? + .as_any() + .downcast_ref::() + .ok_or(SceneItemCollectionLookupError::DowncastFailure) + } + + pub fn get_mut(&mut self) -> Result<&mut T, SceneItemCollectionLookupError> { + self.0 + .get_mut(&std::any::TypeId::of::()) + .ok_or(SceneItemCollectionLookupError::TypeNotFound)? + .as_any_mut() + .downcast_mut::() + .ok_or(SceneItemCollectionLookupError::DowncastFailure) + } +} + +macro_rules! scene_element_collection_from_tuple { + ($($idx:tt => $name:ident),*) => { + impl<$($name: SceneElement),*> From<($($name,)*)> for SceneElementCollection { + #[allow(unused_mut)] + fn from(_value: ($($name,)*)) -> Self { + let mut map = HashMap::>::default(); + $( + map.insert(std::any::TypeId::of::<$name>(), Box::new(_value.$idx)); + )* + Self(map) + } + } + }; +} + +scene_element_collection_from_tuple!(); +scene_element_collection_from_tuple!(0 => T0); +scene_element_collection_from_tuple!(0 => T0, 1 => T1); +scene_element_collection_from_tuple!(0 => T0, 1 => T1, 2 => T2); +scene_element_collection_from_tuple!(0 => T0, 1 => T1, 2 => T2, 3 => T3); +scene_element_collection_from_tuple!(0 => T0, 1 => T1, 2 => T2, 3 => T3, 4 => T4); +scene_element_collection_from_tuple!(0 => T0, 1 => T1, 2 => T2, 3 => T3, 4 => T4, 5 => T5); +scene_element_collection_from_tuple!(0 => T0, 1 => T1, 2 => T2, 3 => T3, 4 => T4, 5 => T5, 6 => T6); +scene_element_collection_from_tuple!(0 => T0, 1 => T1, 2 => T2, 3 => T3, 4 => T4, 5 => T5, 6 => T6, 7 => T7); +scene_element_collection_from_tuple!(0 => T0, 1 => T1, 2 => T2, 3 => T3, 4 => T4, 5 => T5, 6 => T6, 7 => T7, 8 => T8); +// ... + +/// A scene is a collection of scene contexts and elements. +/// +/// When populating a scene, first all contexts are populated, +/// and then all elements with read access to the previously established context objects. +pub struct Scene { + pub contexts: SceneContextCollection, + pub elements: SceneElementCollection, +} + +impl Scene { + /// List of all archetypes this scene queries for its elements. + pub fn supported_element_archetypes(&self) -> Vec { + self.elements.0.values().map(|e| e.archetype()).collect() + } + + /// List of all archetypes this scene queries for its context. + pub fn supported_context_archetypes(&self) -> Vec { + self.contexts.0.values().map(|e| e.archetype()).collect() + } + + /// Populates the scene for a given query. + pub fn populate( + &mut self, + ctx: &mut ViewerContext<'_>, + query: &SceneQuery<'_>, + space_view_state: &dyn SpaceViewState, + ) { + // TODO(andreas): Both loops are great candidates for parallelization. + for context in self.contexts.0.values_mut() { + // TODO(andreas): Restrict the query with the archetype somehow, ideally making it trivial to do the correct thing. + context.populate(ctx, query, space_view_state); + } + for element in self.elements.0.values_mut() { + // TODO(andreas): Restrict the query with the archetype somehow, ideally making it trivial to do the correct thing. + element.populate(ctx, query, space_view_state, &self.contexts); + } + } +} + +/// Element of a scene derived from a single archetype query. +pub trait SceneElement: Any { + /// The archetype queried by this scene element. + fn archetype(&self) -> ArchetypeDefinition; + + /// Queries the data store and performs data conversions to make it ready for display. + /// + /// Musn't query any data outside of the archetype. + fn populate( + &mut self, + ctx: &mut ViewerContext<'_>, + query: &SceneQuery<'_>, + space_view_state: &dyn SpaceViewState, + contexts: &SceneContextCollection, + ); + + /// Converts itself to a reference of [`Any`], which enables downcasting to concrete types. + fn as_any(&self) -> &dyn std::any::Any; + + /// Converts itself to a reference of [`Any`], which enables downcasting to concrete types. + fn as_any_mut(&mut self) -> &mut dyn std::any::Any; +} + +pub trait SceneContext: Any { + /// The archetype queried by this scene context. + fn archetype(&self) -> ArchetypeDefinition; + + /// Queries the data store and performs data conversions to make it ready for consumption by scene elements. + fn populate( + &mut self, + ctx: &mut ViewerContext<'_>, + query: &SceneQuery<'_>, + space_view_state: &dyn SpaceViewState, + ); + + /// Converts itself to a reference of [`Any`], which enables downcasting to concrete types. + fn as_any(&self) -> &dyn std::any::Any; + + /// Converts itself to a reference of [`Any`], which enables downcasting to concrete types. + fn as_any_mut(&mut self) -> &mut dyn std::any::Any; +} diff --git a/crates/re_viewer_context/src/space_view/scene_element_impl.rs b/crates/re_viewer_context/src/space_view/scene_element_impl.rs index ac212c18492f..4fc4b20e277f 100644 --- a/crates/re_viewer_context/src/space_view/scene_element_impl.rs +++ b/crates/re_viewer_context/src/space_view/scene_element_impl.rs @@ -1,5 +1,7 @@ use crate::{ArchetypeDefinition, SceneElement, SceneQuery, SpaceViewState, ViewerContext}; +use super::scene::SceneContextCollection; + /// Element of a scene derived from a single archetype query. pub trait SceneElementImpl { type State: SpaceViewState + Default + 'static; @@ -15,10 +17,8 @@ pub trait SceneElementImpl { ctx: &mut ViewerContext<'_>, query: &SceneQuery<'_>, space_view_state: &Self::State, + contexts: &SceneContextCollection, ); - - /// Converts itself to a reference of [`std::any::Any`], which enables downcasting to concrete types. - fn as_any(&self) -> &dyn std::any::Any; } impl SceneElement for T { @@ -31,15 +31,20 @@ impl SceneElement for T { ctx: &mut ViewerContext<'_>, query: &crate::SceneQuery<'_>, space_view_state: &dyn SpaceViewState, + contexts: &SceneContextCollection, ) { if let Some(state) = space_view_state.as_any().downcast_ref() { - self.populate(ctx, query, state); + self.populate(ctx, query, state, contexts); } else { re_log::error_once!("Incorrect type of space view state."); } } - fn into_any(self: Box) -> Box { + fn as_any(&self) -> &dyn std::any::Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn std::any::Any { self } } diff --git a/crates/re_viewer_context/src/space_view/scene_element_list.rs b/crates/re_viewer_context/src/space_view/scene_element_list.rs deleted file mode 100644 index 98f9be3bb7f3..000000000000 --- a/crates/re_viewer_context/src/space_view/scene_element_list.rs +++ /dev/null @@ -1,86 +0,0 @@ -//! Conversion from and to [`crate::Scene`] for tuples of [`crate::SceneElement`]s. -//! -//! This allows to use tuples of [`crate::SceneElement`]s in [`crate::SpaceViewClassImpl`] - -use std::any::Any; - -use crate::{Scene, SceneElement}; - -#[derive(Debug, thiserror::Error)] -pub enum SceneElementListConversionError { - #[error("Scene element list has not the expected number of elements.")] - ElementCountMismatch, - - #[error("Failed to downcast scene element.")] - DowncastFailure, -} - -impl TryFrom for () { - type Error = SceneElementListConversionError; - - fn try_from(scene: Scene) -> Result { - if !scene.0.is_empty() { - Err(SceneElementListConversionError::ElementCountMismatch) - } else { - Ok(()) - } - } -} - -impl From<()> for Scene { - fn from(_val: ()) -> Self { - Scene(Vec::new()) - } -} - -impl TryFrom for (T0,) { - type Error = SceneElementListConversionError; - - fn try_from(scene: Scene) -> Result { - if scene.0.len() != 1 { - return Err(SceneElementListConversionError::ElementCountMismatch); - } - let mut scene_iter = scene.0.into_iter(); - - let element0 = scene_iter.next().unwrap(); - let t0 = *Box::::downcast::(element0.into_any()) - .map_err(|_err| SceneElementListConversionError::DowncastFailure)?; - - Ok((t0,)) - } -} - -impl From<(T0,)> for Scene { - fn from(val: (T0,)) -> Self { - Scene(vec![Box::new(val.0)]) - } -} - -impl TryFrom for (T0, T1) { - type Error = SceneElementListConversionError; - - fn try_from(scene: Scene) -> Result { - if scene.0.len() != 2 { - return Err(SceneElementListConversionError::ElementCountMismatch); - } - let mut scene_iter = scene.0.into_iter(); - - let element0 = scene_iter.next().unwrap(); - let t0 = *Box::::downcast::(element0.into_any()) - .map_err(|_err| SceneElementListConversionError::DowncastFailure)?; - - let element1 = scene_iter.next().unwrap(); - let t1 = *Box::::downcast::(element1.into_any()) - .map_err(|_err| SceneElementListConversionError::DowncastFailure)?; - - Ok((t0, t1)) - } -} - -impl From<(T0, T1)> for Scene { - fn from(val: (T0, T1)) -> Self { - Scene(vec![Box::new(val.0), Box::new(val.1)]) - } -} - -// TODO(andreas): Devise macro to generate this for tuples of arbitrary length. diff --git a/crates/re_viewer_context/src/space_view/space_view_class.rs b/crates/re_viewer_context/src/space_view/space_view_class.rs index 44086b93d335..48e5669ad180 100644 --- a/crates/re_viewer_context/src/space_view/space_view_class.rs +++ b/crates/re_viewer_context/src/space_view/space_view_class.rs @@ -1,8 +1,7 @@ -use std::any::Any; - -use crate::{SceneQuery, ViewerContext}; use re_log_types::ComponentName; +use crate::{Scene, ViewerContext}; + /// First element is the primary component, all others are optional. /// /// TODO(andreas/clement): More formal definition of an archetype. @@ -86,48 +85,3 @@ pub trait SpaceViewState: std::any::Any { /// Converts itself to a reference of [`Any`], which enables downcasting to concrete types. fn as_any_mut(&mut self) -> &mut dyn std::any::Any; } - -/// A scene is a collection of scene elements. -pub struct Scene(pub Vec>); - -impl Scene { - /// List of all archetypes this type of view supports. - pub fn supported_archetypes(&self) -> Vec { - self.0.iter().map(|e| e.archetype()).collect() - } - - /// Populates the scene for a given query. - pub fn populate( - &mut self, - ctx: &mut ViewerContext<'_>, - query: &SceneQuery<'_>, - space_view_state: &dyn SpaceViewState, - ) { - // TODO(andreas): This is a great entry point for parallelization. - for element in &mut self.0 { - // TODO(andreas): Restrict the query with the archetype somehow, ideally making it trivial to do the correct thing. - element.populate(ctx, query, space_view_state); - } - } -} - -/// Element of a scene derived from a single archetype query. -pub trait SceneElement: Any { - /// The archetype queried by this scene element. - fn archetype(&self) -> ArchetypeDefinition; - - /// Queries the data store and performs data conversions to make it ready for display. - /// - /// Musn't query any data outside of the archetype. - fn populate( - &mut self, - ctx: &mut ViewerContext<'_>, - query: &SceneQuery<'_>, - space_view_state: &dyn SpaceViewState, - ); - - /// Converts a box of itself a Box of [`std::any::Any`], which enables downcasting to concrete types. - fn into_any(self: Box) -> Box; - - // TODO(andreas): Add method for getting draw data for a re_renderer::ViewBuilder. -} diff --git a/crates/re_viewer_context/src/space_view/space_view_class_impl.rs b/crates/re_viewer_context/src/space_view/space_view_class_impl.rs index d9473a9ee1e2..64fb0c12d158 100644 --- a/crates/re_viewer_context/src/space_view/space_view_class_impl.rs +++ b/crates/re_viewer_context/src/space_view/space_view_class_impl.rs @@ -1,6 +1,6 @@ use crate::{Scene, SpaceViewClass, SpaceViewClassName, SpaceViewState, ViewerContext}; -use super::scene_element_list::SceneElementListConversionError; +use super::scene::{SceneContextCollection, SceneElementCollection}; /// Utility for implementing [`SpaceViewClass`] with concrete [`SpaceViewState`] and [`crate::SceneElement`] type. /// @@ -11,11 +11,11 @@ pub trait SpaceViewClassImpl { /// State of a space view. type State: SpaceViewState + Default + 'static; + /// A tuple of [`crate::SceneContext`] types that are supported by this space view class. + type SceneContextTuple: Into + Default + 'static; + /// A tuple of [`crate::SceneElement`] types that are supported by this space view class. - type SceneElementTuple: Into - + TryFrom - + Default - + 'static; + type SceneElementTuple: Into + Default + 'static; /// Name of this space view class. /// @@ -43,7 +43,7 @@ pub trait SpaceViewClassImpl { ctx: &mut ViewerContext<'_>, ui: &mut egui::Ui, state: &mut Self::State, - scene_elements: Self::SceneElementTuple, + scene: Scene, ); } @@ -65,7 +65,10 @@ impl SpaceViewClass for T { #[inline] fn new_scene(&self) -> Scene { - T::SceneElementTuple::default().into() + Scene { + contexts: T::SceneContextTuple::default().into(), + elements: T::SceneElementTuple::default().into(), + } } #[inline] @@ -91,15 +94,7 @@ impl SpaceViewClass for T { state: &mut dyn SpaceViewState, scene: Scene, ) { - let scene_elements = match T::SceneElementTuple::try_from(scene) { - Ok(scene_elements) => scene_elements, - Err(err) => { - re_log::error_once!("Incorrect scene type for space view class: {}", err); - return; - } - }; - - typed_state_wrapper(state, |state| self.ui(ctx, ui, state, scene_elements)); + typed_state_wrapper(state, |state| self.ui(ctx, ui, state, scene)); } } From da9fbf5d7e3adeee8c068f780e7f3e12a2038fd4 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Wed, 31 May 2023 18:48:01 +0200 Subject: [PATCH 02/39] rename scene_parts to elements --- .../{scene_part => elements}/arrows3d.rs | 0 .../scene/{scene_part => elements}/boxes2d.rs | 7 ++---- .../scene/{scene_part => elements}/boxes3d.rs | 0 .../scene/{scene_part => elements}/cameras.rs | 0 .../scene/{scene_part => elements}/images.rs | 0 .../scene/{scene_part => elements}/lines2d.rs | 0 .../scene/{scene_part => elements}/lines3d.rs | 0 .../scene/{scene_part => elements}/meshes.rs | 0 .../src/scene/{scene_part => elements}/mod.rs | 0 .../{scene_part => elements}/points2d.rs | 0 .../{scene_part => elements}/points3d.rs | 2 +- crates/re_space_view_spatial/src/scene/mod.rs | 24 +++++++++---------- 12 files changed, 15 insertions(+), 18 deletions(-) rename crates/re_space_view_spatial/src/scene/{scene_part => elements}/arrows3d.rs (100%) rename crates/re_space_view_spatial/src/scene/{scene_part => elements}/boxes2d.rs (96%) rename crates/re_space_view_spatial/src/scene/{scene_part => elements}/boxes3d.rs (100%) rename crates/re_space_view_spatial/src/scene/{scene_part => elements}/cameras.rs (100%) rename crates/re_space_view_spatial/src/scene/{scene_part => elements}/images.rs (100%) rename crates/re_space_view_spatial/src/scene/{scene_part => elements}/lines2d.rs (100%) rename crates/re_space_view_spatial/src/scene/{scene_part => elements}/lines3d.rs (100%) rename crates/re_space_view_spatial/src/scene/{scene_part => elements}/meshes.rs (100%) rename crates/re_space_view_spatial/src/scene/{scene_part => elements}/mod.rs (100%) rename crates/re_space_view_spatial/src/scene/{scene_part => elements}/points2d.rs (100%) rename crates/re_space_view_spatial/src/scene/{scene_part => elements}/points3d.rs (99%) diff --git a/crates/re_space_view_spatial/src/scene/scene_part/arrows3d.rs b/crates/re_space_view_spatial/src/scene/elements/arrows3d.rs similarity index 100% rename from crates/re_space_view_spatial/src/scene/scene_part/arrows3d.rs rename to crates/re_space_view_spatial/src/scene/elements/arrows3d.rs diff --git a/crates/re_space_view_spatial/src/scene/scene_part/boxes2d.rs b/crates/re_space_view_spatial/src/scene/elements/boxes2d.rs similarity index 96% rename from crates/re_space_view_spatial/src/scene/scene_part/boxes2d.rs rename to crates/re_space_view_spatial/src/scene/elements/boxes2d.rs index 56a78c355144..3769cfd8c521 100644 --- a/crates/re_space_view_spatial/src/scene/scene_part/boxes2d.rs +++ b/crates/re_space_view_spatial/src/scene/elements/boxes2d.rs @@ -6,16 +6,13 @@ use re_renderer::Size; use re_space_view::SpaceViewHighlights; use re_viewer_context::{DefaultColor, SceneQuery, ViewerContext}; +use super::{instance_key_to_picking_id, instance_path_hash_for_picking, ScenePart}; use crate::{ scene::UiLabelTarget, - scene::{ - scene_part::instance_path_hash_for_picking, EntityDepthOffsets, SceneSpatial, UiLabel, - }, + scene::{EntityDepthOffsets, SceneSpatial, UiLabel}, transform_cache::TransformCache, }; -use super::{instance_key_to_picking_id, ScenePart}; - pub struct Boxes2DPart; impl Boxes2DPart { diff --git a/crates/re_space_view_spatial/src/scene/scene_part/boxes3d.rs b/crates/re_space_view_spatial/src/scene/elements/boxes3d.rs similarity index 100% rename from crates/re_space_view_spatial/src/scene/scene_part/boxes3d.rs rename to crates/re_space_view_spatial/src/scene/elements/boxes3d.rs diff --git a/crates/re_space_view_spatial/src/scene/scene_part/cameras.rs b/crates/re_space_view_spatial/src/scene/elements/cameras.rs similarity index 100% rename from crates/re_space_view_spatial/src/scene/scene_part/cameras.rs rename to crates/re_space_view_spatial/src/scene/elements/cameras.rs diff --git a/crates/re_space_view_spatial/src/scene/scene_part/images.rs b/crates/re_space_view_spatial/src/scene/elements/images.rs similarity index 100% rename from crates/re_space_view_spatial/src/scene/scene_part/images.rs rename to crates/re_space_view_spatial/src/scene/elements/images.rs diff --git a/crates/re_space_view_spatial/src/scene/scene_part/lines2d.rs b/crates/re_space_view_spatial/src/scene/elements/lines2d.rs similarity index 100% rename from crates/re_space_view_spatial/src/scene/scene_part/lines2d.rs rename to crates/re_space_view_spatial/src/scene/elements/lines2d.rs diff --git a/crates/re_space_view_spatial/src/scene/scene_part/lines3d.rs b/crates/re_space_view_spatial/src/scene/elements/lines3d.rs similarity index 100% rename from crates/re_space_view_spatial/src/scene/scene_part/lines3d.rs rename to crates/re_space_view_spatial/src/scene/elements/lines3d.rs diff --git a/crates/re_space_view_spatial/src/scene/scene_part/meshes.rs b/crates/re_space_view_spatial/src/scene/elements/meshes.rs similarity index 100% rename from crates/re_space_view_spatial/src/scene/scene_part/meshes.rs rename to crates/re_space_view_spatial/src/scene/elements/meshes.rs diff --git a/crates/re_space_view_spatial/src/scene/scene_part/mod.rs b/crates/re_space_view_spatial/src/scene/elements/mod.rs similarity index 100% rename from crates/re_space_view_spatial/src/scene/scene_part/mod.rs rename to crates/re_space_view_spatial/src/scene/elements/mod.rs diff --git a/crates/re_space_view_spatial/src/scene/scene_part/points2d.rs b/crates/re_space_view_spatial/src/scene/elements/points2d.rs similarity index 100% rename from crates/re_space_view_spatial/src/scene/scene_part/points2d.rs rename to crates/re_space_view_spatial/src/scene/elements/points2d.rs diff --git a/crates/re_space_view_spatial/src/scene/scene_part/points3d.rs b/crates/re_space_view_spatial/src/scene/elements/points3d.rs similarity index 99% rename from crates/re_space_view_spatial/src/scene/scene_part/points3d.rs rename to crates/re_space_view_spatial/src/scene/elements/points3d.rs index 0b0f6d8e727d..e22e86171a21 100644 --- a/crates/re_space_view_spatial/src/scene/scene_part/points3d.rs +++ b/crates/re_space_view_spatial/src/scene/elements/points3d.rs @@ -11,7 +11,7 @@ use crate::{ { scene::UiLabelTarget, scene::{ - scene_part::{ + elements::{ instance_key_to_picking_id, instance_path_hash_for_picking, process_annotations_and_keypoints, process_colors, process_radii, }, diff --git a/crates/re_space_view_spatial/src/scene/mod.rs b/crates/re_space_view_spatial/src/scene/mod.rs index 73f60439b96b..55f1df707784 100644 --- a/crates/re_space_view_spatial/src/scene/mod.rs +++ b/crates/re_space_view_spatial/src/scene/mod.rs @@ -18,13 +18,13 @@ use crate::{ mesh_loader::LoadedMesh, space_camera_3d::SpaceCamera3D, transform_cache::TransformCache, }; +mod elements; mod picking; mod primitives; -mod scene_part; pub use self::picking::{PickingContext, PickingHitType, PickingRayHit, PickingResult}; pub use self::primitives::SceneSpatialPrimitives; -use scene_part::ScenePart; +use elements::ScenePart; /// TODO(andreas): Scene should only care about converted rendering primitive. pub struct MeshSource { @@ -237,21 +237,21 @@ impl SceneSpatial { self.annotation_map.load(ctx, query); let parts: Vec<&dyn ScenePart> = vec![ - &scene_part::Points3DPart { max_labels: 10 }, + &elements::Points3DPart { max_labels: 10 }, // -- - &scene_part::Boxes3DPart, - &scene_part::Lines3DPart, - &scene_part::Arrows3DPart, - &scene_part::MeshPart, - &scene_part::ImagesPart, + &elements::Boxes3DPart, + &elements::Lines3DPart, + &elements::Arrows3DPart, + &elements::MeshPart, + &elements::ImagesPart, // -- - &scene_part::Boxes2DPart, + &elements::Boxes2DPart, // -- // Note: Lines2DPart handles both Segments and LinesPaths since they are unified on the logging-side. - &scene_part::Lines2DPart, - &scene_part::Points2DPart { max_labels: 10 }, + &elements::Lines2DPart, + &elements::Points2DPart { max_labels: 10 }, // --- - &scene_part::CamerasPart, + &elements::CamerasPart, ]; let depth_offsets = Self::determine_depth_offsets(ctx, query); From 368393b1667af9513c9614ac9684228f00c6d071 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Wed, 31 May 2023 22:42:41 +0200 Subject: [PATCH 03/39] space view highlights are now part of Scene --- crates/re_space_view/src/lib.rs | 2 -- .../src/scene/elements/arrows3d.rs | 2 +- .../src/scene/elements/boxes2d.rs | 2 +- .../src/scene/elements/boxes3d.rs | 2 +- .../src/scene/elements/cameras.rs | 2 +- .../src/scene/elements/images.rs | 2 +- .../src/scene/elements/lines2d.rs | 2 +- .../src/scene/elements/lines3d.rs | 2 +- .../src/scene/elements/meshes.rs | 2 +- .../src/scene/elements/mod.rs | 2 +- .../src/scene/elements/points2d.rs | 2 +- .../src/scene/elements/points3d.rs | 2 +- crates/re_space_view_spatial/src/scene/mod.rs | 2 +- crates/re_space_view_spatial/src/ui.rs | 6 +++--- crates/re_space_view_spatial/src/ui_2d.rs | 9 ++++----- crates/re_space_view_spatial/src/ui_3d.rs | 13 ++++++------ .../re_space_view_text/src/scene_element.rs | 4 +++- .../src/scene_element.rs | 4 +++- crates/re_viewer_context/src/lib.rs | 3 ++- .../src/space_view}/highlights.rs | 2 +- .../re_viewer_context/src/space_view/mod.rs | 3 +++ .../re_viewer_context/src/space_view/scene.rs | 20 +++++++++++++++---- .../src/space_view/scene_element_impl.rs | 9 +++++++-- .../src/space_view/space_view_class_impl.rs | 1 + crates/re_viewport/src/space_view.rs | 16 +++++++-------- .../re_viewport/src/space_view_highlights.rs | 6 ++++-- crates/re_viewport/src/viewport.rs | 8 ++++---- 27 files changed, 76 insertions(+), 54 deletions(-) rename crates/{re_space_view/src => re_viewer_context/src/space_view}/highlights.rs (98%) diff --git a/crates/re_space_view/src/lib.rs b/crates/re_space_view/src/lib.rs index 8ccc845b334d..28231d7c6ab9 100644 --- a/crates/re_space_view/src/lib.rs +++ b/crates/re_space_view/src/lib.rs @@ -4,9 +4,7 @@ pub mod controls; mod data_blueprint; -mod highlights; mod screenshot; pub use data_blueprint::{DataBlueprintGroup, DataBlueprintTree}; -pub use highlights::{SpaceViewEntityHighlight, SpaceViewHighlights, SpaceViewOutlineMasks}; pub use screenshot::ScreenshotMode; diff --git a/crates/re_space_view_spatial/src/scene/elements/arrows3d.rs b/crates/re_space_view_spatial/src/scene/elements/arrows3d.rs index 028656d2fc2c..ac86d98dab25 100644 --- a/crates/re_space_view_spatial/src/scene/elements/arrows3d.rs +++ b/crates/re_space_view_spatial/src/scene/elements/arrows3d.rs @@ -2,7 +2,7 @@ use re_components::{Arrow3D, ColorRGBA, Component as _, InstanceKey, Label, Radi use re_data_store::EntityPath; use re_query::{query_primary_with_history, EntityView, QueryError}; use re_renderer::{renderer::LineStripFlags, Size}; -use re_space_view::SpaceViewHighlights; +use re_viewer_context::SpaceViewHighlights; use re_viewer_context::{DefaultColor, SceneQuery, ViewerContext}; use crate::{ diff --git a/crates/re_space_view_spatial/src/scene/elements/boxes2d.rs b/crates/re_space_view_spatial/src/scene/elements/boxes2d.rs index 3769cfd8c521..7381fc50fdfc 100644 --- a/crates/re_space_view_spatial/src/scene/elements/boxes2d.rs +++ b/crates/re_space_view_spatial/src/scene/elements/boxes2d.rs @@ -3,7 +3,7 @@ use re_data_store::EntityPath; use re_log_types::Component as _; use re_query::{query_primary_with_history, EntityView, QueryError}; use re_renderer::Size; -use re_space_view::SpaceViewHighlights; +use re_viewer_context::SpaceViewHighlights; use re_viewer_context::{DefaultColor, SceneQuery, ViewerContext}; use super::{instance_key_to_picking_id, instance_path_hash_for_picking, ScenePart}; diff --git a/crates/re_space_view_spatial/src/scene/elements/boxes3d.rs b/crates/re_space_view_spatial/src/scene/elements/boxes3d.rs index c0491ec48154..9da1fa0e11d5 100644 --- a/crates/re_space_view_spatial/src/scene/elements/boxes3d.rs +++ b/crates/re_space_view_spatial/src/scene/elements/boxes3d.rs @@ -4,8 +4,8 @@ use re_components::{ use re_data_store::EntityPath; use re_query::{query_primary_with_history, EntityView, QueryError}; use re_renderer::Size; -use re_space_view::{SpaceViewHighlights, SpaceViewOutlineMasks}; use re_viewer_context::{DefaultColor, SceneQuery, ViewerContext}; +use re_viewer_context::{SpaceViewHighlights, SpaceViewOutlineMasks}; use crate::{ scene::EntityDepthOffsets, diff --git a/crates/re_space_view_spatial/src/scene/elements/cameras.rs b/crates/re_space_view_spatial/src/scene/elements/cameras.rs index 3e80d6d83bd9..c9f9f2245fa2 100644 --- a/crates/re_space_view_spatial/src/scene/elements/cameras.rs +++ b/crates/re_space_view_spatial/src/scene/elements/cameras.rs @@ -4,9 +4,9 @@ use re_components::{ }; use re_data_store::{EntityPath, EntityProperties}; use re_renderer::renderer::LineStripFlags; -use re_space_view::{SpaceViewHighlights, SpaceViewOutlineMasks}; use re_viewer_context::TimeControl; use re_viewer_context::{SceneQuery, ViewerContext}; +use re_viewer_context::{SpaceViewHighlights, SpaceViewOutlineMasks}; use super::{instance_path_hash_for_picking, ScenePart}; use crate::{ diff --git a/crates/re_space_view_spatial/src/scene/elements/images.rs b/crates/re_space_view_spatial/src/scene/elements/images.rs index 09f2a4b898d2..d9acb21ab668 100644 --- a/crates/re_space_view_spatial/src/scene/elements/images.rs +++ b/crates/re_space_view_spatial/src/scene/elements/images.rs @@ -14,11 +14,11 @@ use re_renderer::{ resource_managers::Texture2DCreationDesc, Colormap, OutlineMaskPreference, }; -use re_space_view::{SpaceViewHighlights, SpaceViewOutlineMasks}; use re_viewer_context::{ gpu_bridge, Annotations, DefaultColor, SceneQuery, TensorDecodeCache, TensorStatsCache, ViewerContext, }; +use re_viewer_context::{SpaceViewHighlights, SpaceViewOutlineMasks}; use crate::{ scene::{EntityDepthOffsets, Image, SceneSpatial}, diff --git a/crates/re_space_view_spatial/src/scene/elements/lines2d.rs b/crates/re_space_view_spatial/src/scene/elements/lines2d.rs index 4f94f9c684ae..716f8f25c190 100644 --- a/crates/re_space_view_spatial/src/scene/elements/lines2d.rs +++ b/crates/re_space_view_spatial/src/scene/elements/lines2d.rs @@ -2,8 +2,8 @@ use re_components::{ColorRGBA, Component as _, InstanceKey, LineStrip2D, Radius} use re_data_store::EntityPath; use re_query::{query_primary_with_history, EntityView, QueryError}; use re_renderer::Size; -use re_space_view::{SpaceViewHighlights, SpaceViewOutlineMasks}; use re_viewer_context::{DefaultColor, SceneQuery, ViewerContext}; +use re_viewer_context::{SpaceViewHighlights, SpaceViewOutlineMasks}; use crate::{ scene::{EntityDepthOffsets, SceneSpatial}, diff --git a/crates/re_space_view_spatial/src/scene/elements/lines3d.rs b/crates/re_space_view_spatial/src/scene/elements/lines3d.rs index 86492c944a65..7798d09fa0a3 100644 --- a/crates/re_space_view_spatial/src/scene/elements/lines3d.rs +++ b/crates/re_space_view_spatial/src/scene/elements/lines3d.rs @@ -2,8 +2,8 @@ use re_components::{ColorRGBA, Component as _, InstanceKey, LineStrip3D, Radius} use re_data_store::EntityPath; use re_query::{query_primary_with_history, EntityView, QueryError}; use re_renderer::Size; -use re_space_view::{SpaceViewHighlights, SpaceViewOutlineMasks}; use re_viewer_context::{DefaultColor, SceneQuery, ViewerContext}; +use re_viewer_context::{SpaceViewHighlights, SpaceViewOutlineMasks}; use crate::{ scene::{EntityDepthOffsets, SceneSpatial}, diff --git a/crates/re_space_view_spatial/src/scene/elements/meshes.rs b/crates/re_space_view_spatial/src/scene/elements/meshes.rs index f133ba4084ff..d026bbbf9396 100644 --- a/crates/re_space_view_spatial/src/scene/elements/meshes.rs +++ b/crates/re_space_view_spatial/src/scene/elements/meshes.rs @@ -1,7 +1,7 @@ use re_components::{ColorRGBA, Component, InstanceKey, Mesh3D}; use re_data_store::EntityPath; use re_query::{query_primary_with_history, EntityView, QueryError}; -use re_space_view::SpaceViewHighlights; +use re_viewer_context::SpaceViewHighlights; use re_viewer_context::{DefaultColor, SceneQuery, ViewerContext}; use crate::{ diff --git a/crates/re_space_view_spatial/src/scene/elements/mod.rs b/crates/re_space_view_spatial/src/scene/elements/mod.rs index 71cd2c5d239f..2a3c73d1c3ec 100644 --- a/crates/re_space_view_spatial/src/scene/elements/mod.rs +++ b/crates/re_space_view_spatial/src/scene/elements/mod.rs @@ -28,7 +28,7 @@ pub(crate) use points3d::Points3DPart; use re_components::{ClassId, ColorRGBA, KeypointId, Radius}; use re_data_store::{EntityPath, InstancePathHash}; -use re_space_view::SpaceViewHighlights; +use re_viewer_context::SpaceViewHighlights; use re_viewer_context::{ Annotations, DefaultColor, ResolvedAnnotationInfo, SceneQuery, ViewerContext, }; diff --git a/crates/re_space_view_spatial/src/scene/elements/points2d.rs b/crates/re_space_view_spatial/src/scene/elements/points2d.rs index 944183f546fb..3fea718e45d0 100644 --- a/crates/re_space_view_spatial/src/scene/elements/points2d.rs +++ b/crates/re_space_view_spatial/src/scene/elements/points2d.rs @@ -3,8 +3,8 @@ use re_components::{ }; use re_data_store::{EntityPath, InstancePathHash}; use re_query::{query_primary_with_history, EntityView, QueryError}; -use re_space_view::{SpaceViewHighlights, SpaceViewOutlineMasks}; use re_viewer_context::{ResolvedAnnotationInfo, SceneQuery, ViewerContext}; +use re_viewer_context::{SpaceViewHighlights, SpaceViewOutlineMasks}; use crate::{ scene::{EntityDepthOffsets, SceneSpatial, UiLabel, UiLabelTarget}, diff --git a/crates/re_space_view_spatial/src/scene/elements/points3d.rs b/crates/re_space_view_spatial/src/scene/elements/points3d.rs index e22e86171a21..aba799bad9fd 100644 --- a/crates/re_space_view_spatial/src/scene/elements/points3d.rs +++ b/crates/re_space_view_spatial/src/scene/elements/points3d.rs @@ -3,8 +3,8 @@ use re_components::{ }; use re_data_store::{EntityPath, InstancePathHash}; use re_query::{query_primary_with_history, EntityView, QueryError}; -use re_space_view::{SpaceViewHighlights, SpaceViewOutlineMasks}; use re_viewer_context::{ResolvedAnnotationInfo, SceneQuery, ViewerContext}; +use re_viewer_context::{SpaceViewHighlights, SpaceViewOutlineMasks}; use crate::{ transform_cache::TransformCache, diff --git a/crates/re_space_view_spatial/src/scene/mod.rs b/crates/re_space_view_spatial/src/scene/mod.rs index 55f1df707784..1cd6456508aa 100644 --- a/crates/re_space_view_spatial/src/scene/mod.rs +++ b/crates/re_space_view_spatial/src/scene/mod.rs @@ -10,7 +10,7 @@ use re_components::{ClassId, DecodedTensor, DrawOrder, InstanceKey, KeypointId}; use re_data_store::{EntityPath, InstancePathHash}; use re_log_types::EntityPathHash; use re_renderer::{renderer::TexturedRect, Color32, OutlineMaskPreference, Size}; -use re_space_view::SpaceViewHighlights; +use re_viewer_context::SpaceViewHighlights; use re_viewer_context::{auto_color, AnnotationMap, Annotations, SceneQuery, ViewerContext}; use super::SpatialNavigationMode; diff --git a/crates/re_space_view_spatial/src/ui.rs b/crates/re_space_view_spatial/src/ui.rs index 08723c83fc5b..0a089ddbbea6 100644 --- a/crates/re_space_view_spatial/src/ui.rs +++ b/crates/re_space_view_spatial/src/ui.rs @@ -8,10 +8,10 @@ use re_data_ui::{item_ui, DataUi}; use re_data_ui::{show_zoomed_image_region, show_zoomed_image_region_area_outline}; use re_format::format_f32; use re_renderer::OutlineConfig; -use re_space_view::{DataBlueprintTree, ScreenshotMode, SpaceViewHighlights}; +use re_space_view::{DataBlueprintTree, ScreenshotMode}; use re_viewer_context::{ - HoverHighlight, HoveredSpace, Item, SelectionHighlight, SpaceViewId, TensorDecodeCache, - TensorStatsCache, UiVerbosity, ViewerContext, + HoverHighlight, HoveredSpace, Item, SelectionHighlight, SpaceViewHighlights, SpaceViewId, + TensorDecodeCache, TensorStatsCache, UiVerbosity, ViewerContext, }; use super::{ diff --git a/crates/re_space_view_spatial/src/ui_2d.rs b/crates/re_space_view_spatial/src/ui_2d.rs index dd0e43b1ad2a..e97c5855610a 100644 --- a/crates/re_space_view_spatial/src/ui_2d.rs +++ b/crates/re_space_view_spatial/src/ui_2d.rs @@ -4,7 +4,10 @@ use macaw::IsoTransform; use re_components::Pinhole; use re_data_store::{EntityPath, EntityPropertyMap}; use re_renderer::view_builder::{TargetConfiguration, ViewBuilder}; -use re_viewer_context::{gpu_bridge, HoveredSpace, SpaceViewId, ViewerContext}; +use re_space_view::controls::{DRAG_PAN2D_BUTTON, RESET_VIEW_BUTTON_TEXT, ZOOM_SCROLL_MODIFIER}; +use re_viewer_context::{ + gpu_bridge, HoveredSpace, SpaceViewHighlights, SpaceViewId, ViewerContext, +}; use super::{ eye::Eye, @@ -16,10 +19,6 @@ use crate::{ ui::{outline_config, ViewSpatialState}, ui_renderer_bridge::{fill_view_builder, ScreenBackground}, }; -use re_space_view::{ - controls::{DRAG_PAN2D_BUTTON, RESET_VIEW_BUTTON_TEXT, ZOOM_SCROLL_MODIFIER}, - SpaceViewHighlights, -}; // --- diff --git a/crates/re_space_view_spatial/src/ui_3d.rs b/crates/re_space_view_spatial/src/ui_3d.rs index c95c0a394ab8..6d08f86a1684 100644 --- a/crates/re_space_view_spatial/src/ui_3d.rs +++ b/crates/re_space_view_spatial/src/ui_3d.rs @@ -10,14 +10,13 @@ use re_renderer::{ view_builder::{Projection, TargetConfiguration, ViewBuilder}, Size, }; -use re_space_view::{ - controls::{ - DRAG_PAN3D_BUTTON, RESET_VIEW_BUTTON_TEXT, ROLL_MOUSE, ROLL_MOUSE_ALT, ROLL_MOUSE_MODIFIER, - ROTATE3D_BUTTON, SLOW_DOWN_3D_MODIFIER, SPEED_UP_3D_MODIFIER, TRACKED_CAMERA_RESTORE_KEY, - }, - SpaceViewHighlights, +use re_space_view::controls::{ + DRAG_PAN3D_BUTTON, RESET_VIEW_BUTTON_TEXT, ROLL_MOUSE, ROLL_MOUSE_ALT, ROLL_MOUSE_MODIFIER, + ROTATE3D_BUTTON, SLOW_DOWN_3D_MODIFIER, SPEED_UP_3D_MODIFIER, TRACKED_CAMERA_RESTORE_KEY, +}; +use re_viewer_context::{ + gpu_bridge, HoveredSpace, Item, SpaceViewHighlights, SpaceViewId, ViewerContext, }; -use re_viewer_context::{gpu_bridge, HoveredSpace, Item, SpaceViewId, ViewerContext}; use crate::{ scene::SceneSpatial, diff --git a/crates/re_space_view_text/src/scene_element.rs b/crates/re_space_view_text/src/scene_element.rs index f9f151c64be2..b13a3aae140a 100644 --- a/crates/re_space_view_text/src/scene_element.rs +++ b/crates/re_space_view_text/src/scene_element.rs @@ -3,7 +3,8 @@ use re_data_store::EntityPath; use re_log_types::{Component as _, InstanceKey, RowId}; use re_query::{range_entity_with_primary, QueryError}; use re_viewer_context::{ - ArchetypeDefinition, SceneContextCollection, SceneElementImpl, SceneQuery, ViewerContext, + ArchetypeDefinition, SceneContextCollection, SceneElementImpl, SceneQuery, SpaceViewHighlights, + ViewerContext, }; use super::space_view_class::TextSpaceViewState; @@ -44,6 +45,7 @@ impl SceneElementImpl for SceneText { query: &SceneQuery<'_>, state: &TextSpaceViewState, _contexts: &SceneContextCollection, + _highlights: &SpaceViewHighlights, ) { let store = &ctx.store_db.entity_db.data_store; diff --git a/crates/re_space_view_text_box/src/scene_element.rs b/crates/re_space_view_text_box/src/scene_element.rs index 5caa0e789a7f..5ef8c7b9a505 100644 --- a/crates/re_space_view_text_box/src/scene_element.rs +++ b/crates/re_space_view_text_box/src/scene_element.rs @@ -2,7 +2,8 @@ use re_arrow_store::LatestAtQuery; use re_components::Component; use re_query::{query_entity_with_primary, QueryError}; use re_viewer_context::{ - ArchetypeDefinition, SceneContextCollection, SceneElementImpl, SceneQuery, ViewerContext, + ArchetypeDefinition, SceneContextCollection, SceneElementImpl, SceneQuery, SpaceViewHighlights, + ViewerContext, }; use crate::space_view_class::TextBoxSpaceViewState; @@ -33,6 +34,7 @@ impl SceneElementImpl for SceneTextBox { query: &SceneQuery<'_>, _space_view_state: &Self::State, _contexts: &SceneContextCollection, + _highlights: &SpaceViewHighlights, ) { let store = &ctx.store_db.entity_db.data_store; diff --git a/crates/re_viewer_context/src/lib.rs b/crates/re_viewer_context/src/lib.rs index ea3c91b3f0a4..abf947b7ff84 100644 --- a/crates/re_viewer_context/src/lib.rs +++ b/crates/re_viewer_context/src/lib.rs @@ -34,7 +34,8 @@ pub use selection_state::{ pub use space_view::{ ArchetypeDefinition, EmptySpaceViewState, Scene, SceneContext, SceneContextCollection, SceneElement, SceneElementCollection, SceneElementImpl, SpaceViewClass, SpaceViewClassImpl, - SpaceViewClassName, SpaceViewClassRegistry, SpaceViewClassRegistryError, SpaceViewState, + SpaceViewClassName, SpaceViewClassRegistry, SpaceViewClassRegistryError, + SpaceViewEntityHighlight, SpaceViewHighlights, SpaceViewOutlineMasks, SpaceViewState, }; pub use tensor::{TensorDecodeCache, TensorStats, TensorStatsCache}; pub use time_control::{Looping, PlayState, TimeControl, TimeView}; diff --git a/crates/re_space_view/src/highlights.rs b/crates/re_viewer_context/src/space_view/highlights.rs similarity index 98% rename from crates/re_space_view/src/highlights.rs rename to crates/re_viewer_context/src/space_view/highlights.rs index 2211ec493b80..e421c14390be 100644 --- a/crates/re_space_view/src/highlights.rs +++ b/crates/re_viewer_context/src/space_view/highlights.rs @@ -4,7 +4,7 @@ use nohash_hasher::IntMap; use re_log_types::{EntityPathHash, InstanceKey}; use re_renderer::OutlineMaskPreference; -use re_viewer_context::InteractionHighlight; +use crate::InteractionHighlight; /// Highlights of a specific entity path in a specific space view. /// diff --git a/crates/re_viewer_context/src/space_view/mod.rs b/crates/re_viewer_context/src/space_view/mod.rs index cbd760b1b73a..81feb7ed835e 100644 --- a/crates/re_viewer_context/src/space_view/mod.rs +++ b/crates/re_viewer_context/src/space_view/mod.rs @@ -3,12 +3,15 @@ //! Defines a framework & utilities for defining classes of space views in the Rerun viewer. //! Does not implement any concrete space view. +// TODO(andreas): Can we move some of this to the `re_space_view` crate? +mod highlights; mod scene; mod scene_element_impl; mod space_view_class; mod space_view_class_impl; mod space_view_class_registry; +pub use highlights::{SpaceViewEntityHighlight, SpaceViewHighlights, SpaceViewOutlineMasks}; pub use scene::{ Scene, SceneContext, SceneContextCollection, SceneElement, SceneElementCollection, }; diff --git a/crates/re_viewer_context/src/space_view/scene.rs b/crates/re_viewer_context/src/space_view/scene.rs index 414c44afb543..40f43b49faa2 100644 --- a/crates/re_viewer_context/src/space_view/scene.rs +++ b/crates/re_viewer_context/src/space_view/scene.rs @@ -2,7 +2,7 @@ use std::any::Any; use ahash::HashMap; -use crate::{ArchetypeDefinition, SceneQuery, SpaceViewState, ViewerContext}; +use crate::{ArchetypeDefinition, SceneQuery, SpaceViewHighlights, SpaceViewState, ViewerContext}; #[derive(Debug, thiserror::Error)] pub enum SceneItemCollectionLookupError { @@ -112,15 +112,15 @@ scene_element_collection_from_tuple!(0 => T0, 1 => T1, 2 => T2, 3 => T3, 4 => T4 scene_element_collection_from_tuple!(0 => T0, 1 => T1, 2 => T2, 3 => T3, 4 => T4, 5 => T5, 6 => T6); scene_element_collection_from_tuple!(0 => T0, 1 => T1, 2 => T2, 3 => T3, 4 => T4, 5 => T5, 6 => T6, 7 => T7); scene_element_collection_from_tuple!(0 => T0, 1 => T1, 2 => T2, 3 => T3, 4 => T4, 5 => T5, 6 => T6, 7 => T7, 8 => T8); -// ... -/// A scene is a collection of scene contexts and elements. +/// A scene is a collection of scene contexts and elements, as well as a collection of highlights. /// /// When populating a scene, first all contexts are populated, /// and then all elements with read access to the previously established context objects. pub struct Scene { pub contexts: SceneContextCollection, pub elements: SceneElementCollection, + pub highlights: SpaceViewHighlights, } impl Scene { @@ -140,7 +140,12 @@ impl Scene { ctx: &mut ViewerContext<'_>, query: &SceneQuery<'_>, space_view_state: &dyn SpaceViewState, + highlights: SpaceViewHighlights, ) { + re_tracing::profile_function!(); + + self.highlights = highlights; + // TODO(andreas): Both loops are great candidates for parallelization. for context in self.contexts.0.values_mut() { // TODO(andreas): Restrict the query with the archetype somehow, ideally making it trivial to do the correct thing. @@ -148,7 +153,13 @@ impl Scene { } for element in self.elements.0.values_mut() { // TODO(andreas): Restrict the query with the archetype somehow, ideally making it trivial to do the correct thing. - element.populate(ctx, query, space_view_state, &self.contexts); + element.populate( + ctx, + query, + space_view_state, + &self.contexts, + &self.highlights, + ); } } } @@ -167,6 +178,7 @@ pub trait SceneElement: Any { query: &SceneQuery<'_>, space_view_state: &dyn SpaceViewState, contexts: &SceneContextCollection, + highlights: &SpaceViewHighlights, ); /// Converts itself to a reference of [`Any`], which enables downcasting to concrete types. diff --git a/crates/re_viewer_context/src/space_view/scene_element_impl.rs b/crates/re_viewer_context/src/space_view/scene_element_impl.rs index 4fc4b20e277f..33975d4e8e9a 100644 --- a/crates/re_viewer_context/src/space_view/scene_element_impl.rs +++ b/crates/re_viewer_context/src/space_view/scene_element_impl.rs @@ -1,4 +1,7 @@ -use crate::{ArchetypeDefinition, SceneElement, SceneQuery, SpaceViewState, ViewerContext}; +use crate::{ + ArchetypeDefinition, SceneElement, SceneQuery, SpaceViewHighlights, SpaceViewState, + ViewerContext, +}; use super::scene::SceneContextCollection; @@ -18,6 +21,7 @@ pub trait SceneElementImpl { query: &SceneQuery<'_>, space_view_state: &Self::State, contexts: &SceneContextCollection, + highlights: &SpaceViewHighlights, ); } @@ -32,9 +36,10 @@ impl SceneElement for T { query: &crate::SceneQuery<'_>, space_view_state: &dyn SpaceViewState, contexts: &SceneContextCollection, + highlights: &SpaceViewHighlights, ) { if let Some(state) = space_view_state.as_any().downcast_ref() { - self.populate(ctx, query, state, contexts); + self.populate(ctx, query, state, contexts, highlights); } else { re_log::error_once!("Incorrect type of space view state."); } diff --git a/crates/re_viewer_context/src/space_view/space_view_class_impl.rs b/crates/re_viewer_context/src/space_view/space_view_class_impl.rs index 64fb0c12d158..b379bbb6f1d2 100644 --- a/crates/re_viewer_context/src/space_view/space_view_class_impl.rs +++ b/crates/re_viewer_context/src/space_view/space_view_class_impl.rs @@ -68,6 +68,7 @@ impl SpaceViewClass for T { Scene { contexts: T::SceneContextTuple::default().into(), elements: T::SceneElementTuple::default().into(), + highlights: Default::default(), } } diff --git a/crates/re_viewport/src/space_view.rs b/crates/re_viewport/src/space_view.rs index 595bbff8f2c1..0f1617ff1ded 100644 --- a/crates/re_viewport/src/space_view.rs +++ b/crates/re_viewport/src/space_view.rs @@ -1,9 +1,9 @@ use re_arrow_store::Timeline; use re_data_store::{EntityPath, EntityPropertyMap, EntityTree, InstancePath, TimeInt}; use re_renderer::ScreenshotProcessor; -use re_space_view::{DataBlueprintTree, ScreenshotMode, SpaceViewHighlights}; +use re_space_view::{DataBlueprintTree, ScreenshotMode}; use re_space_view_spatial::{SceneSpatial, TransformCache, ViewSpatialState}; -use re_viewer_context::{SpaceViewClassName, SpaceViewId, ViewerContext}; +use re_viewer_context::{SpaceViewClassName, SpaceViewHighlights, SpaceViewId, ViewerContext}; use crate::{ space_info::SpaceInfoCollection, @@ -186,7 +186,7 @@ impl SpaceViewBlueprint { ctx: &mut ViewerContext<'_>, ui: &mut egui::Ui, latest_at: TimeInt, - highlights: &SpaceViewHighlights, + highlights: SpaceViewHighlights, ) { re_tracing::profile_function!(); @@ -208,10 +208,8 @@ impl SpaceViewBlueprint { space_view_class.prepare_populate(ctx, view_state.state.as_mut()); } let mut scene = space_view_class.new_scene(); - { - re_tracing::profile_scope!("scene.populate", space_view_class.name()); - scene.populate(ctx, &query, view_state.state.as_ref()); - } + scene.populate(ctx, &query, view_state.state.as_ref(), highlights); + // TODO(andreas): Pass scene to renderer. // TODO(andreas): Setup re_renderer view. { @@ -245,7 +243,7 @@ impl SpaceViewBlueprint { self.data_blueprint.data_blueprints_projected(), ); let mut scene = SceneSpatial::new(ctx.render_ctx); - scene.load(ctx, &query, &transforms, highlights); + scene.load(ctx, &query, &transforms, &highlights); view_state .state_spatial .update_object_property_heuristics(ctx, &mut self.data_blueprint); @@ -255,7 +253,7 @@ impl SpaceViewBlueprint { &self.space_path, scene, self.id, - highlights, + &highlights, self.data_blueprint.data_blueprints_projected(), ); } diff --git a/crates/re_viewport/src/space_view_highlights.rs b/crates/re_viewport/src/space_view_highlights.rs index 2a52be000fa4..8143df90d931 100644 --- a/crates/re_viewport/src/space_view_highlights.rs +++ b/crates/re_viewport/src/space_view_highlights.rs @@ -4,8 +4,10 @@ use nohash_hasher::IntMap; use re_log_types::{EntityPath, EntityPathHash}; use re_renderer::OutlineMaskPreference; -use re_space_view::{SpaceViewEntityHighlight, SpaceViewHighlights, SpaceViewOutlineMasks}; -use re_viewer_context::{HoverHighlight, Item, SelectionHighlight, SelectionState, SpaceViewId}; +use re_viewer_context::{ + HoverHighlight, Item, SelectionHighlight, SelectionState, SpaceViewEntityHighlight, + SpaceViewHighlights, SpaceViewId, SpaceViewOutlineMasks, +}; use crate::SpaceViewBlueprint; diff --git a/crates/re_viewport/src/viewport.rs b/crates/re_viewport/src/viewport.rs index ce838028fe06..bef1486a8a76 100644 --- a/crates/re_viewport/src/viewport.rs +++ b/crates/re_viewport/src/viewport.rs @@ -7,10 +7,10 @@ use itertools::Itertools as _; use re_data_store::EntityPath; use re_data_ui::item_ui; -use re_space_view::{DataBlueprintGroup, SpaceViewHighlights}; +use re_space_view::DataBlueprintGroup; use re_viewer_context::{ DataBlueprintGroupHandle, EmptySpaceViewState, Item, SpaceViewClassName, - SpaceViewClassRegistry, SpaceViewId, ViewerContext, + SpaceViewClassRegistry, SpaceViewHighlights, SpaceViewId, ViewerContext, }; use crate::{ @@ -705,7 +705,7 @@ impl<'a, 'b> egui_tiles::Behavior for TabViewer<'a, 'b> { ui, space_view_blueprint, space_view_state, - &highlights, + highlights, ); Default::default() @@ -844,7 +844,7 @@ fn space_view_ui( ui: &mut egui::Ui, space_view_blueprint: &mut SpaceViewBlueprint, space_view_state: &mut SpaceViewState, - space_view_highlights: &SpaceViewHighlights, + space_view_highlights: SpaceViewHighlights, ) { let Some(latest_at) = ctx.rec_cfg.time_ctrl.time_int() else { ui.centered_and_justified(|ui| { From f7adfa380ebaf30036870df259b8a98ef9532470 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Wed, 31 May 2023 22:54:02 +0200 Subject: [PATCH 04/39] entity depth offset is now a SceneContext --- Cargo.lock | 1 + crates/re_space_view_spatial/Cargo.toml | 1 + .../src/scene/contexts/depth_offsets.rs | 124 ++++++++++++++++++ .../src/scene/contexts/mod.rs | 3 + crates/re_space_view_spatial/src/scene/mod.rs | 123 ++--------------- 5 files changed, 139 insertions(+), 113 deletions(-) create mode 100644 crates/re_space_view_spatial/src/scene/contexts/depth_offsets.rs create mode 100644 crates/re_space_view_spatial/src/scene/contexts/mod.rs diff --git a/Cargo.lock b/Cargo.lock index f732eaafaa51..67b129dfd6cf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4288,6 +4288,7 @@ dependencies = [ "re_viewer_context", "serde", "smallvec", + "vec1", "wgpu", ] diff --git a/crates/re_space_view_spatial/Cargo.toml b/crates/re_space_view_spatial/Cargo.toml index aac374867e03..c079e5f38e11 100644 --- a/crates/re_space_view_spatial/Cargo.toml +++ b/crates/re_space_view_spatial/Cargo.toml @@ -42,4 +42,5 @@ macaw = { workspace = true, features = ["with_serde"] } nohash-hasher.workspace = true serde = "1" smallvec = { workspace = true, features = ["serde"] } +vec1.workspace = true wgpu.workspace = true diff --git a/crates/re_space_view_spatial/src/scene/contexts/depth_offsets.rs b/crates/re_space_view_spatial/src/scene/contexts/depth_offsets.rs new file mode 100644 index 000000000000..6f1fde8cf0c7 --- /dev/null +++ b/crates/re_space_view_spatial/src/scene/contexts/depth_offsets.rs @@ -0,0 +1,124 @@ +use std::collections::{BTreeMap, BTreeSet}; + +use nohash_hasher::IntMap; +use re_components::DrawOrder; +use re_log_types::{Component, EntityPathHash}; +use re_viewer_context::SceneContext; + +#[derive(Default)] +pub struct EntityDepthOffsets { + pub per_entity: IntMap, + pub box2d: re_renderer::DepthOffset, + pub lines2d: re_renderer::DepthOffset, + pub image: re_renderer::DepthOffset, + pub points: re_renderer::DepthOffset, +} + +impl SceneContext for EntityDepthOffsets { + fn archetype(&self) -> re_viewer_context::ArchetypeDefinition { + vec1::vec1![DrawOrder::name()] + } + + fn populate( + &mut self, + ctx: &mut re_viewer_context::ViewerContext<'_>, + query: &re_viewer_context::SceneQuery<'_>, + _space_view_state: &dyn re_viewer_context::SpaceViewState, + ) { + re_tracing::profile_function!(); + + #[derive(PartialEq, PartialOrd, Eq, Ord)] + enum DrawOrderTarget { + Entity(EntityPathHash), + DefaultBox2D, + DefaultLines2D, + DefaultImage, + DefaultPoints, + } + + let store = &ctx.store_db.entity_db.data_store; + + // Use a BTreeSet for entity hashes to get a stable order. + let mut entities_per_draw_order = BTreeMap::>::new(); + for (ent_path, _) in query.iter_entities() { + if let Some(draw_order) = store.query_latest_component::( + ent_path, + &ctx.rec_cfg.time_ctrl.current_query(), + ) { + entities_per_draw_order + .entry(draw_order) + .or_default() + .insert(DrawOrderTarget::Entity(ent_path.hash())); + } + } + + // Push in default draw orders. All of them using the none hash. + entities_per_draw_order.insert( + DrawOrder::DEFAULT_BOX2D, + [DrawOrderTarget::DefaultBox2D].into(), + ); + entities_per_draw_order.insert( + DrawOrder::DEFAULT_IMAGE, + [DrawOrderTarget::DefaultImage].into(), + ); + entities_per_draw_order.insert( + DrawOrder::DEFAULT_LINES2D, + [DrawOrderTarget::DefaultLines2D].into(), + ); + entities_per_draw_order.insert( + DrawOrder::DEFAULT_POINTS2D, + [DrawOrderTarget::DefaultPoints].into(), + ); + + // Determine re_renderer draw order from this. + // + // We give objects with the same `DrawOrder` still a different depth offset + // in order to avoid z-fighting artifacts when rendering in 3D. + // (for pure 2D this isn't necessary) + // + // We want to be as tightly around 0 as possible. + let num_entities_with_draw_order: usize = entities_per_draw_order + .values() + .map(|entities| entities.len()) + .sum(); + let mut draw_order = -((num_entities_with_draw_order / 2) as re_renderer::DepthOffset); + self.per_entity = entities_per_draw_order + .into_values() + .flat_map(|targets| { + targets + .into_iter() + .filter_map(|target| { + draw_order += 1; + match target { + DrawOrderTarget::Entity(entity) => Some((entity, draw_order)), + DrawOrderTarget::DefaultBox2D => { + self.box2d = draw_order; + None + } + DrawOrderTarget::DefaultLines2D => { + self.lines2d = draw_order; + None + } + DrawOrderTarget::DefaultImage => { + self.image = draw_order; + None + } + DrawOrderTarget::DefaultPoints => { + self.points = draw_order; + None + } + } + }) + .collect::>() + }) + .collect(); + } + + fn as_any(&self) -> &dyn std::any::Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn std::any::Any { + self + } +} diff --git a/crates/re_space_view_spatial/src/scene/contexts/mod.rs b/crates/re_space_view_spatial/src/scene/contexts/mod.rs new file mode 100644 index 000000000000..3691aef437c9 --- /dev/null +++ b/crates/re_space_view_spatial/src/scene/contexts/mod.rs @@ -0,0 +1,3 @@ +mod depth_offsets; + +pub use depth_offsets::EntityDepthOffsets; diff --git a/crates/re_space_view_spatial/src/scene/mod.rs b/crates/re_space_view_spatial/src/scene/mod.rs index 1cd6456508aa..b68a9ae60e3c 100644 --- a/crates/re_space_view_spatial/src/scene/mod.rs +++ b/crates/re_space_view_spatial/src/scene/mod.rs @@ -1,17 +1,16 @@ -use std::{ - collections::{BTreeMap, BTreeSet}, - sync::Arc, -}; +use std::sync::Arc; use ahash::HashMap; -use nohash_hasher::IntMap; use re_components::{ClassId, DecodedTensor, DrawOrder, InstanceKey, KeypointId}; use re_data_store::{EntityPath, InstancePathHash}; use re_log_types::EntityPathHash; use re_renderer::{renderer::TexturedRect, Color32, OutlineMaskPreference, Size}; -use re_viewer_context::SpaceViewHighlights; -use re_viewer_context::{auto_color, AnnotationMap, Annotations, SceneQuery, ViewerContext}; +use re_viewer_context::{ + auto_color, AnnotationMap, Annotations, EmptySpaceViewState, SceneQuery, ViewerContext, +}; +use re_viewer_context::{SceneContext, SpaceViewHighlights}; +mod contexts; use super::SpatialNavigationMode; use crate::{ @@ -26,6 +25,8 @@ pub use self::picking::{PickingContext, PickingHitType, PickingRayHit, PickingRe pub use self::primitives::SceneSpatialPrimitives; use elements::ScenePart; +use contexts::EntityDepthOffsets; + /// TODO(andreas): Scene should only care about converted rendering primitive. pub struct MeshSource { pub picking_instance_hash: InstancePathHash, @@ -101,15 +102,6 @@ pub struct SceneSpatial { pub type Keypoints = HashMap<(ClassId, i64), HashMap>; -#[derive(Default)] -pub struct EntityDepthOffsets { - pub per_entity: IntMap, - pub box2d: re_renderer::DepthOffset, - pub lines2d: re_renderer::DepthOffset, - pub image: re_renderer::DepthOffset, - pub points: re_renderer::DepthOffset, -} - impl EntityDepthOffsets { pub fn get(&self, ent_path: &EntityPath) -> Option { self.per_entity.get(&ent_path.hash()).cloned() @@ -128,102 +120,6 @@ impl SceneSpatial { } } - fn determine_depth_offsets( - ctx: &mut ViewerContext<'_>, - query: &SceneQuery<'_>, - ) -> EntityDepthOffsets { - re_tracing::profile_function!(); - - #[derive(PartialEq, PartialOrd, Eq, Ord)] - enum DrawOrderTarget { - Entity(EntityPathHash), - DefaultBox2D, - DefaultLines2D, - DefaultImage, - DefaultPoints, - } - - let store = &ctx.store_db.entity_db.data_store; - - // Use a BTreeSet for entity hashes to get a stable order. - let mut entities_per_draw_order = BTreeMap::>::new(); - for (ent_path, _) in query.iter_entities() { - if let Some(draw_order) = store.query_latest_component::( - ent_path, - &ctx.rec_cfg.time_ctrl.current_query(), - ) { - entities_per_draw_order - .entry(draw_order) - .or_default() - .insert(DrawOrderTarget::Entity(ent_path.hash())); - } - } - - // Push in default draw orders. All of them using the none hash. - entities_per_draw_order.insert( - DrawOrder::DEFAULT_BOX2D, - [DrawOrderTarget::DefaultBox2D].into(), - ); - entities_per_draw_order.insert( - DrawOrder::DEFAULT_IMAGE, - [DrawOrderTarget::DefaultImage].into(), - ); - entities_per_draw_order.insert( - DrawOrder::DEFAULT_LINES2D, - [DrawOrderTarget::DefaultLines2D].into(), - ); - entities_per_draw_order.insert( - DrawOrder::DEFAULT_POINTS2D, - [DrawOrderTarget::DefaultPoints].into(), - ); - - // Determine re_renderer draw order from this. - // - // We give objects with the same `DrawOrder` still a different depth offset - // in order to avoid z-fighting artifacts when rendering in 3D. - // (for pure 2D this isn't necessary) - // - // We want to be as tightly around 0 as possible. - let mut offsets = EntityDepthOffsets::default(); - let num_entities_with_draw_order: usize = entities_per_draw_order - .values() - .map(|entities| entities.len()) - .sum(); - let mut draw_order = -((num_entities_with_draw_order / 2) as re_renderer::DepthOffset); - offsets.per_entity = entities_per_draw_order - .into_values() - .flat_map(|targets| { - targets - .into_iter() - .filter_map(|target| { - draw_order += 1; - match target { - DrawOrderTarget::Entity(entity) => Some((entity, draw_order)), - DrawOrderTarget::DefaultBox2D => { - offsets.box2d = draw_order; - None - } - DrawOrderTarget::DefaultLines2D => { - offsets.lines2d = draw_order; - None - } - DrawOrderTarget::DefaultImage => { - offsets.image = draw_order; - None - } - DrawOrderTarget::DefaultPoints => { - offsets.points = draw_order; - None - } - } - }) - .collect::>() - }) - .collect(); - - offsets - } - /// Loads all 3D objects into the scene according to the given query. pub fn load( &mut self, @@ -254,7 +150,8 @@ impl SceneSpatial { &elements::CamerasPart, ]; - let depth_offsets = Self::determine_depth_offsets(ctx, query); + let mut depth_offsets = EntityDepthOffsets::default(); + depth_offsets.populate(ctx, query, &EmptySpaceViewState); for part in parts { part.load(self, ctx, query, transforms, highlights, &depth_offsets); From 3a48d8a8f1b368a599a05362dabd8f5b40b2db69 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 1 Jun 2023 11:09:19 +0200 Subject: [PATCH 05/39] transform cache is now a scene context --- crates/re_space_view_spatial/src/lib.rs | 4 +- .../src/scene/contexts/depth_offsets.rs | 7 +- .../src/scene/contexts/mod.rs | 2 + .../{ => scene/contexts}/transform_cache.rs | 76 +++++++++++++------ .../src/scene/elements/arrows3d.rs | 2 +- .../src/scene/elements/boxes2d.rs | 2 +- .../src/scene/elements/boxes3d.rs | 2 +- .../src/scene/elements/cameras.rs | 2 +- .../src/scene/elements/images.rs | 2 +- .../src/scene/elements/lines2d.rs | 2 +- .../src/scene/elements/lines3d.rs | 2 +- .../src/scene/elements/meshes.rs | 2 +- .../src/scene/elements/mod.rs | 2 +- .../src/scene/elements/points2d.rs | 2 +- .../src/scene/elements/points3d.rs | 2 +- crates/re_space_view_spatial/src/scene/mod.rs | 13 ++-- .../re_viewer_context/src/space_view/scene.rs | 16 ++-- crates/re_viewport/src/space_view.rs | 18 ++--- 18 files changed, 94 insertions(+), 64 deletions(-) rename crates/re_space_view_spatial/src/{ => scene/contexts}/transform_cache.rs (89%) diff --git a/crates/re_space_view_spatial/src/lib.rs b/crates/re_space_view_spatial/src/lib.rs index 49e97d6463ac..c19db1d78d2e 100644 --- a/crates/re_space_view_spatial/src/lib.rs +++ b/crates/re_space_view_spatial/src/lib.rs @@ -8,7 +8,6 @@ mod mesh_cache; mod mesh_loader; mod scene; mod space_camera_3d; -mod transform_cache; mod ui; mod ui_2d; mod ui_3d; @@ -16,6 +15,5 @@ mod ui_renderer_bridge; // TODO(andreas) should only make the main type public -pub use scene::SceneSpatial; -pub use transform_cache::{TransformCache, UnreachableTransform}; +pub use scene::{SceneSpatial, TransformCache, UnreachableTransform}; pub use ui::{SpatialNavigationMode, ViewSpatialState}; diff --git a/crates/re_space_view_spatial/src/scene/contexts/depth_offsets.rs b/crates/re_space_view_spatial/src/scene/contexts/depth_offsets.rs index 6f1fde8cf0c7..0c7d83f2c4dd 100644 --- a/crates/re_space_view_spatial/src/scene/contexts/depth_offsets.rs +++ b/crates/re_space_view_spatial/src/scene/contexts/depth_offsets.rs @@ -2,7 +2,7 @@ use std::collections::{BTreeMap, BTreeSet}; use nohash_hasher::IntMap; use re_components::DrawOrder; -use re_log_types::{Component, EntityPathHash}; +use re_log_types::{Component, ComponentName, EntityPathHash}; use re_viewer_context::SceneContext; #[derive(Default)] @@ -15,8 +15,8 @@ pub struct EntityDepthOffsets { } impl SceneContext for EntityDepthOffsets { - fn archetype(&self) -> re_viewer_context::ArchetypeDefinition { - vec1::vec1![DrawOrder::name()] + fn component_names(&self) -> Vec { + vec![DrawOrder::name()] } fn populate( @@ -24,6 +24,7 @@ impl SceneContext for EntityDepthOffsets { ctx: &mut re_viewer_context::ViewerContext<'_>, query: &re_viewer_context::SceneQuery<'_>, _space_view_state: &dyn re_viewer_context::SpaceViewState, + _space_view_root: &re_log_types::EntityPath, ) { re_tracing::profile_function!(); diff --git a/crates/re_space_view_spatial/src/scene/contexts/mod.rs b/crates/re_space_view_spatial/src/scene/contexts/mod.rs index 3691aef437c9..0ce9d167b3cc 100644 --- a/crates/re_space_view_spatial/src/scene/contexts/mod.rs +++ b/crates/re_space_view_spatial/src/scene/contexts/mod.rs @@ -1,3 +1,5 @@ mod depth_offsets; +mod transform_cache; pub use depth_offsets::EntityDepthOffsets; +pub use transform_cache::{TransformCache, UnreachableTransform}; diff --git a/crates/re_space_view_spatial/src/transform_cache.rs b/crates/re_space_view_spatial/src/scene/contexts/transform_cache.rs similarity index 89% rename from crates/re_space_view_spatial/src/transform_cache.rs rename to crates/re_space_view_spatial/src/scene/contexts/transform_cache.rs index 1fa1960ef7ca..bc4be22e1ac4 100644 --- a/crates/re_space_view_spatial/src/transform_cache.rs +++ b/crates/re_space_view_spatial/src/scene/contexts/transform_cache.rs @@ -1,9 +1,10 @@ use nohash_hasher::IntMap; + use re_arrow_store::LatestAtQuery; use re_components::{DisconnectedSpace, Pinhole, Transform3D}; -use re_data_store::{store_db::EntityDb, EntityPath, EntityPropertyMap, EntityTree}; -use re_log_types::EntityPathHash; -use re_viewer_context::TimeControl; +use re_data_store::{EntityPath, EntityPropertyMap, EntityTree}; +use re_log_types::{Component, ComponentName, EntityPathHash}; +use re_viewer_context::SceneContext; #[derive(Clone)] struct TransformInfo { @@ -39,6 +40,17 @@ pub struct TransformCache { first_unreachable_parent: Option<(EntityPath, UnreachableTransform)>, } +impl Default for TransformCache { + fn default() -> Self { + Self { + reference_path: EntityPath::root(), + transform_per_entity: Default::default(), + unreachable_descendants: Default::default(), + first_unreachable_parent: None, + } + } +} + #[derive(Clone, Copy)] pub enum UnreachableTransform { /// `SpaceInfoCollection` is outdated and can't find a corresponding space info for the given path. @@ -71,39 +83,47 @@ impl std::fmt::Display for UnreachableTransform { } } -impl TransformCache { +impl SceneContext for TransformCache { + fn component_names(&self) -> Vec { + vec![ + Transform3D::name(), + Pinhole::name(), + DisconnectedSpace::name(), + ] + } + /// Determines transforms for all entities relative to a space path which serves as the "reference". /// I.e. the resulting transforms are "reference from scene" /// /// This means that the entities in `reference_space` get the identity transform and all other /// entities are transformed relative to it. - pub fn determine_transforms( - entity_db: &EntityDb, - time_ctrl: &TimeControl, - space_path: &EntityPath, - entity_prop_map: &EntityPropertyMap, - ) -> Self { + fn populate( + &mut self, + ctx: &mut re_viewer_context::ViewerContext<'_>, + query: &re_viewer_context::SceneQuery<'_>, + _space_view_state: &dyn re_viewer_context::SpaceViewState, + space_view_root: &EntityPath, + ) { re_tracing::profile_function!(); - let mut transforms = TransformCache { - reference_path: space_path.clone(), - transform_per_entity: Default::default(), - unreachable_descendants: Default::default(), - first_unreachable_parent: None, - }; + let entity_db = &ctx.store_db.entity_db; + let time_ctrl = &ctx.rec_cfg.time_ctrl; + let entity_prop_map = query.entity_props_map; + + self.reference_path = space_view_root.clone(); // Find the entity path tree for the root. - let Some(mut current_tree) = &entity_db.tree.subtree(space_path) else { + let Some(mut current_tree) = &entity_db.tree.subtree(space_view_root) else { // It seems the space path is not part of the object tree! // This happens frequently when the viewer remembers space views from a previous run that weren't shown yet. // Naturally, in this case we don't have any transforms yet. - return transforms; + return; }; let query = time_ctrl.current_query(); // Child transforms of this space - transforms.gather_descendants_transforms( + self.gather_descendants_transforms( current_tree, &entity_db.data_store, &query, @@ -120,9 +140,9 @@ impl TransformCache { // Unlike not having the space path in the hierarchy, this should be impossible. re_log::error_once!( "Path {} is not part of the global Entity tree whereas its child {} is", - parent_path, space_path + parent_path, space_view_root ); - return transforms; + return; }; // Note that the transform at the reference is the first that needs to be inverted to "break out" of its hierarchy. @@ -137,7 +157,7 @@ impl TransformCache { &mut encountered_pinhole, ) { Err(unreachable_reason) => { - transforms.first_unreachable_parent = + self.first_unreachable_parent = Some((parent_tree.path.clone(), unreachable_reason)); break; } @@ -148,7 +168,7 @@ impl TransformCache { } // (skip over everything at and under `current_tree` automatically) - transforms.gather_descendants_transforms( + self.gather_descendants_transforms( parent_tree, &entity_db.data_store, &query, @@ -159,10 +179,18 @@ impl TransformCache { current_tree = parent_tree; } + } + + fn as_any(&self) -> &dyn std::any::Any { + self + } - transforms + fn as_any_mut(&mut self) -> &mut dyn std::any::Any { + self } +} +impl TransformCache { fn gather_descendants_transforms( &mut self, tree: &EntityTree, diff --git a/crates/re_space_view_spatial/src/scene/elements/arrows3d.rs b/crates/re_space_view_spatial/src/scene/elements/arrows3d.rs index ac86d98dab25..27b8e608e4d5 100644 --- a/crates/re_space_view_spatial/src/scene/elements/arrows3d.rs +++ b/crates/re_space_view_spatial/src/scene/elements/arrows3d.rs @@ -7,7 +7,7 @@ use re_viewer_context::{DefaultColor, SceneQuery, ViewerContext}; use crate::{ scene::{EntityDepthOffsets, SceneSpatial}, - transform_cache::TransformCache, + TransformCache, }; use super::{instance_key_to_picking_id, ScenePart}; diff --git a/crates/re_space_view_spatial/src/scene/elements/boxes2d.rs b/crates/re_space_view_spatial/src/scene/elements/boxes2d.rs index 7381fc50fdfc..2ad67843e254 100644 --- a/crates/re_space_view_spatial/src/scene/elements/boxes2d.rs +++ b/crates/re_space_view_spatial/src/scene/elements/boxes2d.rs @@ -10,7 +10,7 @@ use super::{instance_key_to_picking_id, instance_path_hash_for_picking, ScenePar use crate::{ scene::UiLabelTarget, scene::{EntityDepthOffsets, SceneSpatial, UiLabel}, - transform_cache::TransformCache, + TransformCache, }; pub struct Boxes2DPart; diff --git a/crates/re_space_view_spatial/src/scene/elements/boxes3d.rs b/crates/re_space_view_spatial/src/scene/elements/boxes3d.rs index 9da1fa0e11d5..38664df95562 100644 --- a/crates/re_space_view_spatial/src/scene/elements/boxes3d.rs +++ b/crates/re_space_view_spatial/src/scene/elements/boxes3d.rs @@ -10,7 +10,7 @@ use re_viewer_context::{SpaceViewHighlights, SpaceViewOutlineMasks}; use crate::{ scene::EntityDepthOffsets, scene::{SceneSpatial, UiLabel, UiLabelTarget}, - transform_cache::TransformCache, + TransformCache, }; use super::{instance_key_to_picking_id, instance_path_hash_for_picking, ScenePart}; diff --git a/crates/re_space_view_spatial/src/scene/elements/cameras.rs b/crates/re_space_view_spatial/src/scene/elements/cameras.rs index c9f9f2245fa2..d2232c5f8a4f 100644 --- a/crates/re_space_view_spatial/src/scene/elements/cameras.rs +++ b/crates/re_space_view_spatial/src/scene/elements/cameras.rs @@ -13,7 +13,7 @@ use crate::{ instance_hash_conversions::picking_layer_id_from_instance_path_hash, scene::{EntityDepthOffsets, SceneSpatial}, space_camera_3d::SpaceCamera3D, - transform_cache::TransformCache, + TransformCache, }; /// Determine the view coordinates (i.e.) the axis semantics. diff --git a/crates/re_space_view_spatial/src/scene/elements/images.rs b/crates/re_space_view_spatial/src/scene/elements/images.rs index d9acb21ab668..8d30793a6ad5 100644 --- a/crates/re_space_view_spatial/src/scene/elements/images.rs +++ b/crates/re_space_view_spatial/src/scene/elements/images.rs @@ -22,7 +22,7 @@ use re_viewer_context::{SpaceViewHighlights, SpaceViewOutlineMasks}; use crate::{ scene::{EntityDepthOffsets, Image, SceneSpatial}, - transform_cache::TransformCache, + TransformCache, }; use super::ScenePart; diff --git a/crates/re_space_view_spatial/src/scene/elements/lines2d.rs b/crates/re_space_view_spatial/src/scene/elements/lines2d.rs index 716f8f25c190..235ec741feba 100644 --- a/crates/re_space_view_spatial/src/scene/elements/lines2d.rs +++ b/crates/re_space_view_spatial/src/scene/elements/lines2d.rs @@ -7,7 +7,7 @@ use re_viewer_context::{SpaceViewHighlights, SpaceViewOutlineMasks}; use crate::{ scene::{EntityDepthOffsets, SceneSpatial}, - transform_cache::TransformCache, + TransformCache, }; use super::{instance_key_to_picking_id, ScenePart}; diff --git a/crates/re_space_view_spatial/src/scene/elements/lines3d.rs b/crates/re_space_view_spatial/src/scene/elements/lines3d.rs index 7798d09fa0a3..d6ff08363bfd 100644 --- a/crates/re_space_view_spatial/src/scene/elements/lines3d.rs +++ b/crates/re_space_view_spatial/src/scene/elements/lines3d.rs @@ -7,7 +7,7 @@ use re_viewer_context::{SpaceViewHighlights, SpaceViewOutlineMasks}; use crate::{ scene::{EntityDepthOffsets, SceneSpatial}, - transform_cache::TransformCache, + TransformCache, }; use super::{instance_key_to_picking_id, ScenePart}; diff --git a/crates/re_space_view_spatial/src/scene/elements/meshes.rs b/crates/re_space_view_spatial/src/scene/elements/meshes.rs index d026bbbf9396..be2b1a8dd115 100644 --- a/crates/re_space_view_spatial/src/scene/elements/meshes.rs +++ b/crates/re_space_view_spatial/src/scene/elements/meshes.rs @@ -7,7 +7,7 @@ use re_viewer_context::{DefaultColor, SceneQuery, ViewerContext}; use crate::{ mesh_cache::MeshCache, scene::{EntityDepthOffsets, MeshSource, SceneSpatial}, - transform_cache::TransformCache, + TransformCache, }; use super::{instance_path_hash_for_picking, ScenePart}; diff --git a/crates/re_space_view_spatial/src/scene/elements/mod.rs b/crates/re_space_view_spatial/src/scene/elements/mod.rs index 2a3c73d1c3ec..dd0be4b86b4e 100644 --- a/crates/re_space_view_spatial/src/scene/elements/mod.rs +++ b/crates/re_space_view_spatial/src/scene/elements/mod.rs @@ -34,7 +34,7 @@ use re_viewer_context::{ }; use super::{EntityDepthOffsets, SceneSpatial}; -use crate::{scene::Keypoints, transform_cache::TransformCache}; +use crate::{scene::Keypoints, TransformCache}; pub trait ScenePart { fn load( diff --git a/crates/re_space_view_spatial/src/scene/elements/points2d.rs b/crates/re_space_view_spatial/src/scene/elements/points2d.rs index 3fea718e45d0..0283f748d2d4 100644 --- a/crates/re_space_view_spatial/src/scene/elements/points2d.rs +++ b/crates/re_space_view_spatial/src/scene/elements/points2d.rs @@ -8,7 +8,7 @@ use re_viewer_context::{SpaceViewHighlights, SpaceViewOutlineMasks}; use crate::{ scene::{EntityDepthOffsets, SceneSpatial, UiLabel, UiLabelTarget}, - transform_cache::TransformCache, + TransformCache, }; use super::{ diff --git a/crates/re_space_view_spatial/src/scene/elements/points3d.rs b/crates/re_space_view_spatial/src/scene/elements/points3d.rs index aba799bad9fd..8229d415cdac 100644 --- a/crates/re_space_view_spatial/src/scene/elements/points3d.rs +++ b/crates/re_space_view_spatial/src/scene/elements/points3d.rs @@ -7,7 +7,7 @@ use re_viewer_context::{ResolvedAnnotationInfo, SceneQuery, ViewerContext}; use re_viewer_context::{SpaceViewHighlights, SpaceViewOutlineMasks}; use crate::{ - transform_cache::TransformCache, + TransformCache, { scene::UiLabelTarget, scene::{ diff --git a/crates/re_space_view_spatial/src/scene/mod.rs b/crates/re_space_view_spatial/src/scene/mod.rs index b68a9ae60e3c..3bbc40876d0e 100644 --- a/crates/re_space_view_spatial/src/scene/mod.rs +++ b/crates/re_space_view_spatial/src/scene/mod.rs @@ -13,9 +13,7 @@ use re_viewer_context::{SceneContext, SpaceViewHighlights}; mod contexts; use super::SpatialNavigationMode; -use crate::{ - mesh_loader::LoadedMesh, space_camera_3d::SpaceCamera3D, transform_cache::TransformCache, -}; +use crate::{mesh_loader::LoadedMesh, space_camera_3d::SpaceCamera3D}; mod elements; mod picking; @@ -26,6 +24,7 @@ pub use self::primitives::SceneSpatialPrimitives; use elements::ScenePart; use contexts::EntityDepthOffsets; +pub use contexts::{TransformCache, UnreachableTransform}; /// TODO(andreas): Scene should only care about converted rendering primitive. pub struct MeshSource { @@ -125,8 +124,8 @@ impl SceneSpatial { &mut self, ctx: &mut ViewerContext<'_>, query: &SceneQuery<'_>, - transforms: &TransformCache, highlights: &SpaceViewHighlights, + space_view_root: &EntityPath, ) { re_tracing::profile_function!(); @@ -151,10 +150,12 @@ impl SceneSpatial { ]; let mut depth_offsets = EntityDepthOffsets::default(); - depth_offsets.populate(ctx, query, &EmptySpaceViewState); + depth_offsets.populate(ctx, query, &EmptySpaceViewState, space_view_root); + let mut transforms = TransformCache::default(); + transforms.populate(ctx, query, &EmptySpaceViewState, space_view_root); for part in parts { - part.load(self, ctx, query, transforms, highlights, &depth_offsets); + part.load(self, ctx, query, &transforms, highlights, &depth_offsets); } self.primitives.any_outlines = highlights.any_outlines(); diff --git a/crates/re_viewer_context/src/space_view/scene.rs b/crates/re_viewer_context/src/space_view/scene.rs index 40f43b49faa2..0e8c8f9dd33e 100644 --- a/crates/re_viewer_context/src/space_view/scene.rs +++ b/crates/re_viewer_context/src/space_view/scene.rs @@ -1,6 +1,7 @@ use std::any::Any; use ahash::HashMap; +use re_log_types::{ComponentName, EntityPath}; use crate::{ArchetypeDefinition, SceneQuery, SpaceViewHighlights, SpaceViewState, ViewerContext}; @@ -129,17 +130,13 @@ impl Scene { self.elements.0.values().map(|e| e.archetype()).collect() } - /// List of all archetypes this scene queries for its context. - pub fn supported_context_archetypes(&self) -> Vec { - self.contexts.0.values().map(|e| e.archetype()).collect() - } - /// Populates the scene for a given query. pub fn populate( &mut self, ctx: &mut ViewerContext<'_>, query: &SceneQuery<'_>, space_view_state: &dyn SpaceViewState, + space_view_root: &EntityPath, highlights: SpaceViewHighlights, ) { re_tracing::profile_function!(); @@ -149,7 +146,7 @@ impl Scene { // TODO(andreas): Both loops are great candidates for parallelization. for context in self.contexts.0.values_mut() { // TODO(andreas): Restrict the query with the archetype somehow, ideally making it trivial to do the correct thing. - context.populate(ctx, query, space_view_state); + context.populate(ctx, query, space_view_state, space_view_root); } for element in self.elements.0.values_mut() { // TODO(andreas): Restrict the query with the archetype somehow, ideally making it trivial to do the correct thing. @@ -189,8 +186,10 @@ pub trait SceneElement: Any { } pub trait SceneContext: Any { - /// The archetype queried by this scene context. - fn archetype(&self) -> ArchetypeDefinition; + /// Scene contexts query loose components instead of archetypes in their populate method. + /// + /// This lists all components out that the context queries. + fn component_names(&self) -> Vec; /// Queries the data store and performs data conversions to make it ready for consumption by scene elements. fn populate( @@ -198,6 +197,7 @@ pub trait SceneContext: Any { ctx: &mut ViewerContext<'_>, query: &SceneQuery<'_>, space_view_state: &dyn SpaceViewState, + space_view_root: &EntityPath, ); /// Converts itself to a reference of [`Any`], which enables downcasting to concrete types. diff --git a/crates/re_viewport/src/space_view.rs b/crates/re_viewport/src/space_view.rs index 0f1617ff1ded..b8fe778f0052 100644 --- a/crates/re_viewport/src/space_view.rs +++ b/crates/re_viewport/src/space_view.rs @@ -2,7 +2,7 @@ use re_arrow_store::Timeline; use re_data_store::{EntityPath, EntityPropertyMap, EntityTree, InstancePath, TimeInt}; use re_renderer::ScreenshotProcessor; use re_space_view::{DataBlueprintTree, ScreenshotMode}; -use re_space_view_spatial::{SceneSpatial, TransformCache, ViewSpatialState}; +use re_space_view_spatial::{SceneSpatial, ViewSpatialState}; use re_viewer_context::{SpaceViewClassName, SpaceViewHighlights, SpaceViewId, ViewerContext}; use crate::{ @@ -208,7 +208,13 @@ impl SpaceViewBlueprint { space_view_class.prepare_populate(ctx, view_state.state.as_mut()); } let mut scene = space_view_class.new_scene(); - scene.populate(ctx, &query, view_state.state.as_ref(), highlights); + scene.populate( + ctx, + &query, + view_state.state.as_ref(), + &self.space_path, + highlights, + ); // TODO(andreas): Pass scene to renderer. // TODO(andreas): Setup re_renderer view. @@ -236,14 +242,8 @@ impl SpaceViewBlueprint { } ViewCategory::Spatial => { - let transforms = TransformCache::determine_transforms( - &ctx.store_db.entity_db, - &ctx.rec_cfg.time_ctrl, - &self.space_path, - self.data_blueprint.data_blueprints_projected(), - ); let mut scene = SceneSpatial::new(ctx.render_ctx); - scene.load(ctx, &query, &transforms, &highlights); + scene.load(ctx, &query, &highlights, &self.space_path); view_state .state_spatial .update_object_property_heuristics(ctx, &mut self.data_blueprint); From d9f4dbd06680fab3d0680c7cdf2a6ea9cfe38e60 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 1 Jun 2023 11:10:47 +0200 Subject: [PATCH 06/39] rename transform cache to transform context --- crates/re_space_view_spatial/src/lib.rs | 2 +- crates/re_space_view_spatial/src/scene/contexts/mod.rs | 4 ++-- .../contexts/{transform_cache.rs => transform_context.rs} | 8 ++++---- .../re_space_view_spatial/src/scene/elements/arrows3d.rs | 4 ++-- .../re_space_view_spatial/src/scene/elements/boxes2d.rs | 4 ++-- .../re_space_view_spatial/src/scene/elements/boxes3d.rs | 4 ++-- .../re_space_view_spatial/src/scene/elements/cameras.rs | 6 +++--- crates/re_space_view_spatial/src/scene/elements/images.rs | 8 ++++---- .../re_space_view_spatial/src/scene/elements/lines2d.rs | 4 ++-- .../re_space_view_spatial/src/scene/elements/lines3d.rs | 4 ++-- crates/re_space_view_spatial/src/scene/elements/meshes.rs | 4 ++-- crates/re_space_view_spatial/src/scene/elements/mod.rs | 4 ++-- .../re_space_view_spatial/src/scene/elements/points2d.rs | 4 ++-- .../re_space_view_spatial/src/scene/elements/points3d.rs | 4 ++-- crates/re_space_view_spatial/src/scene/mod.rs | 4 ++-- 15 files changed, 34 insertions(+), 34 deletions(-) rename crates/re_space_view_spatial/src/scene/contexts/{transform_cache.rs => transform_context.rs} (99%) diff --git a/crates/re_space_view_spatial/src/lib.rs b/crates/re_space_view_spatial/src/lib.rs index c19db1d78d2e..9ed3b0c61fd7 100644 --- a/crates/re_space_view_spatial/src/lib.rs +++ b/crates/re_space_view_spatial/src/lib.rs @@ -15,5 +15,5 @@ mod ui_renderer_bridge; // TODO(andreas) should only make the main type public -pub use scene::{SceneSpatial, TransformCache, UnreachableTransform}; +pub use scene::{SceneSpatial, TransformContext, UnreachableTransform}; pub use ui::{SpatialNavigationMode, ViewSpatialState}; diff --git a/crates/re_space_view_spatial/src/scene/contexts/mod.rs b/crates/re_space_view_spatial/src/scene/contexts/mod.rs index 0ce9d167b3cc..7270e362b062 100644 --- a/crates/re_space_view_spatial/src/scene/contexts/mod.rs +++ b/crates/re_space_view_spatial/src/scene/contexts/mod.rs @@ -1,5 +1,5 @@ mod depth_offsets; -mod transform_cache; +mod transform_context; pub use depth_offsets::EntityDepthOffsets; -pub use transform_cache::{TransformCache, UnreachableTransform}; +pub use transform_context::{TransformContext, UnreachableTransform}; diff --git a/crates/re_space_view_spatial/src/scene/contexts/transform_cache.rs b/crates/re_space_view_spatial/src/scene/contexts/transform_context.rs similarity index 99% rename from crates/re_space_view_spatial/src/scene/contexts/transform_cache.rs rename to crates/re_space_view_spatial/src/scene/contexts/transform_context.rs index bc4be22e1ac4..7bf7be9917c2 100644 --- a/crates/re_space_view_spatial/src/scene/contexts/transform_cache.rs +++ b/crates/re_space_view_spatial/src/scene/contexts/transform_context.rs @@ -26,7 +26,7 @@ struct TransformInfo { /// /// Should be recomputed every frame. #[derive(Clone)] -pub struct TransformCache { +pub struct TransformContext { /// All transforms provided are relative to this reference path. reference_path: EntityPath, @@ -40,7 +40,7 @@ pub struct TransformCache { first_unreachable_parent: Option<(EntityPath, UnreachableTransform)>, } -impl Default for TransformCache { +impl Default for TransformContext { fn default() -> Self { Self { reference_path: EntityPath::root(), @@ -83,7 +83,7 @@ impl std::fmt::Display for UnreachableTransform { } } -impl SceneContext for TransformCache { +impl SceneContext for TransformContext { fn component_names(&self) -> Vec { vec![ Transform3D::name(), @@ -190,7 +190,7 @@ impl SceneContext for TransformCache { } } -impl TransformCache { +impl TransformContext { fn gather_descendants_transforms( &mut self, tree: &EntityTree, diff --git a/crates/re_space_view_spatial/src/scene/elements/arrows3d.rs b/crates/re_space_view_spatial/src/scene/elements/arrows3d.rs index 27b8e608e4d5..b033e3e43ef1 100644 --- a/crates/re_space_view_spatial/src/scene/elements/arrows3d.rs +++ b/crates/re_space_view_spatial/src/scene/elements/arrows3d.rs @@ -7,7 +7,7 @@ use re_viewer_context::{DefaultColor, SceneQuery, ViewerContext}; use crate::{ scene::{EntityDepthOffsets, SceneSpatial}, - TransformCache, + TransformContext, }; use super::{instance_key_to_picking_id, ScenePart}; @@ -90,7 +90,7 @@ impl ScenePart for Arrows3DPart { scene: &mut SceneSpatial, ctx: &mut ViewerContext<'_>, query: &SceneQuery<'_>, - transforms: &TransformCache, + transforms: &TransformContext, highlights: &SpaceViewHighlights, _depth_offsets: &EntityDepthOffsets, ) { diff --git a/crates/re_space_view_spatial/src/scene/elements/boxes2d.rs b/crates/re_space_view_spatial/src/scene/elements/boxes2d.rs index 2ad67843e254..10cd852371e0 100644 --- a/crates/re_space_view_spatial/src/scene/elements/boxes2d.rs +++ b/crates/re_space_view_spatial/src/scene/elements/boxes2d.rs @@ -10,7 +10,7 @@ use super::{instance_key_to_picking_id, instance_path_hash_for_picking, ScenePar use crate::{ scene::UiLabelTarget, scene::{EntityDepthOffsets, SceneSpatial, UiLabel}, - TransformCache, + TransformContext, }; pub struct Boxes2DPart; @@ -102,7 +102,7 @@ impl ScenePart for Boxes2DPart { scene: &mut SceneSpatial, ctx: &mut ViewerContext<'_>, query: &SceneQuery<'_>, - transforms: &TransformCache, + transforms: &TransformContext, highlights: &SpaceViewHighlights, depth_offsets: &EntityDepthOffsets, ) { diff --git a/crates/re_space_view_spatial/src/scene/elements/boxes3d.rs b/crates/re_space_view_spatial/src/scene/elements/boxes3d.rs index 38664df95562..fa6520240b60 100644 --- a/crates/re_space_view_spatial/src/scene/elements/boxes3d.rs +++ b/crates/re_space_view_spatial/src/scene/elements/boxes3d.rs @@ -10,7 +10,7 @@ use re_viewer_context::{SpaceViewHighlights, SpaceViewOutlineMasks}; use crate::{ scene::EntityDepthOffsets, scene::{SceneSpatial, UiLabel, UiLabelTarget}, - TransformCache, + TransformContext, }; use super::{instance_key_to_picking_id, instance_path_hash_for_picking, ScenePart}; @@ -96,7 +96,7 @@ impl ScenePart for Boxes3DPart { scene: &mut SceneSpatial, ctx: &mut ViewerContext<'_>, query: &SceneQuery<'_>, - transforms: &TransformCache, + transforms: &TransformContext, highlights: &SpaceViewHighlights, _depth_offsets: &EntityDepthOffsets, ) { diff --git a/crates/re_space_view_spatial/src/scene/elements/cameras.rs b/crates/re_space_view_spatial/src/scene/elements/cameras.rs index d2232c5f8a4f..e5bc4603e2fd 100644 --- a/crates/re_space_view_spatial/src/scene/elements/cameras.rs +++ b/crates/re_space_view_spatial/src/scene/elements/cameras.rs @@ -13,7 +13,7 @@ use crate::{ instance_hash_conversions::picking_layer_id_from_instance_path_hash, scene::{EntityDepthOffsets, SceneSpatial}, space_camera_3d::SpaceCamera3D, - TransformCache, + TransformContext, }; /// Determine the view coordinates (i.e.) the axis semantics. @@ -57,7 +57,7 @@ impl CamerasPart { ent_path: &EntityPath, instance_key: InstanceKey, props: &EntityProperties, - transforms: &TransformCache, + transforms: &TransformContext, pinhole: Pinhole, view_coordinates: ViewCoordinates, entity_highlight: &SpaceViewOutlineMasks, @@ -184,7 +184,7 @@ impl ScenePart for CamerasPart { scene: &mut SceneSpatial, ctx: &mut ViewerContext<'_>, query: &SceneQuery<'_>, - transforms: &TransformCache, + transforms: &TransformContext, highlights: &SpaceViewHighlights, _depth_offsets: &EntityDepthOffsets, ) { diff --git a/crates/re_space_view_spatial/src/scene/elements/images.rs b/crates/re_space_view_spatial/src/scene/elements/images.rs index 8d30793a6ad5..5628099fd919 100644 --- a/crates/re_space_view_spatial/src/scene/elements/images.rs +++ b/crates/re_space_view_spatial/src/scene/elements/images.rs @@ -22,7 +22,7 @@ use re_viewer_context::{SpaceViewHighlights, SpaceViewOutlineMasks}; use crate::{ scene::{EntityDepthOffsets, Image, SceneSpatial}, - TransformCache, + TransformContext, }; use super::ScenePart; @@ -155,7 +155,7 @@ impl ImagesPart { entity_view: &EntityView, scene: &mut SceneSpatial, ctx: &mut ViewerContext<'_>, - transforms: &TransformCache, + transforms: &TransformContext, properties: &EntityProperties, ent_path: &EntityPath, world_from_obj: glam::Affine3A, @@ -252,7 +252,7 @@ impl ImagesPart { fn process_entity_view_as_depth_cloud( scene: &mut SceneSpatial, ctx: &mut ViewerContext<'_>, - transforms: &TransformCache, + transforms: &TransformContext, properties: &EntityProperties, tensor: &DecodedTensor, ent_path: &EntityPath, @@ -380,7 +380,7 @@ impl ScenePart for ImagesPart { scene: &mut SceneSpatial, ctx: &mut ViewerContext<'_>, query: &SceneQuery<'_>, - transforms: &TransformCache, + transforms: &TransformContext, highlights: &SpaceViewHighlights, depth_offsets: &EntityDepthOffsets, ) { diff --git a/crates/re_space_view_spatial/src/scene/elements/lines2d.rs b/crates/re_space_view_spatial/src/scene/elements/lines2d.rs index 235ec741feba..d4d4e6b450dc 100644 --- a/crates/re_space_view_spatial/src/scene/elements/lines2d.rs +++ b/crates/re_space_view_spatial/src/scene/elements/lines2d.rs @@ -7,7 +7,7 @@ use re_viewer_context::{SpaceViewHighlights, SpaceViewOutlineMasks}; use crate::{ scene::{EntityDepthOffsets, SceneSpatial}, - TransformCache, + TransformContext, }; use super::{instance_key_to_picking_id, ScenePart}; @@ -74,7 +74,7 @@ impl ScenePart for Lines2DPart { scene: &mut SceneSpatial, ctx: &mut ViewerContext<'_>, query: &SceneQuery<'_>, - transforms: &TransformCache, + transforms: &TransformContext, highlights: &SpaceViewHighlights, depth_offsets: &EntityDepthOffsets, ) { diff --git a/crates/re_space_view_spatial/src/scene/elements/lines3d.rs b/crates/re_space_view_spatial/src/scene/elements/lines3d.rs index d6ff08363bfd..ad9a25f6ac36 100644 --- a/crates/re_space_view_spatial/src/scene/elements/lines3d.rs +++ b/crates/re_space_view_spatial/src/scene/elements/lines3d.rs @@ -7,7 +7,7 @@ use re_viewer_context::{SpaceViewHighlights, SpaceViewOutlineMasks}; use crate::{ scene::{EntityDepthOffsets, SceneSpatial}, - TransformCache, + TransformContext, }; use super::{instance_key_to_picking_id, ScenePart}; @@ -73,7 +73,7 @@ impl ScenePart for Lines3DPart { scene: &mut SceneSpatial, ctx: &mut ViewerContext<'_>, query: &SceneQuery<'_>, - transforms: &TransformCache, + transforms: &TransformContext, highlights: &SpaceViewHighlights, _depth_offsets: &EntityDepthOffsets, ) { diff --git a/crates/re_space_view_spatial/src/scene/elements/meshes.rs b/crates/re_space_view_spatial/src/scene/elements/meshes.rs index be2b1a8dd115..f77431604463 100644 --- a/crates/re_space_view_spatial/src/scene/elements/meshes.rs +++ b/crates/re_space_view_spatial/src/scene/elements/meshes.rs @@ -7,7 +7,7 @@ use re_viewer_context::{DefaultColor, SceneQuery, ViewerContext}; use crate::{ mesh_cache::MeshCache, scene::{EntityDepthOffsets, MeshSource, SceneSpatial}, - TransformCache, + TransformContext, }; use super::{instance_path_hash_for_picking, ScenePart}; @@ -66,7 +66,7 @@ impl ScenePart for MeshPart { scene: &mut SceneSpatial, ctx: &mut ViewerContext<'_>, query: &SceneQuery<'_>, - transforms: &TransformCache, + transforms: &TransformContext, highlights: &SpaceViewHighlights, _depth_offsets: &EntityDepthOffsets, ) { diff --git a/crates/re_space_view_spatial/src/scene/elements/mod.rs b/crates/re_space_view_spatial/src/scene/elements/mod.rs index dd0be4b86b4e..59e287f28c34 100644 --- a/crates/re_space_view_spatial/src/scene/elements/mod.rs +++ b/crates/re_space_view_spatial/src/scene/elements/mod.rs @@ -34,7 +34,7 @@ use re_viewer_context::{ }; use super::{EntityDepthOffsets, SceneSpatial}; -use crate::{scene::Keypoints, TransformCache}; +use crate::{scene::Keypoints, TransformContext}; pub trait ScenePart { fn load( @@ -42,7 +42,7 @@ pub trait ScenePart { scene: &mut SceneSpatial, ctx: &mut ViewerContext<'_>, query: &SceneQuery<'_>, - transforms: &TransformCache, + transforms: &TransformContext, highlights: &SpaceViewHighlights, depth_offsets: &EntityDepthOffsets, ); diff --git a/crates/re_space_view_spatial/src/scene/elements/points2d.rs b/crates/re_space_view_spatial/src/scene/elements/points2d.rs index 0283f748d2d4..ca62484479a6 100644 --- a/crates/re_space_view_spatial/src/scene/elements/points2d.rs +++ b/crates/re_space_view_spatial/src/scene/elements/points2d.rs @@ -8,7 +8,7 @@ use re_viewer_context::{SpaceViewHighlights, SpaceViewOutlineMasks}; use crate::{ scene::{EntityDepthOffsets, SceneSpatial, UiLabel, UiLabelTarget}, - TransformCache, + TransformContext, }; use super::{ @@ -171,7 +171,7 @@ impl ScenePart for Points2DPart { scene: &mut SceneSpatial, ctx: &mut ViewerContext<'_>, query: &SceneQuery<'_>, - transforms: &TransformCache, + transforms: &TransformContext, highlights: &SpaceViewHighlights, depth_offsets: &EntityDepthOffsets, ) { diff --git a/crates/re_space_view_spatial/src/scene/elements/points3d.rs b/crates/re_space_view_spatial/src/scene/elements/points3d.rs index 8229d415cdac..9acd05c6b288 100644 --- a/crates/re_space_view_spatial/src/scene/elements/points3d.rs +++ b/crates/re_space_view_spatial/src/scene/elements/points3d.rs @@ -7,7 +7,7 @@ use re_viewer_context::{ResolvedAnnotationInfo, SceneQuery, ViewerContext}; use re_viewer_context::{SpaceViewHighlights, SpaceViewOutlineMasks}; use crate::{ - TransformCache, + TransformContext, { scene::UiLabelTarget, scene::{ @@ -174,7 +174,7 @@ impl ScenePart for Points3DPart { scene: &mut SceneSpatial, ctx: &mut ViewerContext<'_>, query: &SceneQuery<'_>, - transforms: &TransformCache, + transforms: &TransformContext, highlights: &SpaceViewHighlights, _depth_offsets: &EntityDepthOffsets, ) { diff --git a/crates/re_space_view_spatial/src/scene/mod.rs b/crates/re_space_view_spatial/src/scene/mod.rs index 3bbc40876d0e..35b456cd1da9 100644 --- a/crates/re_space_view_spatial/src/scene/mod.rs +++ b/crates/re_space_view_spatial/src/scene/mod.rs @@ -24,7 +24,7 @@ pub use self::primitives::SceneSpatialPrimitives; use elements::ScenePart; use contexts::EntityDepthOffsets; -pub use contexts::{TransformCache, UnreachableTransform}; +pub use contexts::{TransformContext, UnreachableTransform}; /// TODO(andreas): Scene should only care about converted rendering primitive. pub struct MeshSource { @@ -151,7 +151,7 @@ impl SceneSpatial { let mut depth_offsets = EntityDepthOffsets::default(); depth_offsets.populate(ctx, query, &EmptySpaceViewState, space_view_root); - let mut transforms = TransformCache::default(); + let mut transforms = TransformContext::default(); transforms.populate(ctx, query, &EmptySpaceViewState, space_view_root); for part in parts { From 4586c9009dd0672b2c720b22e9acdf17f48ece96 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 1 Jun 2023 11:25:10 +0200 Subject: [PATCH 07/39] scene query now knows the scene root, simplifying some interfaces --- crates/re_data_ui/src/lib.rs | 1 + .../src/scene/contexts/depth_offsets.rs | 1 - .../src/scene/contexts/transform_context.rs | 11 +++++------ crates/re_space_view_spatial/src/scene/mod.rs | 5 ++--- crates/re_viewer_context/src/lib.rs | 6 ++---- crates/re_viewer_context/src/space_view/mod.rs | 4 +++- crates/re_viewer_context/src/space_view/scene.rs | 6 ++---- .../src/{ => space_view}/scene_query.rs | 11 +++++++++++ crates/re_viewport/src/space_view.rs | 11 +++-------- 9 files changed, 29 insertions(+), 27 deletions(-) rename crates/re_viewer_context/src/{ => space_view}/scene_query.rs (68%) diff --git a/crates/re_data_ui/src/lib.rs b/crates/re_data_ui/src/lib.rs index 6ff26917fe23..80ee07fb0dcb 100644 --- a/crates/re_data_ui/src/lib.rs +++ b/crates/re_data_ui/src/lib.rs @@ -159,6 +159,7 @@ pub fn annotations( let entity_paths: nohash_hasher::IntSet<_> = std::iter::once(entity_path.clone()).collect(); let entity_props_map = re_data_store::EntityPropertyMap::default(); let scene_query = re_viewer_context::SceneQuery { + space_path: entity_path, entity_paths: &entity_paths, timeline: query.timeline, latest_at: query.at, diff --git a/crates/re_space_view_spatial/src/scene/contexts/depth_offsets.rs b/crates/re_space_view_spatial/src/scene/contexts/depth_offsets.rs index 0c7d83f2c4dd..abfc94e08453 100644 --- a/crates/re_space_view_spatial/src/scene/contexts/depth_offsets.rs +++ b/crates/re_space_view_spatial/src/scene/contexts/depth_offsets.rs @@ -24,7 +24,6 @@ impl SceneContext for EntityDepthOffsets { ctx: &mut re_viewer_context::ViewerContext<'_>, query: &re_viewer_context::SceneQuery<'_>, _space_view_state: &dyn re_viewer_context::SpaceViewState, - _space_view_root: &re_log_types::EntityPath, ) { re_tracing::profile_function!(); diff --git a/crates/re_space_view_spatial/src/scene/contexts/transform_context.rs b/crates/re_space_view_spatial/src/scene/contexts/transform_context.rs index 7bf7be9917c2..cff0a35f92b7 100644 --- a/crates/re_space_view_spatial/src/scene/contexts/transform_context.rs +++ b/crates/re_space_view_spatial/src/scene/contexts/transform_context.rs @@ -100,20 +100,19 @@ impl SceneContext for TransformContext { fn populate( &mut self, ctx: &mut re_viewer_context::ViewerContext<'_>, - query: &re_viewer_context::SceneQuery<'_>, + scene_query: &re_viewer_context::SceneQuery<'_>, _space_view_state: &dyn re_viewer_context::SpaceViewState, - space_view_root: &EntityPath, ) { re_tracing::profile_function!(); let entity_db = &ctx.store_db.entity_db; let time_ctrl = &ctx.rec_cfg.time_ctrl; - let entity_prop_map = query.entity_props_map; + let entity_prop_map = scene_query.entity_props_map; - self.reference_path = space_view_root.clone(); + self.reference_path = scene_query.space_path.clone(); // Find the entity path tree for the root. - let Some(mut current_tree) = &entity_db.tree.subtree(space_view_root) else { + let Some(mut current_tree) = &entity_db.tree.subtree(scene_query.space_path) else { // It seems the space path is not part of the object tree! // This happens frequently when the viewer remembers space views from a previous run that weren't shown yet. // Naturally, in this case we don't have any transforms yet. @@ -140,7 +139,7 @@ impl SceneContext for TransformContext { // Unlike not having the space path in the hierarchy, this should be impossible. re_log::error_once!( "Path {} is not part of the global Entity tree whereas its child {} is", - parent_path, space_view_root + parent_path, scene_query.space_path ); return; }; diff --git a/crates/re_space_view_spatial/src/scene/mod.rs b/crates/re_space_view_spatial/src/scene/mod.rs index 35b456cd1da9..83291300afe0 100644 --- a/crates/re_space_view_spatial/src/scene/mod.rs +++ b/crates/re_space_view_spatial/src/scene/mod.rs @@ -125,7 +125,6 @@ impl SceneSpatial { ctx: &mut ViewerContext<'_>, query: &SceneQuery<'_>, highlights: &SpaceViewHighlights, - space_view_root: &EntityPath, ) { re_tracing::profile_function!(); @@ -150,9 +149,9 @@ impl SceneSpatial { ]; let mut depth_offsets = EntityDepthOffsets::default(); - depth_offsets.populate(ctx, query, &EmptySpaceViewState, space_view_root); + depth_offsets.populate(ctx, query, &EmptySpaceViewState); let mut transforms = TransformContext::default(); - transforms.populate(ctx, query, &EmptySpaceViewState, space_view_root); + transforms.populate(ctx, query, &EmptySpaceViewState); for part in parts { part.load(self, ctx, query, &transforms, highlights, &depth_offsets); diff --git a/crates/re_viewer_context/src/lib.rs b/crates/re_viewer_context/src/lib.rs index abf947b7ff84..9ae5be3045cd 100644 --- a/crates/re_viewer_context/src/lib.rs +++ b/crates/re_viewer_context/src/lib.rs @@ -7,7 +7,6 @@ mod app_options; mod caches; mod component_ui_registry; mod item; -mod scene_query; mod selection_history; mod selection_state; mod space_view; @@ -26,15 +25,14 @@ pub use app_options::AppOptions; pub use caches::{Cache, Caches}; pub use component_ui_registry::{ComponentUiRegistry, UiVerbosity}; pub use item::{Item, ItemCollection}; -pub use scene_query::SceneQuery; pub use selection_history::SelectionHistory; pub use selection_state::{ HoverHighlight, HoveredSpace, InteractionHighlight, SelectionHighlight, SelectionState, }; pub use space_view::{ ArchetypeDefinition, EmptySpaceViewState, Scene, SceneContext, SceneContextCollection, - SceneElement, SceneElementCollection, SceneElementImpl, SpaceViewClass, SpaceViewClassImpl, - SpaceViewClassName, SpaceViewClassRegistry, SpaceViewClassRegistryError, + SceneElement, SceneElementCollection, SceneElementImpl, SceneQuery, SpaceViewClass, + SpaceViewClassImpl, SpaceViewClassName, SpaceViewClassRegistry, SpaceViewClassRegistryError, SpaceViewEntityHighlight, SpaceViewHighlights, SpaceViewOutlineMasks, SpaceViewState, }; pub use tensor::{TensorDecodeCache, TensorStats, TensorStatsCache}; diff --git a/crates/re_viewer_context/src/space_view/mod.rs b/crates/re_viewer_context/src/space_view/mod.rs index 81feb7ed835e..0c1097f853e7 100644 --- a/crates/re_viewer_context/src/space_view/mod.rs +++ b/crates/re_viewer_context/src/space_view/mod.rs @@ -3,10 +3,11 @@ //! Defines a framework & utilities for defining classes of space views in the Rerun viewer. //! Does not implement any concrete space view. -// TODO(andreas): Can we move some of this to the `re_space_view` crate? +// TODO(andreas): Can we move some of these to the `re_space_view` crate? mod highlights; mod scene; mod scene_element_impl; +mod scene_query; mod space_view_class; mod space_view_class_impl; mod space_view_class_registry; @@ -16,6 +17,7 @@ pub use scene::{ Scene, SceneContext, SceneContextCollection, SceneElement, SceneElementCollection, }; pub use scene_element_impl::SceneElementImpl; +pub use scene_query::SceneQuery; pub use space_view_class::{ ArchetypeDefinition, SpaceViewClass, SpaceViewClassName, SpaceViewState, }; diff --git a/crates/re_viewer_context/src/space_view/scene.rs b/crates/re_viewer_context/src/space_view/scene.rs index 0e8c8f9dd33e..e41654eddfc0 100644 --- a/crates/re_viewer_context/src/space_view/scene.rs +++ b/crates/re_viewer_context/src/space_view/scene.rs @@ -1,7 +1,7 @@ use std::any::Any; use ahash::HashMap; -use re_log_types::{ComponentName, EntityPath}; +use re_log_types::ComponentName; use crate::{ArchetypeDefinition, SceneQuery, SpaceViewHighlights, SpaceViewState, ViewerContext}; @@ -136,7 +136,6 @@ impl Scene { ctx: &mut ViewerContext<'_>, query: &SceneQuery<'_>, space_view_state: &dyn SpaceViewState, - space_view_root: &EntityPath, highlights: SpaceViewHighlights, ) { re_tracing::profile_function!(); @@ -146,7 +145,7 @@ impl Scene { // TODO(andreas): Both loops are great candidates for parallelization. for context in self.contexts.0.values_mut() { // TODO(andreas): Restrict the query with the archetype somehow, ideally making it trivial to do the correct thing. - context.populate(ctx, query, space_view_state, space_view_root); + context.populate(ctx, query, space_view_state); } for element in self.elements.0.values_mut() { // TODO(andreas): Restrict the query with the archetype somehow, ideally making it trivial to do the correct thing. @@ -197,7 +196,6 @@ pub trait SceneContext: Any { ctx: &mut ViewerContext<'_>, query: &SceneQuery<'_>, space_view_state: &dyn SpaceViewState, - space_view_root: &EntityPath, ); /// Converts itself to a reference of [`Any`], which enables downcasting to concrete types. diff --git a/crates/re_viewer_context/src/scene_query.rs b/crates/re_viewer_context/src/space_view/scene_query.rs similarity index 68% rename from crates/re_viewer_context/src/scene_query.rs rename to crates/re_viewer_context/src/space_view/scene_query.rs index a790973b6871..0d0a1e326cf2 100644 --- a/crates/re_viewer_context/src/scene_query.rs +++ b/crates/re_viewer_context/src/space_view/scene_query.rs @@ -3,9 +3,20 @@ use nohash_hasher::IntSet; use re_data_store::{EntityPath, EntityProperties, EntityPropertyMap, TimeInt, Timeline}; pub struct SceneQuery<'s> { + /// The root of the space in which context the query happens. + pub space_path: &'s EntityPath, + + /// All queried entities. pub entity_paths: &'s IntSet, + + /// The timeline we're on. pub timeline: Timeline, + + /// The time on the timeline we're currently at. pub latest_at: TimeInt, + + /// The entity properties for all queried entities. + /// TODO(jleibs/wumpf): This will be replaced by blueprint queries. pub entity_props_map: &'s EntityPropertyMap, } diff --git a/crates/re_viewport/src/space_view.rs b/crates/re_viewport/src/space_view.rs index b8fe778f0052..0ceb44be0628 100644 --- a/crates/re_viewport/src/space_view.rs +++ b/crates/re_viewport/src/space_view.rs @@ -196,6 +196,7 @@ impl SpaceViewBlueprint { } let query = re_viewer_context::SceneQuery { + space_path: &self.space_path, entity_paths: self.data_blueprint.entity_paths(), timeline: *ctx.rec_cfg.time_ctrl.timeline(), latest_at, @@ -208,13 +209,7 @@ impl SpaceViewBlueprint { space_view_class.prepare_populate(ctx, view_state.state.as_mut()); } let mut scene = space_view_class.new_scene(); - scene.populate( - ctx, - &query, - view_state.state.as_ref(), - &self.space_path, - highlights, - ); + scene.populate(ctx, &query, view_state.state.as_ref(), highlights); // TODO(andreas): Pass scene to renderer. // TODO(andreas): Setup re_renderer view. @@ -243,7 +238,7 @@ impl SpaceViewBlueprint { ViewCategory::Spatial => { let mut scene = SceneSpatial::new(ctx.render_ctx); - scene.load(ctx, &query, &highlights, &self.space_path); + scene.load(ctx, &query, &highlights); view_state .state_spatial .update_object_property_heuristics(ctx, &mut self.data_blueprint); From 901df1a6a705f3d8a2fb9b09d337a716224fa180 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 1 Jun 2023 12:56:23 +0200 Subject: [PATCH 08/39] scene element now return drawables --- Cargo.lock | 3 +++ crates/re_space_view_spatial/src/scene/elements/mod.rs | 2 +- .../re_space_view_spatial/src/scene/elements/points2d.rs | 6 +++--- crates/re_space_view_spatial/src/scene/mod.rs | 2 +- crates/re_space_view_text/Cargo.toml | 1 + crates/re_space_view_text/src/scene_element.rs | 6 ++++-- crates/re_space_view_text_box/Cargo.toml | 1 + crates/re_space_view_text_box/src/scene_element.rs | 3 ++- crates/re_viewer_context/Cargo.toml | 1 + crates/re_viewer_context/src/space_view/scene.rs | 2 +- .../re_viewer_context/src/space_view/scene_element_impl.rs | 7 ++++--- 11 files changed, 22 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 67b129dfd6cf..9a4b6ce5fcc6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4305,6 +4305,7 @@ dependencies = [ "re_log", "re_log_types", "re_query", + "re_renderer", "re_tracing", "re_ui", "re_viewer_context", @@ -4320,6 +4321,7 @@ dependencies = [ "re_components", "re_log", "re_query", + "re_renderer", "re_ui", "re_viewer_context", "vec1", @@ -4487,6 +4489,7 @@ dependencies = [ "serde", "slotmap", "thiserror", + "tinyvec", "uuid", "vec1", "wgpu", diff --git a/crates/re_space_view_spatial/src/scene/elements/mod.rs b/crates/re_space_view_spatial/src/scene/elements/mod.rs index 59e287f28c34..a242046abe1b 100644 --- a/crates/re_space_view_spatial/src/scene/elements/mod.rs +++ b/crates/re_space_view_spatial/src/scene/elements/mod.rs @@ -23,7 +23,7 @@ pub(crate) use lines2d::Lines2DPart; pub(crate) use lines3d::Lines3DPart; pub(crate) use meshes::MeshPart; -pub(crate) use points2d::Points2DPart; +pub(crate) use points2d::Points2DSceneElement; pub(crate) use points3d::Points3DPart; use re_components::{ClassId, ColorRGBA, KeypointId, Radius}; diff --git a/crates/re_space_view_spatial/src/scene/elements/points2d.rs b/crates/re_space_view_spatial/src/scene/elements/points2d.rs index ca62484479a6..6ee0aa48205a 100644 --- a/crates/re_space_view_spatial/src/scene/elements/points2d.rs +++ b/crates/re_space_view_spatial/src/scene/elements/points2d.rs @@ -16,12 +16,12 @@ use super::{ process_colors, process_radii, ScenePart, }; -pub struct Points2DPart { +pub struct Points2DSceneElement { /// If the number of points in the batch is > max_labels, don't render point labels. pub(crate) max_labels: usize, } -impl Points2DPart { +impl Points2DSceneElement { fn process_labels<'a>( entity_view: &'a EntityView, instance_path_hashes: &'a [InstancePathHash], @@ -165,7 +165,7 @@ impl Points2DPart { } } -impl ScenePart for Points2DPart { +impl ScenePart for Points2DSceneElement { fn load( &self, scene: &mut SceneSpatial, diff --git a/crates/re_space_view_spatial/src/scene/mod.rs b/crates/re_space_view_spatial/src/scene/mod.rs index 83291300afe0..9b5bac38f3b4 100644 --- a/crates/re_space_view_spatial/src/scene/mod.rs +++ b/crates/re_space_view_spatial/src/scene/mod.rs @@ -143,7 +143,7 @@ impl SceneSpatial { // -- // Note: Lines2DPart handles both Segments and LinesPaths since they are unified on the logging-side. &elements::Lines2DPart, - &elements::Points2DPart { max_labels: 10 }, + &elements::Points2DSceneElement { max_labels: 10 }, // --- &elements::CamerasPart, ]; diff --git a/crates/re_space_view_text/Cargo.toml b/crates/re_space_view_text/Cargo.toml index 840c4583481b..4286de0ec950 100644 --- a/crates/re_space_view_text/Cargo.toml +++ b/crates/re_space_view_text/Cargo.toml @@ -23,6 +23,7 @@ re_data_ui.workspace = true re_log_types.workspace = true re_log.workspace = true re_query.workspace = true +re_renderer.workspace = true re_tracing.workspace = true re_ui.workspace = true re_viewer_context.workspace = true diff --git a/crates/re_space_view_text/src/scene_element.rs b/crates/re_space_view_text/src/scene_element.rs index b13a3aae140a..1c1040c7c2c3 100644 --- a/crates/re_space_view_text/src/scene_element.rs +++ b/crates/re_space_view_text/src/scene_element.rs @@ -46,7 +46,7 @@ impl SceneElementImpl for SceneText { state: &TextSpaceViewState, _contexts: &SceneContextCollection, _highlights: &SpaceViewHighlights, - ) { + ) -> Vec { let store = &ctx.store_db.entity_db.data_store; for entity_path in query.entity_paths { @@ -55,7 +55,7 @@ impl SceneElementImpl for SceneText { // Early filtering: if we're not showing it the view, there isn't much point // in querying it to begin with... at least for now. if !state.filters.is_entity_path_visible(ent_path) { - return; + continue; } let query = re_arrow_store::RangeQuery::new( @@ -103,5 +103,7 @@ impl SceneElementImpl for SceneText { } } } + + Vec::new() } } diff --git a/crates/re_space_view_text_box/Cargo.toml b/crates/re_space_view_text_box/Cargo.toml index 5da18e5dda8b..cc2381526ea5 100644 --- a/crates/re_space_view_text_box/Cargo.toml +++ b/crates/re_space_view_text_box/Cargo.toml @@ -20,6 +20,7 @@ re_arrow_store.workspace = true re_components.workspace = true re_log.workspace = true re_query.workspace = true +re_renderer.workspace = true re_ui.workspace = true re_viewer_context.workspace = true diff --git a/crates/re_space_view_text_box/src/scene_element.rs b/crates/re_space_view_text_box/src/scene_element.rs index 5ef8c7b9a505..08a3ac091d46 100644 --- a/crates/re_space_view_text_box/src/scene_element.rs +++ b/crates/re_space_view_text_box/src/scene_element.rs @@ -35,7 +35,7 @@ impl SceneElementImpl for SceneTextBox { _space_view_state: &Self::State, _contexts: &SceneContextCollection, _highlights: &SpaceViewHighlights, - ) { + ) -> Vec { let store = &ctx.store_db.entity_db.data_store; for (ent_path, props) in query.iter_entities() { @@ -58,5 +58,6 @@ impl SceneElementImpl for SceneTextBox { } } } + Vec::new() } } diff --git a/crates/re_viewer_context/Cargo.toml b/crates/re_viewer_context/Cargo.toml index 0701bc37c1aa..40076172a15b 100644 --- a/crates/re_viewer_context/Cargo.toml +++ b/crates/re_viewer_context/Cargo.toml @@ -42,6 +42,7 @@ nohash-hasher.workspace = true serde = "1" slotmap.workspace = true thiserror.workspace = true +tinyvec.workspace = true uuid = { version = "1.1", features = ["serde", "v4", "js"] } vec1.workspace = true wgpu.workspace = true diff --git a/crates/re_viewer_context/src/space_view/scene.rs b/crates/re_viewer_context/src/space_view/scene.rs index e41654eddfc0..7a5b7795be08 100644 --- a/crates/re_viewer_context/src/space_view/scene.rs +++ b/crates/re_viewer_context/src/space_view/scene.rs @@ -175,7 +175,7 @@ pub trait SceneElement: Any { space_view_state: &dyn SpaceViewState, contexts: &SceneContextCollection, highlights: &SpaceViewHighlights, - ); + ) -> Vec; /// Converts itself to a reference of [`Any`], which enables downcasting to concrete types. fn as_any(&self) -> &dyn std::any::Any; diff --git a/crates/re_viewer_context/src/space_view/scene_element_impl.rs b/crates/re_viewer_context/src/space_view/scene_element_impl.rs index 33975d4e8e9a..f4627733eb41 100644 --- a/crates/re_viewer_context/src/space_view/scene_element_impl.rs +++ b/crates/re_viewer_context/src/space_view/scene_element_impl.rs @@ -22,7 +22,7 @@ pub trait SceneElementImpl { space_view_state: &Self::State, contexts: &SceneContextCollection, highlights: &SpaceViewHighlights, - ); + ) -> Vec; } impl SceneElement for T { @@ -37,11 +37,12 @@ impl SceneElement for T { space_view_state: &dyn SpaceViewState, contexts: &SceneContextCollection, highlights: &SpaceViewHighlights, - ) { + ) -> Vec { if let Some(state) = space_view_state.as_any().downcast_ref() { - self.populate(ctx, query, state, contexts, highlights); + self.populate(ctx, query, state, contexts, highlights) } else { re_log::error_once!("Incorrect type of space view state."); + Vec::new() } } From 0962fbedd6e735678dfcf74fd33aee5c3f99eef4 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 1 Jun 2023 16:58:41 +0200 Subject: [PATCH 09/39] 2d point scene part is now a SpatialSceneElement --- .../src/scene/contexts/annotation_context.rs | 29 +++ .../src/scene/contexts/mod.rs | 2 + .../src/scene/elements/points2d.rs | 173 ++++++++++-------- .../src/scene/elements/points3d.rs | 3 +- crates/re_space_view_spatial/src/scene/mod.rs | 92 +++++----- .../src/scene/spatial_scene_element.rs | 172 +++++++++++++++++ crates/re_viewer_context/src/lib.rs | 7 +- .../re_viewer_context/src/space_view/mod.rs | 1 + 8 files changed, 357 insertions(+), 122 deletions(-) create mode 100644 crates/re_space_view_spatial/src/scene/contexts/annotation_context.rs create mode 100644 crates/re_space_view_spatial/src/scene/spatial_scene_element.rs diff --git a/crates/re_space_view_spatial/src/scene/contexts/annotation_context.rs b/crates/re_space_view_spatial/src/scene/contexts/annotation_context.rs new file mode 100644 index 000000000000..2759271ba308 --- /dev/null +++ b/crates/re_space_view_spatial/src/scene/contexts/annotation_context.rs @@ -0,0 +1,29 @@ +use re_components::DrawOrder; +use re_log_types::{Component, ComponentName}; +use re_viewer_context::{AnnotationMap, SceneContext}; + +#[derive(Default)] +pub struct AnnotationSceneContext(pub AnnotationMap); + +impl SceneContext for AnnotationSceneContext { + fn component_names(&self) -> Vec { + vec![DrawOrder::name()] + } + + fn populate( + &mut self, + ctx: &mut re_viewer_context::ViewerContext<'_>, + query: &re_viewer_context::SceneQuery<'_>, + _space_view_state: &dyn re_viewer_context::SpaceViewState, + ) { + self.0.load(ctx, query); + } + + fn as_any(&self) -> &dyn std::any::Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn std::any::Any { + self + } +} diff --git a/crates/re_space_view_spatial/src/scene/contexts/mod.rs b/crates/re_space_view_spatial/src/scene/contexts/mod.rs index 7270e362b062..8336361f11ab 100644 --- a/crates/re_space_view_spatial/src/scene/contexts/mod.rs +++ b/crates/re_space_view_spatial/src/scene/contexts/mod.rs @@ -1,5 +1,7 @@ +mod annotation_context; mod depth_offsets; mod transform_context; +pub use annotation_context::AnnotationSceneContext; pub use depth_offsets::EntityDepthOffsets; pub use transform_context::{TransformContext, UnreachableTransform}; diff --git a/crates/re_space_view_spatial/src/scene/elements/points2d.rs b/crates/re_space_view_spatial/src/scene/elements/points2d.rs index 6ee0aa48205a..2fc2c41cc4bf 100644 --- a/crates/re_space_view_spatial/src/scene/elements/points2d.rs +++ b/crates/re_space_view_spatial/src/scene/elements/points2d.rs @@ -2,23 +2,37 @@ use re_components::{ ClassId, ColorRGBA, Component, InstanceKey, KeypointId, Label, Point2D, Radius, }; use re_data_store::{EntityPath, InstancePathHash}; -use re_query::{query_primary_with_history, EntityView, QueryError}; +use re_log_types::ComponentName; +use re_query::{EntityView, QueryError}; +use re_renderer::{LineStripSeriesBuilder, PointCloudBuilder}; use re_viewer_context::{ResolvedAnnotationInfo, SceneQuery, ViewerContext}; -use re_viewer_context::{SpaceViewHighlights, SpaceViewOutlineMasks}; -use crate::{ - scene::{EntityDepthOffsets, SceneSpatial, UiLabel, UiLabelTarget}, - TransformContext, +use crate::scene::{ + load_keypoint_connections, + spatial_scene_element::{SpatialSceneContext, SpatialSceneElement, SpatialSceneEntityContext}, + UiLabel, UiLabelTarget, }; use super::{ instance_key_to_picking_id, instance_path_hash_for_picking, process_annotations_and_keypoints, - process_colors, process_radii, ScenePart, + process_colors, process_radii, }; pub struct Points2DSceneElement { /// If the number of points in the batch is > max_labels, don't render point labels. - pub(crate) max_labels: usize, + pub max_labels: usize, + pub num_entities: usize, + pub ui_labels: Vec, +} + +impl Default for Points2DSceneElement { + fn default() -> Self { + Self { + max_labels: 10, + num_entities: 0, + ui_labels: Vec::new(), + } + } } impl Points2DSceneElement { @@ -52,25 +66,21 @@ impl Points2DSceneElement { Ok(labels) } - #[allow(clippy::too_many_arguments)] fn process_entity_view( - &self, - scene: &mut SceneSpatial, + &mut self, query: &SceneQuery<'_>, entity_view: &EntityView, ent_path: &EntityPath, - world_from_obj: glam::Affine3A, - entity_highlight: &SpaceViewOutlineMasks, - depth_offset: re_renderer::DepthOffset, + ent_context: &SpatialSceneEntityContext<'_>, + point_builder: &mut PointCloudBuilder, + line_builder: &mut re_renderer::LineStripSeriesBuilder, ) -> Result<(), QueryError> { re_tracing::profile_function!(); - scene.num_logged_2d_objects += 1; - - let annotations = scene.annotation_map.find(ent_path); + self.num_entities += 1; let (annotation_infos, keypoints) = - process_annotations_and_keypoints(query, entity_view, &annotations)?; + process_annotations_and_keypoints(query, entity_view, &ent_context.annotations)?; let colors = process_colors(entity_view, ent_path, &annotation_infos)?; let radii = process_radii(ent_path, entity_view)?; @@ -89,13 +99,13 @@ impl Points2DSceneElement { ent_path, instance_key, entity_view.num_instances(), - entity_highlight.any_selection_highlight, + ent_context.highlight.any_selection_highlight, ) }) .collect::>() }; - scene.ui.labels.extend(Self::process_labels( + self.ui_labels.extend(Self::process_labels( entity_view, &instance_path_hashes_for_picking, &colors, @@ -104,17 +114,15 @@ impl Points2DSceneElement { } { - let point_batch = scene - .primitives - .points + let point_batch = point_builder .batch("2d points") - .depth_offset(depth_offset) + .depth_offset(ent_context.depth_offset) .flags( re_renderer::renderer::PointCloudBatchFlags::FLAG_DRAW_AS_CIRCLES | re_renderer::renderer::PointCloudBatchFlags::FLAG_ENABLE_SHADING, ) - .world_from_obj(world_from_obj) - .outline_mask_ids(entity_highlight.overall) + .world_from_obj(ent_context.world_from_obj) + .outline_mask_ids(ent_context.highlight.overall) .picking_object_id(re_renderer::PickingLayerObjectId(ent_path.hash64())); let point_positions = { @@ -128,7 +136,7 @@ impl Points2DSceneElement { instance_key_to_picking_id( instance_key, entity_view.num_instances(), - entity_highlight.any_selection_highlight, + ent_context.highlight.any_selection_highlight, ) }); @@ -143,7 +151,7 @@ impl Points2DSceneElement { // Determine if there's any sub-ranges that need extra highlighting. { re_tracing::profile_scope!("marking additional highlight points"); - for (highlighted_key, instance_mask_ids) in &entity_highlight.instances { + for (highlighted_key, instance_mask_ids) in &ent_context.highlight.instances { // TODO(andreas/jeremy): We can do this much more efficiently let highlighted_point_index = entity_view .iter_instance_keys() @@ -159,65 +167,84 @@ impl Points2DSceneElement { } } - scene.load_keypoint_connections(ent_path, keypoints, &annotations); + load_keypoint_connections(line_builder, ent_path, keypoints, &ent_context.annotations); Ok(()) } } -impl ScenePart for Points2DSceneElement { - fn load( - &self, - scene: &mut SceneSpatial, +impl SpatialSceneElement<7> for Points2DSceneElement { + type Primary = Point2D; + + fn archetype() -> [ComponentName; 7] { + [ + Point2D::name(), + InstanceKey::name(), + ColorRGBA::name(), + Radius::name(), + Label::name(), + ClassId::name(), + KeypointId::name(), + ] + } + + fn populate( + &mut self, ctx: &mut ViewerContext<'_>, query: &SceneQuery<'_>, - transforms: &TransformContext, - highlights: &SpaceViewHighlights, - depth_offsets: &EntityDepthOffsets, - ) { + context: SpatialSceneContext<'_>, + ) -> Vec { re_tracing::profile_scope!("Points2DPart"); - for (ent_path, props) in query.iter_entities() { - let Some(world_from_obj) = transforms.reference_from_entity(ent_path) else { - continue; - }; - let entity_highlight = highlights.entity_outline_mask(ent_path.hash()); - - match query_primary_with_history::( - &ctx.store_db.entity_db.data_store, - &query.timeline, - &query.latest_at, - &props.visible_history, - ent_path, - [ - Point2D::name(), - InstanceKey::name(), - ColorRGBA::name(), - Radius::name(), - Label::name(), - ClassId::name(), - KeypointId::name(), - ], - ) - .and_then(|entities| { - for entity in entities { - self.process_entity_view( - scene, - query, - &entity, - ent_path, - world_from_obj, - entity_highlight, - depth_offsets.get(ent_path).unwrap_or(depth_offsets.points), - )?; + let mut point_builder = PointCloudBuilder::new(ctx.render_ctx); + let mut line_builder = LineStripSeriesBuilder::new(ctx.render_ctx); + + Self::for_each_entity_view( + ctx, + query, + &context, + context.depth_offsets.points, + |ent_path, entity_view, ent_context| { + self.process_entity_view( + query, + &entity_view, + ent_path, + ent_context, + &mut point_builder, + &mut line_builder, + ) + }, + ); + + let mut draw_data_list = Vec::new(); + + if !point_builder.vertices.is_empty() { + match point_builder.to_draw_data(ctx.render_ctx) { + Ok(draw_data) => draw_data_list.push(draw_data.into()), + Err(err) => { + re_log::error_once!( + "Failed to create point cloud draw data for 2D points: {}", + err + ); } - Ok(()) - }) { - Ok(_) | Err(QueryError::PrimaryNotFound) => {} + } + } + if !line_builder.batches.is_empty() { + match line_builder.to_draw_data(ctx.render_ctx) { + Ok(draw_data) => draw_data_list.push(draw_data.into()), Err(err) => { - re_log::error_once!("Unexpected error querying {ent_path:?}: {err}"); + re_log::error_once!( + "Failed to create line data for 2D point connections: {}", + err + ); } } } + + draw_data_list + } + + fn ui_labels(&self) -> &[UiLabel] { + &self.ui_labels } } diff --git a/crates/re_space_view_spatial/src/scene/elements/points3d.rs b/crates/re_space_view_spatial/src/scene/elements/points3d.rs index 9acd05c6b288..f2d8a6c3907e 100644 --- a/crates/re_space_view_spatial/src/scene/elements/points3d.rs +++ b/crates/re_space_view_spatial/src/scene/elements/points3d.rs @@ -162,7 +162,8 @@ impl Points3DPart { } } - scene.load_keypoint_connections(ent_path, keypoints, &annotations); + // TODO: + //scene.load_keypoint_connections(ent_path, keypoints, &annotations); Ok(()) } diff --git a/crates/re_space_view_spatial/src/scene/mod.rs b/crates/re_space_view_spatial/src/scene/mod.rs index 9b5bac38f3b4..d55346dda8bd 100644 --- a/crates/re_space_view_spatial/src/scene/mod.rs +++ b/crates/re_space_view_spatial/src/scene/mod.rs @@ -7,17 +7,20 @@ use re_data_store::{EntityPath, InstancePathHash}; use re_log_types::EntityPathHash; use re_renderer::{renderer::TexturedRect, Color32, OutlineMaskPreference, Size}; use re_viewer_context::{ - auto_color, AnnotationMap, Annotations, EmptySpaceViewState, SceneQuery, ViewerContext, + auto_color, AnnotationMap, Annotations, EmptySpaceViewState, SceneElement, SceneQuery, + ViewerContext, }; use re_viewer_context::{SceneContext, SpaceViewHighlights}; -mod contexts; use super::SpatialNavigationMode; +use crate::scene::spatial_scene_element::SpatialSceneElement; use crate::{mesh_loader::LoadedMesh, space_camera_3d::SpaceCamera3D}; +mod contexts; mod elements; mod picking; mod primitives; +mod spatial_scene_element; pub use self::picking::{PickingContext, PickingHitType, PickingRayHit, PickingResult}; pub use self::primitives::SceneSpatialPrimitives; @@ -143,10 +146,11 @@ impl SceneSpatial { // -- // Note: Lines2DPart handles both Segments and LinesPaths since they are unified on the logging-side. &elements::Lines2DPart, - &elements::Points2DSceneElement { max_labels: 10 }, // --- &elements::CamerasPart, ]; + let elements: Vec<&dyn SceneElement> = + vec![&elements::Points2DSceneElement::default().wrap()]; let mut depth_offsets = EntityDepthOffsets::default(); depth_offsets.populate(ctx, query, &EmptySpaceViewState); @@ -163,48 +167,6 @@ impl SceneSpatial { const CAMERA_COLOR: Color32 = Color32::from_rgb(150, 150, 150); - fn load_keypoint_connections( - &mut self, - entity_path: &re_data_store::EntityPath, - keypoints: Keypoints, - annotations: &Arc, - ) { - // Generate keypoint connections if any. - let mut line_batch = self - .primitives - .line_strips - .batch("keypoint connections") - .picking_object_id(re_renderer::PickingLayerObjectId(entity_path.hash64())); - - for ((class_id, _time), keypoints_in_class) in keypoints { - let Some(class_description) = annotations.context.class_map.get(&class_id) else { - continue; - }; - - let color = class_description.info.color.map_or_else( - || auto_color(class_description.info.id), - |color| color.into(), - ); - - for (a, b) in &class_description.keypoint_connections { - let (Some(a), Some(b)) = (keypoints_in_class.get(a), keypoints_in_class.get(b)) else { - re_log::warn_once!( - "Keypoint connection from index {:?} to {:?} could not be resolved in object {:?}", - a, b, entity_path - ); - continue; - }; - line_batch - .add_segment(*a, *b) - .radius(Size::AUTO) - .color(color) - .flags(re_renderer::renderer::LineStripFlags::FLAG_COLOR_GRADIENT) - // Select the entire object when clicking any of the lines. - .picking_instance_id(re_renderer::PickingLayerInstanceId(InstanceKey::SPLAT.0)); - } - } - } - /// Heuristic whether the default way of looking at this scene should be 2d or 3d. pub fn preferred_navigation_mode(&self, space_info_path: &EntityPath) -> SpatialNavigationMode { // If there's any space cameras that are not the root, we need to go 3D, otherwise we can't display them. @@ -226,3 +188,43 @@ impl SceneSpatial { SpatialNavigationMode::ThreeD } } + +pub fn load_keypoint_connections( + line_builder: &mut re_renderer::LineStripSeriesBuilder, + entity_path: &re_data_store::EntityPath, + keypoints: Keypoints, + annotations: &Arc, +) { + // Generate keypoint connections if any. + let mut line_batch = line_builder + .batch("keypoint connections") + .picking_object_id(re_renderer::PickingLayerObjectId(entity_path.hash64())); + + for ((class_id, _time), keypoints_in_class) in keypoints { + let Some(class_description) = annotations.context.class_map.get(&class_id) else { + continue; + }; + + let color = class_description.info.color.map_or_else( + || auto_color(class_description.info.id), + |color| color.into(), + ); + + for (a, b) in &class_description.keypoint_connections { + let (Some(a), Some(b)) = (keypoints_in_class.get(a), keypoints_in_class.get(b)) else { + re_log::warn_once!( + "Keypoint connection from index {:?} to {:?} could not be resolved in object {:?}", + a, b, entity_path + ); + continue; + }; + line_batch + .add_segment(*a, *b) + .radius(Size::AUTO) + .color(color) + .flags(re_renderer::renderer::LineStripFlags::FLAG_COLOR_GRADIENT) + // Select the entire object when clicking any of the lines. + .picking_instance_id(re_renderer::PickingLayerInstanceId(InstanceKey::SPLAT.0)); + } + } +} diff --git a/crates/re_space_view_spatial/src/scene/spatial_scene_element.rs b/crates/re_space_view_spatial/src/scene/spatial_scene_element.rs new file mode 100644 index 000000000000..09dd83c151ab --- /dev/null +++ b/crates/re_space_view_spatial/src/scene/spatial_scene_element.rs @@ -0,0 +1,172 @@ +use std::sync::Arc; + +use re_components::Component; +use re_data_store::EntityPath; +use re_log_types::ComponentName; +use re_query::{query_primary_with_history, EntityView, QueryError}; +use re_renderer::DepthOffset; +use re_viewer_context::{ + Annotations, SceneContextCollection, SceneElement, SceneItemCollectionLookupError, SceneQuery, + ViewerContext, +}; +use re_viewer_context::{SpaceViewHighlights, SpaceViewOutlineMasks}; + +use crate::{scene::EntityDepthOffsets, TransformContext}; + +use super::contexts::AnnotationSceneContext; +use super::UiLabel; + +/// Context objects for a single entity in a spatial scene. +pub struct SpatialSceneEntityContext<'a> { + pub world_from_obj: glam::Affine3A, + pub depth_offset: DepthOffset, + pub annotations: Arc, + pub highlight: &'a SpaceViewOutlineMasks, +} + +/// Reference to all context objects of a spatial scene. +pub struct SpatialSceneContext<'a> { + pub transforms: &'a TransformContext, + pub depth_offsets: &'a EntityDepthOffsets, + pub annotations: &'a AnnotationSceneContext, + pub highlights: &'a SpaceViewHighlights, // Not part of the context collection, but convenient to have here. +} + +impl<'a> SpatialSceneContext<'a> { + fn new( + contexts: &'a SceneContextCollection, + highlights: &'a SpaceViewHighlights, + ) -> Result { + Ok(Self { + transforms: contexts.get::()?, + depth_offsets: contexts.get::()?, + annotations: contexts.get::()?, + highlights, + }) + } + + fn query( + &self, + ent_path: &EntityPath, + default_depth_offset: DepthOffset, + ) -> Option> { + Some(SpatialSceneEntityContext { + world_from_obj: self.transforms.reference_from_entity(ent_path)?, + depth_offset: *self + .depth_offsets + .per_entity + .get(&ent_path.hash()) + .unwrap_or(&default_depth_offset), + annotations: self.annotations.0.find(ent_path), + highlight: self.highlights.entity_outline_mask(ent_path.hash()), + }) + } +} + +pub trait SpatialSceneElement: std::any::Any { + type Primary: Component + 'static; + + fn archetype() -> [ComponentName; N]; + + fn populate( + &mut self, + ctx: &mut ViewerContext<'_>, + query: &SceneQuery<'_>, + context: SpatialSceneContext<'_>, + ) -> Vec; + + fn for_each_entity_view( + ctx: &mut ViewerContext<'_>, + query: &SceneQuery<'_>, + context: &SpatialSceneContext<'_>, + default_depth_offset: DepthOffset, + mut fun: F, + ) where + F: FnMut( + &EntityPath, + EntityView, + &SpatialSceneEntityContext<'_>, + ) -> Result<(), QueryError>, + { + for (ent_path, props) in query.iter_entities() { + let Some(entity_context) = context.query(ent_path, default_depth_offset) else { + continue; + }; + + match query_primary_with_history::( + &ctx.log_db.entity_db.data_store, + &query.timeline, + &query.latest_at, + &props.visible_history, + ent_path, + Self::archetype(), + ) + .and_then(|entity_views| { + for entity_view in entity_views { + fun(ent_path, entity_view, &entity_context)?; + } + Ok(()) + }) { + Ok(_) | Err(QueryError::PrimaryNotFound) => {} + Err(err) => { + re_log::error_once!("Unexpected error querying {ent_path:?}: {err}"); + } + } + } + } + + fn wrap(self) -> SpatialSceneElementWrapper + where + Self: Sized, + { + SpatialSceneElementWrapper(self) + } + + /// Retrieves all ui labels that this scene element should render. + fn ui_labels(&self) -> &[UiLabel]; +} + +/// A wrapper for `SpatialSceneElement` that implements `SceneElement`. +/// +/// Can't implement directly due to Rust limitations around higher kinded traits. +pub struct SpatialSceneElementWrapper>(pub T); + +impl> SpatialSceneElementWrapper { + /// Retrieves all ui labels that this scene element should render. + fn ui_labels(&self) -> &[UiLabel] { + self.0.ui_labels() + } +} + +impl> SceneElement for SpatialSceneElementWrapper { + fn archetype(&self) -> re_viewer_context::ArchetypeDefinition { + debug_assert!(N > 0); + T::archetype().to_vec().try_into().unwrap() + } + + fn populate( + &mut self, + ctx: &mut ViewerContext<'_>, + query: &SceneQuery<'_>, + _space_view_state: &dyn re_viewer_context::SpaceViewState, + contexts: &re_viewer_context::SceneContextCollection, + highlights: &SpaceViewHighlights, + ) -> Vec { + let contexts = match SpatialSceneContext::new(contexts, highlights) { + Ok(ctx) => ctx, + Err(err) => { + re_log::error_once!("Failed to get required scene contexts: {err}"); + return Vec::new(); + } + }; + self.0.populate(ctx, query, contexts) + } + + fn as_any(&self) -> &dyn std::any::Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn std::any::Any { + self + } +} diff --git a/crates/re_viewer_context/src/lib.rs b/crates/re_viewer_context/src/lib.rs index 9ae5be3045cd..6d8c71664f62 100644 --- a/crates/re_viewer_context/src/lib.rs +++ b/crates/re_viewer_context/src/lib.rs @@ -31,9 +31,10 @@ pub use selection_state::{ }; pub use space_view::{ ArchetypeDefinition, EmptySpaceViewState, Scene, SceneContext, SceneContextCollection, - SceneElement, SceneElementCollection, SceneElementImpl, SceneQuery, SpaceViewClass, - SpaceViewClassImpl, SpaceViewClassName, SpaceViewClassRegistry, SpaceViewClassRegistryError, - SpaceViewEntityHighlight, SpaceViewHighlights, SpaceViewOutlineMasks, SpaceViewState, + SceneElement, SceneElementCollection, SceneElementImpl, SceneItemCollectionLookupError, + SceneQuery, SpaceViewClass, SpaceViewClassImpl, SpaceViewClassName, SpaceViewClassRegistry, + SpaceViewClassRegistryError, SpaceViewEntityHighlight, SpaceViewHighlights, + SpaceViewOutlineMasks, SpaceViewState, }; pub use tensor::{TensorDecodeCache, TensorStats, TensorStatsCache}; pub use time_control::{Looping, PlayState, TimeControl, TimeView}; diff --git a/crates/re_viewer_context/src/space_view/mod.rs b/crates/re_viewer_context/src/space_view/mod.rs index 0c1097f853e7..3c8eb86b476b 100644 --- a/crates/re_viewer_context/src/space_view/mod.rs +++ b/crates/re_viewer_context/src/space_view/mod.rs @@ -15,6 +15,7 @@ mod space_view_class_registry; pub use highlights::{SpaceViewEntityHighlight, SpaceViewHighlights, SpaceViewOutlineMasks}; pub use scene::{ Scene, SceneContext, SceneContextCollection, SceneElement, SceneElementCollection, + SceneItemCollectionLookupError, }; pub use scene_element_impl::SceneElementImpl; pub use scene_query::SceneQuery; From f1260c9373032ccd58f6e19d4d80c30eaa939041 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 1 Jun 2023 18:47:01 +0200 Subject: [PATCH 10/39] port 3d points and wire up scene elements so far --- .../src/scene/elements/mod.rs | 40 +++- .../src/scene/elements/points2d.rs | 43 ++--- .../src/scene/elements/points3d.rs | 178 +++++++++--------- crates/re_space_view_spatial/src/scene/mod.rs | 54 ++++-- .../src/scene/primitives.rs | 1 - .../src/scene/spatial_scene_element.rs | 4 +- crates/re_space_view_spatial/src/ui.rs | 3 - crates/re_space_view_spatial/src/ui_2d.rs | 12 +- crates/re_space_view_spatial/src/ui_3d.rs | 13 +- .../re_viewer_context/src/space_view/scene.rs | 34 ++-- crates/re_viewport/src/space_view.rs | 5 +- 11 files changed, 219 insertions(+), 168 deletions(-) diff --git a/crates/re_space_view_spatial/src/scene/elements/mod.rs b/crates/re_space_view_spatial/src/scene/elements/mod.rs index a242046abe1b..432d09bc4705 100644 --- a/crates/re_space_view_spatial/src/scene/elements/mod.rs +++ b/crates/re_space_view_spatial/src/scene/elements/mod.rs @@ -22,12 +22,12 @@ pub(crate) use images::ImagesPart; pub(crate) use lines2d::Lines2DPart; pub(crate) use lines3d::Lines3DPart; pub(crate) use meshes::MeshPart; - pub(crate) use points2d::Points2DSceneElement; -pub(crate) use points3d::Points3DPart; +pub(crate) use points3d::Points3DSceneElement; use re_components::{ClassId, ColorRGBA, KeypointId, Radius}; use re_data_store::{EntityPath, InstancePathHash}; +use re_renderer::{LineStripSeriesBuilder, PointCloudBuilder}; use re_viewer_context::SpaceViewHighlights; use re_viewer_context::{ Annotations, DefaultColor, ResolvedAnnotationInfo, SceneQuery, ViewerContext, @@ -197,3 +197,39 @@ where Ok((annotation_info, keypoints)) } + +fn try_add_point_draw_data( + render_ctx: &mut re_renderer::RenderContext, + point_builder: PointCloudBuilder, + draw_data_list: &mut Vec, +) { + if !point_builder.vertices.is_empty() { + match point_builder.to_draw_data(render_ctx) { + Ok(draw_data) => draw_data_list.push(draw_data.into()), + Err(err) => { + re_log::error_once!( + "Failed to create point cloud draw data for 2D points: {}", + err + ); + } + } + } +} + +fn try_add_line_draw_data( + render_ctx: &mut re_renderer::RenderContext, + line_builder: LineStripSeriesBuilder, + draw_data_list: &mut Vec, +) { + if !line_builder.batches.is_empty() { + match line_builder.to_draw_data(render_ctx) { + Ok(draw_data) => draw_data_list.push(draw_data.into()), + Err(err) => { + re_log::error_once!( + "Failed to create line data for 2D point connections: {}", + err + ); + } + } + } +} diff --git a/crates/re_space_view_spatial/src/scene/elements/points2d.rs b/crates/re_space_view_spatial/src/scene/elements/points2d.rs index 2fc2c41cc4bf..d8b04ec0972f 100644 --- a/crates/re_space_view_spatial/src/scene/elements/points2d.rs +++ b/crates/re_space_view_spatial/src/scene/elements/points2d.rs @@ -8,6 +8,7 @@ use re_renderer::{LineStripSeriesBuilder, PointCloudBuilder}; use re_viewer_context::{ResolvedAnnotationInfo, SceneQuery, ViewerContext}; use crate::scene::{ + elements::{try_add_line_draw_data, try_add_point_draw_data}, load_keypoint_connections, spatial_scene_element::{SpatialSceneContext, SpatialSceneElement, SpatialSceneEntityContext}, UiLabel, UiLabelTarget, @@ -21,16 +22,16 @@ use super::{ pub struct Points2DSceneElement { /// If the number of points in the batch is > max_labels, don't render point labels. pub max_labels: usize, - pub num_entities: usize, pub ui_labels: Vec, + pub bounding_box: macaw::BoundingBox, } impl Default for Points2DSceneElement { fn default() -> Self { Self { max_labels: 10, - num_entities: 0, ui_labels: Vec::new(), + bounding_box: macaw::BoundingBox::nothing(), } } } @@ -77,8 +78,6 @@ impl Points2DSceneElement { ) -> Result<(), QueryError> { re_tracing::profile_function!(); - self.num_entities += 1; - let (annotation_infos, keypoints) = process_annotations_and_keypoints(query, entity_view, &ent_context.annotations)?; @@ -113,6 +112,7 @@ impl Points2DSceneElement { )?); } + //let batch_bb = { { let point_batch = point_builder .batch("2d points") @@ -131,6 +131,7 @@ impl Points2DSceneElement { .iter_primary()? .filter_map(|pt| pt.map(glam::Vec2::from)) }; + //let batch_bb = macaw::BoundingBox::from_points(point_positions.map(|p| p.extend(0.0))); let picking_instance_ids = entity_view.iter_instance_keys().map(|instance_key| { instance_key_to_picking_id( @@ -165,10 +166,16 @@ impl Points2DSceneElement { } } } - } + + // batch_bb + }; load_keypoint_connections(line_builder, ent_path, keypoints, &ent_context.annotations); + // self.bounding_box = self + // .bounding_box + // .union(batch_bb.transform_affine3(&ent_context.world_from_obj)); + Ok(()) } } @@ -217,30 +224,8 @@ impl SpatialSceneElement<7> for Points2DSceneElement { ); let mut draw_data_list = Vec::new(); - - if !point_builder.vertices.is_empty() { - match point_builder.to_draw_data(ctx.render_ctx) { - Ok(draw_data) => draw_data_list.push(draw_data.into()), - Err(err) => { - re_log::error_once!( - "Failed to create point cloud draw data for 2D points: {}", - err - ); - } - } - } - if !line_builder.batches.is_empty() { - match line_builder.to_draw_data(ctx.render_ctx) { - Ok(draw_data) => draw_data_list.push(draw_data.into()), - Err(err) => { - re_log::error_once!( - "Failed to create line data for 2D point connections: {}", - err - ); - } - } - } - + try_add_point_draw_data(ctx.render_ctx, point_builder, &mut draw_data_list); + try_add_line_draw_data(ctx.render_ctx, line_builder, &mut draw_data_list); draw_data_list } diff --git a/crates/re_space_view_spatial/src/scene/elements/points3d.rs b/crates/re_space_view_spatial/src/scene/elements/points3d.rs index f2d8a6c3907e..e3debe26610e 100644 --- a/crates/re_space_view_spatial/src/scene/elements/points3d.rs +++ b/crates/re_space_view_spatial/src/scene/elements/points3d.rs @@ -2,32 +2,40 @@ use re_components::{ ClassId, ColorRGBA, Component as _, InstanceKey, KeypointId, Label, Point3D, Radius, }; use re_data_store::{EntityPath, InstancePathHash}; -use re_query::{query_primary_with_history, EntityView, QueryError}; +use re_log_types::ComponentName; +use re_query::{EntityView, QueryError}; +use re_renderer::{LineStripSeriesBuilder, PointCloudBuilder}; use re_viewer_context::{ResolvedAnnotationInfo, SceneQuery, ViewerContext}; -use re_viewer_context::{SpaceViewHighlights, SpaceViewOutlineMasks}; - -use crate::{ - TransformContext, - { - scene::UiLabelTarget, - scene::{ - elements::{ - instance_key_to_picking_id, instance_path_hash_for_picking, - process_annotations_and_keypoints, process_colors, process_radii, - }, - EntityDepthOffsets, SceneSpatial, UiLabel, - }, + +use crate::scene::{ + elements::{ + instance_key_to_picking_id, instance_path_hash_for_picking, + process_annotations_and_keypoints, process_colors, process_radii, try_add_line_draw_data, + try_add_point_draw_data, }, + load_keypoint_connections, + spatial_scene_element::{SpatialSceneContext, SpatialSceneElement, SpatialSceneEntityContext}, + UiLabel, UiLabelTarget, }; -use super::ScenePart; - -pub struct Points3DPart { +pub struct Points3DSceneElement { /// If the number of points in the batch is > max_labels, don't render point labels. - pub(crate) max_labels: usize, + pub max_labels: usize, + pub ui_labels: Vec, + pub bounding_box: macaw::BoundingBox, +} + +impl Default for Points3DSceneElement { + fn default() -> Self { + Self { + max_labels: 10, + ui_labels: Vec::new(), + bounding_box: macaw::BoundingBox::nothing(), + } + } } -impl Points3DPart { +impl Points3DSceneElement { fn process_labels<'a>( entity_view: &'a EntityView, instance_path_hashes: &'a [InstancePathHash], @@ -61,24 +69,19 @@ impl Points3DPart { Ok(labels) } - #[allow(clippy::too_many_arguments)] fn process_entity_view( - &self, - scene: &mut SceneSpatial, + &mut self, query: &SceneQuery<'_>, entity_view: &EntityView, ent_path: &EntityPath, - world_from_obj: glam::Affine3A, - entity_highlight: &SpaceViewOutlineMasks, + ent_context: &SpatialSceneEntityContext<'_>, + point_builder: &mut PointCloudBuilder, + line_builder: &mut re_renderer::LineStripSeriesBuilder, ) -> Result<(), QueryError> { re_tracing::profile_function!(); - scene.num_logged_3d_objects += 1; - - let annotations = scene.annotation_map.find(ent_path); - let (annotation_infos, keypoints) = - process_annotations_and_keypoints(query, entity_view, &annotations)?; + process_annotations_and_keypoints(query, entity_view, &ent_context.annotations)?; let colors = process_colors(entity_view, ent_path, &annotation_infos)?; let radii = process_radii(ent_path, entity_view)?; @@ -97,28 +100,26 @@ impl Points3DPart { ent_path, instance_key, entity_view.num_instances(), - entity_highlight.any_selection_highlight, + ent_context.highlight.any_selection_highlight, ) }) .collect::>() }; - scene.ui.labels.extend(Self::process_labels( + self.ui_labels.extend(Self::process_labels( entity_view, &instance_path_hashes_for_picking, &colors, &annotation_infos, - world_from_obj, + ent_context.world_from_obj, )?); } { - let point_batch = scene - .primitives - .points + let point_batch = point_builder .batch("3d points") - .world_from_obj(world_from_obj) - .outline_mask_ids(entity_highlight.overall) + .world_from_obj(ent_context.world_from_obj) + .outline_mask_ids(ent_context.highlight.overall) .picking_object_id(re_renderer::PickingLayerObjectId(ent_path.hash64())); let point_positions = { @@ -132,7 +133,7 @@ impl Points3DPart { instance_key_to_picking_id( instance_key, entity_view.num_instances(), - entity_highlight.any_selection_highlight, + ent_context.highlight.any_selection_highlight, ) }); let mut point_range_builder = point_batch.add_points( @@ -146,7 +147,7 @@ impl Points3DPart { // Determine if there's any sub-ranges that need extra highlighting. { re_tracing::profile_scope!("marking additional highlight points"); - for (highlighted_key, instance_mask_ids) in &entity_highlight.instances { + for (highlighted_key, instance_mask_ids) in &ent_context.highlight.instances { // TODO(andreas/jeremy): We can do this much more efficiently let highlighted_point_index = entity_view .iter_instance_keys() @@ -162,65 +163,62 @@ impl Points3DPart { } } - // TODO: - //scene.load_keypoint_connections(ent_path, keypoints, &annotations); + load_keypoint_connections(line_builder, ent_path, keypoints, &ent_context.annotations); Ok(()) } } -impl ScenePart for Points3DPart { - fn load( - &self, - scene: &mut SceneSpatial, +impl SpatialSceneElement<7> for Points3DSceneElement { + type Primary = Point3D; + + fn archetype() -> [ComponentName; 7] { + [ + Point3D::name(), + InstanceKey::name(), + ColorRGBA::name(), + Radius::name(), + Label::name(), + ClassId::name(), + KeypointId::name(), + ] + } + + fn populate( + &mut self, ctx: &mut ViewerContext<'_>, query: &SceneQuery<'_>, - transforms: &TransformContext, - highlights: &SpaceViewHighlights, - _depth_offsets: &EntityDepthOffsets, - ) { + context: SpatialSceneContext<'_>, + ) -> Vec { re_tracing::profile_scope!("Points3DPart"); - for (ent_path, props) in query.iter_entities() { - let Some(world_from_obj) = transforms.reference_from_entity(ent_path) else { - continue; - }; - let entity_highlight = highlights.entity_outline_mask(ent_path.hash()); - - match query_primary_with_history::( - &ctx.store_db.entity_db.data_store, - &query.timeline, - &query.latest_at, - &props.visible_history, - ent_path, - [ - Point3D::name(), - InstanceKey::name(), - ColorRGBA::name(), - Radius::name(), - Label::name(), - ClassId::name(), - KeypointId::name(), - ], - ) - .and_then(|entities| { - for entity in entities { - self.process_entity_view( - scene, - query, - &entity, - ent_path, - world_from_obj, - entity_highlight, - )?; - } - Ok(()) - }) { - Ok(_) | Err(QueryError::PrimaryNotFound) => {} - Err(err) => { - re_log::error_once!("Unexpected error querying {ent_path:?}: {err}"); - } - } - } + let mut point_builder = PointCloudBuilder::new(ctx.render_ctx); + let mut line_builder = LineStripSeriesBuilder::new(ctx.render_ctx); + + Self::for_each_entity_view( + ctx, + query, + &context, + context.depth_offsets.points, + |ent_path, entity_view, ent_context| { + self.process_entity_view( + query, + &entity_view, + ent_path, + ent_context, + &mut point_builder, + &mut line_builder, + ) + }, + ); + + let mut draw_data_list = Vec::new(); + try_add_point_draw_data(ctx.render_ctx, point_builder, &mut draw_data_list); + try_add_line_draw_data(ctx.render_ctx, line_builder, &mut draw_data_list); + draw_data_list + } + + fn ui_labels(&self) -> &[UiLabel] { + &self.ui_labels } } diff --git a/crates/re_space_view_spatial/src/scene/mod.rs b/crates/re_space_view_spatial/src/scene/mod.rs index d55346dda8bd..98d1b64d45ea 100644 --- a/crates/re_space_view_spatial/src/scene/mod.rs +++ b/crates/re_space_view_spatial/src/scene/mod.rs @@ -6,14 +6,14 @@ use re_components::{ClassId, DecodedTensor, DrawOrder, InstanceKey, KeypointId}; use re_data_store::{EntityPath, InstancePathHash}; use re_log_types::EntityPathHash; use re_renderer::{renderer::TexturedRect, Color32, OutlineMaskPreference, Size}; +use re_viewer_context::SpaceViewHighlights; use re_viewer_context::{ - auto_color, AnnotationMap, Annotations, EmptySpaceViewState, SceneElement, SceneQuery, - ViewerContext, + auto_color, AnnotationMap, Annotations, EmptySpaceViewState, Scene, SceneQuery, ViewerContext, }; -use re_viewer_context::{SceneContext, SpaceViewHighlights}; use super::SpatialNavigationMode; -use crate::scene::spatial_scene_element::SpatialSceneElement; +use crate::scene::contexts::AnnotationSceneContext; +use crate::scene::spatial_scene_element::{SpatialSceneContext, SpatialSceneElement}; use crate::{mesh_loader::LoadedMesh, space_camera_3d::SpaceCamera3D}; mod contexts; @@ -100,6 +100,10 @@ pub struct SceneSpatial { /// All space cameras in this scene. /// TODO(andreas): Does this belong to `SceneSpatialUiData`? pub space_cameras: Vec, + + // TODO(andreas): Temporary field. The hosting struct will be removed once SpatialScene is fully ported to the SpaceViewClass framework. + pub scene: Scene, + pub draw_data: Vec, } pub type Keypoints = HashMap<(ClassId, i64), HashMap>; @@ -119,6 +123,8 @@ impl SceneSpatial { num_logged_2d_objects: Default::default(), num_logged_3d_objects: Default::default(), space_cameras: Default::default(), + scene: Default::default(), + draw_data: Default::default(), } } @@ -127,14 +133,13 @@ impl SceneSpatial { &mut self, ctx: &mut ViewerContext<'_>, query: &SceneQuery<'_>, - highlights: &SpaceViewHighlights, + highlights: SpaceViewHighlights, ) { re_tracing::profile_function!(); self.annotation_map.load(ctx, query); let parts: Vec<&dyn ScenePart> = vec![ - &elements::Points3DPart { max_labels: 10 }, // -- &elements::Boxes3DPart, &elements::Lines3DPart, @@ -149,20 +154,41 @@ impl SceneSpatial { // --- &elements::CamerasPart, ]; - let elements: Vec<&dyn SceneElement> = - vec![&elements::Points2DSceneElement::default().wrap()]; - let mut depth_offsets = EntityDepthOffsets::default(); - depth_offsets.populate(ctx, query, &EmptySpaceViewState); - let mut transforms = TransformContext::default(); - transforms.populate(ctx, query, &EmptySpaceViewState); + // TODO(andreas): Temporary build up of scene. This will be handled by the SpaceViewClass framework later. + let mut scene = Scene { + contexts: ( + EntityDepthOffsets::default(), + TransformContext::default(), + AnnotationSceneContext::default(), + ) + .into(), + elements: ( + elements::Points2DSceneElement::default().wrap(), + elements::Points3DSceneElement::default().wrap(), + ) + .into(), + highlights: Default::default(), + }; + self.draw_data = scene.populate(ctx, query, &EmptySpaceViewState, highlights); + let scene_context = SpatialSceneContext::new(&scene.contexts, &scene.highlights) + .expect("Failed to query for scene context."); for part in parts { - part.load(self, ctx, query, &transforms, highlights, &depth_offsets); + part.load( + self, + ctx, + query, + scene_context.transforms, + scene_context.highlights, + scene_context.depth_offsets, + ); } - self.primitives.any_outlines = highlights.any_outlines(); + self.primitives.any_outlines = scene_context.highlights.any_outlines(); self.primitives.recalculate_bounding_box(); + + self.scene = scene; } const CAMERA_COLOR: Color32 = Color32::from_rgb(150, 150, 150); diff --git a/crates/re_space_view_spatial/src/scene/primitives.rs b/crates/re_space_view_spatial/src/scene/primitives.rs index afbd4c79f99e..a406c603f566 100644 --- a/crates/re_space_view_spatial/src/scene/primitives.rs +++ b/crates/re_space_view_spatial/src/scene/primitives.rs @@ -103,7 +103,6 @@ impl SceneSpatialPrimitives { // We don't need a very accurate bounding box, so in order to save some time, // we calculate a per batch bounding box for lines and points. - // TODO(andreas): We should keep these around to speed up picking! for (batch, vertex_iter) in points.iter_vertices_by_batch() { let batch_bb = macaw::BoundingBox::from_points(vertex_iter.map(|v| v.position)); *bounding_box = bounding_box.union(batch_bb.transform_affine3(&batch.world_from_obj)); diff --git a/crates/re_space_view_spatial/src/scene/spatial_scene_element.rs b/crates/re_space_view_spatial/src/scene/spatial_scene_element.rs index 09dd83c151ab..c89fee3bdd7c 100644 --- a/crates/re_space_view_spatial/src/scene/spatial_scene_element.rs +++ b/crates/re_space_view_spatial/src/scene/spatial_scene_element.rs @@ -33,7 +33,7 @@ pub struct SpatialSceneContext<'a> { } impl<'a> SpatialSceneContext<'a> { - fn new( + pub fn new( contexts: &'a SceneContextCollection, highlights: &'a SpaceViewHighlights, ) -> Result { @@ -94,7 +94,7 @@ pub trait SpatialSceneElement: std::any::Any { }; match query_primary_with_history::( - &ctx.log_db.entity_db.data_store, + &ctx.store_db.entity_db.data_store, &query.timeline, &query.latest_at, &props.visible_history, diff --git a/crates/re_space_view_spatial/src/ui.rs b/crates/re_space_view_spatial/src/ui.rs index 0a089ddbbea6..80eeec1696e9 100644 --- a/crates/re_space_view_spatial/src/ui.rs +++ b/crates/re_space_view_spatial/src/ui.rs @@ -374,7 +374,6 @@ impl ViewSpatialState { space: &EntityPath, scene: SceneSpatial, space_view_id: SpaceViewId, - highlights: &SpaceViewHighlights, entity_properties: &EntityPropertyMap, ) { self.scene_bbox = scene.primitives.bounding_box(); @@ -401,7 +400,6 @@ impl ViewSpatialState { space, space_view_id, scene, - highlights, entity_properties, ); } @@ -418,7 +416,6 @@ impl ViewSpatialState { scene, scene_rect_accum, space_view_id, - highlights, entity_properties, ); } diff --git a/crates/re_space_view_spatial/src/ui_2d.rs b/crates/re_space_view_spatial/src/ui_2d.rs index e97c5855610a..3ee337d0fd36 100644 --- a/crates/re_space_view_spatial/src/ui_2d.rs +++ b/crates/re_space_view_spatial/src/ui_2d.rs @@ -5,9 +5,7 @@ use re_components::Pinhole; use re_data_store::{EntityPath, EntityPropertyMap}; use re_renderer::view_builder::{TargetConfiguration, ViewBuilder}; use re_space_view::controls::{DRAG_PAN2D_BUTTON, RESET_VIEW_BUTTON_TEXT, ZOOM_SCROLL_MODIFIER}; -use re_viewer_context::{ - gpu_bridge, HoveredSpace, SpaceViewHighlights, SpaceViewId, ViewerContext, -}; +use re_viewer_context::{gpu_bridge, HoveredSpace, SpaceViewId, ViewerContext}; use super::{ eye::Eye, @@ -229,7 +227,6 @@ pub fn view_2d( mut scene: SceneSpatial, scene_rect_accum: Rect, space_view_id: SpaceViewId, - highlights: &SpaceViewHighlights, entity_properties: &EntityPropertyMap, ) -> egui::Response { re_tracing::profile_function!(); @@ -313,7 +310,7 @@ pub fn view_2d( ui_from_canvas, &eye, ui, - highlights, + &scene.scene.highlights, SpatialNavigationMode::TwoD, ); @@ -334,6 +331,11 @@ pub fn view_2d( ); } + // TODO(wumpf): Temporary manual inseration of drawdata. The SpaceViewClass framework will take this over. + for draw_data in scene.draw_data { + view_builder.queue_draw(draw_data); + } + // ------------------------------------------------------------------------ // Screenshot context menu. diff --git a/crates/re_space_view_spatial/src/ui_3d.rs b/crates/re_space_view_spatial/src/ui_3d.rs index 6d08f86a1684..0b5ee5f375bb 100644 --- a/crates/re_space_view_spatial/src/ui_3d.rs +++ b/crates/re_space_view_spatial/src/ui_3d.rs @@ -14,9 +14,7 @@ use re_space_view::controls::{ DRAG_PAN3D_BUTTON, RESET_VIEW_BUTTON_TEXT, ROLL_MOUSE, ROLL_MOUSE_ALT, ROLL_MOUSE_MODIFIER, ROTATE3D_BUTTON, SLOW_DOWN_3D_MODIFIER, SPEED_UP_3D_MODIFIER, TRACKED_CAMERA_RESTORE_KEY, }; -use re_viewer_context::{ - gpu_bridge, HoveredSpace, Item, SpaceViewHighlights, SpaceViewId, ViewerContext, -}; +use re_viewer_context::{gpu_bridge, HoveredSpace, Item, SpaceViewId, ViewerContext}; use crate::{ scene::SceneSpatial, @@ -280,7 +278,6 @@ pub fn help_text(re_ui: &re_ui::ReUi) -> egui::WidgetText { } /// TODO(andreas): Split into smaller parts, more re-use with `ui_2d` -#[allow(clippy::too_many_arguments)] pub fn view_3d( ctx: &mut ViewerContext<'_>, ui: &mut egui::Ui, @@ -288,11 +285,12 @@ pub fn view_3d( space: &EntityPath, space_view_id: SpaceViewId, mut scene: SceneSpatial, - highlights: &SpaceViewHighlights, entity_properties: &EntityPropertyMap, ) { re_tracing::profile_function!(); + let highlights = &scene.scene.highlights; + let (rect, mut response) = ui.allocate_at_least(ui.available_size(), egui::Sense::click_and_drag()); @@ -516,6 +514,11 @@ pub fn view_3d( } } + // TODO(wumpf): Temporary manual inseration of drawdata. The SpaceViewClass framework will take this over. + for draw_data in scene.draw_data { + view_builder.queue_draw(draw_data); + } + // Composite viewbuilder into egui. let command_buffer = match fill_view_builder( ctx.render_ctx, diff --git a/crates/re_viewer_context/src/space_view/scene.rs b/crates/re_viewer_context/src/space_view/scene.rs index 7a5b7795be08..420b775d74c8 100644 --- a/crates/re_viewer_context/src/space_view/scene.rs +++ b/crates/re_viewer_context/src/space_view/scene.rs @@ -19,6 +19,7 @@ pub enum SceneItemCollectionLookupError { /// Collection of scene contexts. /// /// New type pattern to support adding From impls. +#[derive(Default)] pub struct SceneContextCollection(HashMap>); impl SceneContextCollection { @@ -66,6 +67,7 @@ scene_context_collection_from_tuple!(0 => T0, 1 => T1, 2 => T2, 3 => T3, 4 => T4 /// Collections of scene elements. /// /// New type pattern to support adding From impls. +#[derive(Default)] pub struct SceneElementCollection(HashMap>); impl SceneElementCollection { @@ -118,10 +120,11 @@ scene_element_collection_from_tuple!(0 => T0, 1 => T1, 2 => T2, 3 => T3, 4 => T4 /// /// When populating a scene, first all contexts are populated, /// and then all elements with read access to the previously established context objects. +#[derive(Default)] pub struct Scene { pub contexts: SceneContextCollection, pub elements: SceneElementCollection, - pub highlights: SpaceViewHighlights, + pub highlights: SpaceViewHighlights, // TODO(wumpf): Consider making this a scene context - problem: populate can't create it. } impl Scene { @@ -137,7 +140,7 @@ impl Scene { query: &SceneQuery<'_>, space_view_state: &dyn SpaceViewState, highlights: SpaceViewHighlights, - ) { + ) -> Vec { re_tracing::profile_function!(); self.highlights = highlights; @@ -147,16 +150,20 @@ impl Scene { // TODO(andreas): Restrict the query with the archetype somehow, ideally making it trivial to do the correct thing. context.populate(ctx, query, space_view_state); } - for element in self.elements.0.values_mut() { - // TODO(andreas): Restrict the query with the archetype somehow, ideally making it trivial to do the correct thing. - element.populate( - ctx, - query, - space_view_state, - &self.contexts, - &self.highlights, - ); - } + self.elements + .0 + .values_mut() + .flat_map(|element| { + // TODO(andreas): Restrict the query with the archetype somehow, ideally making it trivial to do the correct thing. + element.populate( + ctx, + query, + space_view_state, + &self.contexts, + &self.highlights, + ) + }) + .collect() } } @@ -184,11 +191,12 @@ pub trait SceneElement: Any { fn as_any_mut(&mut self) -> &mut dyn std::any::Any; } +/// TODO: Doc pub trait SceneContext: Any { /// Scene contexts query loose components instead of archetypes in their populate method. /// /// This lists all components out that the context queries. - fn component_names(&self) -> Vec; + fn component_names(&self) -> Vec; // TODO: Back to archetype definitions? /// Queries the data store and performs data conversions to make it ready for consumption by scene elements. fn populate( diff --git a/crates/re_viewport/src/space_view.rs b/crates/re_viewport/src/space_view.rs index 0ceb44be0628..bdb6f2bfcb81 100644 --- a/crates/re_viewport/src/space_view.rs +++ b/crates/re_viewport/src/space_view.rs @@ -238,7 +238,7 @@ impl SpaceViewBlueprint { ViewCategory::Spatial => { let mut scene = SceneSpatial::new(ctx.render_ctx); - scene.load(ctx, &query, &highlights); + scene.load(ctx, &query, highlights); view_state .state_spatial .update_object_property_heuristics(ctx, &mut self.data_blueprint); @@ -248,7 +248,6 @@ impl SpaceViewBlueprint { &self.space_path, scene, self.id, - &highlights, self.data_blueprint.data_blueprints_projected(), ); } @@ -334,7 +333,6 @@ impl SpaceViewState { space: &EntityPath, scene: SceneSpatial, space_view_id: SpaceViewId, - highlights: &SpaceViewHighlights, entity_properties: &EntityPropertyMap, ) { ui.vertical(|ui| { @@ -344,7 +342,6 @@ impl SpaceViewState { space, scene, space_view_id, - highlights, entity_properties, ); }); From a072305de3fc272161810d8c72d0f0bfa300aac2 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 1 Jun 2023 19:38:20 +0200 Subject: [PATCH 11/39] re-enable labels on points --- .../src/scene/elements/points2d.rs | 4 --- .../src/scene/elements/points3d.rs | 6 ---- crates/re_space_view_spatial/src/scene/mod.rs | 9 ++++++ .../src/scene/spatial_scene_element.rs | 17 +++-------- .../re_viewer_context/src/space_view/scene.rs | 30 +++++++++++-------- 5 files changed, 30 insertions(+), 36 deletions(-) diff --git a/crates/re_space_view_spatial/src/scene/elements/points2d.rs b/crates/re_space_view_spatial/src/scene/elements/points2d.rs index d8b04ec0972f..6852918d61b9 100644 --- a/crates/re_space_view_spatial/src/scene/elements/points2d.rs +++ b/crates/re_space_view_spatial/src/scene/elements/points2d.rs @@ -228,8 +228,4 @@ impl SpatialSceneElement<7> for Points2DSceneElement { try_add_line_draw_data(ctx.render_ctx, line_builder, &mut draw_data_list); draw_data_list } - - fn ui_labels(&self) -> &[UiLabel] { - &self.ui_labels - } } diff --git a/crates/re_space_view_spatial/src/scene/elements/points3d.rs b/crates/re_space_view_spatial/src/scene/elements/points3d.rs index e3debe26610e..b7aeb2bcac75 100644 --- a/crates/re_space_view_spatial/src/scene/elements/points3d.rs +++ b/crates/re_space_view_spatial/src/scene/elements/points3d.rs @@ -22,7 +22,6 @@ pub struct Points3DSceneElement { /// If the number of points in the batch is > max_labels, don't render point labels. pub max_labels: usize, pub ui_labels: Vec, - pub bounding_box: macaw::BoundingBox, } impl Default for Points3DSceneElement { @@ -30,7 +29,6 @@ impl Default for Points3DSceneElement { Self { max_labels: 10, ui_labels: Vec::new(), - bounding_box: macaw::BoundingBox::nothing(), } } } @@ -217,8 +215,4 @@ impl SpatialSceneElement<7> for Points3DSceneElement { try_add_line_draw_data(ctx.render_ctx, line_builder, &mut draw_data_list); draw_data_list } - - fn ui_labels(&self) -> &[UiLabel] { - &self.ui_labels - } } diff --git a/crates/re_space_view_spatial/src/scene/mod.rs b/crates/re_space_view_spatial/src/scene/mod.rs index 98d1b64d45ea..5698e4132046 100644 --- a/crates/re_space_view_spatial/src/scene/mod.rs +++ b/crates/re_space_view_spatial/src/scene/mod.rs @@ -188,6 +188,15 @@ impl SceneSpatial { self.primitives.any_outlines = scene_context.highlights.any_outlines(); self.primitives.recalculate_bounding_box(); + // TODO(andreas): Is there a more practical way to get the labels out? + // Rust doesn't generally allow casting from one trait to another, so we can't make this part of a base trait. + if let Ok(points2d) = scene.elements.get_mut::() { + self.ui.labels.append(&mut points2d.ui_labels); + } + if let Ok(points3d) = scene.elements.get_mut::() { + self.ui.labels.append(&mut points3d.ui_labels); + } + self.scene = scene; } diff --git a/crates/re_space_view_spatial/src/scene/spatial_scene_element.rs b/crates/re_space_view_spatial/src/scene/spatial_scene_element.rs index c89fee3bdd7c..2f04c25d97fd 100644 --- a/crates/re_space_view_spatial/src/scene/spatial_scene_element.rs +++ b/crates/re_space_view_spatial/src/scene/spatial_scene_element.rs @@ -14,7 +14,6 @@ use re_viewer_context::{SpaceViewHighlights, SpaceViewOutlineMasks}; use crate::{scene::EntityDepthOffsets, TransformContext}; use super::contexts::AnnotationSceneContext; -use super::UiLabel; /// Context objects for a single entity in a spatial scene. pub struct SpatialSceneEntityContext<'a> { @@ -121,9 +120,6 @@ pub trait SpatialSceneElement: std::any::Any { { SpatialSceneElementWrapper(self) } - - /// Retrieves all ui labels that this scene element should render. - fn ui_labels(&self) -> &[UiLabel]; } /// A wrapper for `SpatialSceneElement` that implements `SceneElement`. @@ -131,13 +127,6 @@ pub trait SpatialSceneElement: std::any::Any { /// Can't implement directly due to Rust limitations around higher kinded traits. pub struct SpatialSceneElementWrapper>(pub T); -impl> SpatialSceneElementWrapper { - /// Retrieves all ui labels that this scene element should render. - fn ui_labels(&self) -> &[UiLabel] { - self.0.ui_labels() - } -} - impl> SceneElement for SpatialSceneElementWrapper { fn archetype(&self) -> re_viewer_context::ArchetypeDefinition { debug_assert!(N > 0); @@ -163,10 +152,12 @@ impl> SceneElement for SpatialSceneEle } fn as_any(&self) -> &dyn std::any::Any { - self + // Forwarding to the inner type allows to cast to the original implementor of SpatialSceneElement. + &self.0 } fn as_any_mut(&mut self) -> &mut dyn std::any::Any { - self + // Forwarding to the inner type allows to cast to the original implementor of SpatialSceneElement. + &mut self.0 } } diff --git a/crates/re_viewer_context/src/space_view/scene.rs b/crates/re_viewer_context/src/space_view/scene.rs index 420b775d74c8..0d4c58a8c9cd 100644 --- a/crates/re_viewer_context/src/space_view/scene.rs +++ b/crates/re_viewer_context/src/space_view/scene.rs @@ -1,4 +1,4 @@ -use std::any::Any; +use std::any::{Any, TypeId}; use ahash::HashMap; use re_log_types::ComponentName; @@ -20,21 +20,21 @@ pub enum SceneItemCollectionLookupError { /// /// New type pattern to support adding From impls. #[derive(Default)] -pub struct SceneContextCollection(HashMap>); +pub struct SceneContextCollection(HashMap>); impl SceneContextCollection { - pub fn get(&self) -> Result<&T, SceneItemCollectionLookupError> { + pub fn get(&self) -> Result<&T, SceneItemCollectionLookupError> { self.0 - .get(&std::any::TypeId::of::()) + .get(&TypeId::of::()) .ok_or(SceneItemCollectionLookupError::TypeNotFound)? .as_any() .downcast_ref::() .ok_or(SceneItemCollectionLookupError::DowncastFailure) } - pub fn get_mut(&mut self) -> Result<&mut T, SceneItemCollectionLookupError> { + pub fn get_mut(&mut self) -> Result<&mut T, SceneItemCollectionLookupError> { self.0 - .get_mut(&std::any::TypeId::of::()) + .get_mut(&TypeId::of::()) .ok_or(SceneItemCollectionLookupError::TypeNotFound)? .as_any_mut() .downcast_mut::() @@ -49,7 +49,7 @@ macro_rules! scene_context_collection_from_tuple { fn from(_value: ($($name,)*)) -> Self { let mut map = HashMap::>::default(); $( - map.insert(std::any::TypeId::of::<$name>(), Box::new(_value.$idx)); + map.insert(_value.$idx.as_any().type_id(), Box::new(_value.$idx)); )* Self(map) } @@ -68,26 +68,30 @@ scene_context_collection_from_tuple!(0 => T0, 1 => T1, 2 => T2, 3 => T3, 4 => T4 /// /// New type pattern to support adding From impls. #[derive(Default)] -pub struct SceneElementCollection(HashMap>); +pub struct SceneElementCollection(HashMap>); impl SceneElementCollection { - pub fn get(&self) -> Result<&T, SceneItemCollectionLookupError> { + pub fn get(&self) -> Result<&T, SceneItemCollectionLookupError> { self.0 - .get(&std::any::TypeId::of::()) + .get(&TypeId::of::()) .ok_or(SceneItemCollectionLookupError::TypeNotFound)? .as_any() .downcast_ref::() .ok_or(SceneItemCollectionLookupError::DowncastFailure) } - pub fn get_mut(&mut self) -> Result<&mut T, SceneItemCollectionLookupError> { + pub fn get_mut(&mut self) -> Result<&mut T, SceneItemCollectionLookupError> { self.0 - .get_mut(&std::any::TypeId::of::()) + .get_mut(&TypeId::of::()) .ok_or(SceneItemCollectionLookupError::TypeNotFound)? .as_any_mut() .downcast_mut::() .ok_or(SceneItemCollectionLookupError::DowncastFailure) } + + pub fn iter(&self) -> impl Iterator> { + self.0.values() + } } macro_rules! scene_element_collection_from_tuple { @@ -97,7 +101,7 @@ macro_rules! scene_element_collection_from_tuple { fn from(_value: ($($name,)*)) -> Self { let mut map = HashMap::>::default(); $( - map.insert(std::any::TypeId::of::<$name>(), Box::new(_value.$idx)); + map.insert(_value.$idx.as_any().type_id(), Box::new(_value.$idx)); )* Self(map) } From 7669ec47c172f9ab84301dc1f2f01d96a47a0eb2 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Fri, 2 Jun 2023 08:41:21 +0200 Subject: [PATCH 12/39] shared draw data workaround --- Cargo.lock | 1 + crates/re_space_view_spatial/Cargo.toml | 3 +- .../src/scene/contexts/annotation_context.rs | 10 ++--- .../src/scene/contexts/depth_offsets.rs | 8 ++-- .../src/scene/contexts/mod.rs | 2 + .../scene/contexts/shared_render_builders.rs | 45 +++++++++++++++++++ .../src/scene/contexts/transform_context.rs | 12 ++--- .../src/scene/elements/mod.rs | 37 --------------- .../src/scene/elements/points2d.rs | 24 ++-------- .../src/scene/elements/points3d.rs | 26 +++-------- crates/re_space_view_spatial/src/scene/mod.rs | 45 +++++++++++++++---- .../src/scene/spatial_scene_element.rs | 6 ++- .../re_viewer_context/src/space_view/scene.rs | 6 +-- 13 files changed, 119 insertions(+), 106 deletions(-) create mode 100644 crates/re_space_view_spatial/src/scene/contexts/shared_render_builders.rs diff --git a/Cargo.lock b/Cargo.lock index 9a4b6ce5fcc6..c442b2886e27 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4272,6 +4272,7 @@ dependencies = [ "itertools", "macaw", "nohash-hasher", + "parking_lot 0.12.1", "re_arrow_store", "re_components", "re_data_store", diff --git a/crates/re_space_view_spatial/Cargo.toml b/crates/re_space_view_spatial/Cargo.toml index c079e5f38e11..4390f337537c 100644 --- a/crates/re_space_view_spatial/Cargo.toml +++ b/crates/re_space_view_spatial/Cargo.toml @@ -34,12 +34,13 @@ re_space_view.workspace = true ahash.workspace = true anyhow.workspace = true bytemuck.workspace = true -egui.workspace = true eframe.workspace = true +egui.workspace = true glam.workspace = true itertools.workspace = true macaw = { workspace = true, features = ["with_serde"] } nohash-hasher.workspace = true +parking_lot.workspace = true serde = "1" smallvec = { workspace = true, features = ["serde"] } vec1.workspace = true diff --git a/crates/re_space_view_spatial/src/scene/contexts/annotation_context.rs b/crates/re_space_view_spatial/src/scene/contexts/annotation_context.rs index 2759271ba308..89c29eb7a89e 100644 --- a/crates/re_space_view_spatial/src/scene/contexts/annotation_context.rs +++ b/crates/re_space_view_spatial/src/scene/contexts/annotation_context.rs @@ -1,13 +1,13 @@ -use re_components::DrawOrder; -use re_log_types::{Component, ComponentName}; -use re_viewer_context::{AnnotationMap, SceneContext}; +use re_components::AnnotationContext; +use re_log_types::Component; +use re_viewer_context::{AnnotationMap, ArchetypeDefinition, SceneContext}; #[derive(Default)] pub struct AnnotationSceneContext(pub AnnotationMap); impl SceneContext for AnnotationSceneContext { - fn component_names(&self) -> Vec { - vec![DrawOrder::name()] + fn archetypes(&self) -> Vec { + vec![vec1::vec1![AnnotationContext::name()]] } fn populate( diff --git a/crates/re_space_view_spatial/src/scene/contexts/depth_offsets.rs b/crates/re_space_view_spatial/src/scene/contexts/depth_offsets.rs index abfc94e08453..37bf59dfcbc8 100644 --- a/crates/re_space_view_spatial/src/scene/contexts/depth_offsets.rs +++ b/crates/re_space_view_spatial/src/scene/contexts/depth_offsets.rs @@ -2,8 +2,8 @@ use std::collections::{BTreeMap, BTreeSet}; use nohash_hasher::IntMap; use re_components::DrawOrder; -use re_log_types::{Component, ComponentName, EntityPathHash}; -use re_viewer_context::SceneContext; +use re_log_types::{Component, EntityPathHash}; +use re_viewer_context::{ArchetypeDefinition, SceneContext}; #[derive(Default)] pub struct EntityDepthOffsets { @@ -15,8 +15,8 @@ pub struct EntityDepthOffsets { } impl SceneContext for EntityDepthOffsets { - fn component_names(&self) -> Vec { - vec![DrawOrder::name()] + fn archetypes(&self) -> Vec { + vec![vec1::vec1![DrawOrder::name()]] } fn populate( diff --git a/crates/re_space_view_spatial/src/scene/contexts/mod.rs b/crates/re_space_view_spatial/src/scene/contexts/mod.rs index 8336361f11ab..72cce8dbdb0a 100644 --- a/crates/re_space_view_spatial/src/scene/contexts/mod.rs +++ b/crates/re_space_view_spatial/src/scene/contexts/mod.rs @@ -1,7 +1,9 @@ mod annotation_context; mod depth_offsets; +mod shared_render_builders; mod transform_context; pub use annotation_context::AnnotationSceneContext; pub use depth_offsets::EntityDepthOffsets; +pub use shared_render_builders::SharedRenderBuilders; pub use transform_context::{TransformContext, UnreachableTransform}; diff --git a/crates/re_space_view_spatial/src/scene/contexts/shared_render_builders.rs b/crates/re_space_view_spatial/src/scene/contexts/shared_render_builders.rs new file mode 100644 index 000000000000..fec2d42cee44 --- /dev/null +++ b/crates/re_space_view_spatial/src/scene/contexts/shared_render_builders.rs @@ -0,0 +1,45 @@ +use parking_lot::{Mutex, MutexGuard}; +use re_renderer::{LineStripSeriesBuilder, PointCloudBuilder}; +use re_viewer_context::{ArchetypeDefinition, SceneContext}; + +// TODO(wumpf): Workaround for Point & Line builder taking up too much memory to emit them on every scene element that as points/lines. +// If these builders/draw-data would allocate space more dynamically, this would not be necessary! +#[derive(Default)] +pub struct SharedRenderBuilders { + pub lines: Option>, + pub points: Option>, +} + +impl SharedRenderBuilders { + pub fn lines(&self) -> MutexGuard<'_, LineStripSeriesBuilder> { + self.lines.as_ref().unwrap().lock() + } + + pub fn points(&self) -> MutexGuard<'_, PointCloudBuilder> { + self.points.as_ref().unwrap().lock() + } +} + +impl SceneContext for SharedRenderBuilders { + fn archetypes(&self) -> Vec { + Vec::new() + } + + fn populate( + &mut self, + ctx: &mut re_viewer_context::ViewerContext<'_>, + _query: &re_viewer_context::SceneQuery<'_>, + _space_view_state: &dyn re_viewer_context::SpaceViewState, + ) { + self.lines = Some(Mutex::new(LineStripSeriesBuilder::new(ctx.render_ctx))); + self.points = Some(Mutex::new(PointCloudBuilder::new(ctx.render_ctx))); + } + + fn as_any(&self) -> &dyn std::any::Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn std::any::Any { + self + } +} diff --git a/crates/re_space_view_spatial/src/scene/contexts/transform_context.rs b/crates/re_space_view_spatial/src/scene/contexts/transform_context.rs index cff0a35f92b7..533beec2af38 100644 --- a/crates/re_space_view_spatial/src/scene/contexts/transform_context.rs +++ b/crates/re_space_view_spatial/src/scene/contexts/transform_context.rs @@ -3,8 +3,8 @@ use nohash_hasher::IntMap; use re_arrow_store::LatestAtQuery; use re_components::{DisconnectedSpace, Pinhole, Transform3D}; use re_data_store::{EntityPath, EntityPropertyMap, EntityTree}; -use re_log_types::{Component, ComponentName, EntityPathHash}; -use re_viewer_context::SceneContext; +use re_log_types::{Component, EntityPathHash}; +use re_viewer_context::{ArchetypeDefinition, SceneContext}; #[derive(Clone)] struct TransformInfo { @@ -84,11 +84,11 @@ impl std::fmt::Display for UnreachableTransform { } impl SceneContext for TransformContext { - fn component_names(&self) -> Vec { + fn archetypes(&self) -> Vec { vec![ - Transform3D::name(), - Pinhole::name(), - DisconnectedSpace::name(), + vec1::vec1![Transform3D::name()], + vec1::vec1![Pinhole::name()], + vec1::vec1![DisconnectedSpace::name()], ] } diff --git a/crates/re_space_view_spatial/src/scene/elements/mod.rs b/crates/re_space_view_spatial/src/scene/elements/mod.rs index 432d09bc4705..aee7235cba9f 100644 --- a/crates/re_space_view_spatial/src/scene/elements/mod.rs +++ b/crates/re_space_view_spatial/src/scene/elements/mod.rs @@ -27,7 +27,6 @@ pub(crate) use points3d::Points3DSceneElement; use re_components::{ClassId, ColorRGBA, KeypointId, Radius}; use re_data_store::{EntityPath, InstancePathHash}; -use re_renderer::{LineStripSeriesBuilder, PointCloudBuilder}; use re_viewer_context::SpaceViewHighlights; use re_viewer_context::{ Annotations, DefaultColor, ResolvedAnnotationInfo, SceneQuery, ViewerContext, @@ -197,39 +196,3 @@ where Ok((annotation_info, keypoints)) } - -fn try_add_point_draw_data( - render_ctx: &mut re_renderer::RenderContext, - point_builder: PointCloudBuilder, - draw_data_list: &mut Vec, -) { - if !point_builder.vertices.is_empty() { - match point_builder.to_draw_data(render_ctx) { - Ok(draw_data) => draw_data_list.push(draw_data.into()), - Err(err) => { - re_log::error_once!( - "Failed to create point cloud draw data for 2D points: {}", - err - ); - } - } - } -} - -fn try_add_line_draw_data( - render_ctx: &mut re_renderer::RenderContext, - line_builder: LineStripSeriesBuilder, - draw_data_list: &mut Vec, -) { - if !line_builder.batches.is_empty() { - match line_builder.to_draw_data(render_ctx) { - Ok(draw_data) => draw_data_list.push(draw_data.into()), - Err(err) => { - re_log::error_once!( - "Failed to create line data for 2D point connections: {}", - err - ); - } - } - } -} diff --git a/crates/re_space_view_spatial/src/scene/elements/points2d.rs b/crates/re_space_view_spatial/src/scene/elements/points2d.rs index 6852918d61b9..9c7fe372db8a 100644 --- a/crates/re_space_view_spatial/src/scene/elements/points2d.rs +++ b/crates/re_space_view_spatial/src/scene/elements/points2d.rs @@ -4,11 +4,9 @@ use re_components::{ use re_data_store::{EntityPath, InstancePathHash}; use re_log_types::ComponentName; use re_query::{EntityView, QueryError}; -use re_renderer::{LineStripSeriesBuilder, PointCloudBuilder}; use re_viewer_context::{ResolvedAnnotationInfo, SceneQuery, ViewerContext}; use crate::scene::{ - elements::{try_add_line_draw_data, try_add_point_draw_data}, load_keypoint_connections, spatial_scene_element::{SpatialSceneContext, SpatialSceneElement, SpatialSceneEntityContext}, UiLabel, UiLabelTarget, @@ -73,8 +71,6 @@ impl Points2DSceneElement { entity_view: &EntityView, ent_path: &EntityPath, ent_context: &SpatialSceneEntityContext<'_>, - point_builder: &mut PointCloudBuilder, - line_builder: &mut re_renderer::LineStripSeriesBuilder, ) -> Result<(), QueryError> { re_tracing::profile_function!(); @@ -114,6 +110,7 @@ impl Points2DSceneElement { //let batch_bb = { { + let mut point_builder = ent_context.shared_render_builders.points(); let point_batch = point_builder .batch("2d points") .depth_offset(ent_context.depth_offset) @@ -170,7 +167,7 @@ impl Points2DSceneElement { // batch_bb }; - load_keypoint_connections(line_builder, ent_path, keypoints, &ent_context.annotations); + load_keypoint_connections(ent_context, ent_path, keypoints); // self.bounding_box = self // .bounding_box @@ -203,29 +200,16 @@ impl SpatialSceneElement<7> for Points2DSceneElement { ) -> Vec { re_tracing::profile_scope!("Points2DPart"); - let mut point_builder = PointCloudBuilder::new(ctx.render_ctx); - let mut line_builder = LineStripSeriesBuilder::new(ctx.render_ctx); - Self::for_each_entity_view( ctx, query, &context, context.depth_offsets.points, |ent_path, entity_view, ent_context| { - self.process_entity_view( - query, - &entity_view, - ent_path, - ent_context, - &mut point_builder, - &mut line_builder, - ) + self.process_entity_view(query, &entity_view, ent_path, ent_context) }, ); - let mut draw_data_list = Vec::new(); - try_add_point_draw_data(ctx.render_ctx, point_builder, &mut draw_data_list); - try_add_line_draw_data(ctx.render_ctx, line_builder, &mut draw_data_list); - draw_data_list + Vec::new() // TODO(andreas): Optionally return point & line draw data once SharedRenderBuilders is gone. } } diff --git a/crates/re_space_view_spatial/src/scene/elements/points3d.rs b/crates/re_space_view_spatial/src/scene/elements/points3d.rs index b7aeb2bcac75..7ebbbd337520 100644 --- a/crates/re_space_view_spatial/src/scene/elements/points3d.rs +++ b/crates/re_space_view_spatial/src/scene/elements/points3d.rs @@ -4,14 +4,12 @@ use re_components::{ use re_data_store::{EntityPath, InstancePathHash}; use re_log_types::ComponentName; use re_query::{EntityView, QueryError}; -use re_renderer::{LineStripSeriesBuilder, PointCloudBuilder}; use re_viewer_context::{ResolvedAnnotationInfo, SceneQuery, ViewerContext}; use crate::scene::{ elements::{ instance_key_to_picking_id, instance_path_hash_for_picking, - process_annotations_and_keypoints, process_colors, process_radii, try_add_line_draw_data, - try_add_point_draw_data, + process_annotations_and_keypoints, process_colors, process_radii, }, load_keypoint_connections, spatial_scene_element::{SpatialSceneContext, SpatialSceneElement, SpatialSceneEntityContext}, @@ -73,8 +71,6 @@ impl Points3DSceneElement { entity_view: &EntityView, ent_path: &EntityPath, ent_context: &SpatialSceneEntityContext<'_>, - point_builder: &mut PointCloudBuilder, - line_builder: &mut re_renderer::LineStripSeriesBuilder, ) -> Result<(), QueryError> { re_tracing::profile_function!(); @@ -114,6 +110,7 @@ impl Points3DSceneElement { } { + let mut point_builder = ent_context.shared_render_builders.points(); let point_batch = point_builder .batch("3d points") .world_from_obj(ent_context.world_from_obj) @@ -161,7 +158,7 @@ impl Points3DSceneElement { } } - load_keypoint_connections(line_builder, ent_path, keypoints, &ent_context.annotations); + load_keypoint_connections(ent_context, ent_path, keypoints); Ok(()) } @@ -190,29 +187,16 @@ impl SpatialSceneElement<7> for Points3DSceneElement { ) -> Vec { re_tracing::profile_scope!("Points3DPart"); - let mut point_builder = PointCloudBuilder::new(ctx.render_ctx); - let mut line_builder = LineStripSeriesBuilder::new(ctx.render_ctx); - Self::for_each_entity_view( ctx, query, &context, context.depth_offsets.points, |ent_path, entity_view, ent_context| { - self.process_entity_view( - query, - &entity_view, - ent_path, - ent_context, - &mut point_builder, - &mut line_builder, - ) + self.process_entity_view(query, &entity_view, ent_path, ent_context) }, ); - let mut draw_data_list = Vec::new(); - try_add_point_draw_data(ctx.render_ctx, point_builder, &mut draw_data_list); - try_add_line_draw_data(ctx.render_ctx, line_builder, &mut draw_data_list); - draw_data_list + Vec::new() // TODO(andreas): Optionally return point & line draw data once SharedRenderBuilders is gone. } } diff --git a/crates/re_space_view_spatial/src/scene/mod.rs b/crates/re_space_view_spatial/src/scene/mod.rs index 5698e4132046..97905605ac69 100644 --- a/crates/re_space_view_spatial/src/scene/mod.rs +++ b/crates/re_space_view_spatial/src/scene/mod.rs @@ -8,11 +8,10 @@ use re_log_types::EntityPathHash; use re_renderer::{renderer::TexturedRect, Color32, OutlineMaskPreference, Size}; use re_viewer_context::SpaceViewHighlights; use re_viewer_context::{ - auto_color, AnnotationMap, Annotations, EmptySpaceViewState, Scene, SceneQuery, ViewerContext, + auto_color, AnnotationMap, EmptySpaceViewState, Scene, SceneQuery, ViewerContext, }; use super::SpatialNavigationMode; -use crate::scene::contexts::AnnotationSceneContext; use crate::scene::spatial_scene_element::{SpatialSceneContext, SpatialSceneElement}; use crate::{mesh_loader::LoadedMesh, space_camera_3d::SpaceCamera3D}; @@ -24,6 +23,7 @@ mod spatial_scene_element; pub use self::picking::{PickingContext, PickingHitType, PickingRayHit, PickingResult}; pub use self::primitives::SceneSpatialPrimitives; +use self::spatial_scene_element::SpatialSceneEntityContext; use elements::ScenePart; use contexts::EntityDepthOffsets; @@ -158,9 +158,10 @@ impl SceneSpatial { // TODO(andreas): Temporary build up of scene. This will be handled by the SpaceViewClass framework later. let mut scene = Scene { contexts: ( - EntityDepthOffsets::default(), - TransformContext::default(), - AnnotationSceneContext::default(), + contexts::EntityDepthOffsets::default(), + contexts::TransformContext::default(), + contexts::AnnotationSceneContext::default(), + contexts::SharedRenderBuilders::default(), ) .into(), elements: ( @@ -196,6 +197,30 @@ impl SceneSpatial { if let Ok(points3d) = scene.elements.get_mut::() { self.ui.labels.append(&mut points3d.ui_labels); } + if let Ok(shared_render_builders) = + scene.contexts.get_mut::() + { + self.draw_data + .extend(shared_render_builders.lines.take().and_then(|l| { + match l.into_inner().to_draw_data(ctx.render_ctx) { + Ok(d) => Some(d.into()), + Err(err) => { + re_log::error_once!("Failed to build line strip draw data: {err}"); + None + } + } + })); + self.draw_data + .extend(shared_render_builders.points.take().and_then(|l| { + match l.into_inner().to_draw_data(ctx.render_ctx) { + Ok(d) => Some(d.into()), + Err(err) => { + re_log::error_once!("Failed to build point draw data: {err}"); + None + } + } + })); + } self.scene = scene; } @@ -225,18 +250,22 @@ impl SceneSpatial { } pub fn load_keypoint_connections( - line_builder: &mut re_renderer::LineStripSeriesBuilder, + ent_context: &SpatialSceneEntityContext<'_>, entity_path: &re_data_store::EntityPath, keypoints: Keypoints, - annotations: &Arc, ) { + if keypoints.is_empty() { + return; + } + // Generate keypoint connections if any. + let mut line_builder = ent_context.shared_render_builders.lines(); let mut line_batch = line_builder .batch("keypoint connections") .picking_object_id(re_renderer::PickingLayerObjectId(entity_path.hash64())); for ((class_id, _time), keypoints_in_class) in keypoints { - let Some(class_description) = annotations.context.class_map.get(&class_id) else { + let Some(class_description) = ent_context.annotations.context.class_map.get(&class_id) else { continue; }; diff --git a/crates/re_space_view_spatial/src/scene/spatial_scene_element.rs b/crates/re_space_view_spatial/src/scene/spatial_scene_element.rs index 2f04c25d97fd..d4215a3ba1dd 100644 --- a/crates/re_space_view_spatial/src/scene/spatial_scene_element.rs +++ b/crates/re_space_view_spatial/src/scene/spatial_scene_element.rs @@ -13,7 +13,7 @@ use re_viewer_context::{SpaceViewHighlights, SpaceViewOutlineMasks}; use crate::{scene::EntityDepthOffsets, TransformContext}; -use super::contexts::AnnotationSceneContext; +use super::contexts::{AnnotationSceneContext, SharedRenderBuilders}; /// Context objects for a single entity in a spatial scene. pub struct SpatialSceneEntityContext<'a> { @@ -21,6 +21,7 @@ pub struct SpatialSceneEntityContext<'a> { pub depth_offset: DepthOffset, pub annotations: Arc, pub highlight: &'a SpaceViewOutlineMasks, + pub shared_render_builders: &'a SharedRenderBuilders, } /// Reference to all context objects of a spatial scene. @@ -28,6 +29,7 @@ pub struct SpatialSceneContext<'a> { pub transforms: &'a TransformContext, pub depth_offsets: &'a EntityDepthOffsets, pub annotations: &'a AnnotationSceneContext, + pub shared_render_builders: &'a SharedRenderBuilders, pub highlights: &'a SpaceViewHighlights, // Not part of the context collection, but convenient to have here. } @@ -40,6 +42,7 @@ impl<'a> SpatialSceneContext<'a> { transforms: contexts.get::()?, depth_offsets: contexts.get::()?, annotations: contexts.get::()?, + shared_render_builders: contexts.get::()?, highlights, }) } @@ -57,6 +60,7 @@ impl<'a> SpatialSceneContext<'a> { .get(&ent_path.hash()) .unwrap_or(&default_depth_offset), annotations: self.annotations.0.find(ent_path), + shared_render_builders: self.shared_render_builders, highlight: self.highlights.entity_outline_mask(ent_path.hash()), }) } diff --git a/crates/re_viewer_context/src/space_view/scene.rs b/crates/re_viewer_context/src/space_view/scene.rs index 0d4c58a8c9cd..846c915d7a2a 100644 --- a/crates/re_viewer_context/src/space_view/scene.rs +++ b/crates/re_viewer_context/src/space_view/scene.rs @@ -1,7 +1,6 @@ use std::any::{Any, TypeId}; use ahash::HashMap; -use re_log_types::ComponentName; use crate::{ArchetypeDefinition, SceneQuery, SpaceViewHighlights, SpaceViewState, ViewerContext}; @@ -197,10 +196,11 @@ pub trait SceneElement: Any { /// TODO: Doc pub trait SceneContext: Any { - /// Scene contexts query loose components instead of archetypes in their populate method. + /// Each scene context may query several archetypes. /// /// This lists all components out that the context queries. - fn component_names(&self) -> Vec; // TODO: Back to archetype definitions? + /// A context may also query no archetypes at all and prepare caches or viewer related data instead. + fn archetypes(&self) -> Vec; /// Queries the data store and performs data conversions to make it ready for consumption by scene elements. fn populate( From a04b69317ea09cb3806d774f893932e817b86437 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Fri, 2 Jun 2023 09:07:20 +0200 Subject: [PATCH 13/39] bounding box handling for ported scene elements --- .../scene/contexts/shared_render_builders.rs | 14 ++++++-- .../src/scene/elements/points2d.rs | 36 ++++++++++++------- .../src/scene/elements/points3d.rs | 28 ++++++++++++--- crates/re_space_view_spatial/src/scene/mod.rs | 26 +++++++++----- .../src/scene/primitives.rs | 27 ++++++-------- .../src/scene/spatial_scene_element.rs | 24 +++++++++++++ .../src/ui_renderer_bridge.rs | 1 - .../re_viewer_context/src/space_view/scene.rs | 8 +++++ 8 files changed, 119 insertions(+), 45 deletions(-) diff --git a/crates/re_space_view_spatial/src/scene/contexts/shared_render_builders.rs b/crates/re_space_view_spatial/src/scene/contexts/shared_render_builders.rs index fec2d42cee44..98a0b4551764 100644 --- a/crates/re_space_view_spatial/src/scene/contexts/shared_render_builders.rs +++ b/crates/re_space_view_spatial/src/scene/contexts/shared_render_builders.rs @@ -2,6 +2,10 @@ use parking_lot::{Mutex, MutexGuard}; use re_renderer::{LineStripSeriesBuilder, PointCloudBuilder}; use re_viewer_context::{ArchetypeDefinition, SceneContext}; +use crate::scene::{ + SIZE_BOOST_IN_POINTS_FOR_LINE_OUTLINES, SIZE_BOOST_IN_POINTS_FOR_POINT_OUTLINES, +}; + // TODO(wumpf): Workaround for Point & Line builder taking up too much memory to emit them on every scene element that as points/lines. // If these builders/draw-data would allocate space more dynamically, this would not be necessary! #[derive(Default)] @@ -31,8 +35,14 @@ impl SceneContext for SharedRenderBuilders { _query: &re_viewer_context::SceneQuery<'_>, _space_view_state: &dyn re_viewer_context::SpaceViewState, ) { - self.lines = Some(Mutex::new(LineStripSeriesBuilder::new(ctx.render_ctx))); - self.points = Some(Mutex::new(PointCloudBuilder::new(ctx.render_ctx))); + self.lines = Some(Mutex::new( + LineStripSeriesBuilder::new(ctx.render_ctx) + .radius_boost_in_ui_points_for_outlines(SIZE_BOOST_IN_POINTS_FOR_LINE_OUTLINES), + )); + self.points = Some(Mutex::new( + PointCloudBuilder::new(ctx.render_ctx) + .radius_boost_in_ui_points_for_outlines(SIZE_BOOST_IN_POINTS_FOR_POINT_OUTLINES), + )); } fn as_any(&self) -> &dyn std::any::Any { diff --git a/crates/re_space_view_spatial/src/scene/elements/points2d.rs b/crates/re_space_view_spatial/src/scene/elements/points2d.rs index 9c7fe372db8a..62a8bb116aca 100644 --- a/crates/re_space_view_spatial/src/scene/elements/points2d.rs +++ b/crates/re_space_view_spatial/src/scene/elements/points2d.rs @@ -8,7 +8,10 @@ use re_viewer_context::{ResolvedAnnotationInfo, SceneQuery, ViewerContext}; use crate::scene::{ load_keypoint_connections, - spatial_scene_element::{SpatialSceneContext, SpatialSceneElement, SpatialSceneEntityContext}, + spatial_scene_element::{ + SpatialSceneContext, SpatialSceneElement, SpatialSceneElementData, + SpatialSceneEntityContext, + }, UiLabel, UiLabelTarget, }; @@ -20,16 +23,14 @@ use super::{ pub struct Points2DSceneElement { /// If the number of points in the batch is > max_labels, don't render point labels. pub max_labels: usize, - pub ui_labels: Vec, - pub bounding_box: macaw::BoundingBox, + pub data: SpatialSceneElementData, } impl Default for Points2DSceneElement { fn default() -> Self { Self { max_labels: 10, - ui_labels: Vec::new(), - bounding_box: macaw::BoundingBox::nothing(), + data: Default::default(), } } } @@ -100,7 +101,7 @@ impl Points2DSceneElement { .collect::>() }; - self.ui_labels.extend(Self::process_labels( + self.data.ui_labels.extend(Self::process_labels( entity_view, &instance_path_hashes_for_picking, &colors, @@ -108,7 +109,6 @@ impl Points2DSceneElement { )?); } - //let batch_bb = { { let mut point_builder = ent_context.shared_render_builders.points(); let point_batch = point_builder @@ -128,7 +128,6 @@ impl Points2DSceneElement { .iter_primary()? .filter_map(|pt| pt.map(glam::Vec2::from)) }; - //let batch_bb = macaw::BoundingBox::from_points(point_positions.map(|p| p.extend(0.0))); let picking_instance_ids = entity_view.iter_instance_keys().map(|instance_key| { instance_key_to_picking_id( @@ -163,15 +162,22 @@ impl Points2DSceneElement { } } } - - // batch_bb }; load_keypoint_connections(ent_context, ent_path, keypoints); - // self.bounding_box = self - // .bounding_box - // .union(batch_bb.transform_affine3(&ent_context.world_from_obj)); + { + re_tracing::profile_scope!("points2d.bounding_box"); + self.data.bounding_box = self.data.bounding_box.union( + macaw::BoundingBox::from_points( + entity_view + .iter_primary()? + .filter_map(|pt| pt.map(|pt| glam::vec3(pt.x, pt.y, 0.0))), + ) + .transform_affine3(&ent_context.world_from_obj), + ); + } + self.data.num_primitives += entity_view.num_instances(); Ok(()) } @@ -212,4 +218,8 @@ impl SpatialSceneElement<7> for Points2DSceneElement { Vec::new() // TODO(andreas): Optionally return point & line draw data once SharedRenderBuilders is gone. } + + fn data(&self) -> &SpatialSceneElementData { + &self.data + } } diff --git a/crates/re_space_view_spatial/src/scene/elements/points3d.rs b/crates/re_space_view_spatial/src/scene/elements/points3d.rs index 7ebbbd337520..1710f8d47389 100644 --- a/crates/re_space_view_spatial/src/scene/elements/points3d.rs +++ b/crates/re_space_view_spatial/src/scene/elements/points3d.rs @@ -12,21 +12,24 @@ use crate::scene::{ process_annotations_and_keypoints, process_colors, process_radii, }, load_keypoint_connections, - spatial_scene_element::{SpatialSceneContext, SpatialSceneElement, SpatialSceneEntityContext}, + spatial_scene_element::{ + SpatialSceneContext, SpatialSceneElement, SpatialSceneElementData, + SpatialSceneEntityContext, + }, UiLabel, UiLabelTarget, }; pub struct Points3DSceneElement { /// If the number of points in the batch is > max_labels, don't render point labels. pub max_labels: usize, - pub ui_labels: Vec, + pub data: SpatialSceneElementData, } impl Default for Points3DSceneElement { fn default() -> Self { Self { max_labels: 10, - ui_labels: Vec::new(), + data: Default::default(), } } } @@ -100,7 +103,7 @@ impl Points3DSceneElement { .collect::>() }; - self.ui_labels.extend(Self::process_labels( + self.data.ui_labels.extend(Self::process_labels( entity_view, &instance_path_hashes_for_picking, &colors, @@ -160,6 +163,19 @@ impl Points3DSceneElement { load_keypoint_connections(ent_context, ent_path, keypoints); + { + re_tracing::profile_scope!("points3d.bounding_box"); + self.data.bounding_box = self.data.bounding_box.union( + macaw::BoundingBox::from_points( + entity_view + .iter_primary()? + .filter_map(|pt| pt.map(|pt| pt.into())), + ) + .transform_affine3(&ent_context.world_from_obj), + ); + } + self.data.num_primitives += entity_view.num_instances(); + Ok(()) } } @@ -199,4 +215,8 @@ impl SpatialSceneElement<7> for Points3DSceneElement { Vec::new() // TODO(andreas): Optionally return point & line draw data once SharedRenderBuilders is gone. } + + fn data(&self) -> &crate::scene::spatial_scene_element::SpatialSceneElementData { + &self.data + } } diff --git a/crates/re_space_view_spatial/src/scene/mod.rs b/crates/re_space_view_spatial/src/scene/mod.rs index 97905605ac69..ba8229577ae3 100644 --- a/crates/re_space_view_spatial/src/scene/mod.rs +++ b/crates/re_space_view_spatial/src/scene/mod.rs @@ -12,7 +12,9 @@ use re_viewer_context::{ }; use super::SpatialNavigationMode; -use crate::scene::spatial_scene_element::{SpatialSceneContext, SpatialSceneElement}; +use crate::scene::spatial_scene_element::{ + SpatialSceneContext, SpatialSceneElement, SpatialSceneElementData, +}; use crate::{mesh_loader::LoadedMesh, space_camera_3d::SpaceCamera3D}; mod contexts; @@ -29,6 +31,9 @@ use elements::ScenePart; use contexts::EntityDepthOffsets; pub use contexts::{TransformContext, UnreachableTransform}; +const SIZE_BOOST_IN_POINTS_FOR_LINE_OUTLINES: f32 = 1.5; +const SIZE_BOOST_IN_POINTS_FOR_POINT_OUTLINES: f32 = 2.5; + /// TODO(andreas): Scene should only care about converted rendering primitive. pub struct MeshSource { pub picking_instance_hash: InstancePathHash, @@ -54,6 +59,7 @@ pub struct Image { pub draw_order: DrawOrder, } +#[derive(Clone)] pub enum UiLabelTarget { /// Labels a given rect (in scene coordinates) Rect(egui::Rect), @@ -65,6 +71,7 @@ pub enum UiLabelTarget { Position3D(glam::Vec3), } +#[derive(Clone)] pub struct UiLabel { pub text: String, pub color: Color32, @@ -189,13 +196,16 @@ impl SceneSpatial { self.primitives.any_outlines = scene_context.highlights.any_outlines(); self.primitives.recalculate_bounding_box(); - // TODO(andreas): Is there a more practical way to get the labels out? - // Rust doesn't generally allow casting from one trait to another, so we can't make this part of a base trait. - if let Ok(points2d) = scene.elements.get_mut::() { - self.ui.labels.append(&mut points2d.ui_labels); - } - if let Ok(points3d) = scene.elements.get_mut::() { - self.ui.labels.append(&mut points3d.ui_labels); + for scene_element in scene.elements.iter() { + if let Some(data) = scene_element + .data() + .and_then(|d| d.downcast_ref::()) + { + self.ui.labels.extend(data.ui_labels.iter().cloned()); + self.primitives.bounding_box = + self.primitives.bounding_box.union(data.bounding_box); + self.primitives.num_primitives += data.num_primitives; + } } if let Ok(shared_render_builders) = scene.contexts.get_mut::() diff --git a/crates/re_space_view_spatial/src/scene/primitives.rs b/crates/re_space_view_spatial/src/scene/primitives.rs index a406c603f566..3bc989849b1d 100644 --- a/crates/re_space_view_spatial/src/scene/primitives.rs +++ b/crates/re_space_view_spatial/src/scene/primitives.rs @@ -3,12 +3,14 @@ use re_data_store::EntityPath; use re_log_types::InstanceKey; use re_renderer::{ renderer::{DepthClouds, MeshInstance}, - LineStripSeriesBuilder, PointCloudBuilder, + LineStripSeriesBuilder, }; use crate::instance_hash_conversions::picking_layer_id_from_instance_path_hash; -use super::MeshSource; +use super::{ + MeshSource, SIZE_BOOST_IN_POINTS_FOR_LINE_OUTLINES, SIZE_BOOST_IN_POINTS_FOR_POINT_OUTLINES, +}; /// Primitives sent off to `re_renderer`. /// (Some meta information still relevant to ui setup as well) @@ -20,9 +22,10 @@ pub struct SceneSpatialPrimitives { /// Estimated bounding box of all data in scene coordinates. Accumulated. pub(super) bounding_box: macaw::BoundingBox, + pub num_primitives: usize, + pub images: Vec, pub line_strips: LineStripSeriesBuilder, - pub points: PointCloudBuilder, pub meshes: Vec, pub depth_clouds: DepthClouds, @@ -33,18 +36,14 @@ const AXIS_COLOR_X: Color32 = Color32::from_rgb(255, 25, 25); const AXIS_COLOR_Y: Color32 = Color32::from_rgb(0, 240, 0); const AXIS_COLOR_Z: Color32 = Color32::from_rgb(80, 80, 255); -const SIZE_BOOST_IN_POINTS_FOR_LINE_OUTLINES: f32 = 1.5; -const SIZE_BOOST_IN_POINTS_FOR_POINT_OUTLINES: f32 = 2.5; - impl SceneSpatialPrimitives { pub fn new(re_ctx: &mut re_renderer::RenderContext) -> Self { Self { bounding_box: macaw::BoundingBox::nothing(), + num_primitives: 0, images: Default::default(), line_strips: LineStripSeriesBuilder::new(re_ctx) .radius_boost_in_ui_points_for_outlines(SIZE_BOOST_IN_POINTS_FOR_LINE_OUTLINES), - points: PointCloudBuilder::new(re_ctx) - .radius_boost_in_ui_points_for_outlines(SIZE_BOOST_IN_POINTS_FOR_POINT_OUTLINES), meshes: Default::default(), depth_clouds: DepthClouds { clouds: Default::default(), @@ -63,9 +62,9 @@ impl SceneSpatialPrimitives { pub fn num_primitives(&self) -> usize { let Self { bounding_box: _, + num_primitives, images, line_strips, - points, meshes, depth_clouds, any_outlines: _, @@ -73,7 +72,7 @@ impl SceneSpatialPrimitives { images.len() + line_strips.vertices.len() - + points.vertices.len() + + num_primitives + meshes.len() + depth_clouds.clouds.len() } @@ -83,16 +82,14 @@ impl SceneSpatialPrimitives { let Self { bounding_box, + num_primitives: _, images, line_strips, - points, meshes, depth_clouds, any_outlines: _, } = self; - *bounding_box = macaw::BoundingBox::nothing(); - for image in images { let rect = &image.textured_rect; bounding_box.extend(rect.top_left_corner_position); @@ -103,10 +100,6 @@ impl SceneSpatialPrimitives { // We don't need a very accurate bounding box, so in order to save some time, // we calculate a per batch bounding box for lines and points. - for (batch, vertex_iter) in points.iter_vertices_by_batch() { - let batch_bb = macaw::BoundingBox::from_points(vertex_iter.map(|v| v.position)); - *bounding_box = bounding_box.union(batch_bb.transform_affine3(&batch.world_from_obj)); - } for (batch, vertex_iter) in line_strips.iter_vertices_by_batch() { let batch_bb = macaw::BoundingBox::from_points(vertex_iter.map(|v| v.position)); *bounding_box = bounding_box.union(batch_bb.transform_affine3(&batch.world_from_obj)); diff --git a/crates/re_space_view_spatial/src/scene/spatial_scene_element.rs b/crates/re_space_view_spatial/src/scene/spatial_scene_element.rs index d4215a3ba1dd..17fd0d477342 100644 --- a/crates/re_space_view_spatial/src/scene/spatial_scene_element.rs +++ b/crates/re_space_view_spatial/src/scene/spatial_scene_element.rs @@ -14,6 +14,7 @@ use re_viewer_context::{SpaceViewHighlights, SpaceViewOutlineMasks}; use crate::{scene::EntityDepthOffsets, TransformContext}; use super::contexts::{AnnotationSceneContext, SharedRenderBuilders}; +use super::UiLabel; /// Context objects for a single entity in a spatial scene. pub struct SpatialSceneEntityContext<'a> { @@ -66,6 +67,23 @@ impl<'a> SpatialSceneContext<'a> { } } +/// Common data struct for all spatial scene elements. +pub struct SpatialSceneElementData { + pub ui_labels: Vec, + pub bounding_box: macaw::BoundingBox, + pub num_primitives: usize, +} + +impl Default for SpatialSceneElementData { + fn default() -> Self { + Self { + ui_labels: Vec::new(), + bounding_box: macaw::BoundingBox::nothing(), + num_primitives: 0, + } + } +} + pub trait SpatialSceneElement: std::any::Any { type Primary: Component + 'static; @@ -78,6 +96,8 @@ pub trait SpatialSceneElement: std::any::Any { context: SpatialSceneContext<'_>, ) -> Vec; + fn data(&self) -> &SpatialSceneElementData; + fn for_each_entity_view( ctx: &mut ViewerContext<'_>, query: &SceneQuery<'_>, @@ -155,6 +175,10 @@ impl> SceneElement for SpatialSceneEle self.0.populate(ctx, query, contexts) } + fn data(&self) -> Option<&dyn std::any::Any> { + Some(self.0.data()) + } + fn as_any(&self) -> &dyn std::any::Any { // Forwarding to the inner type allows to cast to the original implementor of SpatialSceneElement. &self.0 diff --git a/crates/re_space_view_spatial/src/ui_renderer_bridge.rs b/crates/re_space_view_spatial/src/ui_renderer_bridge.rs index ba9625f535e5..61f97467b9a7 100644 --- a/crates/re_space_view_spatial/src/ui_renderer_bridge.rs +++ b/crates/re_space_view_spatial/src/ui_renderer_bridge.rs @@ -26,7 +26,6 @@ pub fn fill_view_builder( )?) .queue_draw(MeshDrawData::new(render_ctx, &primitives.mesh_instances())?) .queue_draw(primitives.line_strips.to_draw_data(render_ctx)?) - .queue_draw(primitives.points.to_draw_data(render_ctx)?) .queue_draw(RectangleDrawData::new( render_ctx, &primitives diff --git a/crates/re_viewer_context/src/space_view/scene.rs b/crates/re_viewer_context/src/space_view/scene.rs index 846c915d7a2a..0524cdb4f687 100644 --- a/crates/re_viewer_context/src/space_view/scene.rs +++ b/crates/re_viewer_context/src/space_view/scene.rs @@ -187,6 +187,14 @@ pub trait SceneElement: Any { highlights: &SpaceViewHighlights, ) -> Vec; + /// Optionally retrieves a data store reference from the scene element. + /// + /// This is a useful for retrieving a data struct that may be common for all scene elements + /// of a particular [`crate::SpaceViewClass`]. + fn data(&self) -> Option<&dyn std::any::Any> { + None + } + /// Converts itself to a reference of [`Any`], which enables downcasting to concrete types. fn as_any(&self) -> &dyn std::any::Any; From f7a8a189d5f44b75c787f933314a82025d201b53 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Fri, 2 Jun 2023 09:29:20 +0200 Subject: [PATCH 14/39] scene context docs --- crates/re_viewer_context/src/space_view/scene.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/re_viewer_context/src/space_view/scene.rs b/crates/re_viewer_context/src/space_view/scene.rs index 0524cdb4f687..641feb121cdd 100644 --- a/crates/re_viewer_context/src/space_view/scene.rs +++ b/crates/re_viewer_context/src/space_view/scene.rs @@ -171,6 +171,8 @@ impl Scene { } /// Element of a scene derived from a single archetype query. +/// +/// Is populated after scene contexts and has access to them. pub trait SceneElement: Any { /// The archetype queried by this scene element. fn archetype(&self) -> ArchetypeDefinition; @@ -202,7 +204,9 @@ pub trait SceneElement: Any { fn as_any_mut(&mut self) -> &mut dyn std::any::Any; } -/// TODO: Doc +/// Scene context that can be used by scene elements and ui methods to retrieve information about the scene as a whole. +/// +/// Is always populated before scene elements. pub trait SceneContext: Any { /// Each scene context may query several archetypes. /// From 948623efe3c3d6f7099b0c7c45c3ae50c695dd76 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Fri, 2 Jun 2023 10:45:33 +0200 Subject: [PATCH 15/39] scene context is now more strongly typed --- .../src/scene/contexts/annotation_context.rs | 4 +- .../src/scene/contexts/depth_offsets.rs | 6 +- .../src/scene/contexts/mod.rs | 75 ++++++++++++ .../scene/contexts/shared_render_builders.rs | 4 +- .../src/scene/contexts/transform_context.rs | 4 +- .../src/scene/elements/points2d.rs | 46 ++++--- .../src/scene/elements/points3d.rs | 46 ++++--- crates/re_space_view_spatial/src/scene/mod.rs | 87 +++++++------- .../src/scene/spatial_scene_element.rs | 113 ++++-------------- .../re_space_view_text/src/scene_element.rs | 9 +- .../src/space_view_class.rs | 12 +- .../src/scene_element.rs | 9 +- .../src/space_view_class.rs | 10 +- crates/re_viewer_context/src/lib.rs | 8 +- .../re_viewer_context/src/space_view/mod.rs | 4 +- .../re_viewer_context/src/space_view/scene.rs | 73 +++++------ .../src/space_view/scene_element_impl.rs | 47 +++++--- .../src/space_view/space_view_class_impl.rs | 25 ++-- 18 files changed, 301 insertions(+), 281 deletions(-) diff --git a/crates/re_space_view_spatial/src/scene/contexts/annotation_context.rs b/crates/re_space_view_spatial/src/scene/contexts/annotation_context.rs index 89c29eb7a89e..29d3ef637bc5 100644 --- a/crates/re_space_view_spatial/src/scene/contexts/annotation_context.rs +++ b/crates/re_space_view_spatial/src/scene/contexts/annotation_context.rs @@ -1,11 +1,11 @@ use re_components::AnnotationContext; use re_log_types::Component; -use re_viewer_context::{AnnotationMap, ArchetypeDefinition, SceneContext}; +use re_viewer_context::{AnnotationMap, ArchetypeDefinition, SceneContextPart}; #[derive(Default)] pub struct AnnotationSceneContext(pub AnnotationMap); -impl SceneContext for AnnotationSceneContext { +impl SceneContextPart for AnnotationSceneContext { fn archetypes(&self) -> Vec { vec![vec1::vec1![AnnotationContext::name()]] } diff --git a/crates/re_space_view_spatial/src/scene/contexts/depth_offsets.rs b/crates/re_space_view_spatial/src/scene/contexts/depth_offsets.rs index 37bf59dfcbc8..c64be11f2fdc 100644 --- a/crates/re_space_view_spatial/src/scene/contexts/depth_offsets.rs +++ b/crates/re_space_view_spatial/src/scene/contexts/depth_offsets.rs @@ -3,8 +3,10 @@ use std::collections::{BTreeMap, BTreeSet}; use nohash_hasher::IntMap; use re_components::DrawOrder; use re_log_types::{Component, EntityPathHash}; -use re_viewer_context::{ArchetypeDefinition, SceneContext}; +use re_viewer_context::{ArchetypeDefinition, SceneContextPart}; +// TODO(wumpf): In the new traitified system it would be likely more ergonomic to map from darw order to depth offset +// This would also yield more consistent/meaningful archetypes and avoid queries where not needed. #[derive(Default)] pub struct EntityDepthOffsets { pub per_entity: IntMap, @@ -14,7 +16,7 @@ pub struct EntityDepthOffsets { pub points: re_renderer::DepthOffset, } -impl SceneContext for EntityDepthOffsets { +impl SceneContextPart for EntityDepthOffsets { fn archetypes(&self) -> Vec { vec![vec1::vec1![DrawOrder::name()]] } diff --git a/crates/re_space_view_spatial/src/scene/contexts/mod.rs b/crates/re_space_view_spatial/src/scene/contexts/mod.rs index 72cce8dbdb0a..6a1f89e6ff39 100644 --- a/crates/re_space_view_spatial/src/scene/contexts/mod.rs +++ b/crates/re_space_view_spatial/src/scene/contexts/mod.rs @@ -3,7 +3,82 @@ mod depth_offsets; mod shared_render_builders; mod transform_context; +use std::sync::atomic::AtomicUsize; + pub use annotation_context::AnnotationSceneContext; pub use depth_offsets::EntityDepthOffsets; pub use shared_render_builders::SharedRenderBuilders; pub use transform_context::{TransformContext, UnreachableTransform}; + +// ----------------------------------------------------------------------------- + +use re_log_types::EntityPath; +use re_renderer::DepthOffset; +use re_viewer_context::{Annotations, SceneContext}; + +#[derive(Default)] +pub struct SpatialSceneContext { + pub transforms: TransformContext, + pub depth_offsets: EntityDepthOffsets, + pub annotations: AnnotationSceneContext, + pub shared_render_builders: SharedRenderBuilders, + + pub num_primitives: AtomicUsize, +} + +impl SceneContext for SpatialSceneContext { + fn vec_mut(&mut self) -> Vec<&mut dyn re_viewer_context::SceneContextPart> { + let Self { + transforms, + depth_offsets, + annotations, + shared_render_builders, + + num_primitives: _, + } = self; + vec![ + transforms, + depth_offsets, + annotations, + shared_render_builders, + ] + } + + fn as_any(&self) -> &dyn std::any::Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn std::any::Any { + self + } +} + +impl SpatialSceneContext { + pub fn query<'a>( + &'a self, + ent_path: &EntityPath, + highlights: &'a re_viewer_context::SpaceViewHighlights, + default_depth_offset: DepthOffset, + ) -> Option> { + Some(SpatialSceneEntityContext { + world_from_obj: self.transforms.reference_from_entity(ent_path)?, + depth_offset: *self + .depth_offsets + .per_entity + .get(&ent_path.hash()) + .unwrap_or(&default_depth_offset), + annotations: self.annotations.0.find(ent_path), + shared_render_builders: &self.shared_render_builders, + highlight: highlights.entity_outline_mask(ent_path.hash()), + }) + } +} + +/// Context objects for a single entity in a spatial scene. +pub struct SpatialSceneEntityContext<'a> { + pub world_from_obj: glam::Affine3A, + pub depth_offset: DepthOffset, + pub annotations: std::sync::Arc, + pub shared_render_builders: &'a SharedRenderBuilders, + pub highlight: &'a re_viewer_context::SpaceViewOutlineMasks, // Not part of the context, but convenient to have here. +} diff --git a/crates/re_space_view_spatial/src/scene/contexts/shared_render_builders.rs b/crates/re_space_view_spatial/src/scene/contexts/shared_render_builders.rs index 98a0b4551764..b78573300d9a 100644 --- a/crates/re_space_view_spatial/src/scene/contexts/shared_render_builders.rs +++ b/crates/re_space_view_spatial/src/scene/contexts/shared_render_builders.rs @@ -1,6 +1,6 @@ use parking_lot::{Mutex, MutexGuard}; use re_renderer::{LineStripSeriesBuilder, PointCloudBuilder}; -use re_viewer_context::{ArchetypeDefinition, SceneContext}; +use re_viewer_context::{ArchetypeDefinition, SceneContextPart}; use crate::scene::{ SIZE_BOOST_IN_POINTS_FOR_LINE_OUTLINES, SIZE_BOOST_IN_POINTS_FOR_POINT_OUTLINES, @@ -24,7 +24,7 @@ impl SharedRenderBuilders { } } -impl SceneContext for SharedRenderBuilders { +impl SceneContextPart for SharedRenderBuilders { fn archetypes(&self) -> Vec { Vec::new() } diff --git a/crates/re_space_view_spatial/src/scene/contexts/transform_context.rs b/crates/re_space_view_spatial/src/scene/contexts/transform_context.rs index 533beec2af38..56364f89bec6 100644 --- a/crates/re_space_view_spatial/src/scene/contexts/transform_context.rs +++ b/crates/re_space_view_spatial/src/scene/contexts/transform_context.rs @@ -4,7 +4,7 @@ use re_arrow_store::LatestAtQuery; use re_components::{DisconnectedSpace, Pinhole, Transform3D}; use re_data_store::{EntityPath, EntityPropertyMap, EntityTree}; use re_log_types::{Component, EntityPathHash}; -use re_viewer_context::{ArchetypeDefinition, SceneContext}; +use re_viewer_context::{ArchetypeDefinition, SceneContextPart}; #[derive(Clone)] struct TransformInfo { @@ -83,7 +83,7 @@ impl std::fmt::Display for UnreachableTransform { } } -impl SceneContext for TransformContext { +impl SceneContextPart for TransformContext { fn archetypes(&self) -> Vec { vec![ vec1::vec1![Transform3D::name()], diff --git a/crates/re_space_view_spatial/src/scene/elements/points2d.rs b/crates/re_space_view_spatial/src/scene/elements/points2d.rs index 62a8bb116aca..507003369d8c 100644 --- a/crates/re_space_view_spatial/src/scene/elements/points2d.rs +++ b/crates/re_space_view_spatial/src/scene/elements/points2d.rs @@ -4,14 +4,12 @@ use re_components::{ use re_data_store::{EntityPath, InstancePathHash}; use re_log_types::ComponentName; use re_query::{EntityView, QueryError}; -use re_viewer_context::{ResolvedAnnotationInfo, SceneQuery, ViewerContext}; +use re_viewer_context::{ResolvedAnnotationInfo, SceneQuery, SpaceViewHighlights, ViewerContext}; use crate::scene::{ + contexts::{SpatialSceneContext, SpatialSceneEntityContext}, load_keypoint_connections, - spatial_scene_element::{ - SpatialSceneContext, SpatialSceneElement, SpatialSceneElementData, - SpatialSceneEntityContext, - }, + spatial_scene_element::{SpatialSceneElement, SpatialSceneElementData}, UiLabel, UiLabelTarget, }; @@ -69,32 +67,31 @@ impl Points2DSceneElement { fn process_entity_view( &mut self, query: &SceneQuery<'_>, - entity_view: &EntityView, + ent_view: &EntityView, ent_path: &EntityPath, ent_context: &SpatialSceneEntityContext<'_>, ) -> Result<(), QueryError> { re_tracing::profile_function!(); let (annotation_infos, keypoints) = - process_annotations_and_keypoints(query, entity_view, &ent_context.annotations)?; + process_annotations_and_keypoints(query, ent_view, &ent_context.annotations)?; - let colors = process_colors(entity_view, ent_path, &annotation_infos)?; - let radii = process_radii(ent_path, entity_view)?; + let colors = process_colors(ent_view, ent_path, &annotation_infos)?; + let radii = process_radii(ent_path, ent_view)?; - if entity_view.num_instances() <= self.max_labels { + if ent_view.num_instances() <= self.max_labels { // Max labels is small enough that we can afford iterating on the colors again. - let colors = - process_colors(entity_view, ent_path, &annotation_infos)?.collect::>(); + let colors = process_colors(ent_view, ent_path, &annotation_infos)?.collect::>(); let instance_path_hashes_for_picking = { re_tracing::profile_scope!("instance_hashes"); - entity_view + ent_view .iter_instance_keys() .map(|instance_key| { instance_path_hash_for_picking( ent_path, instance_key, - entity_view.num_instances(), + ent_view.num_instances(), ent_context.highlight.any_selection_highlight, ) }) @@ -102,7 +99,7 @@ impl Points2DSceneElement { }; self.data.ui_labels.extend(Self::process_labels( - entity_view, + ent_view, &instance_path_hashes_for_picking, &colors, &annotation_infos, @@ -124,21 +121,21 @@ impl Points2DSceneElement { let point_positions = { re_tracing::profile_scope!("collect_points"); - entity_view + ent_view .iter_primary()? .filter_map(|pt| pt.map(glam::Vec2::from)) }; - let picking_instance_ids = entity_view.iter_instance_keys().map(|instance_key| { + let picking_instance_ids = ent_view.iter_instance_keys().map(|instance_key| { instance_key_to_picking_id( instance_key, - entity_view.num_instances(), + ent_view.num_instances(), ent_context.highlight.any_selection_highlight, ) }); let mut point_range_builder = point_batch.add_points_2d( - entity_view.num_instances(), + ent_view.num_instances(), point_positions, radii, colors, @@ -150,7 +147,7 @@ impl Points2DSceneElement { re_tracing::profile_scope!("marking additional highlight points"); for (highlighted_key, instance_mask_ids) in &ent_context.highlight.instances { // TODO(andreas/jeremy): We can do this much more efficiently - let highlighted_point_index = entity_view + let highlighted_point_index = ent_view .iter_instance_keys() .position(|key| key == *highlighted_key); if let Some(highlighted_point_index) = highlighted_point_index { @@ -170,14 +167,13 @@ impl Points2DSceneElement { re_tracing::profile_scope!("points2d.bounding_box"); self.data.bounding_box = self.data.bounding_box.union( macaw::BoundingBox::from_points( - entity_view + ent_view .iter_primary()? .filter_map(|pt| pt.map(|pt| glam::vec3(pt.x, pt.y, 0.0))), ) .transform_affine3(&ent_context.world_from_obj), ); } - self.data.num_primitives += entity_view.num_instances(); Ok(()) } @@ -202,14 +198,16 @@ impl SpatialSceneElement<7> for Points2DSceneElement { &mut self, ctx: &mut ViewerContext<'_>, query: &SceneQuery<'_>, - context: SpatialSceneContext<'_>, + context: &SpatialSceneContext, + highlights: &SpaceViewHighlights, ) -> Vec { re_tracing::profile_scope!("Points2DPart"); Self::for_each_entity_view( ctx, query, - &context, + context, + highlights, context.depth_offsets.points, |ent_path, entity_view, ent_context| { self.process_entity_view(query, &entity_view, ent_path, ent_context) diff --git a/crates/re_space_view_spatial/src/scene/elements/points3d.rs b/crates/re_space_view_spatial/src/scene/elements/points3d.rs index 1710f8d47389..dafa3d49eb18 100644 --- a/crates/re_space_view_spatial/src/scene/elements/points3d.rs +++ b/crates/re_space_view_spatial/src/scene/elements/points3d.rs @@ -4,18 +4,16 @@ use re_components::{ use re_data_store::{EntityPath, InstancePathHash}; use re_log_types::ComponentName; use re_query::{EntityView, QueryError}; -use re_viewer_context::{ResolvedAnnotationInfo, SceneQuery, ViewerContext}; +use re_viewer_context::{ResolvedAnnotationInfo, SceneQuery, SpaceViewHighlights, ViewerContext}; use crate::scene::{ + contexts::{SpatialSceneContext, SpatialSceneEntityContext}, elements::{ instance_key_to_picking_id, instance_path_hash_for_picking, process_annotations_and_keypoints, process_colors, process_radii, }, load_keypoint_connections, - spatial_scene_element::{ - SpatialSceneContext, SpatialSceneElement, SpatialSceneElementData, - SpatialSceneEntityContext, - }, + spatial_scene_element::{SpatialSceneElement, SpatialSceneElementData}, UiLabel, UiLabelTarget, }; @@ -71,32 +69,31 @@ impl Points3DSceneElement { fn process_entity_view( &mut self, query: &SceneQuery<'_>, - entity_view: &EntityView, + ent_view: &EntityView, ent_path: &EntityPath, ent_context: &SpatialSceneEntityContext<'_>, ) -> Result<(), QueryError> { re_tracing::profile_function!(); let (annotation_infos, keypoints) = - process_annotations_and_keypoints(query, entity_view, &ent_context.annotations)?; + process_annotations_and_keypoints(query, ent_view, &ent_context.annotations)?; - let colors = process_colors(entity_view, ent_path, &annotation_infos)?; - let radii = process_radii(ent_path, entity_view)?; + let colors = process_colors(ent_view, ent_path, &annotation_infos)?; + let radii = process_radii(ent_path, ent_view)?; - if entity_view.num_instances() <= self.max_labels { + if ent_view.num_instances() <= self.max_labels { // Max labels is small enough that we can afford iterating on the colors again. - let colors = - process_colors(entity_view, ent_path, &annotation_infos)?.collect::>(); + let colors = process_colors(ent_view, ent_path, &annotation_infos)?.collect::>(); let instance_path_hashes_for_picking = { re_tracing::profile_scope!("instance_hashes"); - entity_view + ent_view .iter_instance_keys() .map(|instance_key| { instance_path_hash_for_picking( ent_path, instance_key, - entity_view.num_instances(), + ent_view.num_instances(), ent_context.highlight.any_selection_highlight, ) }) @@ -104,7 +101,7 @@ impl Points3DSceneElement { }; self.data.ui_labels.extend(Self::process_labels( - entity_view, + ent_view, &instance_path_hashes_for_picking, &colors, &annotation_infos, @@ -122,20 +119,20 @@ impl Points3DSceneElement { let point_positions = { re_tracing::profile_scope!("collect_points"); - entity_view + ent_view .iter_primary()? .filter_map(|pt| pt.map(glam::Vec3::from)) }; - let picking_instance_ids = entity_view.iter_instance_keys().map(|instance_key| { + let picking_instance_ids = ent_view.iter_instance_keys().map(|instance_key| { instance_key_to_picking_id( instance_key, - entity_view.num_instances(), + ent_view.num_instances(), ent_context.highlight.any_selection_highlight, ) }); let mut point_range_builder = point_batch.add_points( - entity_view.num_instances(), + ent_view.num_instances(), point_positions, radii, colors, @@ -147,7 +144,7 @@ impl Points3DSceneElement { re_tracing::profile_scope!("marking additional highlight points"); for (highlighted_key, instance_mask_ids) in &ent_context.highlight.instances { // TODO(andreas/jeremy): We can do this much more efficiently - let highlighted_point_index = entity_view + let highlighted_point_index = ent_view .iter_instance_keys() .position(|key| key == *highlighted_key); if let Some(highlighted_point_index) = highlighted_point_index { @@ -167,14 +164,13 @@ impl Points3DSceneElement { re_tracing::profile_scope!("points3d.bounding_box"); self.data.bounding_box = self.data.bounding_box.union( macaw::BoundingBox::from_points( - entity_view + ent_view .iter_primary()? .filter_map(|pt| pt.map(|pt| pt.into())), ) .transform_affine3(&ent_context.world_from_obj), ); } - self.data.num_primitives += entity_view.num_instances(); Ok(()) } @@ -199,14 +195,16 @@ impl SpatialSceneElement<7> for Points3DSceneElement { &mut self, ctx: &mut ViewerContext<'_>, query: &SceneQuery<'_>, - context: SpatialSceneContext<'_>, + context: &SpatialSceneContext, + highlights: &SpaceViewHighlights, ) -> Vec { re_tracing::profile_scope!("Points3DPart"); Self::for_each_entity_view( ctx, query, - &context, + context, + highlights, context.depth_offsets.points, |ent_path, entity_view, ent_context| { self.process_entity_view(query, &entity_view, ent_path, ent_context) diff --git a/crates/re_space_view_spatial/src/scene/mod.rs b/crates/re_space_view_spatial/src/scene/mod.rs index ba8229577ae3..ea98390d1b78 100644 --- a/crates/re_space_view_spatial/src/scene/mod.rs +++ b/crates/re_space_view_spatial/src/scene/mod.rs @@ -6,15 +6,14 @@ use re_components::{ClassId, DecodedTensor, DrawOrder, InstanceKey, KeypointId}; use re_data_store::{EntityPath, InstancePathHash}; use re_log_types::EntityPathHash; use re_renderer::{renderer::TexturedRect, Color32, OutlineMaskPreference, Size}; -use re_viewer_context::SpaceViewHighlights; use re_viewer_context::{ auto_color, AnnotationMap, EmptySpaceViewState, Scene, SceneQuery, ViewerContext, }; +use re_viewer_context::{EmptySceneContext, SpaceViewHighlights}; use super::SpatialNavigationMode; -use crate::scene::spatial_scene_element::{ - SpatialSceneContext, SpatialSceneElement, SpatialSceneElementData, -}; +use crate::scene::contexts::SpatialSceneContext; +use crate::scene::spatial_scene_element::{SpatialSceneElement, SpatialSceneElementData}; use crate::{mesh_loader::LoadedMesh, space_camera_3d::SpaceCamera3D}; mod contexts; @@ -23,9 +22,9 @@ mod picking; mod primitives; mod spatial_scene_element; +use self::contexts::SpatialSceneEntityContext; pub use self::picking::{PickingContext, PickingHitType, PickingRayHit, PickingResult}; pub use self::primitives::SceneSpatialPrimitives; -use self::spatial_scene_element::SpatialSceneEntityContext; use elements::ScenePart; use contexts::EntityDepthOffsets; @@ -130,7 +129,12 @@ impl SceneSpatial { num_logged_2d_objects: Default::default(), num_logged_3d_objects: Default::default(), space_cameras: Default::default(), - scene: Default::default(), + // TODO(andreas): Workaround for not having default on `Scene`. Soon not needed anyways + scene: Scene { + context: Box::::default(), + elements: ().into(), + highlights: Default::default(), + }, draw_data: Default::default(), } } @@ -164,13 +168,7 @@ impl SceneSpatial { // TODO(andreas): Temporary build up of scene. This will be handled by the SpaceViewClass framework later. let mut scene = Scene { - contexts: ( - contexts::EntityDepthOffsets::default(), - contexts::TransformContext::default(), - contexts::AnnotationSceneContext::default(), - contexts::SharedRenderBuilders::default(), - ) - .into(), + context: Box::::default(), elements: ( elements::Points2DSceneElement::default().wrap(), elements::Points3DSceneElement::default().wrap(), @@ -179,21 +177,24 @@ impl SceneSpatial { highlights: Default::default(), }; self.draw_data = scene.populate(ctx, query, &EmptySpaceViewState, highlights); - let scene_context = SpatialSceneContext::new(&scene.contexts, &scene.highlights) - .expect("Failed to query for scene context."); + let scene_context = scene + .context + .as_any_mut() + .downcast_mut::() + .unwrap(); for part in parts { part.load( self, ctx, query, - scene_context.transforms, - scene_context.highlights, - scene_context.depth_offsets, + &scene_context.transforms, + &scene.highlights, + &scene_context.depth_offsets, ); } - self.primitives.any_outlines = scene_context.highlights.any_outlines(); + self.primitives.any_outlines = scene.highlights.any_outlines(); self.primitives.recalculate_bounding_box(); for scene_element in scene.elements.iter() { @@ -204,33 +205,35 @@ impl SceneSpatial { self.ui.labels.extend(data.ui_labels.iter().cloned()); self.primitives.bounding_box = self.primitives.bounding_box.union(data.bounding_box); - self.primitives.num_primitives += data.num_primitives; } } - if let Ok(shared_render_builders) = - scene.contexts.get_mut::() - { - self.draw_data - .extend(shared_render_builders.lines.take().and_then(|l| { - match l.into_inner().to_draw_data(ctx.render_ctx) { - Ok(d) => Some(d.into()), - Err(err) => { - re_log::error_once!("Failed to build line strip draw data: {err}"); - None - } + + self.draw_data.extend( + scene_context + .shared_render_builders + .lines + .take() + .and_then(|l| match l.into_inner().to_draw_data(ctx.render_ctx) { + Ok(d) => Some(d.into()), + Err(err) => { + re_log::error_once!("Failed to build line strip draw data: {err}"); + None } - })); - self.draw_data - .extend(shared_render_builders.points.take().and_then(|l| { - match l.into_inner().to_draw_data(ctx.render_ctx) { - Ok(d) => Some(d.into()), - Err(err) => { - re_log::error_once!("Failed to build point draw data: {err}"); - None - } + }), + ); + self.draw_data.extend( + scene_context + .shared_render_builders + .points + .take() + .and_then(|l| match l.into_inner().to_draw_data(ctx.render_ctx) { + Ok(d) => Some(d.into()), + Err(err) => { + re_log::error_once!("Failed to build point draw data: {err}"); + None } - })); - } + }), + ); self.scene = scene; } diff --git a/crates/re_space_view_spatial/src/scene/spatial_scene_element.rs b/crates/re_space_view_spatial/src/scene/spatial_scene_element.rs index 17fd0d477342..0f0236bb2697 100644 --- a/crates/re_space_view_spatial/src/scene/spatial_scene_element.rs +++ b/crates/re_space_view_spatial/src/scene/spatial_scene_element.rs @@ -1,77 +1,18 @@ -use std::sync::Arc; - use re_components::Component; use re_data_store::EntityPath; use re_log_types::ComponentName; use re_query::{query_primary_with_history, EntityView, QueryError}; use re_renderer::DepthOffset; -use re_viewer_context::{ - Annotations, SceneContextCollection, SceneElement, SceneItemCollectionLookupError, SceneQuery, - ViewerContext, -}; -use re_viewer_context::{SpaceViewHighlights, SpaceViewOutlineMasks}; - -use crate::{scene::EntityDepthOffsets, TransformContext}; +use re_viewer_context::SpaceViewHighlights; +use re_viewer_context::{EmptySpaceViewState, SceneElementImpl, SceneQuery, ViewerContext}; -use super::contexts::{AnnotationSceneContext, SharedRenderBuilders}; +use super::contexts::{SpatialSceneContext, SpatialSceneEntityContext}; use super::UiLabel; -/// Context objects for a single entity in a spatial scene. -pub struct SpatialSceneEntityContext<'a> { - pub world_from_obj: glam::Affine3A, - pub depth_offset: DepthOffset, - pub annotations: Arc, - pub highlight: &'a SpaceViewOutlineMasks, - pub shared_render_builders: &'a SharedRenderBuilders, -} - -/// Reference to all context objects of a spatial scene. -pub struct SpatialSceneContext<'a> { - pub transforms: &'a TransformContext, - pub depth_offsets: &'a EntityDepthOffsets, - pub annotations: &'a AnnotationSceneContext, - pub shared_render_builders: &'a SharedRenderBuilders, - pub highlights: &'a SpaceViewHighlights, // Not part of the context collection, but convenient to have here. -} - -impl<'a> SpatialSceneContext<'a> { - pub fn new( - contexts: &'a SceneContextCollection, - highlights: &'a SpaceViewHighlights, - ) -> Result { - Ok(Self { - transforms: contexts.get::()?, - depth_offsets: contexts.get::()?, - annotations: contexts.get::()?, - shared_render_builders: contexts.get::()?, - highlights, - }) - } - - fn query( - &self, - ent_path: &EntityPath, - default_depth_offset: DepthOffset, - ) -> Option> { - Some(SpatialSceneEntityContext { - world_from_obj: self.transforms.reference_from_entity(ent_path)?, - depth_offset: *self - .depth_offsets - .per_entity - .get(&ent_path.hash()) - .unwrap_or(&default_depth_offset), - annotations: self.annotations.0.find(ent_path), - shared_render_builders: self.shared_render_builders, - highlight: self.highlights.entity_outline_mask(ent_path.hash()), - }) - } -} - /// Common data struct for all spatial scene elements. pub struct SpatialSceneElementData { pub ui_labels: Vec, pub bounding_box: macaw::BoundingBox, - pub num_primitives: usize, } impl Default for SpatialSceneElementData { @@ -79,7 +20,6 @@ impl Default for SpatialSceneElementData { Self { ui_labels: Vec::new(), bounding_box: macaw::BoundingBox::nothing(), - num_primitives: 0, } } } @@ -93,7 +33,8 @@ pub trait SpatialSceneElement: std::any::Any { &mut self, ctx: &mut ViewerContext<'_>, query: &SceneQuery<'_>, - context: SpatialSceneContext<'_>, + context: &SpatialSceneContext, + highlights: &SpaceViewHighlights, ) -> Vec; fn data(&self) -> &SpatialSceneElementData; @@ -101,7 +42,8 @@ pub trait SpatialSceneElement: std::any::Any { fn for_each_entity_view( ctx: &mut ViewerContext<'_>, query: &SceneQuery<'_>, - context: &SpatialSceneContext<'_>, + context: &SpatialSceneContext, + highlights: &SpaceViewHighlights, default_depth_offset: DepthOffset, mut fun: F, ) where @@ -112,7 +54,7 @@ pub trait SpatialSceneElement: std::any::Any { ) -> Result<(), QueryError>, { for (ent_path, props) in query.iter_entities() { - let Some(entity_context) = context.query(ent_path, default_depth_offset) else { + let Some(entity_context) = context.query(ent_path, highlights, default_depth_offset) else { continue; }; @@ -125,8 +67,13 @@ pub trait SpatialSceneElement: std::any::Any { Self::archetype(), ) .and_then(|entity_views| { - for entity_view in entity_views { - fun(ent_path, entity_view, &entity_context)?; + for ent_view in entity_views { + context.num_primitives.fetch_add( + ent_view.num_instances(), + std::sync::atomic::Ordering::Relaxed, + ); + + fun(ent_path, ent_view, &entity_context)?; } Ok(()) }) { @@ -151,7 +98,12 @@ pub trait SpatialSceneElement: std::any::Any { /// Can't implement directly due to Rust limitations around higher kinded traits. pub struct SpatialSceneElementWrapper>(pub T); -impl> SceneElement for SpatialSceneElementWrapper { +impl> SceneElementImpl + for SpatialSceneElementWrapper +{ + type SpaceViewState = EmptySpaceViewState; + type SceneContext = SpatialSceneContext; + fn archetype(&self) -> re_viewer_context::ArchetypeDefinition { debug_assert!(N > 0); T::archetype().to_vec().try_into().unwrap() @@ -161,31 +113,14 @@ impl> SceneElement for SpatialSceneEle &mut self, ctx: &mut ViewerContext<'_>, query: &SceneQuery<'_>, - _space_view_state: &dyn re_viewer_context::SpaceViewState, - contexts: &re_viewer_context::SceneContextCollection, + _space_view_state: &EmptySpaceViewState, + context: &SpatialSceneContext, highlights: &SpaceViewHighlights, ) -> Vec { - let contexts = match SpatialSceneContext::new(contexts, highlights) { - Ok(ctx) => ctx, - Err(err) => { - re_log::error_once!("Failed to get required scene contexts: {err}"); - return Vec::new(); - } - }; - self.0.populate(ctx, query, contexts) + self.0.populate(ctx, query, context, highlights) } fn data(&self) -> Option<&dyn std::any::Any> { Some(self.0.data()) } - - fn as_any(&self) -> &dyn std::any::Any { - // Forwarding to the inner type allows to cast to the original implementor of SpatialSceneElement. - &self.0 - } - - fn as_any_mut(&mut self) -> &mut dyn std::any::Any { - // Forwarding to the inner type allows to cast to the original implementor of SpatialSceneElement. - &mut self.0 - } } diff --git a/crates/re_space_view_text/src/scene_element.rs b/crates/re_space_view_text/src/scene_element.rs index 1c1040c7c2c3..554690c1ed7d 100644 --- a/crates/re_space_view_text/src/scene_element.rs +++ b/crates/re_space_view_text/src/scene_element.rs @@ -3,8 +3,8 @@ use re_data_store::EntityPath; use re_log_types::{Component as _, InstanceKey, RowId}; use re_query::{range_entity_with_primary, QueryError}; use re_viewer_context::{ - ArchetypeDefinition, SceneContextCollection, SceneElementImpl, SceneQuery, SpaceViewHighlights, - ViewerContext, + ArchetypeDefinition, EmptySceneContext, SceneContextPart, SceneElementImpl, SceneQuery, + SpaceViewHighlights, ViewerContext, }; use super::space_view_class::TextSpaceViewState; @@ -33,7 +33,8 @@ pub struct SceneText { } impl SceneElementImpl for SceneText { - type State = TextSpaceViewState; + type SpaceViewState = TextSpaceViewState; + type SceneContext = EmptySceneContext; fn archetype(&self) -> ArchetypeDefinition { vec1::vec1![re_components::TextEntry::name()] @@ -44,7 +45,7 @@ impl SceneElementImpl for SceneText { ctx: &mut ViewerContext<'_>, query: &SceneQuery<'_>, state: &TextSpaceViewState, - _contexts: &SceneContextCollection, + _context: &EmptySceneContext, _highlights: &SpaceViewHighlights, ) -> Vec { let store = &ctx.store_db.entity_db.data_store; diff --git a/crates/re_space_view_text/src/space_view_class.rs b/crates/re_space_view_text/src/space_view_class.rs index 47d2228a9159..c2c56b218670 100644 --- a/crates/re_space_view_text/src/space_view_class.rs +++ b/crates/re_space_view_text/src/space_view_class.rs @@ -3,8 +3,8 @@ use std::collections::BTreeMap; use re_data_ui::item_ui; use re_log_types::{EntityPath, TimePoint, Timeline}; use re_viewer_context::{ - level_to_rich_text, Scene, SpaceViewClassImpl, SpaceViewClassName, SpaceViewState, - ViewerContext, + level_to_rich_text, EmptySceneContext, Scene, SpaceViewClassImpl, SpaceViewClassName, + SpaceViewState, ViewerContext, }; use super::scene_element::{SceneText, TextEntry}; @@ -37,8 +37,8 @@ impl SpaceViewState for TextSpaceViewState { pub struct TextSpaceView; impl SpaceViewClassImpl for TextSpaceView { - type State = TextSpaceViewState; - type SceneContextTuple = (); + type SpaceViewState = TextSpaceViewState; + type SceneContext = EmptySceneContext; type SceneElementTuple = (SceneText,); fn name(&self) -> SpaceViewClassName { @@ -57,7 +57,7 @@ impl SpaceViewClassImpl for TextSpaceView { &self, ctx: &mut ViewerContext<'_>, ui: &mut egui::Ui, - state: &mut Self::State, + state: &mut Self::SpaceViewState, ) { let ViewTextFilters { col_timelines, @@ -107,7 +107,7 @@ impl SpaceViewClassImpl for TextSpaceView { &self, ctx: &mut ViewerContext<'_>, ui: &mut egui::Ui, - state: &mut Self::State, + state: &mut Self::SpaceViewState, scene: Scene, ) { let scene = match scene.elements.get::() { diff --git a/crates/re_space_view_text_box/src/scene_element.rs b/crates/re_space_view_text_box/src/scene_element.rs index 08a3ac091d46..03b952332dba 100644 --- a/crates/re_space_view_text_box/src/scene_element.rs +++ b/crates/re_space_view_text_box/src/scene_element.rs @@ -2,7 +2,7 @@ use re_arrow_store::LatestAtQuery; use re_components::Component; use re_query::{query_entity_with_primary, QueryError}; use re_viewer_context::{ - ArchetypeDefinition, SceneContextCollection, SceneElementImpl, SceneQuery, SpaceViewHighlights, + ArchetypeDefinition, EmptySceneContext, SceneElementImpl, SceneQuery, SpaceViewHighlights, ViewerContext, }; @@ -22,7 +22,8 @@ pub struct SceneTextBox { } impl SceneElementImpl for SceneTextBox { - type State = TextBoxSpaceViewState; + type SpaceViewState = TextBoxSpaceViewState; + type SceneContext = EmptySceneContext; fn archetype(&self) -> ArchetypeDefinition { vec1::vec1![re_components::TextBox::name()] @@ -32,8 +33,8 @@ impl SceneElementImpl for SceneTextBox { &mut self, ctx: &mut ViewerContext<'_>, query: &SceneQuery<'_>, - _space_view_state: &Self::State, - _contexts: &SceneContextCollection, + _space_view_state: &Self::SpaceViewState, + _context: &EmptySceneContext, _highlights: &SpaceViewHighlights, ) -> Vec { let store = &ctx.store_db.entity_db.data_store; diff --git a/crates/re_space_view_text_box/src/space_view_class.rs b/crates/re_space_view_text_box/src/space_view_class.rs index 528866e6a78c..a293bbdd63d2 100644 --- a/crates/re_space_view_text_box/src/space_view_class.rs +++ b/crates/re_space_view_text_box/src/space_view_class.rs @@ -1,6 +1,6 @@ use egui::Label; use re_viewer_context::{ - Scene, SpaceViewClassImpl, SpaceViewClassName, SpaceViewState, ViewerContext, + EmptySceneContext, Scene, SpaceViewClassImpl, SpaceViewClassName, SpaceViewState, ViewerContext, }; use super::scene_element::SceneTextBox; @@ -35,9 +35,9 @@ impl SpaceViewState for TextBoxSpaceViewState { pub struct TextBoxSpaceView; impl SpaceViewClassImpl for TextBoxSpaceView { - type State = TextBoxSpaceViewState; + type SpaceViewState = TextBoxSpaceViewState; type SceneElementTuple = (SceneTextBox,); - type SceneContextTuple = (); + type SceneContext = EmptySceneContext; fn name(&self) -> SpaceViewClassName { "Text Box".into() @@ -55,7 +55,7 @@ impl SpaceViewClassImpl for TextBoxSpaceView { &self, ctx: &mut ViewerContext<'_>, ui: &mut egui::Ui, - state: &mut Self::State, + state: &mut Self::SpaceViewState, ) { ctx.re_ui.selection_grid(ui, "text_config").show(ui, |ui| { ctx.re_ui.grid_left_hand_label(ui, "Text style"); @@ -72,7 +72,7 @@ impl SpaceViewClassImpl for TextBoxSpaceView { &self, _ctx: &mut ViewerContext<'_>, ui: &mut egui::Ui, - state: &mut Self::State, + state: &mut Self::SpaceViewState, scene: Scene, ) { let scene = match scene.elements.get::() { diff --git a/crates/re_viewer_context/src/lib.rs b/crates/re_viewer_context/src/lib.rs index 6d8c71664f62..9e410b4ef0d5 100644 --- a/crates/re_viewer_context/src/lib.rs +++ b/crates/re_viewer_context/src/lib.rs @@ -30,11 +30,11 @@ pub use selection_state::{ HoverHighlight, HoveredSpace, InteractionHighlight, SelectionHighlight, SelectionState, }; pub use space_view::{ - ArchetypeDefinition, EmptySpaceViewState, Scene, SceneContext, SceneContextCollection, - SceneElement, SceneElementCollection, SceneElementImpl, SceneItemCollectionLookupError, - SceneQuery, SpaceViewClass, SpaceViewClassImpl, SpaceViewClassName, SpaceViewClassRegistry, + ArchetypeDefinition, EmptySpaceViewState, Scene, SceneContext, SceneContextPart, SceneElement, + SceneElementCollection, SceneElementImpl, SceneItemCollectionLookupError, SceneQuery, + SpaceViewClass, SpaceViewClassImpl, SpaceViewClassName, SpaceViewClassRegistry, SpaceViewClassRegistryError, SpaceViewEntityHighlight, SpaceViewHighlights, - SpaceViewOutlineMasks, SpaceViewState, + SpaceViewOutlineMasks, SpaceViewState, EmptySceneContext }; pub use tensor::{TensorDecodeCache, TensorStats, TensorStatsCache}; pub use time_control::{Looping, PlayState, TimeControl, TimeView}; diff --git a/crates/re_viewer_context/src/space_view/mod.rs b/crates/re_viewer_context/src/space_view/mod.rs index 3c8eb86b476b..6942258e26f6 100644 --- a/crates/re_viewer_context/src/space_view/mod.rs +++ b/crates/re_viewer_context/src/space_view/mod.rs @@ -14,8 +14,8 @@ mod space_view_class_registry; pub use highlights::{SpaceViewEntityHighlight, SpaceViewHighlights, SpaceViewOutlineMasks}; pub use scene::{ - Scene, SceneContext, SceneContextCollection, SceneElement, SceneElementCollection, - SceneItemCollectionLookupError, + Scene, SceneContext, SceneContextPart, SceneElement, SceneElementCollection, + SceneItemCollectionLookupError, EmptySceneContext }; pub use scene_element_impl::SceneElementImpl; pub use scene_query::SceneQuery; diff --git a/crates/re_viewer_context/src/space_view/scene.rs b/crates/re_viewer_context/src/space_view/scene.rs index 641feb121cdd..44350cf75036 100644 --- a/crates/re_viewer_context/src/space_view/scene.rs +++ b/crates/re_viewer_context/src/space_view/scene.rs @@ -15,54 +15,36 @@ pub enum SceneItemCollectionLookupError { // TODO(andreas): Use tinyvec for these. -/// Collection of scene contexts. -/// -/// New type pattern to support adding From impls. +/// Scene context, consisting of several [`SceneContextPart`] which may be populated in parallel. +pub trait SceneContext { + /// Retrieves a list of all underlying scene context part for parallel population. + fn vec_mut(&mut self) -> Vec<&mut dyn SceneContextPart>; + + /// Converts itself to a reference of [`Any`], which enables downcasting to concrete types. + fn as_any(&self) -> &dyn std::any::Any; + + /// Converts itself to a reference of [`Any`], which enables downcasting to concrete types. + fn as_any_mut(&mut self) -> &mut dyn std::any::Any; +} + +/// Implementation of an empty scene context. #[derive(Default)] -pub struct SceneContextCollection(HashMap>); +pub struct EmptySceneContext; -impl SceneContextCollection { - pub fn get(&self) -> Result<&T, SceneItemCollectionLookupError> { - self.0 - .get(&TypeId::of::()) - .ok_or(SceneItemCollectionLookupError::TypeNotFound)? - .as_any() - .downcast_ref::() - .ok_or(SceneItemCollectionLookupError::DowncastFailure) +impl SceneContext for EmptySceneContext { + fn vec_mut(&mut self) -> Vec<&mut dyn SceneContextPart> { + Vec::new() } - pub fn get_mut(&mut self) -> Result<&mut T, SceneItemCollectionLookupError> { - self.0 - .get_mut(&TypeId::of::()) - .ok_or(SceneItemCollectionLookupError::TypeNotFound)? - .as_any_mut() - .downcast_mut::() - .ok_or(SceneItemCollectionLookupError::DowncastFailure) + fn as_any(&self) -> &dyn std::any::Any { + self } -} -macro_rules! scene_context_collection_from_tuple { - ($($idx:tt => $name:ident),*) => { - impl<$($name: SceneContext),*> From<($($name,)*)> for SceneContextCollection { - #[allow(unused_mut)] - fn from(_value: ($($name,)*)) -> Self { - let mut map = HashMap::>::default(); - $( - map.insert(_value.$idx.as_any().type_id(), Box::new(_value.$idx)); - )* - Self(map) - } - } - }; + fn as_any_mut(&mut self) -> &mut dyn std::any::Any { + self + } } -scene_context_collection_from_tuple!(); -scene_context_collection_from_tuple!(0 => T0); -scene_context_collection_from_tuple!(0 => T0, 1 => T1); -scene_context_collection_from_tuple!(0 => T0, 1 => T1, 2 => T2); -scene_context_collection_from_tuple!(0 => T0, 1 => T1, 2 => T2, 3 => T3); -scene_context_collection_from_tuple!(0 => T0, 1 => T1, 2 => T2, 3 => T3, 4 => T4); - /// Collections of scene elements. /// /// New type pattern to support adding From impls. @@ -123,9 +105,8 @@ scene_element_collection_from_tuple!(0 => T0, 1 => T1, 2 => T2, 3 => T3, 4 => T4 /// /// When populating a scene, first all contexts are populated, /// and then all elements with read access to the previously established context objects. -#[derive(Default)] pub struct Scene { - pub contexts: SceneContextCollection, + pub context: Box, pub elements: SceneElementCollection, pub highlights: SpaceViewHighlights, // TODO(wumpf): Consider making this a scene context - problem: populate can't create it. } @@ -149,7 +130,7 @@ impl Scene { self.highlights = highlights; // TODO(andreas): Both loops are great candidates for parallelization. - for context in self.contexts.0.values_mut() { + for context in self.context.vec_mut() { // TODO(andreas): Restrict the query with the archetype somehow, ideally making it trivial to do the correct thing. context.populate(ctx, query, space_view_state); } @@ -162,7 +143,7 @@ impl Scene { ctx, query, space_view_state, - &self.contexts, + self.context.as_ref(), &self.highlights, ) }) @@ -185,7 +166,7 @@ pub trait SceneElement: Any { ctx: &mut ViewerContext<'_>, query: &SceneQuery<'_>, space_view_state: &dyn SpaceViewState, - contexts: &SceneContextCollection, + context: &dyn SceneContext, highlights: &SpaceViewHighlights, ) -> Vec; @@ -207,7 +188,7 @@ pub trait SceneElement: Any { /// Scene context that can be used by scene elements and ui methods to retrieve information about the scene as a whole. /// /// Is always populated before scene elements. -pub trait SceneContext: Any { +pub trait SceneContextPart: Any { /// Each scene context may query several archetypes. /// /// This lists all components out that the context queries. diff --git a/crates/re_viewer_context/src/space_view/scene_element_impl.rs b/crates/re_viewer_context/src/space_view/scene_element_impl.rs index f4627733eb41..bee8c8fe8271 100644 --- a/crates/re_viewer_context/src/space_view/scene_element_impl.rs +++ b/crates/re_viewer_context/src/space_view/scene_element_impl.rs @@ -1,13 +1,12 @@ use crate::{ - ArchetypeDefinition, SceneElement, SceneQuery, SpaceViewHighlights, SpaceViewState, - ViewerContext, + ArchetypeDefinition, SceneContext, SceneElement, SceneQuery, SpaceViewHighlights, + SpaceViewState, ViewerContext, }; -use super::scene::SceneContextCollection; - -/// Element of a scene derived from a single archetype query. +/// Implementation utility for [`crate::SceneElement`] pub trait SceneElementImpl { - type State: SpaceViewState + Default + 'static; + type SpaceViewState: SpaceViewState + Default + 'static; + type SceneContext: SceneContext + 'static; /// The archetype queried by this scene element. fn archetype(&self) -> ArchetypeDefinition; @@ -19,38 +18,58 @@ pub trait SceneElementImpl { &mut self, ctx: &mut ViewerContext<'_>, query: &SceneQuery<'_>, - space_view_state: &Self::State, - contexts: &SceneContextCollection, + space_view_state: &Self::SpaceViewState, + scene_context: &Self::SceneContext, highlights: &SpaceViewHighlights, ) -> Vec; + + /// Optionally retrieves a data store reference from the scene element. + /// + /// This is a useful for retrieving a data struct that may be common for all scene elements + /// of a particular [`crate::SpaceViewClass`]. + fn data(&self) -> Option<&dyn std::any::Any> { + None + } } impl SceneElement for T { + #[inline] fn archetype(&self) -> ArchetypeDefinition { self.archetype() } + #[inline] fn populate( &mut self, ctx: &mut ViewerContext<'_>, query: &crate::SceneQuery<'_>, space_view_state: &dyn SpaceViewState, - contexts: &SceneContextCollection, + scene_context: &dyn SceneContext, highlights: &SpaceViewHighlights, ) -> Vec { - if let Some(state) = space_view_state.as_any().downcast_ref() { - self.populate(ctx, query, state, contexts, highlights) - } else { + let Some(state) = space_view_state.as_any().downcast_ref() else { re_log::error_once!("Incorrect type of space view state."); - Vec::new() - } + return Vec::new(); + }; + let Some(context) = scene_context.as_any().downcast_ref() else { + re_log::error_once!("Incorrect type of space view context."); + return Vec::new(); + }; + self.populate(ctx, query, state, context, highlights) } + #[inline] fn as_any(&self) -> &dyn std::any::Any { self } + #[inline] fn as_any_mut(&mut self) -> &mut dyn std::any::Any { self } + + #[inline] + fn data(&self) -> Option<&dyn std::any::Any> { + self.data() + } } diff --git a/crates/re_viewer_context/src/space_view/space_view_class_impl.rs b/crates/re_viewer_context/src/space_view/space_view_class_impl.rs index b379bbb6f1d2..be636581fdd3 100644 --- a/crates/re_viewer_context/src/space_view/space_view_class_impl.rs +++ b/crates/re_viewer_context/src/space_view/space_view_class_impl.rs @@ -1,6 +1,8 @@ -use crate::{Scene, SpaceViewClass, SpaceViewClassName, SpaceViewState, ViewerContext}; +use crate::{ + Scene, SceneContext, SpaceViewClass, SpaceViewClassName, SpaceViewState, ViewerContext, +}; -use super::scene::{SceneContextCollection, SceneElementCollection}; +use super::scene::SceneElementCollection; /// Utility for implementing [`SpaceViewClass`] with concrete [`SpaceViewState`] and [`crate::SceneElement`] type. /// @@ -9,10 +11,10 @@ use super::scene::{SceneContextCollection, SceneElementCollection}; /// It determines which entities are queried, how they are rendered, and how the user can interact with them. pub trait SpaceViewClassImpl { /// State of a space view. - type State: SpaceViewState + Default + 'static; + type SpaceViewState: SpaceViewState + Default + 'static; - /// A tuple of [`crate::SceneContext`] types that are supported by this space view class. - type SceneContextTuple: Into + Default + 'static; + /// Context of the scene, which is passed to all [`crate::SceneElement`]s and ui drawing on population. + type SceneContext: SceneContext + Default + 'static; /// A tuple of [`crate::SceneElement`] types that are supported by this space view class. type SceneElementTuple: Into + Default + 'static; @@ -32,7 +34,12 @@ pub trait SpaceViewClassImpl { /// Ui shown when the user selects a space view of this class. /// /// TODO(andreas): Should this be instead implemented via a registered `data_ui` of all blueprint relevant types? - fn selection_ui(&self, ctx: &mut ViewerContext<'_>, ui: &mut egui::Ui, state: &mut Self::State); + fn selection_ui( + &self, + ctx: &mut ViewerContext<'_>, + ui: &mut egui::Ui, + state: &mut Self::SpaceViewState, + ); /// Draws the ui for this space view class and handles ui events. /// @@ -42,7 +49,7 @@ pub trait SpaceViewClassImpl { &self, ctx: &mut ViewerContext<'_>, ui: &mut egui::Ui, - state: &mut Self::State, + state: &mut Self::SpaceViewState, scene: Scene, ); } @@ -66,7 +73,7 @@ impl SpaceViewClass for T { #[inline] fn new_scene(&self) -> Scene { Scene { - contexts: T::SceneContextTuple::default().into(), + context: Box::::default(), elements: T::SceneElementTuple::default().into(), highlights: Default::default(), } @@ -74,7 +81,7 @@ impl SpaceViewClass for T { #[inline] fn new_state(&self) -> Box { - Box::::default() + Box::::default() } #[inline] From ef74ebd0254985064eeae507dcb89b1fb4412bdd Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Fri, 2 Jun 2023 10:52:46 +0200 Subject: [PATCH 16/39] move empty space view state/context to re_space_view --- Cargo.lock | 2 ++ .../re_space_view/src/empty_scene_context.rs | 19 +++++++++++++++++++ .../src/empty_space_view_state.rs | 15 +++++++++++++++ crates/re_space_view/src/lib.rs | 4 ++++ crates/re_space_view_spatial/src/scene/mod.rs | 19 ++++++++++++------- .../src/scene/spatial_scene_element.rs | 15 ++++++++------- crates/re_space_view_text/Cargo.toml | 1 + .../re_space_view_text/src/scene_element.rs | 7 +++---- .../src/space_view_class.rs | 6 +++--- crates/re_space_view_text_box/Cargo.toml | 1 + .../src/scene_element.rs | 7 +++---- .../src/space_view_class.rs | 4 ++-- crates/re_viewer_context/src/lib.rs | 4 ++-- .../re_viewer_context/src/space_view/mod.rs | 4 ++-- .../re_viewer_context/src/space_view/scene.rs | 18 ------------------ .../src/space_view/space_view_class_impl.rs | 14 -------------- crates/re_viewport/src/viewport.rs | 6 +++--- 17 files changed, 80 insertions(+), 66 deletions(-) create mode 100644 crates/re_space_view/src/empty_scene_context.rs create mode 100644 crates/re_space_view/src/empty_space_view_state.rs diff --git a/Cargo.lock b/Cargo.lock index c442b2886e27..a3983b9840b9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4307,6 +4307,7 @@ dependencies = [ "re_log_types", "re_query", "re_renderer", + "re_space_view", "re_tracing", "re_ui", "re_viewer_context", @@ -4323,6 +4324,7 @@ dependencies = [ "re_log", "re_query", "re_renderer", + "re_space_view", "re_ui", "re_viewer_context", "vec1", diff --git a/crates/re_space_view/src/empty_scene_context.rs b/crates/re_space_view/src/empty_scene_context.rs new file mode 100644 index 000000000000..2e43c66318c3 --- /dev/null +++ b/crates/re_space_view/src/empty_scene_context.rs @@ -0,0 +1,19 @@ +use re_viewer_context::{SceneContext, SceneContextPart}; + +/// Implementation of an empty scene context. +#[derive(Default)] +pub struct EmptySceneContext; + +impl SceneContext for EmptySceneContext { + fn vec_mut(&mut self) -> Vec<&mut dyn SceneContextPart> { + Vec::new() + } + + fn as_any(&self) -> &dyn std::any::Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn std::any::Any { + self + } +} diff --git a/crates/re_space_view/src/empty_space_view_state.rs b/crates/re_space_view/src/empty_space_view_state.rs new file mode 100644 index 000000000000..671dfa29ca70 --- /dev/null +++ b/crates/re_space_view/src/empty_space_view_state.rs @@ -0,0 +1,15 @@ +use re_viewer_context::SpaceViewState; + +/// Space view state without any contents. +#[derive(Default)] +pub struct EmptySpaceViewState; + +impl SpaceViewState for EmptySpaceViewState { + fn as_any(&self) -> &dyn std::any::Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn std::any::Any { + self + } +} diff --git a/crates/re_space_view/src/lib.rs b/crates/re_space_view/src/lib.rs index 28231d7c6ab9..1ac9cc4cb7aa 100644 --- a/crates/re_space_view/src/lib.rs +++ b/crates/re_space_view/src/lib.rs @@ -4,7 +4,11 @@ pub mod controls; mod data_blueprint; +mod empty_scene_context; +mod empty_space_view_state; mod screenshot; pub use data_blueprint::{DataBlueprintGroup, DataBlueprintTree}; +pub use empty_scene_context::EmptySceneContext; +pub use empty_space_view_state::EmptySpaceViewState; pub use screenshot::ScreenshotMode; diff --git a/crates/re_space_view_spatial/src/scene/mod.rs b/crates/re_space_view_spatial/src/scene/mod.rs index ea98390d1b78..8d1eafe88214 100644 --- a/crates/re_space_view_spatial/src/scene/mod.rs +++ b/crates/re_space_view_spatial/src/scene/mod.rs @@ -7,14 +7,18 @@ use re_data_store::{EntityPath, InstancePathHash}; use re_log_types::EntityPathHash; use re_renderer::{renderer::TexturedRect, Color32, OutlineMaskPreference, Size}; use re_viewer_context::{ - auto_color, AnnotationMap, EmptySpaceViewState, Scene, SceneQuery, ViewerContext, + auto_color, AnnotationMap, Scene, SceneQuery, SpaceViewHighlights, ViewerContext, }; -use re_viewer_context::{EmptySceneContext, SpaceViewHighlights}; use super::SpatialNavigationMode; -use crate::scene::contexts::SpatialSceneContext; -use crate::scene::spatial_scene_element::{SpatialSceneElement, SpatialSceneElementData}; -use crate::{mesh_loader::LoadedMesh, space_camera_3d::SpaceCamera3D}; +use crate::{ + mesh_loader::LoadedMesh, + scene::{ + contexts::SpatialSceneContext, + spatial_scene_element::{SpatialSceneElement, SpatialSceneElementData}, + }, + space_camera_3d::SpaceCamera3D, +}; mod contexts; mod elements; @@ -131,7 +135,7 @@ impl SceneSpatial { space_cameras: Default::default(), // TODO(andreas): Workaround for not having default on `Scene`. Soon not needed anyways scene: Scene { - context: Box::::default(), + context: Box::::default(), elements: ().into(), highlights: Default::default(), }, @@ -176,7 +180,8 @@ impl SceneSpatial { .into(), highlights: Default::default(), }; - self.draw_data = scene.populate(ctx, query, &EmptySpaceViewState, highlights); + self.draw_data = + scene.populate(ctx, query, &re_space_view::EmptySpaceViewState, highlights); let scene_context = scene .context .as_any_mut() diff --git a/crates/re_space_view_spatial/src/scene/spatial_scene_element.rs b/crates/re_space_view_spatial/src/scene/spatial_scene_element.rs index 0f0236bb2697..909ad81f77b9 100644 --- a/crates/re_space_view_spatial/src/scene/spatial_scene_element.rs +++ b/crates/re_space_view_spatial/src/scene/spatial_scene_element.rs @@ -3,11 +3,12 @@ use re_data_store::EntityPath; use re_log_types::ComponentName; use re_query::{query_primary_with_history, EntityView, QueryError}; use re_renderer::DepthOffset; -use re_viewer_context::SpaceViewHighlights; -use re_viewer_context::{EmptySpaceViewState, SceneElementImpl, SceneQuery, ViewerContext}; +use re_viewer_context::{SceneElementImpl, SceneQuery, SpaceViewHighlights, ViewerContext}; -use super::contexts::{SpatialSceneContext, SpatialSceneEntityContext}; -use super::UiLabel; +use super::{ + contexts::{SpatialSceneContext, SpatialSceneEntityContext}, + UiLabel, +}; /// Common data struct for all spatial scene elements. pub struct SpatialSceneElementData { @@ -101,7 +102,7 @@ pub struct SpatialSceneElementWrapper> impl> SceneElementImpl for SpatialSceneElementWrapper { - type SpaceViewState = EmptySpaceViewState; + type SpaceViewState = re_space_view::EmptySpaceViewState; type SceneContext = SpatialSceneContext; fn archetype(&self) -> re_viewer_context::ArchetypeDefinition { @@ -113,8 +114,8 @@ impl> SceneElementImpl &mut self, ctx: &mut ViewerContext<'_>, query: &SceneQuery<'_>, - _space_view_state: &EmptySpaceViewState, - context: &SpatialSceneContext, + _space_view_state: &Self::SpaceViewState, + context: &Self::SceneContext, highlights: &SpaceViewHighlights, ) -> Vec { self.0.populate(ctx, query, context, highlights) diff --git a/crates/re_space_view_text/Cargo.toml b/crates/re_space_view_text/Cargo.toml index 4286de0ec950..57e751c4f7d6 100644 --- a/crates/re_space_view_text/Cargo.toml +++ b/crates/re_space_view_text/Cargo.toml @@ -24,6 +24,7 @@ re_log_types.workspace = true re_log.workspace = true re_query.workspace = true re_renderer.workspace = true +re_space_view.workspace = true re_tracing.workspace = true re_ui.workspace = true re_viewer_context.workspace = true diff --git a/crates/re_space_view_text/src/scene_element.rs b/crates/re_space_view_text/src/scene_element.rs index 554690c1ed7d..f42d83d7783b 100644 --- a/crates/re_space_view_text/src/scene_element.rs +++ b/crates/re_space_view_text/src/scene_element.rs @@ -3,8 +3,7 @@ use re_data_store::EntityPath; use re_log_types::{Component as _, InstanceKey, RowId}; use re_query::{range_entity_with_primary, QueryError}; use re_viewer_context::{ - ArchetypeDefinition, EmptySceneContext, SceneContextPart, SceneElementImpl, SceneQuery, - SpaceViewHighlights, ViewerContext, + ArchetypeDefinition, SceneElementImpl, SceneQuery, SpaceViewHighlights, ViewerContext, }; use super::space_view_class::TextSpaceViewState; @@ -34,7 +33,7 @@ pub struct SceneText { impl SceneElementImpl for SceneText { type SpaceViewState = TextSpaceViewState; - type SceneContext = EmptySceneContext; + type SceneContext = re_space_view::EmptySceneContext; fn archetype(&self) -> ArchetypeDefinition { vec1::vec1![re_components::TextEntry::name()] @@ -45,7 +44,7 @@ impl SceneElementImpl for SceneText { ctx: &mut ViewerContext<'_>, query: &SceneQuery<'_>, state: &TextSpaceViewState, - _context: &EmptySceneContext, + _context: &Self::SceneContext, _highlights: &SpaceViewHighlights, ) -> Vec { let store = &ctx.store_db.entity_db.data_store; diff --git a/crates/re_space_view_text/src/space_view_class.rs b/crates/re_space_view_text/src/space_view_class.rs index c2c56b218670..c55148419041 100644 --- a/crates/re_space_view_text/src/space_view_class.rs +++ b/crates/re_space_view_text/src/space_view_class.rs @@ -3,8 +3,8 @@ use std::collections::BTreeMap; use re_data_ui::item_ui; use re_log_types::{EntityPath, TimePoint, Timeline}; use re_viewer_context::{ - level_to_rich_text, EmptySceneContext, Scene, SpaceViewClassImpl, SpaceViewClassName, - SpaceViewState, ViewerContext, + level_to_rich_text, Scene, SpaceViewClassImpl, SpaceViewClassName, SpaceViewState, + ViewerContext, }; use super::scene_element::{SceneText, TextEntry}; @@ -38,7 +38,7 @@ pub struct TextSpaceView; impl SpaceViewClassImpl for TextSpaceView { type SpaceViewState = TextSpaceViewState; - type SceneContext = EmptySceneContext; + type SceneContext = re_space_view::EmptySceneContext; type SceneElementTuple = (SceneText,); fn name(&self) -> SpaceViewClassName { diff --git a/crates/re_space_view_text_box/Cargo.toml b/crates/re_space_view_text_box/Cargo.toml index cc2381526ea5..672e4881cf33 100644 --- a/crates/re_space_view_text_box/Cargo.toml +++ b/crates/re_space_view_text_box/Cargo.toml @@ -21,6 +21,7 @@ re_components.workspace = true re_log.workspace = true re_query.workspace = true re_renderer.workspace = true +re_space_view.workspace = true re_ui.workspace = true re_viewer_context.workspace = true diff --git a/crates/re_space_view_text_box/src/scene_element.rs b/crates/re_space_view_text_box/src/scene_element.rs index 03b952332dba..9c092383384f 100644 --- a/crates/re_space_view_text_box/src/scene_element.rs +++ b/crates/re_space_view_text_box/src/scene_element.rs @@ -2,8 +2,7 @@ use re_arrow_store::LatestAtQuery; use re_components::Component; use re_query::{query_entity_with_primary, QueryError}; use re_viewer_context::{ - ArchetypeDefinition, EmptySceneContext, SceneElementImpl, SceneQuery, SpaceViewHighlights, - ViewerContext, + ArchetypeDefinition, SceneElementImpl, SceneQuery, SpaceViewHighlights, ViewerContext, }; use crate::space_view_class::TextBoxSpaceViewState; @@ -23,7 +22,7 @@ pub struct SceneTextBox { impl SceneElementImpl for SceneTextBox { type SpaceViewState = TextBoxSpaceViewState; - type SceneContext = EmptySceneContext; + type SceneContext = re_space_view::EmptySceneContext; fn archetype(&self) -> ArchetypeDefinition { vec1::vec1![re_components::TextBox::name()] @@ -34,7 +33,7 @@ impl SceneElementImpl for SceneTextBox { ctx: &mut ViewerContext<'_>, query: &SceneQuery<'_>, _space_view_state: &Self::SpaceViewState, - _context: &EmptySceneContext, + _context: &Self::SceneContext, _highlights: &SpaceViewHighlights, ) -> Vec { let store = &ctx.store_db.entity_db.data_store; diff --git a/crates/re_space_view_text_box/src/space_view_class.rs b/crates/re_space_view_text_box/src/space_view_class.rs index a293bbdd63d2..e2bd47a32774 100644 --- a/crates/re_space_view_text_box/src/space_view_class.rs +++ b/crates/re_space_view_text_box/src/space_view_class.rs @@ -1,6 +1,6 @@ use egui::Label; use re_viewer_context::{ - EmptySceneContext, Scene, SpaceViewClassImpl, SpaceViewClassName, SpaceViewState, ViewerContext, + Scene, SpaceViewClassImpl, SpaceViewClassName, SpaceViewState, ViewerContext, }; use super::scene_element::SceneTextBox; @@ -37,7 +37,7 @@ pub struct TextBoxSpaceView; impl SpaceViewClassImpl for TextBoxSpaceView { type SpaceViewState = TextBoxSpaceViewState; type SceneElementTuple = (SceneTextBox,); - type SceneContext = EmptySceneContext; + type SceneContext = re_space_view::EmptySceneContext; fn name(&self) -> SpaceViewClassName { "Text Box".into() diff --git a/crates/re_viewer_context/src/lib.rs b/crates/re_viewer_context/src/lib.rs index 9e410b4ef0d5..041cefe5eed6 100644 --- a/crates/re_viewer_context/src/lib.rs +++ b/crates/re_viewer_context/src/lib.rs @@ -30,11 +30,11 @@ pub use selection_state::{ HoverHighlight, HoveredSpace, InteractionHighlight, SelectionHighlight, SelectionState, }; pub use space_view::{ - ArchetypeDefinition, EmptySpaceViewState, Scene, SceneContext, SceneContextPart, SceneElement, + ArchetypeDefinition, Scene, SceneContext, SceneContextPart, SceneElement, SceneElementCollection, SceneElementImpl, SceneItemCollectionLookupError, SceneQuery, SpaceViewClass, SpaceViewClassImpl, SpaceViewClassName, SpaceViewClassRegistry, SpaceViewClassRegistryError, SpaceViewEntityHighlight, SpaceViewHighlights, - SpaceViewOutlineMasks, SpaceViewState, EmptySceneContext + SpaceViewOutlineMasks, SpaceViewState, }; pub use tensor::{TensorDecodeCache, TensorStats, TensorStatsCache}; pub use time_control::{Looping, PlayState, TimeControl, TimeView}; diff --git a/crates/re_viewer_context/src/space_view/mod.rs b/crates/re_viewer_context/src/space_view/mod.rs index 6942258e26f6..e9295770a680 100644 --- a/crates/re_viewer_context/src/space_view/mod.rs +++ b/crates/re_viewer_context/src/space_view/mod.rs @@ -15,12 +15,12 @@ mod space_view_class_registry; pub use highlights::{SpaceViewEntityHighlight, SpaceViewHighlights, SpaceViewOutlineMasks}; pub use scene::{ Scene, SceneContext, SceneContextPart, SceneElement, SceneElementCollection, - SceneItemCollectionLookupError, EmptySceneContext + SceneItemCollectionLookupError, }; pub use scene_element_impl::SceneElementImpl; pub use scene_query::SceneQuery; pub use space_view_class::{ ArchetypeDefinition, SpaceViewClass, SpaceViewClassName, SpaceViewState, }; -pub use space_view_class_impl::{EmptySpaceViewState, SpaceViewClassImpl}; +pub use space_view_class_impl::SpaceViewClassImpl; pub use space_view_class_registry::{SpaceViewClassRegistry, SpaceViewClassRegistryError}; diff --git a/crates/re_viewer_context/src/space_view/scene.rs b/crates/re_viewer_context/src/space_view/scene.rs index 44350cf75036..ba8722388e0d 100644 --- a/crates/re_viewer_context/src/space_view/scene.rs +++ b/crates/re_viewer_context/src/space_view/scene.rs @@ -27,24 +27,6 @@ pub trait SceneContext { fn as_any_mut(&mut self) -> &mut dyn std::any::Any; } -/// Implementation of an empty scene context. -#[derive(Default)] -pub struct EmptySceneContext; - -impl SceneContext for EmptySceneContext { - fn vec_mut(&mut self) -> Vec<&mut dyn SceneContextPart> { - Vec::new() - } - - fn as_any(&self) -> &dyn std::any::Any { - self - } - - fn as_any_mut(&mut self) -> &mut dyn std::any::Any { - self - } -} - /// Collections of scene elements. /// /// New type pattern to support adding From impls. diff --git a/crates/re_viewer_context/src/space_view/space_view_class_impl.rs b/crates/re_viewer_context/src/space_view/space_view_class_impl.rs index be636581fdd3..e1b5633c4c17 100644 --- a/crates/re_viewer_context/src/space_view/space_view_class_impl.rs +++ b/crates/re_viewer_context/src/space_view/space_view_class_impl.rs @@ -116,17 +116,3 @@ fn typed_state_wrapper( re_log::error_once!("Incorrect type of space view state."); } } - -/// Space view state without any contents. -#[derive(Default)] -pub struct EmptySpaceViewState; - -impl SpaceViewState for EmptySpaceViewState { - fn as_any(&self) -> &dyn std::any::Any { - self - } - - fn as_any_mut(&mut self) -> &mut dyn std::any::Any { - self - } -} diff --git a/crates/re_viewport/src/viewport.rs b/crates/re_viewport/src/viewport.rs index bef1486a8a76..3209a4297632 100644 --- a/crates/re_viewport/src/viewport.rs +++ b/crates/re_viewport/src/viewport.rs @@ -7,10 +7,10 @@ use itertools::Itertools as _; use re_data_store::EntityPath; use re_data_ui::item_ui; -use re_space_view::DataBlueprintGroup; +use re_space_view::{DataBlueprintGroup, EmptySpaceViewState}; use re_viewer_context::{ - DataBlueprintGroupHandle, EmptySpaceViewState, Item, SpaceViewClassName, - SpaceViewClassRegistry, SpaceViewHighlights, SpaceViewId, ViewerContext, + DataBlueprintGroupHandle, Item, SpaceViewClassName, SpaceViewClassRegistry, + SpaceViewHighlights, SpaceViewId, ViewerContext, }; use crate::{ From 596a90e29a6afaa5896e66d4b4e9c8021bd5b3c5 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Fri, 2 Jun 2023 11:22:33 +0200 Subject: [PATCH 17/39] split up scene module and rename SceneElement to ScenePart --- .../src/scene/elements/mod.rs | 4 +- .../src/scene/elements/points2d.rs | 14 +- .../src/scene/elements/points3d.rs | 14 +- crates/re_space_view_spatial/src/scene/mod.rs | 14 +- ...scene_element.rs => spatial_scene_part.rs} | 22 ++- crates/re_space_view_text/src/lib.rs | 2 +- .../src/{scene_element.rs => scene_part.rs} | 4 +- .../src/space_view_class.rs | 4 +- crates/re_space_view_text_box/src/lib.rs | 2 +- .../src/{scene_element.rs => scene_part.rs} | 4 +- .../src/space_view_class.rs | 4 +- crates/re_viewer_context/src/lib.rs | 9 +- .../re_viewer_context/src/space_view/mod.rs | 15 +- .../re_viewer_context/src/space_view/scene.rs | 160 ++---------------- .../src/space_view/scene_context.rs | 38 +++++ .../src/space_view/scene_part.rs | 38 +++++ .../src/space_view/scene_part_collection.rs | 72 ++++++++ ...ene_element_impl.rs => scene_part_impl.rs} | 10 +- .../src/space_view/space_view_class_impl.rs | 15 +- 19 files changed, 226 insertions(+), 219 deletions(-) rename crates/re_space_view_spatial/src/scene/{spatial_scene_element.rs => spatial_scene_part.rs} (83%) rename crates/re_space_view_text/src/{scene_element.rs => scene_part.rs} (96%) rename crates/re_space_view_text_box/src/{scene_element.rs => scene_part.rs} (93%) create mode 100644 crates/re_viewer_context/src/space_view/scene_context.rs create mode 100644 crates/re_viewer_context/src/space_view/scene_part.rs create mode 100644 crates/re_viewer_context/src/space_view/scene_part_collection.rs rename crates/re_viewer_context/src/space_view/{scene_element_impl.rs => scene_part_impl.rs} (88%) diff --git a/crates/re_space_view_spatial/src/scene/elements/mod.rs b/crates/re_space_view_spatial/src/scene/elements/mod.rs index aee7235cba9f..44d5978514ab 100644 --- a/crates/re_space_view_spatial/src/scene/elements/mod.rs +++ b/crates/re_space_view_spatial/src/scene/elements/mod.rs @@ -22,8 +22,8 @@ pub(crate) use images::ImagesPart; pub(crate) use lines2d::Lines2DPart; pub(crate) use lines3d::Lines3DPart; pub(crate) use meshes::MeshPart; -pub(crate) use points2d::Points2DSceneElement; -pub(crate) use points3d::Points3DSceneElement; +pub(crate) use points2d::Points2DScenePart; +pub(crate) use points3d::Points3DScenePart; use re_components::{ClassId, ColorRGBA, KeypointId, Radius}; use re_data_store::{EntityPath, InstancePathHash}; diff --git a/crates/re_space_view_spatial/src/scene/elements/points2d.rs b/crates/re_space_view_spatial/src/scene/elements/points2d.rs index 507003369d8c..33b4be3dfcb3 100644 --- a/crates/re_space_view_spatial/src/scene/elements/points2d.rs +++ b/crates/re_space_view_spatial/src/scene/elements/points2d.rs @@ -9,7 +9,7 @@ use re_viewer_context::{ResolvedAnnotationInfo, SceneQuery, SpaceViewHighlights, use crate::scene::{ contexts::{SpatialSceneContext, SpatialSceneEntityContext}, load_keypoint_connections, - spatial_scene_element::{SpatialSceneElement, SpatialSceneElementData}, + spatial_scene_part::{SpatialScenePart, SpatialScenePartData}, UiLabel, UiLabelTarget, }; @@ -18,13 +18,13 @@ use super::{ process_colors, process_radii, }; -pub struct Points2DSceneElement { +pub struct Points2DScenePart { /// If the number of points in the batch is > max_labels, don't render point labels. pub max_labels: usize, - pub data: SpatialSceneElementData, + pub data: SpatialScenePartData, } -impl Default for Points2DSceneElement { +impl Default for Points2DScenePart { fn default() -> Self { Self { max_labels: 10, @@ -33,7 +33,7 @@ impl Default for Points2DSceneElement { } } -impl Points2DSceneElement { +impl Points2DScenePart { fn process_labels<'a>( entity_view: &'a EntityView, instance_path_hashes: &'a [InstancePathHash], @@ -179,7 +179,7 @@ impl Points2DSceneElement { } } -impl SpatialSceneElement<7> for Points2DSceneElement { +impl SpatialScenePart<7> for Points2DScenePart { type Primary = Point2D; fn archetype() -> [ComponentName; 7] { @@ -217,7 +217,7 @@ impl SpatialSceneElement<7> for Points2DSceneElement { Vec::new() // TODO(andreas): Optionally return point & line draw data once SharedRenderBuilders is gone. } - fn data(&self) -> &SpatialSceneElementData { + fn data(&self) -> &SpatialScenePartData { &self.data } } diff --git a/crates/re_space_view_spatial/src/scene/elements/points3d.rs b/crates/re_space_view_spatial/src/scene/elements/points3d.rs index dafa3d49eb18..28d8c6bdc4a9 100644 --- a/crates/re_space_view_spatial/src/scene/elements/points3d.rs +++ b/crates/re_space_view_spatial/src/scene/elements/points3d.rs @@ -13,17 +13,17 @@ use crate::scene::{ process_annotations_and_keypoints, process_colors, process_radii, }, load_keypoint_connections, - spatial_scene_element::{SpatialSceneElement, SpatialSceneElementData}, + spatial_scene_part::{SpatialScenePart, SpatialScenePartData}, UiLabel, UiLabelTarget, }; -pub struct Points3DSceneElement { +pub struct Points3DScenePart { /// If the number of points in the batch is > max_labels, don't render point labels. pub max_labels: usize, - pub data: SpatialSceneElementData, + pub data: SpatialScenePartData, } -impl Default for Points3DSceneElement { +impl Default for Points3DScenePart { fn default() -> Self { Self { max_labels: 10, @@ -32,7 +32,7 @@ impl Default for Points3DSceneElement { } } -impl Points3DSceneElement { +impl Points3DScenePart { fn process_labels<'a>( entity_view: &'a EntityView, instance_path_hashes: &'a [InstancePathHash], @@ -176,7 +176,7 @@ impl Points3DSceneElement { } } -impl SpatialSceneElement<7> for Points3DSceneElement { +impl SpatialScenePart<7> for Points3DScenePart { type Primary = Point3D; fn archetype() -> [ComponentName; 7] { @@ -214,7 +214,7 @@ impl SpatialSceneElement<7> for Points3DSceneElement { Vec::new() // TODO(andreas): Optionally return point & line draw data once SharedRenderBuilders is gone. } - fn data(&self) -> &crate::scene::spatial_scene_element::SpatialSceneElementData { + fn data(&self) -> &crate::scene::spatial_scene_part::SpatialScenePartData { &self.data } } diff --git a/crates/re_space_view_spatial/src/scene/mod.rs b/crates/re_space_view_spatial/src/scene/mod.rs index 8d1eafe88214..a62234f6f514 100644 --- a/crates/re_space_view_spatial/src/scene/mod.rs +++ b/crates/re_space_view_spatial/src/scene/mod.rs @@ -15,7 +15,7 @@ use crate::{ mesh_loader::LoadedMesh, scene::{ contexts::SpatialSceneContext, - spatial_scene_element::{SpatialSceneElement, SpatialSceneElementData}, + spatial_scene_part::{SpatialScenePart, SpatialScenePartData}, }, space_camera_3d::SpaceCamera3D, }; @@ -24,7 +24,7 @@ mod contexts; mod elements; mod picking; mod primitives; -mod spatial_scene_element; +mod spatial_scene_part; use self::contexts::SpatialSceneEntityContext; pub use self::picking::{PickingContext, PickingHitType, PickingRayHit, PickingResult}; @@ -174,8 +174,8 @@ impl SceneSpatial { let mut scene = Scene { context: Box::::default(), elements: ( - elements::Points2DSceneElement::default().wrap(), - elements::Points3DSceneElement::default().wrap(), + elements::Points2DScenePart::default().wrap(), + elements::Points3DScenePart::default().wrap(), ) .into(), highlights: Default::default(), @@ -202,10 +202,10 @@ impl SceneSpatial { self.primitives.any_outlines = scene.highlights.any_outlines(); self.primitives.recalculate_bounding_box(); - for scene_element in scene.elements.iter() { - if let Some(data) = scene_element + for scene_part in scene.elements.iter() { + if let Some(data) = scene_part .data() - .and_then(|d| d.downcast_ref::()) + .and_then(|d| d.downcast_ref::()) { self.ui.labels.extend(data.ui_labels.iter().cloned()); self.primitives.bounding_box = diff --git a/crates/re_space_view_spatial/src/scene/spatial_scene_element.rs b/crates/re_space_view_spatial/src/scene/spatial_scene_part.rs similarity index 83% rename from crates/re_space_view_spatial/src/scene/spatial_scene_element.rs rename to crates/re_space_view_spatial/src/scene/spatial_scene_part.rs index 909ad81f77b9..911f92461293 100644 --- a/crates/re_space_view_spatial/src/scene/spatial_scene_element.rs +++ b/crates/re_space_view_spatial/src/scene/spatial_scene_part.rs @@ -3,7 +3,7 @@ use re_data_store::EntityPath; use re_log_types::ComponentName; use re_query::{query_primary_with_history, EntityView, QueryError}; use re_renderer::DepthOffset; -use re_viewer_context::{SceneElementImpl, SceneQuery, SpaceViewHighlights, ViewerContext}; +use re_viewer_context::{ScenePartImpl, SceneQuery, SpaceViewHighlights, ViewerContext}; use super::{ contexts::{SpatialSceneContext, SpatialSceneEntityContext}, @@ -11,12 +11,12 @@ use super::{ }; /// Common data struct for all spatial scene elements. -pub struct SpatialSceneElementData { +pub struct SpatialScenePartData { pub ui_labels: Vec, pub bounding_box: macaw::BoundingBox, } -impl Default for SpatialSceneElementData { +impl Default for SpatialScenePartData { fn default() -> Self { Self { ui_labels: Vec::new(), @@ -25,7 +25,7 @@ impl Default for SpatialSceneElementData { } } -pub trait SpatialSceneElement: std::any::Any { +pub trait SpatialScenePart: std::any::Any { type Primary: Component + 'static; fn archetype() -> [ComponentName; N]; @@ -38,7 +38,7 @@ pub trait SpatialSceneElement: std::any::Any { highlights: &SpaceViewHighlights, ) -> Vec; - fn data(&self) -> &SpatialSceneElementData; + fn data(&self) -> &SpatialScenePartData; fn for_each_entity_view( ctx: &mut ViewerContext<'_>, @@ -86,22 +86,20 @@ pub trait SpatialSceneElement: std::any::Any { } } - fn wrap(self) -> SpatialSceneElementWrapper + fn wrap(self) -> SpatialScenePartWrapper where Self: Sized, { - SpatialSceneElementWrapper(self) + SpatialScenePartWrapper(self) } } -/// A wrapper for `SpatialSceneElement` that implements `SceneElement`. +/// A wrapper for `SpatialScenePart` that implements `ScenePart`. /// /// Can't implement directly due to Rust limitations around higher kinded traits. -pub struct SpatialSceneElementWrapper>(pub T); +pub struct SpatialScenePartWrapper>(pub T); -impl> SceneElementImpl - for SpatialSceneElementWrapper -{ +impl> ScenePartImpl for SpatialScenePartWrapper { type SpaceViewState = re_space_view::EmptySpaceViewState; type SceneContext = SpatialSceneContext; diff --git a/crates/re_space_view_text/src/lib.rs b/crates/re_space_view_text/src/lib.rs index 6e16190b4226..fad5ceea2b3e 100644 --- a/crates/re_space_view_text/src/lib.rs +++ b/crates/re_space_view_text/src/lib.rs @@ -2,7 +2,7 @@ //! //! A Space View that shows text entries in a table and scrolls with the active time. -mod scene_element; +mod scene_part; mod space_view_class; pub use space_view_class::TextSpaceView; diff --git a/crates/re_space_view_text/src/scene_element.rs b/crates/re_space_view_text/src/scene_part.rs similarity index 96% rename from crates/re_space_view_text/src/scene_element.rs rename to crates/re_space_view_text/src/scene_part.rs index f42d83d7783b..28b9166d462a 100644 --- a/crates/re_space_view_text/src/scene_element.rs +++ b/crates/re_space_view_text/src/scene_part.rs @@ -3,7 +3,7 @@ use re_data_store::EntityPath; use re_log_types::{Component as _, InstanceKey, RowId}; use re_query::{range_entity_with_primary, QueryError}; use re_viewer_context::{ - ArchetypeDefinition, SceneElementImpl, SceneQuery, SpaceViewHighlights, ViewerContext, + ArchetypeDefinition, ScenePartImpl, SceneQuery, SpaceViewHighlights, ViewerContext, }; use super::space_view_class::TextSpaceViewState; @@ -31,7 +31,7 @@ pub struct SceneText { pub text_entries: Vec, } -impl SceneElementImpl for SceneText { +impl ScenePartImpl for SceneText { type SpaceViewState = TextSpaceViewState; type SceneContext = re_space_view::EmptySceneContext; diff --git a/crates/re_space_view_text/src/space_view_class.rs b/crates/re_space_view_text/src/space_view_class.rs index c55148419041..09803bf2c720 100644 --- a/crates/re_space_view_text/src/space_view_class.rs +++ b/crates/re_space_view_text/src/space_view_class.rs @@ -7,7 +7,7 @@ use re_viewer_context::{ ViewerContext, }; -use super::scene_element::{SceneText, TextEntry}; +use super::scene_part::{SceneText, TextEntry}; // TODO(andreas): This should be a blueprint component. #[derive(Clone, PartialEq, Eq, Default)] @@ -39,7 +39,7 @@ pub struct TextSpaceView; impl SpaceViewClassImpl for TextSpaceView { type SpaceViewState = TextSpaceViewState; type SceneContext = re_space_view::EmptySceneContext; - type SceneElementTuple = (SceneText,); + type ScenePartTuple = (SceneText,); fn name(&self) -> SpaceViewClassName { "Text".into() diff --git a/crates/re_space_view_text_box/src/lib.rs b/crates/re_space_view_text_box/src/lib.rs index 75abbd822aa9..a8a47e968170 100644 --- a/crates/re_space_view_text_box/src/lib.rs +++ b/crates/re_space_view_text_box/src/lib.rs @@ -2,7 +2,7 @@ //! //! A simple Space View that shows a single text box. -mod scene_element; +mod scene_part; mod space_view_class; pub use space_view_class::TextBoxSpaceView; diff --git a/crates/re_space_view_text_box/src/scene_element.rs b/crates/re_space_view_text_box/src/scene_part.rs similarity index 93% rename from crates/re_space_view_text_box/src/scene_element.rs rename to crates/re_space_view_text_box/src/scene_part.rs index 9c092383384f..976558d65af9 100644 --- a/crates/re_space_view_text_box/src/scene_element.rs +++ b/crates/re_space_view_text_box/src/scene_part.rs @@ -2,7 +2,7 @@ use re_arrow_store::LatestAtQuery; use re_components::Component; use re_query::{query_entity_with_primary, QueryError}; use re_viewer_context::{ - ArchetypeDefinition, SceneElementImpl, SceneQuery, SpaceViewHighlights, ViewerContext, + ArchetypeDefinition, ScenePartImpl, SceneQuery, SpaceViewHighlights, ViewerContext, }; use crate::space_view_class::TextBoxSpaceViewState; @@ -20,7 +20,7 @@ pub struct SceneTextBox { pub text_entries: Vec, } -impl SceneElementImpl for SceneTextBox { +impl ScenePartImpl for SceneTextBox { type SpaceViewState = TextBoxSpaceViewState; type SceneContext = re_space_view::EmptySceneContext; diff --git a/crates/re_space_view_text_box/src/space_view_class.rs b/crates/re_space_view_text_box/src/space_view_class.rs index e2bd47a32774..9ce63e89d32c 100644 --- a/crates/re_space_view_text_box/src/space_view_class.rs +++ b/crates/re_space_view_text_box/src/space_view_class.rs @@ -3,7 +3,7 @@ use re_viewer_context::{ Scene, SpaceViewClassImpl, SpaceViewClassName, SpaceViewState, ViewerContext, }; -use super::scene_element::SceneTextBox; +use super::scene_part::SceneTextBox; // TODO(andreas): This should be a blueprint component. #[derive(Clone, PartialEq, Eq)] @@ -36,7 +36,7 @@ pub struct TextBoxSpaceView; impl SpaceViewClassImpl for TextBoxSpaceView { type SpaceViewState = TextBoxSpaceViewState; - type SceneElementTuple = (SceneTextBox,); + type ScenePartTuple = (SceneTextBox,); type SceneContext = re_space_view::EmptySceneContext; fn name(&self) -> SpaceViewClassName { diff --git a/crates/re_viewer_context/src/lib.rs b/crates/re_viewer_context/src/lib.rs index 041cefe5eed6..42c14c52771f 100644 --- a/crates/re_viewer_context/src/lib.rs +++ b/crates/re_viewer_context/src/lib.rs @@ -30,11 +30,10 @@ pub use selection_state::{ HoverHighlight, HoveredSpace, InteractionHighlight, SelectionHighlight, SelectionState, }; pub use space_view::{ - ArchetypeDefinition, Scene, SceneContext, SceneContextPart, SceneElement, - SceneElementCollection, SceneElementImpl, SceneItemCollectionLookupError, SceneQuery, - SpaceViewClass, SpaceViewClassImpl, SpaceViewClassName, SpaceViewClassRegistry, - SpaceViewClassRegistryError, SpaceViewEntityHighlight, SpaceViewHighlights, - SpaceViewOutlineMasks, SpaceViewState, + ArchetypeDefinition, Scene, SceneContext, SceneContextPart, ScenePart, ScenePartCollection, + ScenePartCollectionLookupError, ScenePartImpl, SceneQuery, SpaceViewClass, SpaceViewClassImpl, + SpaceViewClassName, SpaceViewClassRegistry, SpaceViewClassRegistryError, + SpaceViewEntityHighlight, SpaceViewHighlights, SpaceViewOutlineMasks, SpaceViewState, }; pub use tensor::{TensorDecodeCache, TensorStats, TensorStatsCache}; pub use time_control::{Looping, PlayState, TimeControl, TimeView}; diff --git a/crates/re_viewer_context/src/space_view/mod.rs b/crates/re_viewer_context/src/space_view/mod.rs index e9295770a680..118fc78f129a 100644 --- a/crates/re_viewer_context/src/space_view/mod.rs +++ b/crates/re_viewer_context/src/space_view/mod.rs @@ -6,18 +6,21 @@ // TODO(andreas): Can we move some of these to the `re_space_view` crate? mod highlights; mod scene; -mod scene_element_impl; +mod scene_context; +mod scene_part; +mod scene_part_collection; +mod scene_part_impl; mod scene_query; mod space_view_class; mod space_view_class_impl; mod space_view_class_registry; pub use highlights::{SpaceViewEntityHighlight, SpaceViewHighlights, SpaceViewOutlineMasks}; -pub use scene::{ - Scene, SceneContext, SceneContextPart, SceneElement, SceneElementCollection, - SceneItemCollectionLookupError, -}; -pub use scene_element_impl::SceneElementImpl; +pub use scene::Scene; +pub use scene_context::{SceneContext, SceneContextPart}; +pub use scene_part::ScenePart; +pub use scene_part_collection::{ScenePartCollection, ScenePartCollectionLookupError}; +pub use scene_part_impl::ScenePartImpl; pub use scene_query::SceneQuery; pub use space_view_class::{ ArchetypeDefinition, SpaceViewClass, SpaceViewClassName, SpaceViewState, diff --git a/crates/re_viewer_context/src/space_view/scene.rs b/crates/re_viewer_context/src/space_view/scene.rs index ba8722388e0d..efa6fd27bf6a 100644 --- a/crates/re_viewer_context/src/space_view/scene.rs +++ b/crates/re_viewer_context/src/space_view/scene.rs @@ -1,102 +1,22 @@ -use std::any::{Any, TypeId}; +use crate::{ + ArchetypeDefinition, SceneContext, ScenePartCollection, SceneQuery, SpaceViewHighlights, + SpaceViewState, ViewerContext, +}; -use ahash::HashMap; - -use crate::{ArchetypeDefinition, SceneQuery, SpaceViewHighlights, SpaceViewState, ViewerContext}; - -#[derive(Debug, thiserror::Error)] -pub enum SceneItemCollectionLookupError { - #[error("Type not found in collection")] - TypeNotFound, - - #[error("Failed to downcast type.")] - DowncastFailure, -} - -// TODO(andreas): Use tinyvec for these. - -/// Scene context, consisting of several [`SceneContextPart`] which may be populated in parallel. -pub trait SceneContext { - /// Retrieves a list of all underlying scene context part for parallel population. - fn vec_mut(&mut self) -> Vec<&mut dyn SceneContextPart>; - - /// Converts itself to a reference of [`Any`], which enables downcasting to concrete types. - fn as_any(&self) -> &dyn std::any::Any; - - /// Converts itself to a reference of [`Any`], which enables downcasting to concrete types. - fn as_any_mut(&mut self) -> &mut dyn std::any::Any; -} - -/// Collections of scene elements. -/// -/// New type pattern to support adding From impls. -#[derive(Default)] -pub struct SceneElementCollection(HashMap>); - -impl SceneElementCollection { - pub fn get(&self) -> Result<&T, SceneItemCollectionLookupError> { - self.0 - .get(&TypeId::of::()) - .ok_or(SceneItemCollectionLookupError::TypeNotFound)? - .as_any() - .downcast_ref::() - .ok_or(SceneItemCollectionLookupError::DowncastFailure) - } - - pub fn get_mut(&mut self) -> Result<&mut T, SceneItemCollectionLookupError> { - self.0 - .get_mut(&TypeId::of::()) - .ok_or(SceneItemCollectionLookupError::TypeNotFound)? - .as_any_mut() - .downcast_mut::() - .ok_or(SceneItemCollectionLookupError::DowncastFailure) - } - - pub fn iter(&self) -> impl Iterator> { - self.0.values() - } -} - -macro_rules! scene_element_collection_from_tuple { - ($($idx:tt => $name:ident),*) => { - impl<$($name: SceneElement),*> From<($($name,)*)> for SceneElementCollection { - #[allow(unused_mut)] - fn from(_value: ($($name,)*)) -> Self { - let mut map = HashMap::>::default(); - $( - map.insert(_value.$idx.as_any().type_id(), Box::new(_value.$idx)); - )* - Self(map) - } - } - }; -} - -scene_element_collection_from_tuple!(); -scene_element_collection_from_tuple!(0 => T0); -scene_element_collection_from_tuple!(0 => T0, 1 => T1); -scene_element_collection_from_tuple!(0 => T0, 1 => T1, 2 => T2); -scene_element_collection_from_tuple!(0 => T0, 1 => T1, 2 => T2, 3 => T3); -scene_element_collection_from_tuple!(0 => T0, 1 => T1, 2 => T2, 3 => T3, 4 => T4); -scene_element_collection_from_tuple!(0 => T0, 1 => T1, 2 => T2, 3 => T3, 4 => T4, 5 => T5); -scene_element_collection_from_tuple!(0 => T0, 1 => T1, 2 => T2, 3 => T3, 4 => T4, 5 => T5, 6 => T6); -scene_element_collection_from_tuple!(0 => T0, 1 => T1, 2 => T2, 3 => T3, 4 => T4, 5 => T5, 6 => T6, 7 => T7); -scene_element_collection_from_tuple!(0 => T0, 1 => T1, 2 => T2, 3 => T3, 4 => T4, 5 => T5, 6 => T6, 7 => T7, 8 => T8); - -/// A scene is a collection of scene contexts and elements, as well as a collection of highlights. +/// Every [`crate::SpaceViewClass`] creates and populates a scene to draw a frame and inform the ui about relevant data. /// /// When populating a scene, first all contexts are populated, /// and then all elements with read access to the previously established context objects. pub struct Scene { pub context: Box, - pub elements: SceneElementCollection, + pub elements: ScenePartCollection, pub highlights: SpaceViewHighlights, // TODO(wumpf): Consider making this a scene context - problem: populate can't create it. } impl Scene { - /// List of all archetypes this scene queries for its elements. - pub fn supported_element_archetypes(&self) -> Vec { - self.elements.0.values().map(|e| e.archetype()).collect() + /// List of all archetypes this scene queries for its parts. + pub fn part_archetypes(&self) -> Vec { + self.elements.iter().map(|e| e.archetype()).collect() } /// Populates the scene for a given query. @@ -117,8 +37,7 @@ impl Scene { context.populate(ctx, query, space_view_state); } self.elements - .0 - .values_mut() + .iter_mut() .flat_map(|element| { // TODO(andreas): Restrict the query with the archetype somehow, ideally making it trivial to do the correct thing. element.populate( @@ -132,62 +51,3 @@ impl Scene { .collect() } } - -/// Element of a scene derived from a single archetype query. -/// -/// Is populated after scene contexts and has access to them. -pub trait SceneElement: Any { - /// The archetype queried by this scene element. - fn archetype(&self) -> ArchetypeDefinition; - - /// Queries the data store and performs data conversions to make it ready for display. - /// - /// Musn't query any data outside of the archetype. - fn populate( - &mut self, - ctx: &mut ViewerContext<'_>, - query: &SceneQuery<'_>, - space_view_state: &dyn SpaceViewState, - context: &dyn SceneContext, - highlights: &SpaceViewHighlights, - ) -> Vec; - - /// Optionally retrieves a data store reference from the scene element. - /// - /// This is a useful for retrieving a data struct that may be common for all scene elements - /// of a particular [`crate::SpaceViewClass`]. - fn data(&self) -> Option<&dyn std::any::Any> { - None - } - - /// Converts itself to a reference of [`Any`], which enables downcasting to concrete types. - fn as_any(&self) -> &dyn std::any::Any; - - /// Converts itself to a reference of [`Any`], which enables downcasting to concrete types. - fn as_any_mut(&mut self) -> &mut dyn std::any::Any; -} - -/// Scene context that can be used by scene elements and ui methods to retrieve information about the scene as a whole. -/// -/// Is always populated before scene elements. -pub trait SceneContextPart: Any { - /// Each scene context may query several archetypes. - /// - /// This lists all components out that the context queries. - /// A context may also query no archetypes at all and prepare caches or viewer related data instead. - fn archetypes(&self) -> Vec; - - /// Queries the data store and performs data conversions to make it ready for consumption by scene elements. - fn populate( - &mut self, - ctx: &mut ViewerContext<'_>, - query: &SceneQuery<'_>, - space_view_state: &dyn SpaceViewState, - ); - - /// Converts itself to a reference of [`Any`], which enables downcasting to concrete types. - fn as_any(&self) -> &dyn std::any::Any; - - /// Converts itself to a reference of [`Any`], which enables downcasting to concrete types. - fn as_any_mut(&mut self) -> &mut dyn std::any::Any; -} diff --git a/crates/re_viewer_context/src/space_view/scene_context.rs b/crates/re_viewer_context/src/space_view/scene_context.rs new file mode 100644 index 000000000000..1354360a7d8e --- /dev/null +++ b/crates/re_viewer_context/src/space_view/scene_context.rs @@ -0,0 +1,38 @@ +use crate::{ArchetypeDefinition, SceneQuery, SpaceViewState, ViewerContext}; + +/// Scene context, consisting of several [`SceneContextPart`] which may be populated in parallel. +pub trait SceneContext { + /// Retrieves a list of all underlying scene context part for parallel population. + fn vec_mut(&mut self) -> Vec<&mut dyn SceneContextPart>; + + /// Converts itself to a reference of [`Any`], which enables downcasting to concrete types. + fn as_any(&self) -> &dyn std::any::Any; + + /// Converts itself to a reference of [`Any`], which enables downcasting to concrete types. + fn as_any_mut(&mut self) -> &mut dyn std::any::Any; +} + +/// Scene context that can be used by scene elements and ui methods to retrieve information about the scene as a whole. +/// +/// Is always populated before scene elements. +pub trait SceneContextPart { + /// Each scene context may query several archetypes. + /// + /// This lists all components out that the context queries. + /// A context may also query no archetypes at all and prepare caches or viewer related data instead. + fn archetypes(&self) -> Vec; + + /// Queries the data store and performs data conversions to make it ready for consumption by scene elements. + fn populate( + &mut self, + ctx: &mut ViewerContext<'_>, + query: &SceneQuery<'_>, + space_view_state: &dyn SpaceViewState, + ); + + /// Converts itself to a reference of [`Any`], which enables downcasting to concrete types. + fn as_any(&self) -> &dyn std::any::Any; + + /// Converts itself to a reference of [`Any`], which enables downcasting to concrete types. + fn as_any_mut(&mut self) -> &mut dyn std::any::Any; +} diff --git a/crates/re_viewer_context/src/space_view/scene_part.rs b/crates/re_viewer_context/src/space_view/scene_part.rs new file mode 100644 index 000000000000..b2c1286ae9bd --- /dev/null +++ b/crates/re_viewer_context/src/space_view/scene_part.rs @@ -0,0 +1,38 @@ +use crate::{ + ArchetypeDefinition, SceneContext, SceneQuery, SpaceViewHighlights, SpaceViewState, + ViewerContext, +}; + +/// Element of a scene derived from a single archetype query. +/// +/// Is populated after scene contexts and has access to them. +pub trait ScenePart: std::any::Any { + /// The archetype queried by this scene element. + fn archetype(&self) -> ArchetypeDefinition; + + /// Queries the data store and performs data conversions to make it ready for display. + /// + /// Musn't query any data outside of the archetype. + fn populate( + &mut self, + ctx: &mut ViewerContext<'_>, + query: &SceneQuery<'_>, + space_view_state: &dyn SpaceViewState, + context: &dyn SceneContext, + highlights: &SpaceViewHighlights, + ) -> Vec; + + /// Optionally retrieves a data store reference from the scene element. + /// + /// This is a useful for retrieving a data struct that may be common for all scene elements + /// of a particular [`crate::SpaceViewClass`]. + fn data(&self) -> Option<&dyn std::any::Any> { + None + } + + /// Converts itself to a reference of [`Any`], which enables downcasting to concrete types. + fn as_any(&self) -> &dyn std::any::Any; + + /// Converts itself to a reference of [`Any`], which enables downcasting to concrete types. + fn as_any_mut(&mut self) -> &mut dyn std::any::Any; +} diff --git a/crates/re_viewer_context/src/space_view/scene_part_collection.rs b/crates/re_viewer_context/src/space_view/scene_part_collection.rs new file mode 100644 index 000000000000..0900c7d3a87a --- /dev/null +++ b/crates/re_viewer_context/src/space_view/scene_part_collection.rs @@ -0,0 +1,72 @@ +use ahash::HashMap; + +use crate::ScenePart; + +#[derive(Debug, thiserror::Error)] +pub enum ScenePartCollectionLookupError { + #[error("Type not found in collection")] + TypeNotFound, + + #[error("Failed to downcast type.")] + DowncastFailure, +} + +/// Collections of scene parts. +#[derive(Default)] +pub struct ScenePartCollection(HashMap>); + +impl ScenePartCollection { + pub fn get(&self) -> Result<&T, ScenePartCollectionLookupError> { + self.0 + .get(&std::any::TypeId::of::()) + .ok_or(ScenePartCollectionLookupError::TypeNotFound)? + .as_any() + .downcast_ref::() + .ok_or(ScenePartCollectionLookupError::DowncastFailure) + } + + pub fn get_mut(&mut self) -> Result<&mut T, ScenePartCollectionLookupError> { + self.0 + .get_mut(&std::any::TypeId::of::()) + .ok_or(ScenePartCollectionLookupError::TypeNotFound)? + .as_any_mut() + .downcast_mut::() + .ok_or(ScenePartCollectionLookupError::DowncastFailure) + } + + #[inline] + pub fn iter(&self) -> impl Iterator> { + self.0.values() + } + + #[inline] + pub fn iter_mut(&mut self) -> impl Iterator> { + self.0.values_mut() + } +} + +macro_rules! scene_part_collection_from_tuple { + ($($idx:tt => $name:ident),*) => { + impl<$($name: ScenePart),*> From<($($name,)*)> for ScenePartCollection { + #[allow(unused_mut)] + fn from(_value: ($($name,)*)) -> Self { + let mut map = HashMap::>::default(); + $( + map.insert(_value.$idx.as_any().type_id(), Box::new(_value.$idx)); + )* + Self(map) + } + } + }; +} + +scene_part_collection_from_tuple!(); +scene_part_collection_from_tuple!(0 => T0); +scene_part_collection_from_tuple!(0 => T0, 1 => T1); +scene_part_collection_from_tuple!(0 => T0, 1 => T1, 2 => T2); +scene_part_collection_from_tuple!(0 => T0, 1 => T1, 2 => T2, 3 => T3); +scene_part_collection_from_tuple!(0 => T0, 1 => T1, 2 => T2, 3 => T3, 4 => T4); +scene_part_collection_from_tuple!(0 => T0, 1 => T1, 2 => T2, 3 => T3, 4 => T4, 5 => T5); +scene_part_collection_from_tuple!(0 => T0, 1 => T1, 2 => T2, 3 => T3, 4 => T4, 5 => T5, 6 => T6); +scene_part_collection_from_tuple!(0 => T0, 1 => T1, 2 => T2, 3 => T3, 4 => T4, 5 => T5, 6 => T6, 7 => T7); +scene_part_collection_from_tuple!(0 => T0, 1 => T1, 2 => T2, 3 => T3, 4 => T4, 5 => T5, 6 => T6, 7 => T7, 8 => T8); diff --git a/crates/re_viewer_context/src/space_view/scene_element_impl.rs b/crates/re_viewer_context/src/space_view/scene_part_impl.rs similarity index 88% rename from crates/re_viewer_context/src/space_view/scene_element_impl.rs rename to crates/re_viewer_context/src/space_view/scene_part_impl.rs index bee8c8fe8271..f9c9af16f080 100644 --- a/crates/re_viewer_context/src/space_view/scene_element_impl.rs +++ b/crates/re_viewer_context/src/space_view/scene_part_impl.rs @@ -1,10 +1,10 @@ use crate::{ - ArchetypeDefinition, SceneContext, SceneElement, SceneQuery, SpaceViewHighlights, - SpaceViewState, ViewerContext, + ArchetypeDefinition, SceneContext, ScenePart, SceneQuery, SpaceViewHighlights, SpaceViewState, + ViewerContext, }; -/// Implementation utility for [`crate::SceneElement`] -pub trait SceneElementImpl { +/// Implementation utility for [`crate::ScenePart`] +pub trait ScenePartImpl { type SpaceViewState: SpaceViewState + Default + 'static; type SceneContext: SceneContext + 'static; @@ -32,7 +32,7 @@ pub trait SceneElementImpl { } } -impl SceneElement for T { +impl ScenePart for T { #[inline] fn archetype(&self) -> ArchetypeDefinition { self.archetype() diff --git a/crates/re_viewer_context/src/space_view/space_view_class_impl.rs b/crates/re_viewer_context/src/space_view/space_view_class_impl.rs index e1b5633c4c17..86063a518a65 100644 --- a/crates/re_viewer_context/src/space_view/space_view_class_impl.rs +++ b/crates/re_viewer_context/src/space_view/space_view_class_impl.rs @@ -1,10 +1,9 @@ use crate::{ - Scene, SceneContext, SpaceViewClass, SpaceViewClassName, SpaceViewState, ViewerContext, + Scene, SceneContext, ScenePartCollection, SpaceViewClass, SpaceViewClassName, SpaceViewState, + ViewerContext, }; -use super::scene::SceneElementCollection; - -/// Utility for implementing [`SpaceViewClass`] with concrete [`SpaceViewState`] and [`crate::SceneElement`] type. +/// Utility for implementing [`SpaceViewClass`] with concrete [`SpaceViewState`] and [`crate::ScenePart`] type. /// /// Each Space View in the viewer's viewport has a single class assigned immutable at its creation time. /// The class defines all aspects of its behavior. @@ -13,11 +12,11 @@ pub trait SpaceViewClassImpl { /// State of a space view. type SpaceViewState: SpaceViewState + Default + 'static; - /// Context of the scene, which is passed to all [`crate::SceneElement`]s and ui drawing on population. + /// Context of the scene, which is passed to all [`crate::ScenePart`]s and ui drawing on population. type SceneContext: SceneContext + Default + 'static; - /// A tuple of [`crate::SceneElement`] types that are supported by this space view class. - type SceneElementTuple: Into + Default + 'static; + /// A tuple of [`crate::ScenePart`] types that are supported by this space view class. + type ScenePartTuple: Into + Default + 'static; /// Name of this space view class. /// @@ -74,7 +73,7 @@ impl SpaceViewClass for T { fn new_scene(&self) -> Scene { Scene { context: Box::::default(), - elements: T::SceneElementTuple::default().into(), + elements: T::ScenePartTuple::default().into(), highlights: Default::default(), } } From 9cbcf2731b05153588a38018d4573bb39e911b9a Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Fri, 2 Jun 2023 11:52:24 +0200 Subject: [PATCH 18/39] spatial scene parts are called parts again --- crates/re_space_view_spatial/src/scene/mod.rs | 51 ++++++++++--------- .../src/scene/{elements => parts}/arrows3d.rs | 0 .../src/scene/{elements => parts}/boxes2d.rs | 0 .../src/scene/{elements => parts}/boxes3d.rs | 0 .../src/scene/{elements => parts}/cameras.rs | 0 .../src/scene/{elements => parts}/images.rs | 0 .../src/scene/{elements => parts}/lines2d.rs | 0 .../src/scene/{elements => parts}/lines3d.rs | 0 .../src/scene/{elements => parts}/meshes.rs | 0 .../src/scene/{elements => parts}/mod.rs | 13 +++-- .../src/scene/{elements => parts}/points2d.rs | 14 +++-- .../src/scene/{elements => parts}/points3d.rs | 23 ++++----- .../scene/{ => parts}/spatial_scene_part.rs | 2 +- 13 files changed, 54 insertions(+), 49 deletions(-) rename crates/re_space_view_spatial/src/scene/{elements => parts}/arrows3d.rs (100%) rename crates/re_space_view_spatial/src/scene/{elements => parts}/boxes2d.rs (100%) rename crates/re_space_view_spatial/src/scene/{elements => parts}/boxes3d.rs (100%) rename crates/re_space_view_spatial/src/scene/{elements => parts}/cameras.rs (100%) rename crates/re_space_view_spatial/src/scene/{elements => parts}/images.rs (100%) rename crates/re_space_view_spatial/src/scene/{elements => parts}/lines2d.rs (100%) rename crates/re_space_view_spatial/src/scene/{elements => parts}/lines3d.rs (100%) rename crates/re_space_view_spatial/src/scene/{elements => parts}/meshes.rs (100%) rename crates/re_space_view_spatial/src/scene/{elements => parts}/mod.rs (97%) rename crates/re_space_view_spatial/src/scene/{elements => parts}/points2d.rs (96%) rename crates/re_space_view_spatial/src/scene/{elements => parts}/points3d.rs (93%) rename crates/re_space_view_spatial/src/scene/{ => parts}/spatial_scene_part.rs (99%) diff --git a/crates/re_space_view_spatial/src/scene/mod.rs b/crates/re_space_view_spatial/src/scene/mod.rs index a62234f6f514..3b416af9b556 100644 --- a/crates/re_space_view_spatial/src/scene/mod.rs +++ b/crates/re_space_view_spatial/src/scene/mod.rs @@ -1,6 +1,16 @@ -use std::sync::Arc; +mod contexts; +mod parts; +mod picking; +mod primitives; + +pub use self::{ + picking::{PickingContext, PickingHitType, PickingRayHit, PickingResult}, + primitives::SceneSpatialPrimitives, +}; +pub use contexts::{TransformContext, UnreachableTransform}; use ahash::HashMap; +use std::sync::Arc; use re_components::{ClassId, DecodedTensor, DrawOrder, InstanceKey, KeypointId}; use re_data_store::{EntityPath, InstancePathHash}; @@ -10,29 +20,21 @@ use re_viewer_context::{ auto_color, AnnotationMap, Scene, SceneQuery, SpaceViewHighlights, ViewerContext, }; -use super::SpatialNavigationMode; use crate::{ mesh_loader::LoadedMesh, scene::{ contexts::SpatialSceneContext, - spatial_scene_part::{SpatialScenePart, SpatialScenePartData}, + parts::{SpatialScenePart, SpatialScenePartData}, }, space_camera_3d::SpaceCamera3D, }; -mod contexts; -mod elements; -mod picking; -mod primitives; -mod spatial_scene_part; +use super::SpatialNavigationMode; use self::contexts::SpatialSceneEntityContext; -pub use self::picking::{PickingContext, PickingHitType, PickingRayHit, PickingResult}; -pub use self::primitives::SceneSpatialPrimitives; -use elements::ScenePart; +use parts::ScenePart; use contexts::EntityDepthOffsets; -pub use contexts::{TransformContext, UnreachableTransform}; const SIZE_BOOST_IN_POINTS_FOR_LINE_OUTLINES: f32 = 1.5; const SIZE_BOOST_IN_POINTS_FOR_POINT_OUTLINES: f32 = 2.5; @@ -156,26 +158,29 @@ impl SceneSpatial { let parts: Vec<&dyn ScenePart> = vec![ // -- - &elements::Boxes3DPart, - &elements::Lines3DPart, - &elements::Arrows3DPart, - &elements::MeshPart, - &elements::ImagesPart, + &parts::Boxes3DPart, + &parts::Lines3DPart, + &parts::Arrows3DPart, + &parts::MeshPart, + &parts::ImagesPart, // -- - &elements::Boxes2DPart, + &parts::Boxes2DPart, // -- // Note: Lines2DPart handles both Segments and LinesPaths since they are unified on the logging-side. - &elements::Lines2DPart, + &parts::Lines2DPart, // --- - &elements::CamerasPart, + &parts::CamerasPart, ]; - // TODO(andreas): Temporary build up of scene. This will be handled by the SpaceViewClass framework later. + // TODO(wumpf): Temporary build up of scene. This will be handled by the SpaceViewClass framework later. let mut scene = Scene { context: Box::::default(), + // TODO(wumpf): How can we make this syntax possible instead? + // The problem is that `Points2DScenePart` can't be put directly into the list since only the wrapper implements ScenePart + //elements: parts::ScenePartTuple::default().into(), elements: ( - elements::Points2DScenePart::default().wrap(), - elements::Points3DScenePart::default().wrap(), + parts::Points2DPart::default().wrap(), + parts::Points3DPart::default().wrap(), ) .into(), highlights: Default::default(), diff --git a/crates/re_space_view_spatial/src/scene/elements/arrows3d.rs b/crates/re_space_view_spatial/src/scene/parts/arrows3d.rs similarity index 100% rename from crates/re_space_view_spatial/src/scene/elements/arrows3d.rs rename to crates/re_space_view_spatial/src/scene/parts/arrows3d.rs diff --git a/crates/re_space_view_spatial/src/scene/elements/boxes2d.rs b/crates/re_space_view_spatial/src/scene/parts/boxes2d.rs similarity index 100% rename from crates/re_space_view_spatial/src/scene/elements/boxes2d.rs rename to crates/re_space_view_spatial/src/scene/parts/boxes2d.rs diff --git a/crates/re_space_view_spatial/src/scene/elements/boxes3d.rs b/crates/re_space_view_spatial/src/scene/parts/boxes3d.rs similarity index 100% rename from crates/re_space_view_spatial/src/scene/elements/boxes3d.rs rename to crates/re_space_view_spatial/src/scene/parts/boxes3d.rs diff --git a/crates/re_space_view_spatial/src/scene/elements/cameras.rs b/crates/re_space_view_spatial/src/scene/parts/cameras.rs similarity index 100% rename from crates/re_space_view_spatial/src/scene/elements/cameras.rs rename to crates/re_space_view_spatial/src/scene/parts/cameras.rs diff --git a/crates/re_space_view_spatial/src/scene/elements/images.rs b/crates/re_space_view_spatial/src/scene/parts/images.rs similarity index 100% rename from crates/re_space_view_spatial/src/scene/elements/images.rs rename to crates/re_space_view_spatial/src/scene/parts/images.rs diff --git a/crates/re_space_view_spatial/src/scene/elements/lines2d.rs b/crates/re_space_view_spatial/src/scene/parts/lines2d.rs similarity index 100% rename from crates/re_space_view_spatial/src/scene/elements/lines2d.rs rename to crates/re_space_view_spatial/src/scene/parts/lines2d.rs diff --git a/crates/re_space_view_spatial/src/scene/elements/lines3d.rs b/crates/re_space_view_spatial/src/scene/parts/lines3d.rs similarity index 100% rename from crates/re_space_view_spatial/src/scene/elements/lines3d.rs rename to crates/re_space_view_spatial/src/scene/parts/lines3d.rs diff --git a/crates/re_space_view_spatial/src/scene/elements/meshes.rs b/crates/re_space_view_spatial/src/scene/parts/meshes.rs similarity index 100% rename from crates/re_space_view_spatial/src/scene/elements/meshes.rs rename to crates/re_space_view_spatial/src/scene/parts/meshes.rs diff --git a/crates/re_space_view_spatial/src/scene/elements/mod.rs b/crates/re_space_view_spatial/src/scene/parts/mod.rs similarity index 97% rename from crates/re_space_view_spatial/src/scene/elements/mod.rs rename to crates/re_space_view_spatial/src/scene/parts/mod.rs index 44d5978514ab..a5d21d395ad7 100644 --- a/crates/re_space_view_spatial/src/scene/elements/mod.rs +++ b/crates/re_space_view_spatial/src/scene/parts/mod.rs @@ -10,10 +10,8 @@ mod lines3d; mod meshes; mod points2d; mod points3d; +mod spatial_scene_part; -use std::sync::Arc; - -use ahash::HashMap; pub(crate) use arrows3d::Arrows3DPart; pub(crate) use boxes2d::Boxes2DPart; pub(crate) use boxes3d::Boxes3DPart; @@ -22,8 +20,13 @@ pub(crate) use images::ImagesPart; pub(crate) use lines2d::Lines2DPart; pub(crate) use lines3d::Lines3DPart; pub(crate) use meshes::MeshPart; -pub(crate) use points2d::Points2DScenePart; -pub(crate) use points3d::Points3DScenePart; +pub(crate) use points2d::Points2DPart; +pub(crate) use points3d::Points3DPart; + +pub use spatial_scene_part::{SpatialScenePart, SpatialScenePartData}; + +use ahash::HashMap; +use std::sync::Arc; use re_components::{ClassId, ColorRGBA, KeypointId, Radius}; use re_data_store::{EntityPath, InstancePathHash}; diff --git a/crates/re_space_view_spatial/src/scene/elements/points2d.rs b/crates/re_space_view_spatial/src/scene/parts/points2d.rs similarity index 96% rename from crates/re_space_view_spatial/src/scene/elements/points2d.rs rename to crates/re_space_view_spatial/src/scene/parts/points2d.rs index 33b4be3dfcb3..27cd4f5b2818 100644 --- a/crates/re_space_view_spatial/src/scene/elements/points2d.rs +++ b/crates/re_space_view_spatial/src/scene/parts/points2d.rs @@ -8,23 +8,21 @@ use re_viewer_context::{ResolvedAnnotationInfo, SceneQuery, SpaceViewHighlights, use crate::scene::{ contexts::{SpatialSceneContext, SpatialSceneEntityContext}, - load_keypoint_connections, - spatial_scene_part::{SpatialScenePart, SpatialScenePartData}, - UiLabel, UiLabelTarget, + load_keypoint_connections, UiLabel, UiLabelTarget, }; use super::{ instance_key_to_picking_id, instance_path_hash_for_picking, process_annotations_and_keypoints, - process_colors, process_radii, + process_colors, process_radii, SpatialScenePart, SpatialScenePartData, }; -pub struct Points2DScenePart { +pub struct Points2DPart { /// If the number of points in the batch is > max_labels, don't render point labels. pub max_labels: usize, pub data: SpatialScenePartData, } -impl Default for Points2DScenePart { +impl Default for Points2DPart { fn default() -> Self { Self { max_labels: 10, @@ -33,7 +31,7 @@ impl Default for Points2DScenePart { } } -impl Points2DScenePart { +impl Points2DPart { fn process_labels<'a>( entity_view: &'a EntityView, instance_path_hashes: &'a [InstancePathHash], @@ -179,7 +177,7 @@ impl Points2DScenePart { } } -impl SpatialScenePart<7> for Points2DScenePart { +impl SpatialScenePart<7> for Points2DPart { type Primary = Point2D; fn archetype() -> [ComponentName; 7] { diff --git a/crates/re_space_view_spatial/src/scene/elements/points3d.rs b/crates/re_space_view_spatial/src/scene/parts/points3d.rs similarity index 93% rename from crates/re_space_view_spatial/src/scene/elements/points3d.rs rename to crates/re_space_view_spatial/src/scene/parts/points3d.rs index 28d8c6bdc4a9..3a1a51d792c8 100644 --- a/crates/re_space_view_spatial/src/scene/elements/points3d.rs +++ b/crates/re_space_view_spatial/src/scene/parts/points3d.rs @@ -8,22 +8,21 @@ use re_viewer_context::{ResolvedAnnotationInfo, SceneQuery, SpaceViewHighlights, use crate::scene::{ contexts::{SpatialSceneContext, SpatialSceneEntityContext}, - elements::{ - instance_key_to_picking_id, instance_path_hash_for_picking, - process_annotations_and_keypoints, process_colors, process_radii, - }, - load_keypoint_connections, - spatial_scene_part::{SpatialScenePart, SpatialScenePartData}, - UiLabel, UiLabelTarget, + load_keypoint_connections, UiLabel, UiLabelTarget, }; -pub struct Points3DScenePart { +use super::{ + instance_key_to_picking_id, instance_path_hash_for_picking, process_annotations_and_keypoints, + process_colors, process_radii, SpatialScenePart, SpatialScenePartData, +}; + +pub struct Points3DPart { /// If the number of points in the batch is > max_labels, don't render point labels. pub max_labels: usize, pub data: SpatialScenePartData, } -impl Default for Points3DScenePart { +impl Default for Points3DPart { fn default() -> Self { Self { max_labels: 10, @@ -32,7 +31,7 @@ impl Default for Points3DScenePart { } } -impl Points3DScenePart { +impl Points3DPart { fn process_labels<'a>( entity_view: &'a EntityView, instance_path_hashes: &'a [InstancePathHash], @@ -176,7 +175,7 @@ impl Points3DScenePart { } } -impl SpatialScenePart<7> for Points3DScenePart { +impl SpatialScenePart<7> for Points3DPart { type Primary = Point3D; fn archetype() -> [ComponentName; 7] { @@ -214,7 +213,7 @@ impl SpatialScenePart<7> for Points3DScenePart { Vec::new() // TODO(andreas): Optionally return point & line draw data once SharedRenderBuilders is gone. } - fn data(&self) -> &crate::scene::spatial_scene_part::SpatialScenePartData { + fn data(&self) -> &SpatialScenePartData { &self.data } } diff --git a/crates/re_space_view_spatial/src/scene/spatial_scene_part.rs b/crates/re_space_view_spatial/src/scene/parts/spatial_scene_part.rs similarity index 99% rename from crates/re_space_view_spatial/src/scene/spatial_scene_part.rs rename to crates/re_space_view_spatial/src/scene/parts/spatial_scene_part.rs index 911f92461293..849f62523086 100644 --- a/crates/re_space_view_spatial/src/scene/spatial_scene_part.rs +++ b/crates/re_space_view_spatial/src/scene/parts/spatial_scene_part.rs @@ -5,7 +5,7 @@ use re_query::{query_primary_with_history, EntityView, QueryError}; use re_renderer::DepthOffset; use re_viewer_context::{ScenePartImpl, SceneQuery, SpaceViewHighlights, ViewerContext}; -use super::{ +use crate::scene::{ contexts::{SpatialSceneContext, SpatialSceneEntityContext}, UiLabel, }; From 343c685e0c83e11fc58a1c1ef0f13622af0718e6 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Fri, 2 Jun 2023 14:54:04 +0200 Subject: [PATCH 19/39] space view part collection is now a trait --- crates/re_space_view_spatial/src/scene/mod.rs | 20 +-- .../src/scene/parts/mod.rs | 27 +++- .../src/scene/parts/points2d.rs | 36 +++-- .../src/scene/parts/points3d.rs | 36 +++-- .../src/scene/parts/spatial_scene_part.rs | 151 +++++++----------- crates/re_space_view_text/src/scene_part.rs | 13 +- .../src/space_view_class.rs | 14 +- .../re_space_view_text_box/src/scene_part.rs | 13 +- .../src/space_view_class.rs | 14 +- crates/re_viewer_context/src/lib.rs | 6 +- .../re_viewer_context/src/space_view/mod.rs | 6 +- .../re_viewer_context/src/space_view/scene.rs | 14 +- .../src/space_view/scene_context.rs | 1 + .../src/space_view/scene_part.rs | 12 +- .../src/space_view/scene_part_collection.rs | 72 --------- .../src/space_view/scene_part_impl.rs | 5 - .../src/space_view/space_view_class_impl.rs | 41 ++++- 17 files changed, 214 insertions(+), 267 deletions(-) delete mode 100644 crates/re_viewer_context/src/space_view/scene_part_collection.rs diff --git a/crates/re_space_view_spatial/src/scene/mod.rs b/crates/re_space_view_spatial/src/scene/mod.rs index 3b416af9b556..d7556cfc8cf8 100644 --- a/crates/re_space_view_spatial/src/scene/mod.rs +++ b/crates/re_space_view_spatial/src/scene/mod.rs @@ -22,16 +22,13 @@ use re_viewer_context::{ use crate::{ mesh_loader::LoadedMesh, - scene::{ - contexts::SpatialSceneContext, - parts::{SpatialScenePart, SpatialScenePartData}, - }, + scene::{contexts::SpatialSceneContext, parts::SpatialScenePartData}, space_camera_3d::SpaceCamera3D, }; use super::SpatialNavigationMode; -use self::contexts::SpatialSceneEntityContext; +use self::{contexts::SpatialSceneEntityContext, parts::SpatialScenePartCollection}; use parts::ScenePart; use contexts::EntityDepthOffsets; @@ -138,7 +135,7 @@ impl SceneSpatial { // TODO(andreas): Workaround for not having default on `Scene`. Soon not needed anyways scene: Scene { context: Box::::default(), - elements: ().into(), + elements: Box::::default(), highlights: Default::default(), }, draw_data: Default::default(), @@ -175,14 +172,7 @@ impl SceneSpatial { // TODO(wumpf): Temporary build up of scene. This will be handled by the SpaceViewClass framework later. let mut scene = Scene { context: Box::::default(), - // TODO(wumpf): How can we make this syntax possible instead? - // The problem is that `Points2DScenePart` can't be put directly into the list since only the wrapper implements ScenePart - //elements: parts::ScenePartTuple::default().into(), - elements: ( - parts::Points2DPart::default().wrap(), - parts::Points3DPart::default().wrap(), - ) - .into(), + elements: Box::::default(), highlights: Default::default(), }; self.draw_data = @@ -207,7 +197,7 @@ impl SceneSpatial { self.primitives.any_outlines = scene.highlights.any_outlines(); self.primitives.recalculate_bounding_box(); - for scene_part in scene.elements.iter() { + for scene_part in scene.elements.vec_mut() { if let Some(data) = scene_part .data() .and_then(|d| d.downcast_ref::()) diff --git a/crates/re_space_view_spatial/src/scene/parts/mod.rs b/crates/re_space_view_spatial/src/scene/parts/mod.rs index a5d21d395ad7..a6ffb2941785 100644 --- a/crates/re_space_view_spatial/src/scene/parts/mod.rs +++ b/crates/re_space_view_spatial/src/scene/parts/mod.rs @@ -20,24 +20,43 @@ pub(crate) use images::ImagesPart; pub(crate) use lines2d::Lines2DPart; pub(crate) use lines3d::Lines3DPart; pub(crate) use meshes::MeshPart; -pub(crate) use points2d::Points2DPart; -pub(crate) use points3d::Points3DPart; +use points2d::Points2DPart; +use points3d::Points3DPart; -pub use spatial_scene_part::{SpatialScenePart, SpatialScenePartData}; +use re_space_view::EmptySpaceViewState; +pub use spatial_scene_part::SpatialScenePartData; use ahash::HashMap; use std::sync::Arc; use re_components::{ClassId, ColorRGBA, KeypointId, Radius}; use re_data_store::{EntityPath, InstancePathHash}; -use re_viewer_context::SpaceViewHighlights; use re_viewer_context::{ Annotations, DefaultColor, ResolvedAnnotationInfo, SceneQuery, ViewerContext, }; +use re_viewer_context::{ScenePartCollection, SpaceViewHighlights}; use super::{EntityDepthOffsets, SceneSpatial}; use crate::{scene::Keypoints, TransformContext}; +type SpatialSpaceViewState = EmptySpaceViewState; + +#[derive(Default)] +pub struct SpatialScenePartCollection { + pub points2d: Points2DPart, + pub points3d: Points3DPart, +} + +impl ScenePartCollection for SpatialScenePartCollection { + fn vec_mut(&mut self) -> Vec<&mut dyn re_viewer_context::ScenePart> { + vec![&mut self.points2d, &mut self.points3d] + } + + fn as_any(&self) -> &dyn std::any::Any { + self + } +} + pub trait ScenePart { fn load( &self, diff --git a/crates/re_space_view_spatial/src/scene/parts/points2d.rs b/crates/re_space_view_spatial/src/scene/parts/points2d.rs index 27cd4f5b2818..f69a9b3f8635 100644 --- a/crates/re_space_view_spatial/src/scene/parts/points2d.rs +++ b/crates/re_space_view_spatial/src/scene/parts/points2d.rs @@ -2,18 +2,22 @@ use re_components::{ ClassId, ColorRGBA, Component, InstanceKey, KeypointId, Label, Point2D, Radius, }; use re_data_store::{EntityPath, InstancePathHash}; -use re_log_types::ComponentName; use re_query::{EntityView, QueryError}; -use re_viewer_context::{ResolvedAnnotationInfo, SceneQuery, SpaceViewHighlights, ViewerContext}; +use re_viewer_context::{ + ArchetypeDefinition, ResolvedAnnotationInfo, ScenePartImpl, SceneQuery, SpaceViewHighlights, + ViewerContext, +}; use crate::scene::{ contexts::{SpatialSceneContext, SpatialSceneEntityContext}, - load_keypoint_connections, UiLabel, UiLabelTarget, + load_keypoint_connections, + parts::spatial_scene_part::for_each_entity_view, + UiLabel, UiLabelTarget, }; use super::{ instance_key_to_picking_id, instance_path_hash_for_picking, process_annotations_and_keypoints, - process_colors, process_radii, SpatialScenePart, SpatialScenePartData, + process_colors, process_radii, SpatialScenePartData, SpatialSpaceViewState, }; pub struct Points2DPart { @@ -177,11 +181,12 @@ impl Points2DPart { } } -impl SpatialScenePart<7> for Points2DPart { - type Primary = Point2D; +impl ScenePartImpl for Points2DPart { + type SpaceViewState = SpatialSpaceViewState; + type SceneContext = SpatialSceneContext; - fn archetype() -> [ComponentName; 7] { - [ + fn archetype(&self) -> ArchetypeDefinition { + vec1::vec1![ Point2D::name(), InstanceKey::name(), ColorRGBA::name(), @@ -196,17 +201,20 @@ impl SpatialScenePart<7> for Points2DPart { &mut self, ctx: &mut ViewerContext<'_>, query: &SceneQuery<'_>, - context: &SpatialSceneContext, + _space_view_state: &Self::SpaceViewState, + scene_context: &Self::SceneContext, highlights: &SpaceViewHighlights, ) -> Vec { re_tracing::profile_scope!("Points2DPart"); - Self::for_each_entity_view( + assert_eq!(self.archetype().len(), 7); + for_each_entity_view::( ctx, query, - context, + scene_context, highlights, - context.depth_offsets.points, + scene_context.depth_offsets.points, + self.archetype(), |ent_path, entity_view, ent_context| { self.process_entity_view(query, &entity_view, ent_path, ent_context) }, @@ -215,7 +223,7 @@ impl SpatialScenePart<7> for Points2DPart { Vec::new() // TODO(andreas): Optionally return point & line draw data once SharedRenderBuilders is gone. } - fn data(&self) -> &SpatialScenePartData { - &self.data + fn data(&self) -> Option<&dyn std::any::Any> { + Some(&self.data) } } diff --git a/crates/re_space_view_spatial/src/scene/parts/points3d.rs b/crates/re_space_view_spatial/src/scene/parts/points3d.rs index 3a1a51d792c8..fea780c6c7b2 100644 --- a/crates/re_space_view_spatial/src/scene/parts/points3d.rs +++ b/crates/re_space_view_spatial/src/scene/parts/points3d.rs @@ -2,18 +2,22 @@ use re_components::{ ClassId, ColorRGBA, Component as _, InstanceKey, KeypointId, Label, Point3D, Radius, }; use re_data_store::{EntityPath, InstancePathHash}; -use re_log_types::ComponentName; use re_query::{EntityView, QueryError}; -use re_viewer_context::{ResolvedAnnotationInfo, SceneQuery, SpaceViewHighlights, ViewerContext}; +use re_viewer_context::{ + ArchetypeDefinition, ResolvedAnnotationInfo, ScenePartImpl, SceneQuery, SpaceViewHighlights, + ViewerContext, +}; use crate::scene::{ contexts::{SpatialSceneContext, SpatialSceneEntityContext}, - load_keypoint_connections, UiLabel, UiLabelTarget, + load_keypoint_connections, + parts::spatial_scene_part::for_each_entity_view, + UiLabel, UiLabelTarget, }; use super::{ instance_key_to_picking_id, instance_path_hash_for_picking, process_annotations_and_keypoints, - process_colors, process_radii, SpatialScenePart, SpatialScenePartData, + process_colors, process_radii, SpatialScenePartData, SpatialSpaceViewState, }; pub struct Points3DPart { @@ -175,11 +179,12 @@ impl Points3DPart { } } -impl SpatialScenePart<7> for Points3DPart { - type Primary = Point3D; +impl ScenePartImpl for Points3DPart { + type SpaceViewState = SpatialSpaceViewState; + type SceneContext = SpatialSceneContext; - fn archetype() -> [ComponentName; 7] { - [ + fn archetype(&self) -> ArchetypeDefinition { + vec1::vec1![ Point3D::name(), InstanceKey::name(), ColorRGBA::name(), @@ -194,17 +199,20 @@ impl SpatialScenePart<7> for Points3DPart { &mut self, ctx: &mut ViewerContext<'_>, query: &SceneQuery<'_>, - context: &SpatialSceneContext, + _space_view_state: &Self::SpaceViewState, + scene_context: &Self::SceneContext, highlights: &SpaceViewHighlights, ) -> Vec { re_tracing::profile_scope!("Points3DPart"); - Self::for_each_entity_view( + assert_eq!(self.archetype().len(), 7); + for_each_entity_view::( ctx, query, - context, + scene_context, highlights, - context.depth_offsets.points, + scene_context.depth_offsets.points, + self.archetype(), |ent_path, entity_view, ent_context| { self.process_entity_view(query, &entity_view, ent_path, ent_context) }, @@ -213,7 +221,7 @@ impl SpatialScenePart<7> for Points3DPart { Vec::new() // TODO(andreas): Optionally return point & line draw data once SharedRenderBuilders is gone. } - fn data(&self) -> &SpatialScenePartData { - &self.data + fn data(&self) -> Option<&dyn std::any::Any> { + Some(&self.data) } } diff --git a/crates/re_space_view_spatial/src/scene/parts/spatial_scene_part.rs b/crates/re_space_view_spatial/src/scene/parts/spatial_scene_part.rs index 849f62523086..57b0a65390ab 100644 --- a/crates/re_space_view_spatial/src/scene/parts/spatial_scene_part.rs +++ b/crates/re_space_view_spatial/src/scene/parts/spatial_scene_part.rs @@ -1,9 +1,8 @@ use re_components::Component; use re_data_store::EntityPath; -use re_log_types::ComponentName; use re_query::{query_primary_with_history, EntityView, QueryError}; use re_renderer::DepthOffset; -use re_viewer_context::{ScenePartImpl, SceneQuery, SpaceViewHighlights, ViewerContext}; +use re_viewer_context::{ArchetypeDefinition, SceneQuery, SpaceViewHighlights, ViewerContext}; use crate::scene::{ contexts::{SpatialSceneContext, SpatialSceneEntityContext}, @@ -25,101 +24,61 @@ impl Default for SpatialScenePartData { } } -pub trait SpatialScenePart: std::any::Any { - type Primary: Component + 'static; - - fn archetype() -> [ComponentName; N]; - - fn populate( - &mut self, - ctx: &mut ViewerContext<'_>, - query: &SceneQuery<'_>, - context: &SpatialSceneContext, - highlights: &SpaceViewHighlights, - ) -> Vec; - - fn data(&self) -> &SpatialScenePartData; - - fn for_each_entity_view( - ctx: &mut ViewerContext<'_>, - query: &SceneQuery<'_>, - context: &SpatialSceneContext, - highlights: &SpaceViewHighlights, - default_depth_offset: DepthOffset, - mut fun: F, - ) where - F: FnMut( - &EntityPath, - EntityView, - &SpatialSceneEntityContext<'_>, - ) -> Result<(), QueryError>, - { - for (ent_path, props) in query.iter_entities() { - let Some(entity_context) = context.query(ent_path, highlights, default_depth_offset) else { - continue; - }; - - match query_primary_with_history::( - &ctx.store_db.entity_db.data_store, - &query.timeline, - &query.latest_at, - &props.visible_history, - ent_path, - Self::archetype(), - ) - .and_then(|entity_views| { - for ent_view in entity_views { - context.num_primitives.fetch_add( - ent_view.num_instances(), - std::sync::atomic::Ordering::Relaxed, - ); - - fun(ent_path, ent_view, &entity_context)?; - } - Ok(()) - }) { - Ok(_) | Err(QueryError::PrimaryNotFound) => {} - Err(err) => { - re_log::error_once!("Unexpected error querying {ent_path:?}: {err}"); - } +pub fn for_each_entity_view<'a, Primary, const N: usize, F>( + ctx: &mut ViewerContext<'_>, + query: &SceneQuery<'_>, + context: &SpatialSceneContext, + highlights: &SpaceViewHighlights, + default_depth_offset: DepthOffset, + archetype: ArchetypeDefinition, + mut fun: F, +) where + Primary: Component + 'a, + F: FnMut( + &EntityPath, + EntityView, + &SpatialSceneEntityContext<'_>, + ) -> Result<(), QueryError>, +{ + let archetype = match archetype.try_into() { + Ok(archetype) => archetype, + Err(archetype) => { + re_log::error_once!( + "Archetype {:?} has wrong number of elements, expected {N}", + archetype + ); + return; + } + }; + + for (ent_path, props) in query.iter_entities() { + let Some(entity_context) = context.query(ent_path, highlights, default_depth_offset) else { + continue; + }; + + match query_primary_with_history::( + &ctx.store_db.entity_db.data_store, + &query.timeline, + &query.latest_at, + &props.visible_history, + ent_path, + archetype, + ) + .and_then(|entity_views| { + for ent_view in entity_views { + context.num_primitives.fetch_add( + ent_view.num_instances(), + std::sync::atomic::Ordering::Relaxed, + ); + + fun(ent_path, ent_view, &entity_context)?; + } + Ok(()) + }) { + Ok(_) | Err(QueryError::PrimaryNotFound) => {} + Err(err) => { + re_log::error_once!("Unexpected error querying {ent_path:?}: {err}"); } } } - - fn wrap(self) -> SpatialScenePartWrapper - where - Self: Sized, - { - SpatialScenePartWrapper(self) - } -} - -/// A wrapper for `SpatialScenePart` that implements `ScenePart`. -/// -/// Can't implement directly due to Rust limitations around higher kinded traits. -pub struct SpatialScenePartWrapper>(pub T); - -impl> ScenePartImpl for SpatialScenePartWrapper { - type SpaceViewState = re_space_view::EmptySpaceViewState; - type SceneContext = SpatialSceneContext; - - fn archetype(&self) -> re_viewer_context::ArchetypeDefinition { - debug_assert!(N > 0); - T::archetype().to_vec().try_into().unwrap() - } - - fn populate( - &mut self, - ctx: &mut ViewerContext<'_>, - query: &SceneQuery<'_>, - _space_view_state: &Self::SpaceViewState, - context: &Self::SceneContext, - highlights: &SpaceViewHighlights, - ) -> Vec { - self.0.populate(ctx, query, context, highlights) - } - - fn data(&self) -> Option<&dyn std::any::Any> { - Some(self.0.data()) - } } diff --git a/crates/re_space_view_text/src/scene_part.rs b/crates/re_space_view_text/src/scene_part.rs index 28b9166d462a..e8a33b2b3fbb 100644 --- a/crates/re_space_view_text/src/scene_part.rs +++ b/crates/re_space_view_text/src/scene_part.rs @@ -3,7 +3,8 @@ use re_data_store::EntityPath; use re_log_types::{Component as _, InstanceKey, RowId}; use re_query::{range_entity_with_primary, QueryError}; use re_viewer_context::{ - ArchetypeDefinition, ScenePartImpl, SceneQuery, SpaceViewHighlights, ViewerContext, + ArchetypeDefinition, ScenePartCollection, ScenePartImpl, SceneQuery, SpaceViewHighlights, + ViewerContext, }; use super::space_view_class::TextSpaceViewState; @@ -31,6 +32,16 @@ pub struct SceneText { pub text_entries: Vec, } +impl ScenePartCollection for SceneText { + fn vec_mut(&mut self) -> Vec<&mut dyn re_viewer_context::ScenePart> { + vec![self] + } + + fn as_any(&self) -> &dyn std::any::Any { + self + } +} + impl ScenePartImpl for SceneText { type SpaceViewState = TextSpaceViewState; type SceneContext = re_space_view::EmptySceneContext; diff --git a/crates/re_space_view_text/src/space_view_class.rs b/crates/re_space_view_text/src/space_view_class.rs index 09803bf2c720..cd53384f33dc 100644 --- a/crates/re_space_view_text/src/space_view_class.rs +++ b/crates/re_space_view_text/src/space_view_class.rs @@ -3,7 +3,7 @@ use std::collections::BTreeMap; use re_data_ui::item_ui; use re_log_types::{EntityPath, TimePoint, Timeline}; use re_viewer_context::{ - level_to_rich_text, Scene, SpaceViewClassImpl, SpaceViewClassName, SpaceViewState, + level_to_rich_text, SpaceViewClassImpl, SpaceViewClassName, SpaceViewState, TypedScene, ViewerContext, }; @@ -39,7 +39,7 @@ pub struct TextSpaceView; impl SpaceViewClassImpl for TextSpaceView { type SpaceViewState = TextSpaceViewState; type SceneContext = re_space_view::EmptySceneContext; - type ScenePartTuple = (SceneText,); + type ScenePartCollection = SceneText; fn name(&self) -> SpaceViewClassName { "Text".into() @@ -108,15 +108,9 @@ impl SpaceViewClassImpl for TextSpaceView { ctx: &mut ViewerContext<'_>, ui: &mut egui::Ui, state: &mut Self::SpaceViewState, - scene: Scene, + scene: TypedScene<'_, Self::SceneContext, Self::ScenePartCollection>, ) { - let scene = match scene.elements.get::() { - Ok(scene) => scene, - Err(err) => { - re_log::error_once!("Failed to get text scene element {err}"); - return; - } - }; + let scene = scene.parts; egui::Frame { inner_margin: re_ui::ReUi::view_padding().into(), diff --git a/crates/re_space_view_text_box/src/scene_part.rs b/crates/re_space_view_text_box/src/scene_part.rs index 976558d65af9..80d8fac8227d 100644 --- a/crates/re_space_view_text_box/src/scene_part.rs +++ b/crates/re_space_view_text_box/src/scene_part.rs @@ -2,7 +2,8 @@ use re_arrow_store::LatestAtQuery; use re_components::Component; use re_query::{query_entity_with_primary, QueryError}; use re_viewer_context::{ - ArchetypeDefinition, ScenePartImpl, SceneQuery, SpaceViewHighlights, ViewerContext, + ArchetypeDefinition, ScenePartCollection, ScenePartImpl, SceneQuery, SpaceViewHighlights, + ViewerContext, }; use crate::space_view_class::TextBoxSpaceViewState; @@ -20,6 +21,16 @@ pub struct SceneTextBox { pub text_entries: Vec, } +impl ScenePartCollection for SceneTextBox { + fn vec_mut(&mut self) -> Vec<&mut dyn re_viewer_context::ScenePart> { + vec![self] + } + + fn as_any(&self) -> &dyn std::any::Any { + self + } +} + impl ScenePartImpl for SceneTextBox { type SpaceViewState = TextBoxSpaceViewState; type SceneContext = re_space_view::EmptySceneContext; diff --git a/crates/re_space_view_text_box/src/space_view_class.rs b/crates/re_space_view_text_box/src/space_view_class.rs index 9ce63e89d32c..a2021a8cc0c6 100644 --- a/crates/re_space_view_text_box/src/space_view_class.rs +++ b/crates/re_space_view_text_box/src/space_view_class.rs @@ -1,6 +1,6 @@ use egui::Label; use re_viewer_context::{ - Scene, SpaceViewClassImpl, SpaceViewClassName, SpaceViewState, ViewerContext, + SpaceViewClassImpl, SpaceViewClassName, SpaceViewState, TypedScene, ViewerContext, }; use super::scene_part::SceneTextBox; @@ -36,7 +36,7 @@ pub struct TextBoxSpaceView; impl SpaceViewClassImpl for TextBoxSpaceView { type SpaceViewState = TextBoxSpaceViewState; - type ScenePartTuple = (SceneTextBox,); + type ScenePartCollection = SceneTextBox; type SceneContext = re_space_view::EmptySceneContext; fn name(&self) -> SpaceViewClassName { @@ -73,15 +73,9 @@ impl SpaceViewClassImpl for TextBoxSpaceView { _ctx: &mut ViewerContext<'_>, ui: &mut egui::Ui, state: &mut Self::SpaceViewState, - scene: Scene, + scene: TypedScene<'_, Self::SceneContext, Self::ScenePartCollection>, ) { - let scene = match scene.elements.get::() { - Ok(scene) => scene, - Err(err) => { - re_log::error_once!("Failed to get text box scene element {err}"); - return; - } - }; + let scene = scene.parts; egui::Frame { inner_margin: re_ui::ReUi::view_padding().into(), diff --git a/crates/re_viewer_context/src/lib.rs b/crates/re_viewer_context/src/lib.rs index 42c14c52771f..cd6bf7a2a9a4 100644 --- a/crates/re_viewer_context/src/lib.rs +++ b/crates/re_viewer_context/src/lib.rs @@ -31,9 +31,9 @@ pub use selection_state::{ }; pub use space_view::{ ArchetypeDefinition, Scene, SceneContext, SceneContextPart, ScenePart, ScenePartCollection, - ScenePartCollectionLookupError, ScenePartImpl, SceneQuery, SpaceViewClass, SpaceViewClassImpl, - SpaceViewClassName, SpaceViewClassRegistry, SpaceViewClassRegistryError, - SpaceViewEntityHighlight, SpaceViewHighlights, SpaceViewOutlineMasks, SpaceViewState, + ScenePartImpl, SceneQuery, SpaceViewClass, SpaceViewClassImpl, SpaceViewClassName, + SpaceViewClassRegistry, SpaceViewClassRegistryError, SpaceViewEntityHighlight, + SpaceViewHighlights, SpaceViewOutlineMasks, SpaceViewState, TypedScene, }; pub use tensor::{TensorDecodeCache, TensorStats, TensorStatsCache}; pub use time_control::{Looping, PlayState, TimeControl, TimeView}; diff --git a/crates/re_viewer_context/src/space_view/mod.rs b/crates/re_viewer_context/src/space_view/mod.rs index 118fc78f129a..9ab64e313bc5 100644 --- a/crates/re_viewer_context/src/space_view/mod.rs +++ b/crates/re_viewer_context/src/space_view/mod.rs @@ -8,7 +8,6 @@ mod highlights; mod scene; mod scene_context; mod scene_part; -mod scene_part_collection; mod scene_part_impl; mod scene_query; mod space_view_class; @@ -18,12 +17,11 @@ mod space_view_class_registry; pub use highlights::{SpaceViewEntityHighlight, SpaceViewHighlights, SpaceViewOutlineMasks}; pub use scene::Scene; pub use scene_context::{SceneContext, SceneContextPart}; -pub use scene_part::ScenePart; -pub use scene_part_collection::{ScenePartCollection, ScenePartCollectionLookupError}; +pub use scene_part::{ScenePart, ScenePartCollection}; pub use scene_part_impl::ScenePartImpl; pub use scene_query::SceneQuery; pub use space_view_class::{ ArchetypeDefinition, SpaceViewClass, SpaceViewClassName, SpaceViewState, }; -pub use space_view_class_impl::SpaceViewClassImpl; +pub use space_view_class_impl::{SpaceViewClassImpl, TypedScene}; pub use space_view_class_registry::{SpaceViewClassRegistry, SpaceViewClassRegistryError}; diff --git a/crates/re_viewer_context/src/space_view/scene.rs b/crates/re_viewer_context/src/space_view/scene.rs index efa6fd27bf6a..7c9bb3573ead 100644 --- a/crates/re_viewer_context/src/space_view/scene.rs +++ b/crates/re_viewer_context/src/space_view/scene.rs @@ -1,6 +1,6 @@ use crate::{ - ArchetypeDefinition, SceneContext, ScenePartCollection, SceneQuery, SpaceViewHighlights, - SpaceViewState, ViewerContext, + SceneContext, ScenePartCollection, SceneQuery, SpaceViewHighlights, SpaceViewState, + ViewerContext, }; /// Every [`crate::SpaceViewClass`] creates and populates a scene to draw a frame and inform the ui about relevant data. @@ -9,16 +9,11 @@ use crate::{ /// and then all elements with read access to the previously established context objects. pub struct Scene { pub context: Box, - pub elements: ScenePartCollection, + pub elements: Box, pub highlights: SpaceViewHighlights, // TODO(wumpf): Consider making this a scene context - problem: populate can't create it. } impl Scene { - /// List of all archetypes this scene queries for its parts. - pub fn part_archetypes(&self) -> Vec { - self.elements.iter().map(|e| e.archetype()).collect() - } - /// Populates the scene for a given query. pub fn populate( &mut self, @@ -37,7 +32,8 @@ impl Scene { context.populate(ctx, query, space_view_state); } self.elements - .iter_mut() + .vec_mut() + .into_iter() .flat_map(|element| { // TODO(andreas): Restrict the query with the archetype somehow, ideally making it trivial to do the correct thing. element.populate( diff --git a/crates/re_viewer_context/src/space_view/scene_context.rs b/crates/re_viewer_context/src/space_view/scene_context.rs index 1354360a7d8e..b51fa9fe0734 100644 --- a/crates/re_viewer_context/src/space_view/scene_context.rs +++ b/crates/re_viewer_context/src/space_view/scene_context.rs @@ -9,6 +9,7 @@ pub trait SceneContext { fn as_any(&self) -> &dyn std::any::Any; /// Converts itself to a reference of [`Any`], which enables downcasting to concrete types. + /// TODO(wumpf): Only needed for workarounds in `re_space_view_spatial`. fn as_any_mut(&mut self) -> &mut dyn std::any::Any; } diff --git a/crates/re_viewer_context/src/space_view/scene_part.rs b/crates/re_viewer_context/src/space_view/scene_part.rs index b2c1286ae9bd..fcaede084692 100644 --- a/crates/re_viewer_context/src/space_view/scene_part.rs +++ b/crates/re_viewer_context/src/space_view/scene_part.rs @@ -3,6 +3,15 @@ use crate::{ ViewerContext, }; +/// Scene part collection, consisting of several [`ScenePart`] which may be populated in parallel. +pub trait ScenePartCollection { + /// Retrieves a list of all underlying scene context part for parallel population. + fn vec_mut(&mut self) -> Vec<&mut dyn ScenePart>; + + /// Converts itself to a reference of [`std::any::Any`], which enables downcasting to concrete types. + fn as_any(&self) -> &dyn std::any::Any; +} + /// Element of a scene derived from a single archetype query. /// /// Is populated after scene contexts and has access to them. @@ -32,7 +41,4 @@ pub trait ScenePart: std::any::Any { /// Converts itself to a reference of [`Any`], which enables downcasting to concrete types. fn as_any(&self) -> &dyn std::any::Any; - - /// Converts itself to a reference of [`Any`], which enables downcasting to concrete types. - fn as_any_mut(&mut self) -> &mut dyn std::any::Any; } diff --git a/crates/re_viewer_context/src/space_view/scene_part_collection.rs b/crates/re_viewer_context/src/space_view/scene_part_collection.rs deleted file mode 100644 index 0900c7d3a87a..000000000000 --- a/crates/re_viewer_context/src/space_view/scene_part_collection.rs +++ /dev/null @@ -1,72 +0,0 @@ -use ahash::HashMap; - -use crate::ScenePart; - -#[derive(Debug, thiserror::Error)] -pub enum ScenePartCollectionLookupError { - #[error("Type not found in collection")] - TypeNotFound, - - #[error("Failed to downcast type.")] - DowncastFailure, -} - -/// Collections of scene parts. -#[derive(Default)] -pub struct ScenePartCollection(HashMap>); - -impl ScenePartCollection { - pub fn get(&self) -> Result<&T, ScenePartCollectionLookupError> { - self.0 - .get(&std::any::TypeId::of::()) - .ok_or(ScenePartCollectionLookupError::TypeNotFound)? - .as_any() - .downcast_ref::() - .ok_or(ScenePartCollectionLookupError::DowncastFailure) - } - - pub fn get_mut(&mut self) -> Result<&mut T, ScenePartCollectionLookupError> { - self.0 - .get_mut(&std::any::TypeId::of::()) - .ok_or(ScenePartCollectionLookupError::TypeNotFound)? - .as_any_mut() - .downcast_mut::() - .ok_or(ScenePartCollectionLookupError::DowncastFailure) - } - - #[inline] - pub fn iter(&self) -> impl Iterator> { - self.0.values() - } - - #[inline] - pub fn iter_mut(&mut self) -> impl Iterator> { - self.0.values_mut() - } -} - -macro_rules! scene_part_collection_from_tuple { - ($($idx:tt => $name:ident),*) => { - impl<$($name: ScenePart),*> From<($($name,)*)> for ScenePartCollection { - #[allow(unused_mut)] - fn from(_value: ($($name,)*)) -> Self { - let mut map = HashMap::>::default(); - $( - map.insert(_value.$idx.as_any().type_id(), Box::new(_value.$idx)); - )* - Self(map) - } - } - }; -} - -scene_part_collection_from_tuple!(); -scene_part_collection_from_tuple!(0 => T0); -scene_part_collection_from_tuple!(0 => T0, 1 => T1); -scene_part_collection_from_tuple!(0 => T0, 1 => T1, 2 => T2); -scene_part_collection_from_tuple!(0 => T0, 1 => T1, 2 => T2, 3 => T3); -scene_part_collection_from_tuple!(0 => T0, 1 => T1, 2 => T2, 3 => T3, 4 => T4); -scene_part_collection_from_tuple!(0 => T0, 1 => T1, 2 => T2, 3 => T3, 4 => T4, 5 => T5); -scene_part_collection_from_tuple!(0 => T0, 1 => T1, 2 => T2, 3 => T3, 4 => T4, 5 => T5, 6 => T6); -scene_part_collection_from_tuple!(0 => T0, 1 => T1, 2 => T2, 3 => T3, 4 => T4, 5 => T5, 6 => T6, 7 => T7); -scene_part_collection_from_tuple!(0 => T0, 1 => T1, 2 => T2, 3 => T3, 4 => T4, 5 => T5, 6 => T6, 7 => T7, 8 => T8); diff --git a/crates/re_viewer_context/src/space_view/scene_part_impl.rs b/crates/re_viewer_context/src/space_view/scene_part_impl.rs index f9c9af16f080..f36a7dc10d20 100644 --- a/crates/re_viewer_context/src/space_view/scene_part_impl.rs +++ b/crates/re_viewer_context/src/space_view/scene_part_impl.rs @@ -63,11 +63,6 @@ impl ScenePart for T { self } - #[inline] - fn as_any_mut(&mut self) -> &mut dyn std::any::Any { - self - } - #[inline] fn data(&self) -> Option<&dyn std::any::Any> { self.data() diff --git a/crates/re_viewer_context/src/space_view/space_view_class_impl.rs b/crates/re_viewer_context/src/space_view/space_view_class_impl.rs index 86063a518a65..bd674e2e3e0c 100644 --- a/crates/re_viewer_context/src/space_view/space_view_class_impl.rs +++ b/crates/re_viewer_context/src/space_view/space_view_class_impl.rs @@ -1,8 +1,14 @@ use crate::{ - Scene, SceneContext, ScenePartCollection, SpaceViewClass, SpaceViewClassName, SpaceViewState, - ViewerContext, + Scene, SceneContext, ScenePartCollection, SpaceViewClass, SpaceViewClassName, + SpaceViewHighlights, SpaceViewState, ViewerContext, }; +pub struct TypedScene<'a, C: SceneContext, P: ScenePartCollection> { + pub context: &'a C, + pub parts: &'a P, + pub highlights: SpaceViewHighlights, +} + /// Utility for implementing [`SpaceViewClass`] with concrete [`SpaceViewState`] and [`crate::ScenePart`] type. /// /// Each Space View in the viewer's viewport has a single class assigned immutable at its creation time. @@ -15,8 +21,8 @@ pub trait SpaceViewClassImpl { /// Context of the scene, which is passed to all [`crate::ScenePart`]s and ui drawing on population. type SceneContext: SceneContext + Default + 'static; - /// A tuple of [`crate::ScenePart`] types that are supported by this space view class. - type ScenePartTuple: Into + Default + 'static; + /// Collection of [`crate::ScenePart`]s that this scene populates. + type ScenePartCollection: ScenePartCollection + Default + 'static; /// Name of this space view class. /// @@ -49,7 +55,7 @@ pub trait SpaceViewClassImpl { ctx: &mut ViewerContext<'_>, ui: &mut egui::Ui, state: &mut Self::SpaceViewState, - scene: Scene, + scene: TypedScene<'_, Self::SceneContext, Self::ScenePartCollection>, ); } @@ -73,7 +79,7 @@ impl SpaceViewClass for T { fn new_scene(&self) -> Scene { Scene { context: Box::::default(), - elements: T::ScenePartTuple::default().into(), + elements: Box::::default(), highlights: Default::default(), } } @@ -101,6 +107,29 @@ impl SpaceViewClass for T { state: &mut dyn SpaceViewState, scene: Scene, ) { + let Scene { + context, + elements, + highlights, + } = scene; + + let Some(context) = context.as_any().downcast_ref::() else { + re_log::error_once!("Failed to downcast scene context to the correct type {}.", + std::any::type_name::()); + return; + }; + let Some(parts) = elements.as_any().downcast_ref::() else { + re_log::error_once!("Failed to downcast scene elements to the correct type {}.", + std::any::type_name::()); + return; + }; + + let scene = TypedScene { + context, + parts, + highlights, + }; + typed_state_wrapper(state, |state| self.ui(ctx, ui, state, scene)); } } From 311c2e726c6a0477669eb3399aefa02664d10a80 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Fri, 2 Jun 2023 15:07:03 +0200 Subject: [PATCH 20/39] split up now incorrectly named spatial_scene_part_data file --- ...atial_scene_part.rs => entity_iterator.rs} | 23 ++----------------- .../src/scene/parts/mod.rs | 6 +++-- .../src/scene/parts/points2d.rs | 3 +-- .../src/scene/parts/points3d.rs | 3 +-- .../scene/parts/spatial_scene_part_data.rs | 16 +++++++++++++ 5 files changed, 24 insertions(+), 27 deletions(-) rename crates/re_space_view_spatial/src/scene/parts/{spatial_scene_part.rs => entity_iterator.rs} (78%) create mode 100644 crates/re_space_view_spatial/src/scene/parts/spatial_scene_part_data.rs diff --git a/crates/re_space_view_spatial/src/scene/parts/spatial_scene_part.rs b/crates/re_space_view_spatial/src/scene/parts/entity_iterator.rs similarity index 78% rename from crates/re_space_view_spatial/src/scene/parts/spatial_scene_part.rs rename to crates/re_space_view_spatial/src/scene/parts/entity_iterator.rs index 57b0a65390ab..ab6fe62f926c 100644 --- a/crates/re_space_view_spatial/src/scene/parts/spatial_scene_part.rs +++ b/crates/re_space_view_spatial/src/scene/parts/entity_iterator.rs @@ -1,28 +1,9 @@ -use re_components::Component; -use re_data_store::EntityPath; +use re_log_types::{Component, EntityPath}; use re_query::{query_primary_with_history, EntityView, QueryError}; use re_renderer::DepthOffset; use re_viewer_context::{ArchetypeDefinition, SceneQuery, SpaceViewHighlights, ViewerContext}; -use crate::scene::{ - contexts::{SpatialSceneContext, SpatialSceneEntityContext}, - UiLabel, -}; - -/// Common data struct for all spatial scene elements. -pub struct SpatialScenePartData { - pub ui_labels: Vec, - pub bounding_box: macaw::BoundingBox, -} - -impl Default for SpatialScenePartData { - fn default() -> Self { - Self { - ui_labels: Vec::new(), - bounding_box: macaw::BoundingBox::nothing(), - } - } -} +use crate::scene::contexts::{SpatialSceneContext, SpatialSceneEntityContext}; pub fn for_each_entity_view<'a, Primary, const N: usize, F>( ctx: &mut ViewerContext<'_>, diff --git a/crates/re_space_view_spatial/src/scene/parts/mod.rs b/crates/re_space_view_spatial/src/scene/parts/mod.rs index a6ffb2941785..71dee3a568da 100644 --- a/crates/re_space_view_spatial/src/scene/parts/mod.rs +++ b/crates/re_space_view_spatial/src/scene/parts/mod.rs @@ -4,13 +4,14 @@ mod arrows3d; mod boxes2d; mod boxes3d; mod cameras; +mod entity_iterator; mod images; mod lines2d; mod lines3d; mod meshes; mod points2d; mod points3d; -mod spatial_scene_part; +mod spatial_scene_part_data; pub(crate) use arrows3d::Arrows3DPart; pub(crate) use boxes2d::Boxes2DPart; @@ -24,7 +25,7 @@ use points2d::Points2DPart; use points3d::Points3DPart; use re_space_view::EmptySpaceViewState; -pub use spatial_scene_part::SpatialScenePartData; +use spatial_scene_part_data::SpatialScenePartData; use ahash::HashMap; use std::sync::Arc; @@ -57,6 +58,7 @@ impl ScenePartCollection for SpatialScenePartCollection { } } +// TODO(wumpf): remove pub trait ScenePart { fn load( &self, diff --git a/crates/re_space_view_spatial/src/scene/parts/points2d.rs b/crates/re_space_view_spatial/src/scene/parts/points2d.rs index f69a9b3f8635..a3db5989f86d 100644 --- a/crates/re_space_view_spatial/src/scene/parts/points2d.rs +++ b/crates/re_space_view_spatial/src/scene/parts/points2d.rs @@ -11,7 +11,7 @@ use re_viewer_context::{ use crate::scene::{ contexts::{SpatialSceneContext, SpatialSceneEntityContext}, load_keypoint_connections, - parts::spatial_scene_part::for_each_entity_view, + parts::entity_iterator::for_each_entity_view, UiLabel, UiLabelTarget, }; @@ -207,7 +207,6 @@ impl ScenePartImpl for Points2DPart { ) -> Vec { re_tracing::profile_scope!("Points2DPart"); - assert_eq!(self.archetype().len(), 7); for_each_entity_view::( ctx, query, diff --git a/crates/re_space_view_spatial/src/scene/parts/points3d.rs b/crates/re_space_view_spatial/src/scene/parts/points3d.rs index fea780c6c7b2..cfcaec43dece 100644 --- a/crates/re_space_view_spatial/src/scene/parts/points3d.rs +++ b/crates/re_space_view_spatial/src/scene/parts/points3d.rs @@ -11,7 +11,7 @@ use re_viewer_context::{ use crate::scene::{ contexts::{SpatialSceneContext, SpatialSceneEntityContext}, load_keypoint_connections, - parts::spatial_scene_part::for_each_entity_view, + parts::entity_iterator::for_each_entity_view, UiLabel, UiLabelTarget, }; @@ -205,7 +205,6 @@ impl ScenePartImpl for Points3DPart { ) -> Vec { re_tracing::profile_scope!("Points3DPart"); - assert_eq!(self.archetype().len(), 7); for_each_entity_view::( ctx, query, diff --git a/crates/re_space_view_spatial/src/scene/parts/spatial_scene_part_data.rs b/crates/re_space_view_spatial/src/scene/parts/spatial_scene_part_data.rs new file mode 100644 index 000000000000..6ead1c993689 --- /dev/null +++ b/crates/re_space_view_spatial/src/scene/parts/spatial_scene_part_data.rs @@ -0,0 +1,16 @@ +use crate::scene::UiLabel; + +/// Common data struct for all spatial scene elements. +pub struct SpatialScenePartData { + pub ui_labels: Vec, + pub bounding_box: macaw::BoundingBox, +} + +impl Default for SpatialScenePartData { + fn default() -> Self { + Self { + ui_labels: Vec::new(), + bounding_box: macaw::BoundingBox::nothing(), + } + } +} From 526460ec4e026ee8530b0d4dd6756ee567ba5f41 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Fri, 2 Jun 2023 15:09:07 +0200 Subject: [PATCH 21/39] doc fixes --- crates/re_space_view_spatial/src/scene/parts/mod.rs | 9 ++++----- crates/re_viewer_context/src/space_view/scene_context.rs | 8 ++++---- crates/re_viewer_context/src/space_view/scene_part.rs | 2 +- .../re_viewer_context/src/space_view/space_view_class.rs | 4 ++-- 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/crates/re_space_view_spatial/src/scene/parts/mod.rs b/crates/re_space_view_spatial/src/scene/parts/mod.rs index 71dee3a568da..a3655381512c 100644 --- a/crates/re_space_view_spatial/src/scene/parts/mod.rs +++ b/crates/re_space_view_spatial/src/scene/parts/mod.rs @@ -21,11 +21,10 @@ pub(crate) use images::ImagesPart; pub(crate) use lines2d::Lines2DPart; pub(crate) use lines3d::Lines3DPart; pub(crate) use meshes::MeshPart; -use points2d::Points2DPart; -use points3d::Points3DPart; + +pub use spatial_scene_part_data::SpatialScenePartData; use re_space_view::EmptySpaceViewState; -use spatial_scene_part_data::SpatialScenePartData; use ahash::HashMap; use std::sync::Arc; @@ -44,8 +43,8 @@ type SpatialSpaceViewState = EmptySpaceViewState; #[derive(Default)] pub struct SpatialScenePartCollection { - pub points2d: Points2DPart, - pub points3d: Points3DPart, + pub points2d: points2d::Points2DPart, + pub points3d: points3d::Points3DPart, } impl ScenePartCollection for SpatialScenePartCollection { diff --git a/crates/re_viewer_context/src/space_view/scene_context.rs b/crates/re_viewer_context/src/space_view/scene_context.rs index b51fa9fe0734..7111495be545 100644 --- a/crates/re_viewer_context/src/space_view/scene_context.rs +++ b/crates/re_viewer_context/src/space_view/scene_context.rs @@ -5,10 +5,10 @@ pub trait SceneContext { /// Retrieves a list of all underlying scene context part for parallel population. fn vec_mut(&mut self) -> Vec<&mut dyn SceneContextPart>; - /// Converts itself to a reference of [`Any`], which enables downcasting to concrete types. + /// Converts itself to a reference of [`std::any::Any`], which enables downcasting to concrete types. fn as_any(&self) -> &dyn std::any::Any; - /// Converts itself to a reference of [`Any`], which enables downcasting to concrete types. + /// Converts itself to a reference of [`std::any::Any`], which enables downcasting to concrete types. /// TODO(wumpf): Only needed for workarounds in `re_space_view_spatial`. fn as_any_mut(&mut self) -> &mut dyn std::any::Any; } @@ -31,9 +31,9 @@ pub trait SceneContextPart { space_view_state: &dyn SpaceViewState, ); - /// Converts itself to a reference of [`Any`], which enables downcasting to concrete types. + /// Converts itself to a reference of [`std::any::Any`], which enables downcasting to concrete types. fn as_any(&self) -> &dyn std::any::Any; - /// Converts itself to a reference of [`Any`], which enables downcasting to concrete types. + /// Converts itself to a reference of [`std::any::Any`], which enables downcasting to concrete types. fn as_any_mut(&mut self) -> &mut dyn std::any::Any; } diff --git a/crates/re_viewer_context/src/space_view/scene_part.rs b/crates/re_viewer_context/src/space_view/scene_part.rs index fcaede084692..1de3e7a39aac 100644 --- a/crates/re_viewer_context/src/space_view/scene_part.rs +++ b/crates/re_viewer_context/src/space_view/scene_part.rs @@ -39,6 +39,6 @@ pub trait ScenePart: std::any::Any { None } - /// Converts itself to a reference of [`Any`], which enables downcasting to concrete types. + /// Converts itself to a reference of [`std::any::Any`], which enables downcasting to concrete types. fn as_any(&self) -> &dyn std::any::Any; } diff --git a/crates/re_viewer_context/src/space_view/space_view_class.rs b/crates/re_viewer_context/src/space_view/space_view_class.rs index 48e5669ad180..314e872cdd8f 100644 --- a/crates/re_viewer_context/src/space_view/space_view_class.rs +++ b/crates/re_viewer_context/src/space_view/space_view_class.rs @@ -79,9 +79,9 @@ pub trait SpaceViewClass { /// State of a space view. pub trait SpaceViewState: std::any::Any { - /// Converts itself to a reference of [`Any`], which enables downcasting to concrete types. + /// Converts itself to a reference of [`std::any::Any`], which enables downcasting to concrete types. fn as_any(&self) -> &dyn std::any::Any; - /// Converts itself to a reference of [`Any`], which enables downcasting to concrete types. + /// Converts itself to a reference of [`std::any::Any`], which enables downcasting to concrete types. fn as_any_mut(&mut self) -> &mut dyn std::any::Any; } From 8b1978f14cbba10a287f771f0e1f95e30f49f070 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Fri, 2 Jun 2023 15:10:05 +0200 Subject: [PATCH 22/39] remove unnecessary any method and constraint --- crates/re_viewer_context/src/space_view/scene_part.rs | 5 +---- crates/re_viewer_context/src/space_view/scene_part_impl.rs | 5 ----- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/crates/re_viewer_context/src/space_view/scene_part.rs b/crates/re_viewer_context/src/space_view/scene_part.rs index 1de3e7a39aac..ee40be4d295c 100644 --- a/crates/re_viewer_context/src/space_view/scene_part.rs +++ b/crates/re_viewer_context/src/space_view/scene_part.rs @@ -15,7 +15,7 @@ pub trait ScenePartCollection { /// Element of a scene derived from a single archetype query. /// /// Is populated after scene contexts and has access to them. -pub trait ScenePart: std::any::Any { +pub trait ScenePart { /// The archetype queried by this scene element. fn archetype(&self) -> ArchetypeDefinition; @@ -38,7 +38,4 @@ pub trait ScenePart: std::any::Any { fn data(&self) -> Option<&dyn std::any::Any> { None } - - /// Converts itself to a reference of [`std::any::Any`], which enables downcasting to concrete types. - fn as_any(&self) -> &dyn std::any::Any; } diff --git a/crates/re_viewer_context/src/space_view/scene_part_impl.rs b/crates/re_viewer_context/src/space_view/scene_part_impl.rs index f36a7dc10d20..9bafa069bcbe 100644 --- a/crates/re_viewer_context/src/space_view/scene_part_impl.rs +++ b/crates/re_viewer_context/src/space_view/scene_part_impl.rs @@ -58,11 +58,6 @@ impl ScenePart for T { self.populate(ctx, query, state, context, highlights) } - #[inline] - fn as_any(&self) -> &dyn std::any::Any { - self - } - #[inline] fn data(&self) -> Option<&dyn std::any::Any> { self.data() From ed4a9d8c68d572cda72044855a49742660b6338e Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Fri, 2 Jun 2023 15:11:25 +0200 Subject: [PATCH 23/39] remove even more unused as_any methods --- .../src/scene/contexts/annotation_context.rs | 8 -------- .../src/scene/contexts/depth_offsets.rs | 8 -------- .../src/scene/contexts/shared_render_builders.rs | 8 -------- .../src/scene/contexts/transform_context.rs | 8 -------- crates/re_viewer_context/src/space_view/scene_context.rs | 6 ------ 5 files changed, 38 deletions(-) diff --git a/crates/re_space_view_spatial/src/scene/contexts/annotation_context.rs b/crates/re_space_view_spatial/src/scene/contexts/annotation_context.rs index 29d3ef637bc5..665535ab6195 100644 --- a/crates/re_space_view_spatial/src/scene/contexts/annotation_context.rs +++ b/crates/re_space_view_spatial/src/scene/contexts/annotation_context.rs @@ -18,12 +18,4 @@ impl SceneContextPart for AnnotationSceneContext { ) { self.0.load(ctx, query); } - - fn as_any(&self) -> &dyn std::any::Any { - self - } - - fn as_any_mut(&mut self) -> &mut dyn std::any::Any { - self - } } diff --git a/crates/re_space_view_spatial/src/scene/contexts/depth_offsets.rs b/crates/re_space_view_spatial/src/scene/contexts/depth_offsets.rs index c64be11f2fdc..df3b4935c2e7 100644 --- a/crates/re_space_view_spatial/src/scene/contexts/depth_offsets.rs +++ b/crates/re_space_view_spatial/src/scene/contexts/depth_offsets.rs @@ -115,12 +115,4 @@ impl SceneContextPart for EntityDepthOffsets { }) .collect(); } - - fn as_any(&self) -> &dyn std::any::Any { - self - } - - fn as_any_mut(&mut self) -> &mut dyn std::any::Any { - self - } } diff --git a/crates/re_space_view_spatial/src/scene/contexts/shared_render_builders.rs b/crates/re_space_view_spatial/src/scene/contexts/shared_render_builders.rs index b78573300d9a..efbde262dcec 100644 --- a/crates/re_space_view_spatial/src/scene/contexts/shared_render_builders.rs +++ b/crates/re_space_view_spatial/src/scene/contexts/shared_render_builders.rs @@ -44,12 +44,4 @@ impl SceneContextPart for SharedRenderBuilders { .radius_boost_in_ui_points_for_outlines(SIZE_BOOST_IN_POINTS_FOR_POINT_OUTLINES), )); } - - fn as_any(&self) -> &dyn std::any::Any { - self - } - - fn as_any_mut(&mut self) -> &mut dyn std::any::Any { - self - } } diff --git a/crates/re_space_view_spatial/src/scene/contexts/transform_context.rs b/crates/re_space_view_spatial/src/scene/contexts/transform_context.rs index 56364f89bec6..0d118a7a7249 100644 --- a/crates/re_space_view_spatial/src/scene/contexts/transform_context.rs +++ b/crates/re_space_view_spatial/src/scene/contexts/transform_context.rs @@ -179,14 +179,6 @@ impl SceneContextPart for TransformContext { current_tree = parent_tree; } } - - fn as_any(&self) -> &dyn std::any::Any { - self - } - - fn as_any_mut(&mut self) -> &mut dyn std::any::Any { - self - } } impl TransformContext { diff --git a/crates/re_viewer_context/src/space_view/scene_context.rs b/crates/re_viewer_context/src/space_view/scene_context.rs index 7111495be545..20dc21145f96 100644 --- a/crates/re_viewer_context/src/space_view/scene_context.rs +++ b/crates/re_viewer_context/src/space_view/scene_context.rs @@ -30,10 +30,4 @@ pub trait SceneContextPart { query: &SceneQuery<'_>, space_view_state: &dyn SpaceViewState, ); - - /// Converts itself to a reference of [`std::any::Any`], which enables downcasting to concrete types. - fn as_any(&self) -> &dyn std::any::Any; - - /// Converts itself to a reference of [`std::any::Any`], which enables downcasting to concrete types. - fn as_any_mut(&mut self) -> &mut dyn std::any::Any; } From fc23d5714370e30fea39bcf0c7eec17eef6f0ba6 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Fri, 2 Jun 2023 15:47:18 +0200 Subject: [PATCH 24/39] port arrow3d --- crates/re_space_view_spatial/src/scene/mod.rs | 1 - .../src/scene/parts/arrows3d.rs | 223 +++++++++--------- .../src/scene/parts/entity_iterator.rs | 4 +- .../src/scene/parts/mod.rs | 9 +- .../src/scene/parts/points2d.rs | 21 +- .../src/scene/parts/points3d.rs | 21 +- .../scene/parts/spatial_scene_part_data.rs | 21 ++ 7 files changed, 158 insertions(+), 142 deletions(-) diff --git a/crates/re_space_view_spatial/src/scene/mod.rs b/crates/re_space_view_spatial/src/scene/mod.rs index d7556cfc8cf8..6e4898751590 100644 --- a/crates/re_space_view_spatial/src/scene/mod.rs +++ b/crates/re_space_view_spatial/src/scene/mod.rs @@ -157,7 +157,6 @@ impl SceneSpatial { // -- &parts::Boxes3DPart, &parts::Lines3DPart, - &parts::Arrows3DPart, &parts::MeshPart, &parts::ImagesPart, // -- diff --git a/crates/re_space_view_spatial/src/scene/parts/arrows3d.rs b/crates/re_space_view_spatial/src/scene/parts/arrows3d.rs index b033e3e43ef1..ab45a06a100c 100644 --- a/crates/re_space_view_spatial/src/scene/parts/arrows3d.rs +++ b/crates/re_space_view_spatial/src/scene/parts/arrows3d.rs @@ -1,137 +1,138 @@ use re_components::{Arrow3D, ColorRGBA, Component as _, InstanceKey, Label, Radius}; use re_data_store::EntityPath; -use re_query::{query_primary_with_history, EntityView, QueryError}; +use re_query::{EntityView, QueryError}; use re_renderer::{renderer::LineStripFlags, Size}; -use re_viewer_context::SpaceViewHighlights; -use re_viewer_context::{DefaultColor, SceneQuery, ViewerContext}; - -use crate::{ - scene::{EntityDepthOffsets, SceneSpatial}, - TransformContext, +use re_viewer_context::{ + ArchetypeDefinition, DefaultColor, ScenePartImpl, SceneQuery, SpaceViewHighlights, + ViewerContext, }; -use super::{instance_key_to_picking_id, ScenePart}; +use super::{instance_key_to_picking_id, SpatialScenePartData, SpatialSpaceViewState}; +use crate::scene::{ + contexts::{SpatialSceneContext, SpatialSceneEntityContext}, + parts::entity_iterator::process_entity_views, +}; -pub struct Arrows3DPart; +#[derive(Default)] +pub struct Arrows3DPart { + data: SpatialScenePartData, +} impl Arrows3DPart { fn process_entity_view( - scene: &mut SceneSpatial, - entity_view: &EntityView, + &mut self, + _query: &SceneQuery<'_>, + ent_view: &EntityView, ent_path: &EntityPath, - world_from_obj: glam::Affine3A, - highlights: &SpaceViewHighlights, + ent_context: &SpatialSceneEntityContext<'_>, ) -> Result<(), QueryError> { - scene.num_logged_3d_objects += 1; - - let annotations = scene.annotation_map.find(ent_path); let default_color = DefaultColor::EntityPath(ent_path); - let entity_highlight = highlights.entity_outline_mask(ent_path.hash()); - - let mut line_batch = scene - .primitives - .line_strips + let mut line_builder = ent_context.shared_render_builders.lines(); + let mut line_batch = line_builder .batch("arrows") - .world_from_obj(world_from_obj) - .outline_mask_ids(entity_highlight.overall) + .world_from_obj(ent_context.world_from_obj) + .outline_mask_ids(ent_context.highlight.overall) .picking_object_id(re_renderer::PickingLayerObjectId(ent_path.hash64())); - let visitor = |instance_key: InstanceKey, - arrow: Arrow3D, - color: Option, - radius: Option, - _label: Option