dolly icon indicating copy to clipboard operation
dolly copied to clipboard

Jerkiness in smoothing

Open GBagley opened this issue 1 year ago • 1 comments

I'm noticing that when using smoothing, and when the camera is following an object, there is jerkiness that seems to be coming from the smoothing. And any changes I make to the smoothing parameters don't seem to help.

If the object makes a single jump from point A to point B, or the object stops moving, then the camera moves smoothly to it, but when the object is in constant steady-state motion, the camera has some small jerkiness/oscillation and is not as smooth as I might expect.

Simple test exhibiting this behavior is a small modification to the nested_driver.rs example, just changing the camera rig position to follow the target, and adding a dolly arm (similar to the follow example shown in the README):

diff --git a/examples/nested_driver.rs b/examples/nested_driver.rs
index 643ad0c..9bbd1e5 100644
--- a/examples/nested_driver.rs
+++ b/examples/nested_driver.rs
@@ -20,11 +20,13 @@ impl<H: Handedness> MovableLookAt<H> {
         target_position: dolly::glam::Vec3,
     ) -> Self {
         Self(            
             CameraRig::builder()
                 // Allow moving the camera
-                .with(Position::new(camera_position))
+                .with(Position::new(target_position))
                 // Predict camera movement to make the subsequent smoothing reactive
                 .with(Smooth::new_position(1.25).predictive(true))
+                .with(Arm::new(dolly::glam::Vec3::new(0.0, 1.5, -3.5)))
                 // Smooth the predicted movement
                 .with(Smooth::new_position(2.5))
                 .with(LookAt::new(target_position + dolly::glam::Vec3::Y).tracking_smoothness(1.25))
@@ -37,7 +39,7 @@ impl<H: Handedness> MovableLookAt<H> {
         camera_position: dolly::glam::Vec3,
         target_position: dolly::glam::Vec3,
     ) {
-        self.0.driver_mut::<Position>().position = camera_position;
+        self.0.driver_mut::<Position>().position = target_position;
         self.0.driver_mut::<LookAt>().target = target_position;
     }
 }

Then if you hold down one of the WASD keys, you'll see the jerkiness. Not sure if there's some combination/ordering of smoothing drivers that can help with this, or if it's inherent in the smoother itself. Or any other ideas?

GBagley avatar Sep 03 '23 22:09 GBagley

Yup, could repro it on my system. Looks like the classic problem that physics engines suffer from with varying timesteps. Fixing the them makes it smooth for me:

@@ -85,7 +85,7 @@ async fn main() {
             .set_position_target(camera_position, player_position);
 
         // Update the camera rig, and get the interpolated transform
-        let camera_xform = camera.update(get_frame_time());
+        let camera_xform = camera.update(1.0 / 60.0);
 
         clear_background(LIGHTGRAY);

If you can't / don't want to use fixed timesteps, you could also try filtering the delta times before passing them to dolly (or any other simulation really).

h3r2tic avatar Sep 11 '23 13:09 h3r2tic