Smooth camera

88dc730f0f71e55be39de0ad103bd9ff
0
Alienizer 109 Apr 01, 2013 at 01:37

I’m trying to smooth my camera movements and I just can’t find a way to do it. Basically, my camera is a flying drone, when I move the mouse it’s too jumpy, and if I reduce the sensitivity, I have to drag the mouse too far. Is there a solution to make a camera move more smooth, like the real professional video camera that are on a gyro to prevent sudden sharp movements?

16 Replies

Please log in or register to post a reply.

B5262118b588a5a420230bfbef4a2cdf
0
Stainless 151 Apr 01, 2013 at 08:48

There are lot’s of ways of smoothing movement, you can use the mouse movement to apply an acceleration to the camera instead of just applying it as a velocity for a start.

You can give the camera inertia for the rotational movement as well.

Post some code and we can help

88dc730f0f71e55be39de0ad103bd9ff
0
Alienizer 109 Apr 01, 2013 at 16:25

I do not have any code as all I’m doing right now is read the mouse pos and use that along with the last mouse pos to get the new mouse pos. NewPos = (LastPos-CurrentPos);

Say I move the mouse left, it goes from pixel x=900 down to pixel x=300 for example, and at the same time, y = +-20 since I’m not a robot moving the mouse. So I want to keep y as close to +- 0 as possible, and also, the difference between the last x and the current x is 30 pixels and I want to keep it at around or close to 30 pixels even if at one point during the move it was 50.

But because I don’t know where the mouse is going, I can’t average these numbers to get a smooth transition. Maybe use a predicted vector and velocity? I don’t know!

820ce9018b365a6aeba6e23847f17eda
0
geon 101 Apr 19, 2013 at 11:02

Have the mouse position as a target camera position, then move the camera x% there per second. It wotks well for a lot of situations where you need something to be booth smooth an responsive.

It has a name, but I can’t remember it now.

88dc730f0f71e55be39de0ad103bd9ff
0
Alienizer 109 Apr 19, 2013 at 14:34

What do you mean geon? I’m not understanding the logic of this method :wacko:

C08546fc4340f0be3109019ef869ac9e
0
lightxbulb 101 Apr 21, 2013 at 17:18

First of all - are you talking about a 1st person or 3rd person camera? Secondly I guess this is supposed to be in 3d? Also what do you mean by moving your camera - you mean turning it with the mouse? (something like: CameraYaw = MouseXCurrent - MouseXPrevious and then RotateEntity(camera, 0, CameraYaw,0))
Best of all post a link to a video featuring the camera behaviour you want

88dc730f0f71e55be39de0ad103bd9ff
0
Alienizer 109 Apr 22, 2013 at 00:55

Yes, in 3D, FPS, and as you said, moving the mouse moves the camera. I just want to smooth out the movement so it’s not so jaggy!

C08546fc4340f0be3109019ef869ac9e
0
lightxbulb 101 Apr 22, 2013 at 09:17

What do you mean exactly by jaggy? You want it to be without acceleration or with acceleration? If you want it to be without acceleration then it’s easy - just rotate your camera based on your mouse movement. Something like this:

CameraYawRot = (MouseX() - PrevMouseX())*factor;
RotateEntity(camera, 0, CameraYawRot, 0);

You can of course cap the maximum(and minimum too) rotation you can get per frame. Something like:

if(CameraYawRot<0)
{
    if(CameraYawRot<-cap)
    {
         CameraYawRot = -cap;
    }
}


if(CameraYawRot>0)
{
    if(CameraYawRot>cap)
    {
         CameraYawRot = cap;
    }
}

P.S. More info on what effect exactly you want to get would be appreciated and really helpful(because “I just want to smooth out the movement so it’s not so jaggy!” doesn’t say much) .
Can’t you post a video of what you get now and what you want to get?

/edit:

The question is what exactly do you want:
1)Should the camera rotate exactly depending on how much you move your mouse (the faster movement you do with the mouse the more it turns)?
2)Should it be capped (no matter how fast you rotate at some point it the rotation becomes constant).
3)Should it have acceleration(you move your mouse and then the camera “tries to follow”)

Please post a video of what you have now and what you want to get(maybe from a game this one) - it would be really helpful. :)

88dc730f0f71e55be39de0ad103bd9ff
0
Alienizer 109 Apr 22, 2013 at 12:54

Thanks for helping.

