Animation speed question

I have a playground here Camera movement | Babylon.js Playground (babylonjs.com)

I set the end frame to be 20 in the example, I get a question about how to solve if the camera is changing from 180 degree to the “sphere1” position or just 20 degrees to the “shpere1” position? If I all set end frame always to be 20, the move from 180 degree will be too fast, is there any thing like camera max speed or calculate the new ‘end frame’ based on distance to the “sphere1” position?

Any good suggestion how to solve this? Thanks!

Speed is the distance divided by the time. If you want the speed to be the same for different distances, then you’ll need to have different times (end frames). You’ll need to calculate the angular distance between your position and the final position, divide that by time to obtain the duration (number of frames) of this animation.

1 Like

Thanks, @carolhmj , do we have any method in babylon can calculate the angular distance?

Since you’re using ArcRotateCamera here, the angular distance will just be the distance between the alpha, beta angles

I also need to calculate the camera target position and radius

The distance in this case is just the vector distance

Thank you @carolhmj , but could you give me a simple example or maybe articles , I do not really understand how to calculate the distance with so many things combined (target position, alpha, beta, radius) , thanks!

Work with each property separately. For each property, calculate the distance between the property and the desired value, use the speed to find the final frame, then create an animation.

For my understanding now, is do the following
camera.target.position.x - targetPostion.x
camera.target.position.y - targetPostion.y
camera.target.position.z - targetPostion.z
camera.alpha - targetPosition.alpha
camera.beta- targetPosition.beta
camera.radius - targetPosition.raduis

After these I get 6 different distances, and I will set 6 different speeds?

Yeah I think setting one speed for each variable will be better than setting the same speed for all. @PolygonalSun thoughts?

Well @pigga, you have the right idea with getting your camera’s net position changes. I do have a question. What is the result that you’re trying to go for? For example, are you trying to make your camera move from point A to point B at the same velocity (regardless of time that it takes)? I just want to make sure that I understand your use case so that I could recommend a good approach.

Thank you @PolygonalSun , let me explain more clearly, I think the idea you mention is what I need, camera move with the same velocity

Let me draw an example, b-> d should take 0.5 seconds, b → c should take 1 seconds, b → a should take 2 seconds, it has the same velocity, not the same time

Working with what you have in your diagram, you want the speed at which the camera will rotate to be (PI / 2) radians / second. Since your specified frameRate in your PG is 20, let’s assume that means you want to rotate your camera (PI / 2) radians / 20 frames. Next, you’d have to get a multiplier for how many PI / 2’s there are in your angle deltas (difference). All you’d have to do is to just take your angle change (which will be in radians as our cameras always work in radians) and divide it by PI / 2. Once you do that, just multiply it by your frameRate and that will give you your endFrame value. Just plug that into your key frames and you should be fine. It would look something like this in code:

const startFrame = 0;
const frameRate = 20;
const rotationVelocity = Math.PI / 2;
const alphaRotationDelta = targetCameraPosition.alpha - camera.alpha;
// You want to round your value to the nearest positive integer
const alphaEndFrame = Math.round(Math.abs(alphaRotationDelta / rotationVelocity) * frameRate);

From there you can just take your values and plug them into your key frames:

// ...
const alphaKeyFrames =
            [{ frame: 0, value: camera.alpha },
            { frame: alphaEndFrame, value: targetCameraPosition.alpha }];

This is only a basic approach and YMMV but this should be a good place to start.

1 Like

Thank you for the explanation, @PolygonalSun , I made a playground based on your comment (also consider the condition when the alpha,x,y,z are negative)
and set the max endFrame for all variable to be the end frame, if I use the max endFrame for these 6 variable, I still feel the speed is not the same? For example, if you zoom out, then it moves really slow back, but if you just rotate a little, it’s rotate speed feels really quick.

Camera movement | Babylon.js Playground (babylonjs.com)

This is the playground I set endFrame based on each variable’s delta, which does not work
Camera movement | Babylon.js Playground (babylonjs.com)

Could you help to take a look? Is there any place can improve? Thanks!

I believe it essentially comes from the easing function. If you remove this, the timing seems to be much more similar for each animation. So, I guess the part that would require adjustment would be around the easing. I’m not sure how this can be done but I’m quite sure that working on a delta for your animation speed without modifying the easing won’t do anything to it.

2 Likes

Good find @mawa! By not using an easing function, it should create a more uniform movement. One thing that I did notice was that you were checking for the value of each corresponding value from targetCameraPosition and using that to determine whether to subtract the current camera value from it or vise versa while taking the absolute value of either. For example:

// This ternary operator...
const targetXDelta =
            targetCameraPosition.x > 0 ?
                Math.abs(targetCameraPosition.x - camera.target.x)
                : Math.abs(camera.target.x - targetCameraPosition.x);

// ...could be simlified to this.
const targetXDelta = Math.abs(camera.target.x - targetCameraPosition.x);
2 Likes

Thank you @PolygonalSun , but I need a easing effect, is there any way to achieve this but with a more uniform movement?

Could try using more frames, e.g. try 200 instead of 20 and see if it helps, to make the easing more accurate…

1 Like

Well, I never used this function so far but I quickly checked on something and it seems like it would take bezier curves (which could solve the problem along with longer animations as suggested by @Blake ).
Have a look at this PG from the doc examples and the API. You should be able to work the bezier curves so that the easing kicks in only on the first and last 20 to 30% of your animation.

2 Likes