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

heuristic for camera frustum length is now based on scene size #1433

Merged
merged 2 commits into from
Feb 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions crates/re_data_store/src/editable_auto_value.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/// A value that is either determined automatically by some heuristic, or specified by the user.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're adding more and more things to re_data_store that don't seem to be related at all to the data store 🤔

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, the properties are misplaced there in the first place I think

#[derive(Debug, Clone, serde::Deserialize, serde::Serialize, Eq, PartialEq)]
#[serde(bound = "T: serde::Serialize, for<'de2> T: serde::Deserialize<'de2>")]
pub enum EditableAutoValue<T>
where
T: std::fmt::Debug + Eq + PartialEq + Clone + Default + serde::Serialize,
for<'de2> T: serde::Deserialize<'de2>,
{
/// The user explicitly specified what they wanted
UserEdited(T),

/// The value is determined automatically.
///
/// We may update this at any time or interpret the value stored here differently under certain circumstances.
Auto(T),
}

impl<T> Default for EditableAutoValue<T>
where
T: std::fmt::Debug + Eq + PartialEq + Clone + Default + serde::Serialize,
for<'de2> T: serde::Deserialize<'de2>,
{
fn default() -> Self {
EditableAutoValue::Auto(T::default())
}
}

impl<T> EditableAutoValue<T>
where
T: std::fmt::Debug + Eq + PartialEq + Clone + Default + serde::Serialize,
for<'de2> T: serde::Deserialize<'de2>,
{
pub fn is_auto(&self) -> bool {
matches!(self, EditableAutoValue::Auto(_))
}

/// Gets the value, disregarding if it was user edited or determined by a heuristic.
pub fn get(&self) -> &T {
match self {
EditableAutoValue::Auto(v) | EditableAutoValue::UserEdited(v) => v,
}
}

/// Returns other if self is auto, self otherwise.
pub fn or<'a>(&'a self, other: &'a EditableAutoValue<T>) -> &'a EditableAutoValue<T> {
if self.is_auto() {
other
} else {
self
}
}
}
35 changes: 7 additions & 28 deletions crates/re_data_store/src/entity_properties.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use re_log_types::{
msg_bundle::DeserializableComponent, EntityPath,
};

use crate::log_db::EntityDb;
use crate::{log_db::EntityDb, EditableAutoValue};

// ----------------------------------------------------------------------------

Expand Down Expand Up @@ -39,44 +39,23 @@ pub struct EntityProperties {
pub visible_history: ExtraQueryHistory,
pub interactive: bool,

/// Distance of the projection plane.
/// Distance of the projection plane (frustum far plane).
///
/// Only applies to pinhole cameras when in a spatial view, using 3D navigation.
pinhole_image_plane_distance: Option<ordered_float::NotNan<f32>>,
pub pinhole_image_plane_distance: EditableAutoValue<ordered_float::NotNan<f32>>,
}

