Animation controller

Hi
I have got an animation working

??Is there anything that lets me ‘single-step’ through the animation keyFrame to keyFrame
OR
lets me execute a callback-function at each keyFrame

Thanks

Like this?

It is all the frames defined for the animation. But it is not the key frames.

I don’t think the exact key frames are rendered at runtime. If I understand correctly, the runtime rendering of animation works like this:

Input is current time T.

  • It finds the first key frame that has startTime >= T.
  • Calculate delta = startTime - T
  • Calculate the animation based on the position at key frame and apply tweening function on delta time. You only have exact key frame if delta is 0.

And this happens at bond level. Each bond can have different key frames.

2 Likes

There’s animation events: Advanced Animation Methods | Babylon.js Documentation (babylonjs.com)

Hi
Have just been experimenting with AnimationEvents

I have a for loop to setup my keyFrame array
This now includes adding AnimationEvents to my animation

For example my for loop creates 64 keyFrames / AnimationEvents
When the animation runs - I only get 63 function calls
also the frame numbers are NOT integers - so I don’t seem to be getting back my keyFrame numbers

??Does this make sense

Thanks

It will be much better if we can see your code on a Playground :slight_smile:

Here’s the relevant code snippet


function animateModelSlicer(){
	console.log("in animateModelSlicer");
	var modelMesh = findMesh(scene.meshes, "Mesh");
	if(modelMesh != null){
		var bBox = modelMesh.getBoundingInfo();
		var minXYZ = bBox.minimum;
		var maxXYZ = bBox.maximum;
		var h = Math.abs(maxXYZ.y - minXYZ.y);
		var kFrames = [];
		for(i = 0; i < Math.trunc((modelZOffest + h) / zScannerHeight); i++){
			kFrames.push({
				frame: i,
				value: (zScannerHeight / 2) + i * zScannerHeight
			});
			//	Now add animationEvent for this keyFrame
			scanningAnimation.addEvent(new BABYLON.AnimationEvent(i, 
				(frame) => {
					processKeyFrame(frame);
				}, true)
			);
		}
		scanningAnimation.setKeys(kFrames);
		console.log("set '" + kFrames.length + "' keyFrames");
	}
}

function processKeyFrame(frame){
	console.log("processing keyFrame '" + frame + "'");
}

It’s more helpful if it’s on a Playground: playground.babylonjs.com with a minimal example that reproduces your situation :upside_down_face:

Please take a look at

At runtime, it is not giving you exactly the key frame.
I didn’t know you are doing the animations programmatically. In this case, you just need to iterate through your keyframes array. And set the animated property to be the value of that keyframe.

<targetMesh>.<animProperty>=keyframes[i].value

E.g. https://playground.babylonjs.com/#7V0Y1I#2574

Hi
That code

    // scene.beginAnimation(box, 0, 2 * frameRate, true);
    let i = 0;
    let intervalId;

    intervalId = setInterval(()=>{
        box.position.x = keyFrames[i].value;
        if (i < keyFrames.length - 1) {
            i++;
        }
        else {
            clearInterval(intervalId);
        }
            
    }, 1000);

Still ONLY ‘sees’ 2 of the 3 KeyFrame steps you’ve set up
as controlled by

  if (i < keyFrames.length - 1) {

@Quellist

My code is correct. All 3 frames are executed. Let me change the original position of the box to 0. So it doesn’t start at the same position as key frame 0. Then you should see all 3 steps executed.

    intervalId = setInterval(()=>{
        box.position.x = keyFrames[i].value;
        if (i < keyFrames.length - 1) {
            console.log("Doing something at keyFrame " + i);
            i++;
        }
        else {
            clearInterval(intervalId);
        }
            
    }, 1000);

When run console shows
Doing something at keyFrame 0
Doing something at keyFrame 1

So your code is ONLY ‘seeing’ 2 of the 3 KeyFrame steps you’ve set up

@Quellist

Why don’t you log at the place the position update is executed?

:grinning:there’s a thought

Your method is avoiding use of the scene animation functionality
and you have to figure out your own keyFrame stepping interval in order to get a smooth animation
??Won’t this become awkward when the animation required is quite long / traverses a large part of the screen

??Have you used this method to get smooth animation over 100s of keyFrames

Thanks for your patience & time

Well. Animation is doing the same thing behind the scene: updating the position/rotation/scale of the models. Since you defined the keyframes yourself. You can directly apply the changes.

To make sure the keyframes are animated at 60 FPS, instead of using setInterval, you should put it in an observer. It will be too fast to notice for 3 frames.

    let i = 0;
    scene.onBeforeRenderObservable.add(() => {
        if (i < keyFrames.length) {
            box.position.x = keyFrames[i].value;
        }
        i++;
    });