Skip to content

Commit

Permalink
Fix forever repaint of big scenes (#5071)
Browse files Browse the repository at this point in the history
### What
* Closes #5018

When first loading a scene, before the user interacts, we want to center
the eye-camera on the scene, so each frame we call "interpolate to the
default eye". This should be fine, because we have an early-out if we're
already at target. However, the interpolation code had a rounding error
meaning we reached _very close_ to our goal, but not quite there. In
particular, in `arkit_scenes` it would lead to a forever repaint, since
the eye-camera would never reach its target, and so thus would require
more animation.

This manifested in `arkit_scenes` now due to another bug
(#5070) causing enormous point
clouds, making the rounding errors larger than usual.

### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using newly built examples:
[app.rerun.io](https://app.rerun.io/pr/5071/index.html)
* Using examples from latest `main` build:
[app.rerun.io](https://app.rerun.io/pr/5071/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[app.rerun.io](https://app.rerun.io/pr/5071/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG
* [x] If applicable, add a new check to the [release
checklist](tests/python/release_checklist)!

- [PR Build Summary](https://build.rerun.io/pr/5071)
- [Docs
preview](https://rerun.io/preview/d20d34685e6aaba1daf5c6417e1bb39d22448d40/docs)
<!--DOCS-PREVIEW-->
- [Examples
preview](https://rerun.io/preview/d20d34685e6aaba1daf5c6417e1bb39d22448d40/examples)
<!--EXAMPLES-PREVIEW-->
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)
  • Loading branch information
emilk authored Feb 6, 2024
1 parent 70d14ae commit 74d918d
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 16 deletions.
20 changes: 13 additions & 7 deletions crates/re_space_view_spatial/src/eye.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,13 +209,19 @@ impl OrbitEye {
}

pub fn lerp(&self, other: &Self, t: f32) -> Self {
Self {
orbit_center: self.orbit_center.lerp(other.orbit_center, t),
orbit_radius: lerp(self.orbit_radius..=other.orbit_radius, t),
world_from_view_rot: self.world_from_view_rot.slerp(other.world_from_view_rot, t),
fov_y: egui::lerp(self.fov_y..=other.fov_y, t),
up: self.up.lerp(other.up, t).normalize_or_zero(),
velocity: self.velocity.lerp(other.velocity, t),
if t == 0.0 {
*self // avoid rounding errors
} else if t == 1.0 {
*other // avoid rounding errors
} else {
Self {
orbit_center: self.orbit_center.lerp(other.orbit_center, t),
orbit_radius: lerp(self.orbit_radius..=other.orbit_radius, t),
world_from_view_rot: self.world_from_view_rot.slerp(other.world_from_view_rot, t),
fov_y: egui::lerp(self.fov_y..=other.fov_y, t),
up: self.up.lerp(other.up, t).normalize_or_zero(),
velocity: self.velocity.lerp(other.velocity, t),
}
}
}

Expand Down
19 changes: 10 additions & 9 deletions crates/re_space_view_spatial/src/ui_3d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,10 +147,6 @@ impl View3DState {
let t = t.clamp(0.0, 1.0);
let t = ease_out(t);

if t < 1.0 {
response.ctx.request_repaint();
}

if let Some(target_orbit) = &cam_interpolation.target_orbit {
*orbit_eye = cam_interpolation.start.lerp(target_orbit, t);
} else if let Some(target_eye) = &cam_interpolation.target_eye {
Expand All @@ -160,12 +156,12 @@ impl View3DState {
self.eye_interpolation = None;
}

if 1.0 <= t {
// We have arrived at our target
self.eye_interpolation = None;
} else {
if t < 1.0 {
// There's more frames to render to finish interpolation.
response.ctx.request_repaint();
} else {
// We have arrived at our target
self.eye_interpolation = None;
}
}

Expand Down Expand Up @@ -256,6 +252,10 @@ impl View3DState {
// the user wants to move the camera somewhere, so stop spinning
self.spin = false;

if self.orbit_eye == Some(target) {
return; // We're already there.
}

// Don't restart interpolation if we're already on it.
if let Some(eye_interpolation) = &self.eye_interpolation {
if eye_interpolation.target_orbit == Some(target) {
Expand Down Expand Up @@ -329,7 +329,8 @@ impl EyeInterpolation {
.angle_between(stop.world_from_rub_view.rotation());

// Threshold to avoid doing pointless interpolations that trigger frame requests.
if angle_difference < 0.01 && start.pos_in_world().distance(stop.pos_in_world()) < 0.0001 {
let distance = start.pos_in_world().distance(stop.pos_in_world());
if angle_difference < 0.01 && distance < 0.0001 {
None
} else {
Some(egui::remap_clamp(
Expand Down

0 comments on commit 74d918d

Please sign in to comment.