What I mean by jaggy is that when you move the mouse, it’s not smooth, because we’re humans not perfect robots. Say I want to turn left, if I move my mouse left, then it goes a bit up and a bit down as it goes left, and not at a steady speed. So I want to prevent or reduce that as much as possible so the movement is more stable and the acceleration is more smooth.

C08546fc4340f0be3109019ef869ac9e
0
lightxbulb 101 Apr 22, 2013 at 16:27

Say I want to turn left, if I move my mouse left, then it goes a bit up and a bit down as it goes left, and not at a steady speed.

Well that’s because of the user obviously - if you remove that you’ll be able to turn only in one plane. However I think I got what your problem is - do you feel like the mouse sensitivity is too high and every twitch of your hand changes the rotation of the camera? If it is so you just have to add a sensitivity variable into the equation. Imagine you have the current mouse X position - currentMouseX and the previous mouse X position - prevMouseX, assuming you calculate the angle the camera will rotate by angle = currentMouseX-prevMouseX (later you have some function like RotateEntity(camera, 0, angle, 0) that turns the camera by this angle); you just have to add in sensitivity - something like:

angle = (currentMouseX-prevMouseX)*sensitivity
  • if you want a lower sensitivity just choose 0<sensitivity<1 or if you want higher sensitivity>1 if you want to invert the axis of rotation sensitivity<0. You can give the user the option to choose his sensitivity.
    Also, regarding the problem with the speed not being steady - you got various options - if you want a constant speed always(not depending on the actual speed with which you move the mouse) you can do something like this:

    float angleY = 0.1f; mx = currentMouseX - previousMouseX; if(mx>0) { angleY = angleY; } if(mx<0) { angleY = -angleY; } if(mx = 0) { angleY = 0; } RotateEntity(camera, 0, angleY, 0);

that will make the camera turn at a fixed speed (in this case 0.1f degrees per frame) if you move your mouse (you gotta do the same for Y too).

If you want some freedom though you can do some minimum and maximum caps - for example if the angle>1 -> angle=1 and angle<0.5 -> angle = 0.5

I still can’t get exactly what you’re aiming to do so as I said a video will be really helpful.
Also - in what language are you coding this?

88dc730f0f71e55be39de0ad103bd9ff
0
Alienizer 109 Apr 22, 2013 at 22:41

Thanks for the code and the explanation. Yes, I did use the sensitivity but it gets too slow, but it’s much smoother. Anyways to achieve the same but for a faster mouse movements? It’s like attaching a gyro on the camera to reduce the jumpy effects. For example, when I turn, my up/dn changes slightly and that’s what’s annoying!

C08546fc4340f0be3109019ef869ac9e
0
lightxbulb 101 Apr 23, 2013 at 10:28

For example, when I turn, my up/dn changes slightly and that’s what’s annoying!

Uh, that’s because you move your mouse up and down - right? If you want to eliminate this totally you won’t be able to turn up and down. However if you want to overlook “minimal twitches of the hand” that cause this you can do something like:

my = currentMouseY - prevMouseY;
int twitch_cap = 5; // 5 pixels
float sensitivity = 0.1f;
if(abs(my)<twitch_cap)
{
    angleX = 0;
}
else
{
    angleX = (float)my*sensitivity;
}
RotateEntity(camera, angleX, 0, 0);

Considering this - any movement of the hand per frame under 5 pixels(twitch_cap) on Y would be disregarded(angleX = 0) - though this means that you have to move your mouse more than 5 pixels per frame to get a rotation - you can of course change the value of twitch_cap to suit your situation. You have to do the same for mx and angleY too.
I am not sure though if you just want to exclude the rotations around the X axis(currentMouseY-prevMouseY) or just have a lower cap.
You may find it more intuitive to have the cap condition based on the angle too:

mx = currentMouseX - prevMouseX;
my = currentMouseY - prevMouseY;
float sensitivity = 0.1f;
float twitch_cap = 0.3f; //0.3 degrees
float angleX = (float)my*sensitivity;
float angleY = (float)mx*sensitivity;
if(abs(angleX)<twitch_cap)
{
     angleX = 0;
}
if(abs(angleY)<twitch_cap)
{
    angleY = 0;
}
RotateEntitiy(camera, angleX, angleY, 0);

That will make it so if your mouse movement would cause a camera rotation under 0.3 degrees it will be disregarded and the camera won’t turn at all. In this case you’ll have to move your mouse more than 0.3 degrees (twitch_cap) to actually turn your camera.
You can of course make a different twitch cap for X and Y and a different sensitivity for each too. Depends on what you want.
If something’s unclear please ask :)

