fix(viewer): keep recorded follow locked to rig
This commit is contained in:
parent
90450ae320
commit
a7babf60db
|
|
@ -23,8 +23,8 @@ const vendorRuntime = [
|
|||
packagePath: resolve(packageRoot, "re_viewer_bg.wasm"),
|
||||
vendorPath: resolve(vendorRoot, "re_viewer_bg.nodedc.wasm"),
|
||||
publishedSha256: "3fe7aab8ea6bb0fd03c3ef694932943411ee174029e398c539c390beb0824d35",
|
||||
previousNodedcSha256: "38d19bac06b7c3b8e549489469cf7c4a24f319ec953849e4656b5827a6c105bb",
|
||||
nodedcSha256: "e85dbad1569431620d4fabb18c1dbddd3a26d071eec1bb88a036fa755bc921da",
|
||||
previousNodedcSha256: "e85dbad1569431620d4fabb18c1dbddd3a26d071eec1bb88a036fa755bc921da",
|
||||
nodedcSha256: "6aca9da47ad561d2046ad0c7c0b8a7f653f023a77132c5c6304789320db512c2",
|
||||
},
|
||||
{
|
||||
label: "wasm JavaScript glue",
|
||||
|
|
|
|||
|
|
@ -631,7 +631,7 @@ function SpatialWorkspace({
|
|||
variant={followRecordedTrajectory ? "primary" : "secondary"}
|
||||
icon={<Icon name="target" />}
|
||||
aria-pressed={followRecordedTrajectory}
|
||||
title="Привязать orbital-пивот к текущему положению рига"
|
||||
title="Удерживать orbital-пивот на риге до повторного нажатия"
|
||||
onClick={() => setFollowRecordedTrajectory((current) => !current)}
|
||||
>
|
||||
Следовать
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ test("NODE.DC Rerun runtime is the audited 0.34.1 spatial camera build", () => {
|
|||
const manifest = JSON.parse(readFileSync(resolve(packageRoot, "package.json"), "utf8"));
|
||||
assert.equal(manifest.version, "0.34.1");
|
||||
|
||||
const expectedWasm = "e85dbad1569431620d4fabb18c1dbddd3a26d071eec1bb88a036fa755bc921da";
|
||||
const expectedWasm = "6aca9da47ad561d2046ad0c7c0b8a7f653f023a77132c5c6304789320db512c2";
|
||||
const expectedGlue = "0f7b76c9f24cbd8437021b5d37499894aeadc586183e422ebc82ef556d7b8339";
|
||||
|
||||
assert.equal(sha256(resolve(vendorRoot, "re_viewer_bg.nodedc.wasm")), expectedWasm);
|
||||
|
|
@ -55,7 +55,7 @@ test("custom Rerun WASM initializes and grows its externref table", () => {
|
|||
runtime.deinit();
|
||||
});
|
||||
|
||||
test("source patch carries pointer navigation, camera continuity, and geometry tests", () => {
|
||||
test("source patch carries pointer navigation, persistent follow, and geometry tests", () => {
|
||||
const patch = readFileSync(resolve(vendorRoot, "NODEDC_ZOOM_TO_CURSOR.patch"), "utf8");
|
||||
|
||||
assert.match(patch, /fn pointer_ray_direction/);
|
||||
|
|
@ -69,5 +69,7 @@ test("source patch carries pointer navigation, camera continuity, and geometry t
|
|||
assert.match(patch, /minimum_orbital_navigation_speed/);
|
||||
assert.match(patch, /orbital_rotation_keeps_selected_anchor_on_the_same_view_ray/);
|
||||
assert.match(patch, /orbital_navigation_speed_floor_tracks_scene_scale/);
|
||||
assert.match(patch, /NODEDC_PERSISTENT_ORBIT_TRACKING_ENTITY/);
|
||||
assert.match(patch, /nodedc_rig_orbit_tracking_is_persistent/);
|
||||
assert.match(patch, /previous_picking_result/);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -13,6 +13,9 @@ This directory contains the audited Mission Core camera-controller override for
|
|||
silently ignoring the wheel or moving by imperceptible millimeters;
|
||||
- orbital navigation has a scene-scale speed floor, so WASD and post-limit
|
||||
dolly remain useful at the minimum radius;
|
||||
- Mission Core's explicit `/world/sensor_pose` orbital follow keeps the current
|
||||
eye radius and orientation when enabled, remains attached through manual
|
||||
orbit and zoom, and releases only when the operator toggles follow off;
|
||||
- first-person movement, panning and Rerun's zoom-out cap are unchanged.
|
||||
|
||||
## Source identity
|
||||
|
|
@ -57,13 +60,13 @@ generated `re_viewer.js` is transformed with
|
|||
|
||||
| Artifact | SHA-256 |
|
||||
| --- | --- |
|
||||
| `re_viewer_bg.nodedc.wasm` | `e85dbad1569431620d4fabb18c1dbddd3a26d071eec1bb88a036fa755bc921da` |
|
||||
| `re_viewer_bg.nodedc.wasm` | `6aca9da47ad561d2046ad0c7c0b8a7f653f023a77132c5c6304789320db512c2` |
|
||||
| raw generated `re_viewer.js` | `cc196a93c5be972c801d46be4dc9934f7f042eb62941f0aa0678f1c8416c6874` |
|
||||
| `re_viewer.nodedc.js` | `0f7b76c9f24cbd8437021b5d37499894aeadc586183e422ebc82ef556d7b8339` |
|
||||
|
||||
The focused Rust suite completed with `7 passed, 0 failed`, including the
|
||||
The focused Rust suite completed with `8 passed, 0 failed`, including the
|
||||
orbit-to-dolly boundary, pointer-anchored rotation and scene-scale speed-floor
|
||||
cases. A Node `initSync`
|
||||
cases, plus persistent rig-orbit tracking. A Node `initSync`
|
||||
smoke test completed successfully, including the `externref` table-growth step.
|
||||
The Mission Core Node suite also checks both artifact hashes and verifies that
|
||||
every `wasm.*` reference in the JavaScript glue exists in the paired WASM
|
||||
|
|
|
|||
|
|
@ -1,25 +1,39 @@
|
|||
diff --git a/crates/viewer/re_view_spatial/src/eye.rs b/crates/viewer/re_view_spatial/src/eye.rs
|
||||
index e59b311..7159aab 100644
|
||||
index e59b311..77ac8d7 100644
|
||||
--- a/crates/viewer/re_view_spatial/src/eye.rs
|
||||
+++ b/crates/viewer/re_view_spatial/src/eye.rs
|
||||
@@ -207,0 +208,3 @@ pub struct EyeState {
|
||||
+ /// World-space point selected when the current orbital drag started.
|
||||
+ orbit_drag_anchor: Option<Vec3>,
|
||||
+
|
||||
@@ -434 +437 @@ impl EyeController {
|
||||
@@ -245,0 +249,13 @@ pub(crate) struct EyeController {
|
||||
+/// NODE.DC's operator follow mode is explicitly toggled outside the embedded
|
||||
+/// viewer. Unlike Rerun's transient entity tracking, manual orbit/zoom must
|
||||
+/// therefore keep this rig pivot attached until the operator toggles it off.
|
||||
+const NODEDC_PERSISTENT_ORBIT_TRACKING_ENTITY: &str = "/world/sensor_pose";
|
||||
+
|
||||
+fn keeps_orbital_tracking_after_interaction(
|
||||
+ kind: Eye3DKind,
|
||||
+ tracking_entity: &EntityPath,
|
||||
+) -> bool {
|
||||
+ kind == Eye3DKind::Orbital
|
||||
+ && tracking_entity == &EntityPath::from(NODEDC_PERSISTENT_ORBIT_TRACKING_ENTITY)
|
||||
+}
|
||||
+
|
||||
@@ -434 +450 @@ impl EyeController {
|
||||
- let mut rot = self.rotation();
|
||||
+ let rot = self.rotation_after_delta(delta);
|
||||
@@ -435,0 +439,2 @@ impl EyeController {
|
||||
@@ -435,0 +452,2 @@ impl EyeController {
|
||||
+ self.apply_rotation_and_radius(rot, radius);
|
||||
+ }
|
||||
@@ -436,0 +442,2 @@ impl EyeController {
|
||||
@@ -436,0 +455,2 @@ impl EyeController {
|
||||
+ fn rotation_after_delta(&self, delta: egui::Vec2) -> Quat {
|
||||
+ let mut rot = self.rotation();
|
||||
@@ -452 +459,2 @@ impl EyeController {
|
||||
@@ -452 +472,2 @@ impl EyeController {
|
||||
- rot = rot.normalize();
|
||||
+ rot.normalize()
|
||||
+ }
|
||||
@@ -454 +462,13 @@ impl EyeController {
|
||||
@@ -454 +475,13 @@ impl EyeController {
|
||||
- self.apply_rotation_and_radius(rot, radius);
|
||||
+ /// Rotate around the point selected under the pointer without moving that
|
||||
+ /// point on screen.
|
||||
|
|
@ -34,7 +48,7 @@ index e59b311..7159aab 100644
|
|||
+ fn rotate_around_anchor(&mut self, delta: egui::Vec2, anchor: Vec3) {
|
||||
+ let sensitivity = 0.004;
|
||||
+ self.rotate_radians_around_anchor(sensitivity * delta, anchor);
|
||||
@@ -491 +511,10 @@ impl EyeController {
|
||||
@@ -491 +524,10 @@ impl EyeController {
|
||||
- fn handle_drag(&mut self, response: &egui::Response, drag_threshold: f32) {
|
||||
+ fn handle_drag(
|
||||
+ &mut self,
|
||||
|
|
@ -46,7 +60,7 @@ index e59b311..7159aab 100644
|
|||
+ if !response.dragged_by(ROTATE3D_BUTTON) {
|
||||
+ eye_state.orbit_drag_anchor = None;
|
||||
+ }
|
||||
@@ -503 +532,15 @@ impl EyeController {
|
||||
@@ -503 +545,15 @@ impl EyeController {
|
||||
- self.rotate(response.drag_delta());
|
||||
+ if self.kind == Eye3DKind::Orbital {
|
||||
+ let anchor = *eye_state.orbit_drag_anchor.get_or_insert_with(|| {
|
||||
|
|
@ -63,7 +77,7 @@ index e59b311..7159aab 100644
|
|||
+ } else {
|
||||
+ self.rotate(response.drag_delta());
|
||||
+ }
|
||||
@@ -514,0 +558,86 @@ impl EyeController {
|
||||
@@ -514,0 +571,86 @@ impl EyeController {
|
||||
+ /// Returns the world-space ray under the pointer.
|
||||
+ ///
|
||||
+ /// Keeping this calculation local to the eye controller lets orbital zoom use the pointer
|
||||
|
|
@ -150,16 +164,16 @@ index e59b311..7159aab 100644
|
|||
+ self.did_interact = true;
|
||||
+ }
|
||||
+
|
||||
@@ -516 +645,2 @@ impl EyeController {
|
||||
@@ -516 +658,2 @@ impl EyeController {
|
||||
- fn handle_zoom(&mut self, egui_ctx: &egui::Context, scene_bounding_box: &macaw::BoundingBox) {
|
||||
+ fn handle_zoom(&mut self, response: &egui::Response, scene_bounding_box: &macaw::BoundingBox) {
|
||||
+ let egui_ctx = &response.ctx;
|
||||
@@ -531,2 +660,0 @@ impl EyeController {
|
||||
@@ -531,2 +673,0 @@ impl EyeController {
|
||||
- let radius = self.pos.distance(self.look_target);
|
||||
-
|
||||
@@ -534,0 +663 @@ impl EyeController {
|
||||
@@ -534,0 +676 @@ impl EyeController {
|
||||
+ let radius = self.radius();
|
||||
@@ -536,11 +665,2 @@ impl EyeController {
|
||||
@@ -536,11 +678,2 @@ impl EyeController {
|
||||
- let new_radius = (radius / zoom_factor).clamp(Self::MIN_ORBIT_DISTANCE, max_radius);
|
||||
-
|
||||
- // The user may be scrolling to move the camera closer, but are not realizing
|
||||
|
|
@ -173,21 +187,21 @@ index e59b311..7159aab 100644
|
|||
- }
|
||||
+ let pointer = response.ctx.pointer_latest_pos();
|
||||
+ self.zoom_orbit_towards_pointer(zoom_factor, max_radius, response.rect, pointer);
|
||||
@@ -669,0 +790 @@ impl EyeController {
|
||||
@@ -669,0 +803 @@ impl EyeController {
|
||||
+ pointer_space_position: Option<Vec3>,
|
||||
@@ -671,0 +793,5 @@ impl EyeController {
|
||||
@@ -671,0 +806,5 @@ impl EyeController {
|
||||
+ if self.kind == Eye3DKind::Orbital {
|
||||
+ self.speed = self
|
||||
+ .speed
|
||||
+ .max(minimum_orbital_navigation_speed(scene_bounding_box) as f64);
|
||||
+ }
|
||||
@@ -687 +813 @@ impl EyeController {
|
||||
@@ -687 +826 @@ impl EyeController {
|
||||
- self.handle_drag(response, drag_threshold);
|
||||
+ self.handle_drag(eye_state, response, drag_threshold, pointer_space_position);
|
||||
@@ -690 +816 @@ impl EyeController {
|
||||
@@ -690 +829 @@ impl EyeController {
|
||||
- self.handle_zoom(&response.ctx, scene_bounding_box);
|
||||
+ self.handle_zoom(response, scene_bounding_box);
|
||||
@@ -728,0 +855,18 @@ fn max_orbital_radius(scene_bounding_box: &macaw::BoundingBox) -> f32 {
|
||||
@@ -728,0 +868,18 @@ fn max_orbital_radius(scene_bounding_box: &macaw::BoundingBox) -> f32 {
|
||||
+/// Lower bound for free-flight and post-limit zoom speed in orbital mode.
|
||||
+///
|
||||
+/// The default orbital speed is the current orbit radius. Close to the near
|
||||
|
|
@ -206,15 +220,27 @@ index e59b311..7159aab 100644
|
|||
+ (scene_diagonal * SCENE_DIAGONAL_FACTOR).max(FALLBACK)
|
||||
+}
|
||||
+
|
||||
@@ -773,0 +918 @@ impl EyeState {
|
||||
@@ -773,0 +931 @@ impl EyeState {
|
||||
+ pointer_space_position: Option<Vec3>,
|
||||
@@ -816,0 +962 @@ impl EyeState {
|
||||
@@ -816,0 +975 @@ impl EyeState {
|
||||
+ pointer_space_position,
|
||||
@@ -1189,0 +1336 @@ impl EyeState {
|
||||
@@ -891,0 +1051,2 @@ impl EyeState {
|
||||
+ let persistent_orbit_tracking =
|
||||
+ keeps_orbital_tracking_after_interaction(eye_controller.kind, &tracking_entity);
|
||||
@@ -946 +1107 @@ impl EyeState {
|
||||
- if new_tracking {
|
||||
+ if new_tracking && !persistent_orbit_tracking {
|
||||
@@ -998 +1159,4 @@ impl EyeState {
|
||||
- if eye_controller.did_interact && did_eye_orbit_center_change {
|
||||
+ if eye_controller.did_interact
|
||||
+ && did_eye_orbit_center_change
|
||||
+ && !persistent_orbit_tracking
|
||||
+ {
|
||||
@@ -1189,0 +1354 @@ impl EyeState {
|
||||
+ pointer_space_position: Option<Vec3>,
|
||||
@@ -1203,0 +1351 @@ impl EyeState {
|
||||
@@ -1203,0 +1369 @@ impl EyeState {
|
||||
+ pointer_space_position,
|
||||
@@ -1251,0 +1400,126 @@ impl EyeState {
|
||||
@@ -1251,0 +1418,145 @@ impl EyeState {
|
||||
+
|
||||
+#[cfg(test)]
|
||||
+mod tests {
|
||||
|
|
@ -340,6 +366,25 @@ index e59b311..7159aab 100644
|
|||
+ 0.25
|
||||
+ );
|
||||
+ }
|
||||
+
|
||||
+ #[test]
|
||||
+ fn nodedc_rig_orbit_tracking_is_persistent() {
|
||||
+ let rig = EntityPath::from(NODEDC_PERSISTENT_ORBIT_TRACKING_ENTITY);
|
||||
+ let other = EntityPath::from("/world/another_entity");
|
||||
+
|
||||
+ assert!(keeps_orbital_tracking_after_interaction(
|
||||
+ Eye3DKind::Orbital,
|
||||
+ &rig
|
||||
+ ));
|
||||
+ assert!(!keeps_orbital_tracking_after_interaction(
|
||||
+ Eye3DKind::FirstPerson,
|
||||
+ &rig
|
||||
+ ));
|
||||
+ assert!(!keeps_orbital_tracking_after_interaction(
|
||||
+ Eye3DKind::Orbital,
|
||||
+ &other
|
||||
+ ));
|
||||
+ }
|
||||
+}
|
||||
diff --git a/crates/viewer/re_view_spatial/src/ui_3d.rs b/crates/viewer/re_view_spatial/src/ui_3d.rs
|
||||
index 56257a8..07498ab 100644
|
||||
|
|
|
|||
BIN
apps/control-station/vendor/rerun-web-viewer-0.34.1/re_viewer_bg.nodedc.wasm (Stored with Git LFS)
vendored
BIN
apps/control-station/vendor/rerun-web-viewer-0.34.1/re_viewer_bg.nodedc.wasm (Stored with Git LFS)
vendored
Binary file not shown.
Loading…
Reference in New Issue