Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend/iterate on SpaceViewClass framework with SceneContext & port SpatialSpaceView scene parts #2304

Merged
merged 39 commits into from
Jun 5, 2023
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
70aa6f3
introduce scene context, abandon scene some of the tuple conversions
Wumpf May 31, 2023
da9fbf5
rename scene_parts to elements
Wumpf May 31, 2023
368393b
space view highlights are now part of Scene
Wumpf May 31, 2023
f7adfa3
entity depth offset is now a SceneContext
Wumpf May 31, 2023
3a48d8a
transform cache is now a scene context
Wumpf Jun 1, 2023
d9f4dbd
rename transform cache to transform context
Wumpf Jun 1, 2023
4586c90
scene query now knows the scene root, simplifying some interfaces
Wumpf Jun 1, 2023
901df1a
scene element now return drawables
Wumpf Jun 1, 2023
0962fbe
2d point scene part is now a SpatialSceneElement
Wumpf Jun 1, 2023
f1260c9
port 3d points and wire up scene elements so far
Wumpf Jun 1, 2023
a072305
re-enable labels on points
Wumpf Jun 1, 2023
7669ec4
shared draw data workaround
Wumpf Jun 2, 2023
a04b693
bounding box handling for ported scene elements
Wumpf Jun 2, 2023
f7a8a18
scene context docs
Wumpf Jun 2, 2023
948623e
scene context is now more strongly typed
Wumpf Jun 2, 2023
ef74ebd
move empty space view state/context to re_space_view
Wumpf Jun 2, 2023
596a90e
split up scene module and rename SceneElement to ScenePart
Wumpf Jun 2, 2023
9cbcf27
spatial scene parts are called parts again
Wumpf Jun 2, 2023
343c685
space view part collection is now a trait
Wumpf Jun 2, 2023
311c2e7
split up now incorrectly named spatial_scene_part_data file
Wumpf Jun 2, 2023
526460e
doc fixes
Wumpf Jun 2, 2023
8b1978f
remove unnecessary any method and constraint
Wumpf Jun 2, 2023
ed4a9d8
remove even more unused as_any methods
Wumpf Jun 2, 2023
fc23d57
port arrow3d
Wumpf Jun 2, 2023
77a3555
port boxes 2d
Wumpf Jun 2, 2023
88320ea
port box 3d
Wumpf Jun 2, 2023
78e6a89
port cameras
Wumpf Jun 2, 2023
a9c9a21
port lines2d
Wumpf Jun 2, 2023
7243b88
port 3d lines
Wumpf Jun 2, 2023
16c8c08
port meshes
Wumpf Jun 2, 2023
2f16089
comment fixes
Wumpf Jun 3, 2023
33b2f6c
renamings and comment fixes
Wumpf Jun 3, 2023
2ffe43f
stronger scene typing
Wumpf Jun 3, 2023
6e71df1
strongly typed scene part data
Wumpf Jun 3, 2023
2c08a2e
fixup 2d/3d heuristic
Wumpf Jun 3, 2023
01581c7
formatting
Wumpf Jun 3, 2023
2bfd509
lint fixes
Wumpf Jun 5, 2023
e922f19
documentation improvements
Wumpf Jun 5, 2023
211e46b
spelling
Wumpf Jun 5, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/re_data_ui/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
19 changes: 19 additions & 0 deletions crates/re_space_view/src/empty_scene_context.rs
Original file line number Diff line number Diff line change
@@ -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
}
}
15 changes: 15 additions & 0 deletions crates/re_space_view/src/empty_space_view_state.rs
Original file line number Diff line number Diff line change
@@ -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
}
}
6 changes: 4 additions & 2 deletions crates/re_space_view/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@

pub mod controls;
mod data_blueprint;
mod highlights;
mod empty_scene_context;
mod empty_space_view_state;
mod screenshot;

pub use data_blueprint::{DataBlueprintGroup, DataBlueprintTree};
pub use highlights::{SpaceViewEntityHighlight, SpaceViewHighlights, SpaceViewOutlineMasks};
pub use empty_scene_context::EmptySceneContext;
pub use empty_space_view_state::EmptySpaceViewState;
pub use screenshot::ScreenshotMode;
4 changes: 3 additions & 1 deletion crates/re_space_view_spatial/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,14 @@ 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
wgpu.workspace = true
4 changes: 1 addition & 3 deletions crates/re_space_view_spatial/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,12 @@ mod mesh_cache;
mod mesh_loader;
mod scene;
mod space_camera_3d;
mod transform_cache;
mod ui;
mod ui_2d;
mod ui_3d;
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, TransformContext, UnreachableTransform};
pub use ui::{SpatialNavigationMode, ViewSpatialState};
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use re_components::AnnotationContext;
use re_log_types::Component;
use re_viewer_context::{AnnotationMap, ArchetypeDefinition, SceneContextPart};

#[derive(Default)]
pub struct AnnotationSceneContext(pub AnnotationMap);

impl SceneContextPart for AnnotationSceneContext {
fn archetypes(&self) -> Vec<ArchetypeDefinition> {
vec![vec1::vec1![AnnotationContext::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);
}
}
118 changes: 118 additions & 0 deletions crates/re_space_view_spatial/src/scene/contexts/depth_offsets.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
use std::collections::{BTreeMap, BTreeSet};

use nohash_hasher::IntMap;
use re_components::DrawOrder;
use re_log_types::{Component, EntityPathHash};
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
Wumpf marked this conversation as resolved.
Show resolved Hide resolved
// This would also yield more consistent/meaningful archetypes and avoid queries where not needed.
Wumpf marked this conversation as resolved.
Show resolved Hide resolved
#[derive(Default)]
pub struct EntityDepthOffsets {
pub per_entity: IntMap<EntityPathHash, re_renderer::DepthOffset>,
pub box2d: re_renderer::DepthOffset,
pub lines2d: re_renderer::DepthOffset,
pub image: re_renderer::DepthOffset,
pub points: re_renderer::DepthOffset,
}

impl SceneContextPart for EntityDepthOffsets {
fn archetypes(&self) -> Vec<ArchetypeDefinition> {
vec![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::<DrawOrder, BTreeSet<DrawOrderTarget>>::new();
for (ent_path, _) in query.iter_entities() {
if let Some(draw_order) = store.query_latest_component::<DrawOrder>(
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::<Vec<_>>()
})
.collect();
}
}
84 changes: 84 additions & 0 deletions crates/re_space_view_spatial/src/scene/contexts/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
mod annotation_context;
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>(
Wumpf marked this conversation as resolved.
Show resolved Hide resolved
&'a self,
ent_path: &EntityPath,
highlights: &'a re_viewer_context::SpaceViewHighlights,
default_depth_offset: DepthOffset,
) -> Option<SpatialSceneEntityContext<'a>> {
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<Annotations>,
pub shared_render_builders: &'a SharedRenderBuilders,
pub highlight: &'a re_viewer_context::SpaceViewOutlineMasks, // Not part of the context, but convenient to have here.
}