How to remove Camera Movement Jitter

Hey guys… I cam moving a FreeCamera around my scene using a Lerp and directly setting the Position but i get some camera jitter when moving the camera like this:

            const cameraRig:BABYLON.FreeCamera = BABYLON.UniversalCameraSystem.GetPlayerCamera(this.playerNumber); // Maybe Performace Issue For WebVR Cameras - ???
            if (cameraRig != null) {
                // ..
                // TODO: LookAt To Actual Rotation Code
                // ..
                if (this.followBehind === true) {
                    this.m_followPosition.set(this.transform.position.x, this.transform.position.y, this.transform.position.z);
                    this.m_followPosition.addInPlace(this.transform.forward.scale(this.offsetPosition.z)); // TODO: Optimize New Scale Vector3
                    this.m_followPosition.addInPlace(this.transform.right.scale(this.offsetPosition.x)); // TODO: Optimize New Scale Vector3
                    this.m_followPosition.addInPlace(this.transform.up.scale(this.offsetPosition.y)); // TODO: Optimize New Scale Vector3
                    if (cameraRig != null) BABYLON.Vector3.LerpToRef(cameraRig.position, this.m_followPosition, (this.followSpeed * deltaTime), cameraRig.position);
                }
            }

What does intertia have to do with smooth camera movement. Should i just try setting that ZERO ow what… Basically how can i get rid of the camera jitter ???

Yo @Wingnut … Got any insights on removing camera jitter ?

:slight_smile: Hiya Mackey! Sleepy forum this weekend, eh? nod.

I think what is happening in your code… is a lot of repeated little-lerps… and that’s why she jitters.

I think… hmm… maybe think more like moveWithCollisions(), which uses ummm… small amounts of change toward the “follow direction”… and then YOU need to make it do continuous direction-to-target updating, and the looping/repeating.

This issue is a bit complicated for my simple brain. But moveWithCollision does NOT use a “target” worldCoord (as a param). It uses a direction and magnitude, I believe. I think… every moveWithCollisions() playground… has it INSIDE the renderLoop… https://www.babylonjs-playground.com/#16MDIB#1. It is a very fast “little stepper” and it is working with directions and magnitudes, and not with worldCoords. Any “target” work… is ONLY for updating the direction and maybe the magnitude OF that direction.

Even in a standard followCam… Babylon.js/followCamera.ts at master · BabylonJS/Babylon.js · GitHub (lines 142-166), you don’t see a lerp. You see more of a continuous chasing/pursuit… “live”.

Aren’t lerps actually pre-grown… calculated first, and THEN acted-upon… and thus not “live”? For your jitters, it is POSSIBLY because you are “playing-back” short little “pre-recorded position move-sequences”… one after another. At every little pause in your follow-animation… you are stopping to record (lerp-calc) a new little sequence of positions… and then start it playing. It’s actually not jumping… it’s pausing… repeatedly. (maybe)

Babylon.js/abstractMesh.ts at master · BabylonJS/Babylon.js · GitHub (line 1368… works with a thing called displacement… and no lerps seen).

I dunno if I know what I’m talking about… but perhaps something I have said… makes sense to you. I think repeated lerpings are causing the jerks, jumps, and jitters. Instead… stick your mover in the renderloop… and do little “displacements” towards the target… REAL OFTEN. The “real often” part… is what smoothes-out the follow-animation. The little jumps are too small and too fast for our eyes to notice.

Possibly, it might be wise to notice that followCams are a type of camera input… Babylon.js/src/Cameras/Inputs at master · BabylonJS/Babylon.js · GitHub. Universal cams… none. So, followCams might be updated by the followCam INPUT code. (followCam might “bind” to the renderLoop inside its followCameraInput code). This is why you don’t need to install a followCamera updater/stepper… into the renderLoop… to make it follow.

Therefore… you might need to add a followCam input to your universalCam.inputs, or code-up your own followingUniversalCameraInput interface (a custom camera input for FollowingUniversalCameras). Gruesome, eh? Or maybe simply update (step) your follower… in your scene renderLoop… and not need a custom camera input.

Lastly, I would check to make sure that there is no camera “behavior”… called “follow behavior”. :slight_smile:

Yo @Wingnut … I tried to use Follow Camera before but could get it to quite work. That why i ended up writing a LERPING camera so i can get the “delay” in camra movement and not be SO RIGID and stay DIRECTLY behind the car.

