Skip to content

Commit a20b58e

Browse files
committed
zoom scale dependency and depth with lod
1 parent 4de18b7 commit a20b58e

2 files changed

Lines changed: 61 additions & 10 deletions

File tree

src/visualizer/input/input_controller.cpp

Lines changed: 54 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "core/event_bridge/localization_manager.hpp"
77
#include "core/logger.hpp"
88
#include "core/path_utils.hpp"
9+
#include "core/splat_data_transform.hpp"
910
#include "gui/bounds_gizmo.hpp"
1011
#include "gui/gui_focus_state.hpp"
1112
#include "gui/gui_manager.hpp"
@@ -49,11 +50,22 @@ namespace lfs::vis {
4950
constexpr double kCameraFrustumClickThreshold = 5.0;
5051
namespace string_keys = lichtfeld::Strings;
5152

52-
// Expand [world_min, world_max] by a node's local AABB transformed to world space.
53+
// Expand [world_min, world_max] by a node's local AABB transformed to world
54+
// space. With use_percentile, the splat/point-cloud box is the trimmed
55+
// (1st/99th percentile) AABB so far-flung floaters don't inflate it; meshes
56+
// and other geometry fall back to the full node bounds.
5357
void expandNodeWorldBounds(const core::Scene& scene, const core::SceneNode& node,
54-
glm::vec3& world_min, glm::vec3& world_max) {
58+
glm::vec3& world_min, glm::vec3& world_max,
59+
bool use_percentile = false) {
5560
glm::vec3 local_min, local_max;
56-
if (!scene.getNodeBounds(node.id, local_min, local_max))
61+
bool have_local = false;
62+
if (use_percentile) {
63+
if (node.model && node.model->size() > 0)
64+
have_local = core::compute_bounds(*node.model, local_min, local_max, 0.0f, true);
65+
else if (node.point_cloud && node.point_cloud->size() > 0)
66+
have_local = core::compute_bounds(*node.point_cloud, local_min, local_max, 0.0f, true);
67+
}
68+
if (!have_local && !scene.getNodeBounds(node.id, local_min, local_max))
5769
return;
5870

5971
const glm::mat4 world_xform = scene_coords::nodeVisualizerWorldTransform(scene, node.id);
@@ -343,12 +355,14 @@ namespace lfs::vis {
343355
clearViewportDragState();
344356
clearWasdMomentumViewport();
345357
scene_extent_ = 0.0f;
358+
depth_range_initialized_ = false;
346359
focusSplitPanel(SplitViewPanelId::Left);
347360
});
348361
scene_loaded_handler_id_ = state::SceneLoaded::when([this](const auto&) {
349362
clearViewportDragState();
350363
clearWasdMomentumViewport();
351364
scene_extent_ = 0.0f;
365+
depth_range_initialized_ = false;
352366
focusSplitPanel(SplitViewPanelId::Left);
353367
});
354368

@@ -1816,6 +1830,8 @@ namespace lfs::vis {
18161830
}
18171831

18181832
void InputController::update(float delta_time) {
1833+
maybeInitializeDepthViewRange();
1834+
18191835
if (input_router_) {
18201836
const bool any_mouse_buttons_pressed = SDL_GetMouseState(nullptr, nullptr) != 0;
18211837
input_router_->syncPressedMouseButtons(any_mouse_buttons_pressed);
@@ -2350,7 +2366,9 @@ namespace lfs::vis {
23502366
}
23512367

23522368
// Whole-scene world AABB, skipping container nodes that carry no geometry.
2353-
bool InputController::computeWholeSceneBounds(glm::vec3& out_min, glm::vec3& out_max) const {
2369+
// use_percentile yields the trimmed (outlier-excluding) box.
2370+
bool InputController::computeWholeSceneBounds(glm::vec3& out_min, glm::vec3& out_max,
2371+
const bool use_percentile) const {
23542372
if (!tool_context_)
23552373
return false;
23562374
auto* const sm = tool_context_->getSceneManager();
@@ -2366,27 +2384,54 @@ namespace lfs::vis {
23662384
node->type == core::NodeType::CAMERA_GROUP ||
23672385
node->type == core::NodeType::IMAGE_GROUP)
23682386
continue;
2369-
expandNodeWorldBounds(scene, *node, out_min, out_max);
2387+
expandNodeWorldBounds(scene, *node, out_min, out_max, use_percentile);
23702388
}
23712389

23722390
return out_min.x <= out_max.x;
23732391
}
23742392

23752393
// Cached whole-scene radius used to scale WASD speed and pan distance with
2376-
// splat size. Lazily computed after load (bounds may not exist the instant
2377-
// SceneLoaded fires) and invalidated on scene load/clear. Returns 0 while no
2378-
// geometry is present.
2394+
// splat size. Uses the trimmed (1st/99th percentile) bounds so a few far-flung
2395+
// floaters can't blow up the extent and make navigation far too fast. Lazily
2396+
// computed after load (bounds may not exist the instant SceneLoaded fires) and
2397+
// invalidated on scene load/clear. Returns 0 while no geometry is present.
23792398
float InputController::sceneExtent() {
23802399
if (scene_extent_ > 0.0f)
23812400
return scene_extent_;
23822401

23832402
glm::vec3 min, max;
2384-
if (computeWholeSceneBounds(min, max))
2403+
if (computeWholeSceneBounds(min, max, /*use_percentile=*/true))
23852404
scene_extent_ = glm::length(max - min) * 0.5f;
23862405

23872406
return scene_extent_;
23882407
}
23892408

2409+
// Seed the depth-map range from the trimmed scene scale once the extent is
2410+
// known after a load, so the palette spans the actual content instead of the
2411+
// fixed 0.1..100 default that is useless on large RAD scenes. Runs once per
2412+
// scene; the user owns the range after that.
2413+
void InputController::maybeInitializeDepthViewRange() {
2414+
if (depth_range_initialized_)
2415+
return;
2416+
2417+
const float radius = sceneExtent();
2418+
if (radius <= 0.0f)
2419+
return;
2420+
2421+
auto* const rendering = services().renderingOrNull();
2422+
if (!rendering)
2423+
return;
2424+
2425+
constexpr float kDepthViewInitNear = 1.0f;
2426+
auto settings = rendering->getSettings();
2427+
settings.depth_view_min = kDepthViewInitNear;
2428+
settings.depth_view_max = radius;
2429+
sanitizeDepthViewSettings(settings);
2430+
rendering->updateSettings(settings);
2431+
2432+
depth_range_initialized_ = true;
2433+
}
2434+
23902435
bool InputController::focusSelection() {
23912436
return handleFocusSelection(activeKeyboardViewport());
23922437
}

src/visualizer/input/input_controller.hpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,10 @@ namespace lfs::vis {
148148

149149
void handleGoToCamView(const lfs::core::events::cmd::GoToCamView& event);
150150
bool handleFocusSelection(Viewport& target_viewport);
151-
bool computeWholeSceneBounds(glm::vec3& out_min, glm::vec3& out_max) const;
151+
bool computeWholeSceneBounds(glm::vec3& out_min, glm::vec3& out_max,
152+
bool use_percentile = false) const;
152153
float sceneExtent();
154+
void maybeInitializeDepthViewRange();
153155

154156
// WASD processing with proper frame timing
155157
void processWASDMovement();
@@ -232,6 +234,10 @@ namespace lfs::vis {
232234
// speed and pan distance with splat size; 0 means "recompute" (after scene
233235
// load/clear).
234236
float scene_extent_ = 0.0f;
237+
// One-shot guard: the depth-view range is seeded from the trimmed scene
238+
// radius the first frame the extent is known after a load, then left to
239+
// the user. Reset on scene load/clear.
240+
bool depth_range_initialized_ = false;
235241
SplitViewPanelId drag_split_panel_ = SplitViewPanelId::Left;
236242
SplitViewPanelId node_rect_panel_ = SplitViewPanelId::Left;
237243
int node_rect_button_ = -1;

0 commit comments

Comments
 (0)