88dc730f0f71e55be39de0ad103bd9ff
0
Alienizer 109 Apr 23, 2013 at 15:44

Now I think you’re getting somewhere, thanks for the code and stuff, really appreciate your effort to help me.

In better words, can we apply a “noise reduction” to the mouse movements without compromising the sensitivity or its ability to look in any direction? I forgot to mention that this is only for the view vector, not the position, because while the camera stand still, you can still look around, and that’s what I want to de-noise.

For example, use a 2D paint program and try to draw a line on it, or even a circle (using the pencil tool, not the line tool), now you see how noisy the line is right? Well, that’s what I want to de-noise.

B5262118b588a5a420230bfbef4a2cdf
0
Stainless 151 Apr 23, 2013 at 16:52

Well if you want a very simple noise reduction scheme, express the velocity as a float between 0 and 1 and then square it.

1*1 = 1
0.5*0.5 = 0.25
0.1* 0.1 = 0.001

C08546fc4340f0be3109019ef869ac9e
0
lightxbulb 101 Apr 23, 2013 at 18:39

@Alienizer

Now I think you’re getting somewhere, thanks for the code and stuff, really appreciate your effort to help me.

In better words, can we apply a “noise reduction” to the mouse movements without compromising the sensitivity or its ability to look in any direction? I forgot to mention that this is only for the view vector, not the position, because while the camera stand still, you can still look around, and that’s what I want to de-noise.

For example, use a 2D paint program and try to draw a line on it, or even a circle (using the pencil tool, not the line tool), now you see how noisy the line is right? Well, that’s what I want to de-noise.

The problem with presenting it as noise can be seen from your analogy - if you knew what you want to draw beforehand(circle) you could “remove noise” - however when it comes to random and non-fixed user input you cannot decide which is noise and which is not without affecting the whole thing some way or another - basically you do not know what the user wants to do in the future - you can try to extrapolate based on samples from his previous actions/behaviour but that’s a real double-edged sword(you can totally impede the user input with this).

The easiest way IMO is the thing I suggested - eliminate any “twitch movement” under a certain threshold. You can specifically choose the threshold so it will suit your aims, even more you can make the threshold (previously I used the twitch_cap identifier for it) “dynamic” - it can take in some additional data(more samples, x versus y mouse movement, predicted mouse location at time T) to define this threshold better for the given situation. Anyways I think that all of these “solutions” will impede the user to some extent - moreover I really don’t get why you’d want to add such a “crutch” for the user - he’s got a mouse he should be able to control. A simple analogy - try playing a FPS like Tribes:Ascend - the best way to hit something with a projectile weapon (an aimbot would need a 4th degree equation to find the hit mark and it will still be inaccurate) is lowering your mouse sensitivity to around 10(by doing this you mostly remove any random twitching of the hand) and having control of your hand of course :) If you add any “crutches” as rotation corrections and mouse input corrections you’ll probably just impede users. Still I am not sure what your goal is exactly - as I mentioned a video will be really helpful so people can get what you want( if you don’t want to post a video of your project just post a video of some game or whatever that has your desired effect) or you can try to make a thorough explanation. What are your goals exactly - fps shooter/panoramic view/ “camera recording” etc. - because this:

Is there a solution to make a camera move more smooth, like the real professional video camera that are on a gyro to prevent sudden sharp movements?

isn’t much help.

For now you can try implementing the mouse movement/angle threshold I talked about - by playing with the sensitivity and twitch_cap values you should be able to get something good.

P.S. More info would be highly appreciated - I can’t solve a problem if I don’t have enough data on it :)

88dc730f0f71e55be39de0ad103bd9ff
0
Alienizer 109 Apr 23, 2013 at 21:54

I suppose you’re right, we can not predict the future, that’s why I was asking the pros here :)

I don’t have a video of anything, it was just a thought but going with the threshold as you suggested seems to work better than nothing at all. And as you said, without knowing the actual path the user will do, there is no way to filter the noise entirely. We can only eliminate some as defined by the threshold value.

Thanks to make all this clear to me, and to take the time to even answer in such details. I really appreciate it.

C08546fc4340f0be3109019ef869ac9e
0
lightxbulb 101 Apr 25, 2013 at 09:26

Well hope you manage to make it work. :)