I went back to give FollowCamera another try but i can seem to get it to work like a FOLLOW CAMERA … If i just try the basic setting from documentation

            var startPosition = new BABYLON.Vector3(0, 5, -10);

            //if ((<any>window).BABYLON.UniversalCameraSystem.CameraStartPosition != null) {
            //    startPosition = (<any>window).BABYLON.UniversalCameraSystem.CameraStartPosition.clone();
            //}

            // Parameters: name, position, scene
            var camera = new BABYLON.FollowCamera("FollowCam", startPosition, this.scene);

            // The goal distance of camera from target
            camera.radius = 10;

            // The goal height of camera above local origin (centre) of target
            camera.heightOffset = 2;

            // The goal rotation of camera around local origin (centre) of target in x y plane
            camera.rotationOffset = 0;

            // Acceleration of camera in moving from current to goal position
            camera.cameraAcceleration = 0.1;

            // The speed at which acceleration is halted
            camera.maxCameraSpeed = 10;

            // NOTE:: SET CAMERA TARGET AFTER THE TARGET'S CREATION AND NOTE CHANGE FROM BABYLONJS V 2.5
            camera.lockedTarget = this.getAbstractMesh();

            // Activate camrea
            this.scene.activeCamera = camera;

I would think since the thing being called FOLLOW camera. The camera should be behind the target and following… but i cant get it work right… its always in front of car:

Any ideas ???

Ok… I think i found the Follow Camera Issue i had FOR 2 YEARS…

camera.radius — now this implies to me a circular area. so if you put a value of 10 … thinking that would define a circular area since is called radius.

But that apparently is not the case… so if i want the camera to TRY and follow 10 meters behind the car i have to specify a radius of -10… How can a radius be negative value ???

But anyways… that should be more like camera.followDistance or something like that and should say positive values are in front and negative values are behind.

Because still… Its a FOLLOW camera… a distance of 10 SHOULD BE IMPLIED that its 10 meters BEHIND the object we are following… I dunno… That was really throwing me off :frowning:

But now that i know that camera.radius is actually the distance (negative for behind … i can work with that)

FUCK… Its my Mac. Thats shitty. Im running a MacPro (Early 2009):

  • 2 x 3 GHZ Quad Core Xeons
  • 20 GB Memory
  • NVIDIA GeForce GTX 770 (2048MB) … Only Card i can get for my Mac

And even the basic follow camera is Jittery As Fuck. If i Lower amount of models its a little better but still jitters or skips or whatever you call it… You can see it when playing the game… FUCK :frowning:

Now… I busted out a shitty 12 Year Old Dell Inspiron Laptop with

  • Single Core I7-3630QM Mobile CPU
  • 8 GB Memory
  • NVIDIA GeForce 650M (2048MB) - Mobile GPU Edition

Without toning down any geometry or anything…

Both my Lerping Camera and Babylon default FollowCamera are Smooth As A Babies But

FUCK… Im a Mac Guy… Its seems like there is an Issue With Mac (Safari, Chrome And Firefox) where its just shitty performance… Windows is freaking smooth… Even shitty windows is smooth :frowning:

1 Like

Oh, sorry to hear about the hassles, M!

Cheer up… it’s only 70 hours of lost work and goose chase… no biggie. :slight_smile: (hug and blueberry muffin)

Btw, I think followCam’s .rotationOffset is in degrees. Try setting it to 180… see what happens. It might put you behind the car (without using a negative radius). Perhaps it should have been named orbitalOffset or radialOffset. shrug

Also, beware of using .lockedTarget. Can you instead do ONE followCam.setTarget(car)… and then not need to constantly re-set it… as the car moves? FollowCam and its baseClass TargetCam… don’t have a .target property, so we can’t simply set that, repeatedly or one-time. All in all, .lockedTarget could be trouble… possibly dis-allowing .rotationOffset to work as expected.

Also, be sure to web-search for that stuttering Mac issue. There’s GOTTA be others who have experienced that, and there might be work-arounds. MIGHT BE requestAnimationFrame-related… but that’s a Wingnut grasp-at-straws, for sure. :slight_smile:

1 Like

Yeah im gonna implement the FollowCamera movement code on my Universal Camera so i dont have to LERP… Its a Bit Smoother without the Lerp.

For now… I installed Windows 10 on a Dual Boot Partition for my Mac… The Same Exact Hardware just running Windows… Smooth As A Babies But

Freakin Mac’s … They cost 3 - 4 times as much as a PC and runs like shit (with WebGL And Heavy Graphics)… What a Krock Of Shit Apple :frowning:

OK… Maybe i was mistaken (I could have sworn i ran in windows with follow camera)… The follow camera is not working out either… I am not sure how much inertia the follow camera should have or what the threshold for max camera speed should be when making a high speed driving game.

But it looks like i still get Jitter when trying to follow my race car around the track.

Its really hard to re-produce on the playground… But i will start to try. Maybe someone out there can figure out to make a Smooth High Speed Follow Camera for a racing game :frowning:

I’d try lowering the camera acceleration.

I tried lower the camera acceleration… But then lags too far behind that car… The car gets away from the camera :frowning:

You might need to make it dynamic so that when the camera gets too close you decrease acceleration. When it’s too far you increase it.

Yo @adam … Can you please show example code on how i would smooth out the camera acceleration. Do i lerp a min and max max camera acceleration based on how far from the desired distance the camera actually is… or something like that ???