impl EntityProperties {
/// If this has a pinhole camera transform, how far away is the image plane.
///
/// Scale relative to the respective space the pinhole camera is in.
/// None indicates the user never edited this field (should use a meaningful default then).
///
/// Method returns a pinhole camera specific default if the value hasn't been set yet.
pub fn pinhole_image_plane_distance(&self, pinhole: &re_log_types::Pinhole) -> f32 {
self.pinhole_image_plane_distance
.unwrap_or_else(|| {
let distance = pinhole
.focal_length()
.unwrap_or_else(|| pinhole.focal_length_in_pixels().y());
ordered_float::NotNan::new(distance).unwrap_or_default()
})
.into()
}

/// see `pinhole_image_plane_distance()`
pub fn set_pinhole_image_plane_distance(&mut self, distance: f32) {
self.pinhole_image_plane_distance = ordered_float::NotNan::new(distance).ok();
}

/// Multiply/and these together.
pub fn with_child(&self, child: &Self) -> Self {
Self {
visible: self.visible && child.visible,
visible_history: self.visible_history.with_child(&child.visible_history),
interactive: self.interactive && child.interactive,
pinhole_image_plane_distance: child
pinhole_image_plane_distance: self
.pinhole_image_plane_distance
.or(self.pinhole_image_plane_distance),
.or(&child.pinhole_image_plane_distance)
.clone(),
}
}
}
Expand All @@ -87,7 +66,7 @@ impl Default for EntityProperties {
visible: true,
visible_history: ExtraQueryHistory::default(),
interactive: true,
pinhole_image_plane_distance: None,
pinhole_image_plane_distance: EditableAutoValue::default(),
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions crates/re_data_store/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#![doc = document_features::document_features!()]
//!

mod editable_auto_value;
pub mod entity_properties;
pub mod entity_tree;
mod instance_path;
Expand All @@ -16,6 +17,7 @@ pub use log_db::LogDb;

use re_log_types::msg_bundle;

pub use editable_auto_value::EditableAutoValue;
pub use re_log_types::{ComponentName, EntityPath, EntityPathPart, Index, TimeInt, Timeline};

// ----------------------------------------------------------------------------
Expand Down
6 changes: 2 additions & 4 deletions crates/re_viewer/src/misc/transform_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,10 +239,8 @@ fn transform_at(
// A pinhole camera means that we're looking at an image.
// Images are spanned in their local x/y space.
// Center it and move it along z, scaling the further we move.

let distance = entity_properties
.get(entity_path)
.pinhole_image_plane_distance(&pinhole);
let props = entity_properties.get(entity_path);
let distance: f32 = props.pinhole_image_plane_distance.get().into_inner();

let focal_length = pinhole.focal_length_in_pixels();
let focal_length = glam::vec2(focal_length.x(), focal_length.y());
Expand Down
12 changes: 8 additions & 4 deletions crates/re_viewer/src/ui/selection_panel.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use re_data_store::{query_latest_single, EntityPath, EntityProperties};
use re_data_store::{query_latest_single, EditableAutoValue, EntityPath, EntityProperties};
use re_log_types::{TimeType, Transform};

use crate::{
Expand Down Expand Up @@ -411,11 +411,12 @@ fn entity_props_ui(
if view_state.state_spatial.nav_mode == SpatialNavigationMode::ThreeD {
if let Some(entity_path) = entity_path {
let query = ctx.current_query();
if let Some(re_log_types::Transform::Pinhole(pinhole)) =
if let Some(re_log_types::Transform::Pinhole(_)) =
query_latest_single::<Transform>(&ctx.log_db.entity_db, entity_path, &query)
{
ui.label("Image plane distance");
let mut distance = entity_props.pinhole_image_plane_distance(&pinhole);
let mut distance: f32 =
Wumpf marked this conversation as resolved.
Show resolved Hide resolved
entity_props.pinhole_image_plane_distance.get().into_inner();
let speed = (distance * 0.05).at_least(0.01);
if ui
.add(
Expand All @@ -426,7 +427,10 @@ fn entity_props_ui(
.on_hover_text("Controls how far away the image plane is.")
.changed()
{
entity_props.set_pinhole_image_plane_distance(distance);
entity_props.pinhole_image_plane_distance =
EditableAutoValue::UserEdited(
ordered_float::NotNan::new(distance).unwrap(),
);
}
ui.end_row();
}
Expand Down
3 changes: 3 additions & 0 deletions crates/re_viewer/src/ui/space_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,9 @@ impl SpaceView {
);
let mut scene = view_spatial::SceneSpatial::new(ctx.render_ctx);
scene.load(ctx, &query, &transforms, highlights);
self.view_state
.state_spatial
.update_object_property_heuristics(ctx, &mut self.data_blueprint);
self.view_state
.ui_spatial(ctx, ui, &self.space_path, scene, self.id, highlights);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ impl CamerasPart {
return;
};

let frustum_length = props.pinhole_image_plane_distance(&pinhole);
let frustum_length: f32 = props.pinhole_image_plane_distance.get().into_inner();

scene.space_cameras.push(SpaceCamera3D {
entity_path: entity_path.clone(),
Expand Down
42 changes: 41 additions & 1 deletion crates/re_viewer/src/ui/view_spatial/ui.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use re_data_store::EntityPath;
use re_data_store::{query_latest_single, EditableAutoValue, EntityPath};
use re_format::format_f32;

use egui::{NumExt, WidgetText};
Expand Down Expand Up @@ -147,6 +147,46 @@ impl ViewSpatialState {
heuristic0.min(heuristic1)
}

pub fn update_object_property_heuristics(
&self,
ctx: &mut ViewerContext<'_>,
data_blueprint: &mut DataBlueprintTree,
) {
crate::profile_function!();

let scene_size = self.scene_bbox_accum.size().length();
let default_image_plane_distance = if scene_size.is_finite() && scene_size > 0.0 {
scene_size * 0.05
} else {
1.0
};

let query = ctx.current_query();

let entity_paths = data_blueprint.entity_paths().clone(); // TODO(andreas): Workaround borrow checker
for entity_path in entity_paths {
if let Some(re_log_types::Transform::Pinhole(_)) =
query_latest_single::<re_log_types::Transform>(
&ctx.log_db.entity_db,
&entity_path,
&query,
)
{
let mut properties = data_blueprint
.data_blueprints_individual()
.get(&entity_path);
if properties.pinhole_image_plane_distance.is_auto() {
properties.pinhole_image_plane_distance = EditableAutoValue::Auto(
ordered_float::NotNan::new(default_image_plane_distance).unwrap(),
);
data_blueprint
.data_blueprints_individual()
.set(entity_path, properties);
}
}
}
}

pub fn selection_ui(
&mut self,
ctx: &mut ViewerContext<'_>,
Expand Down