Yo @Deltakosh … You got code snippet insights on how to dynamically update the camera acceleration on a Follow Camera to smooth out the high speed camera jitter ???

That sounds like it could work. Sorry I don’t have time to figure this out. I barely have enough time for my own project.

do a free camera, and then do all custom LERPs…
standby 1 sec… playground coming.

https://playground.babylonjs.com/#JIVNCS

I can show you how to manipulate it with input controls as well…
that’s what the commented out “swivel” section is about.

You can make it more aggressive if you need to by increasing the LERP factor. Ideally a well balanced number will make sure that you never get to close or to far from your object, but takes some tailoring depending on what you setup.

@MackeyK24 if you have any questions let me know.

Yo @Pryme8 … A Few Questions:

First… What is the extra add on the target position ???

Is the targetPosition basically the center of the car transform… And all the extra add puts the actual target behind the car by scaling the car transform forward vector by a negative value (-camera.radius… Which is really the distance how far behind i want the desired target point)

I dont get the target.up clone and normalize and scale though ???

       var tp = target.position.add(
            target.forward.scale(-camera.radius)
        ).add(
            target.up.clone().normalize().scale(camera.offsetHeight)
        )	

Second What is the swivel… Is that some kind of way to lag the rotation a bit so its not to stiff when you turn wheel left and right … Can please Explain ??

        var matr = new BABYLON.Matrix()      
        target.rotationQuaternion.toRotationMatrix(matr)
        var swivil = new BABYLON.Vector3.Zero()
        swivil = BABYLON.Vector3.TransformCoordinates(swivil, matr)

And Last WHY FREE Camera vs TargetCamera ???

And the LERP… 0.8 is that a way to smooth the movement by scaling back that movment a little (like camera.inertia)… So you just play with a value that is enough to keep the care close to the desired target point and not too much to make the camera jitter

If so… How do I apply a bit of lag when turning the wheel… Is That what Swivel is for ???

        camera.position = BABYLON.Vector3.Lerp(camera.position, tp, 0.08)
        camera.setTarget(BABYLON.Vector3.Lerp(target.position, camera.getTarget(), 0.08))        
        camera.upVector = BABYLON.Vector3.Lerp(camera.upVector, target.up, 0.08)

1: Yes spot on, it’s the distance behind your target. The high offset you do want, as this get you up off the top surface of the car. The up vector being taken into account helps as your car tilts around turns the camera will do so as well.

if you want to make sure it never “flips” incase your car does just ABS the y value or clamp it.

2: The swivel is commented out right now because that setup is for controllers. If you have ever played Rocket League its kinda the same setup, left stick for actions and right stick for looking around. But I did not know your control setup so I stripped it.

3: Free camera because no restrictions or other algos being used to control its movement, and yes the Z Value of the LERP is basically the ratio of the interpolation mess with it to get your desired results. you can go infinitesimally small and have it “work” so don’t be afraid to try numbers 0.08 was what was good for my secret projects hotspot I’ll post it here at some point as well.

4: if you want wheel lag, you could do another LERP calculations specifically on your input for turning so like

A = Last Turn Value
B = Target Turn Value
Z = Lerp Ratio

(A,B,C)=>{ return (1 - Z) * A + Z * B)

And that will smooth your input.


Is where I learned all this.

Thanks @Pryme8

Just don’t quite understand where and when to apply the 4th lerp calculation to make the camer lag left or right when turning. Do think you could implement that in your playground as well so I can get my head around that too :slightly_smiling_face:

Thanks again for help wit this

https://playground.babylonjs.com/#VE72NF

Cause The Monkey King <3 you.

A and D are steering.

You can really push this to the extreme and even introduce “road jitter” into the controls and like response from off angle axial contact

UPDATE
https://playground.babylonjs.com/#VE72NF#1
This fixes the input jump from smashing buttons left and right where the accel might be larger then it should be from a swing back. This could all be cleaned up and the logic could be changed to make it so when you press both A and D they cancel each other out… but I mean its all preference.

https://playground.babylonjs.com/#VE72NF#2
This should feel a little bit more like a moving car steering wheel. Ramp up that *2 value on the no input by Forward Speed of the vehicle and it should really play a good effect.

Yo @Pryme8 … Bro… I think your on to something… WITHOUT having to lerp around the camera…

Imagine we make a box to serve as the camera boom arm then we make the box a child of the car. We cam the camera the child of the camera boom arm with an offset position like (0,2,-10).

Then we try your new turn stuff to simple rotate the box that is the camera boom arm… Also must keep box oriented up so if car flips, the boom arm says up.

can you help start on that… Here is a playground using a box and rotating based on A or D… values are no right, sine we need to thing ini rotation radians instead of moving the sphere.position.x

https://playground.babylonjs.com/#VE72NF#3

That might work… I think that is how Unreal Engine does things with a USpringArmComponent

I just could not figure out the math to rotate the boom arm… But your last example is CLOSE to that…

What do you thank about that idea ???