Skip to content

Camera Animation

CameraAnimation animates the camera along a smooth spline path defined by a series of eye-position and look-at-target keyframes. It supports looping, ping-pong, auto-look-forward, and a decaying shake effect for cinematic impact moments.

Quick Start

#include <ivfui/camera_animation.h>

// In onSetup():
auto anim = ivfui::CameraAnimation::create(cameraManipulator());

anim->addKeyframe({0.0f,  5.0f, 15.0f}, {0.0f, 0.0f, 0.0f});
anim->addKeyframe({10.0f, 8.0f,  5.0f}, {0.0f, 1.0f, 0.0f});
anim->addKeyframe({0.0f,  6.0f,-12.0f}, {0.0f, 0.0f, 0.0f});

anim->setDuration(8.0f);
anim->setMode(ivf::SplineAnimMode::Loop);
anim->setAutoLookForward(true);
anim->play();

// In onUpdate():
m_anim->update(ivf::TimeController::instance()->delta());

CameraAnimation uses the TimeController delta so playback respects global pause and time scaling.

Keyframes

Each keyframe is a pair: the camera eye position and a look-at target.

anim->addKeyframe(glm::vec3 pos, glm::vec3 target);
anim->clearKeyframes();  // remove all and reset

The positions follow a CatmullRom spline for smooth, constant-speed travel. Targets follow their own spline unless autoLookForward is enabled.

Tip

Repeat the first keyframe at the end to close a loop without a visible seam.

Playback Modes

Mode Behaviour
SplineAnimMode::Once Play once and stop at the end
SplineAnimMode::Loop Jump back to start when the end is reached
SplineAnimMode::PingPong Reverse direction at each end
anim->setMode(ivf::SplineAnimMode::Loop);

Auto-Look-Forward

When enabled, the camera automatically looks along the tangent of the position spline. The target keyframes are ignored. This gives a natural flying-through-the-scene feel.

anim->setAutoLookForward(true);   // look where you're going
anim->setAutoLookForward(false);  // use explicit target spline

Playback Control

anim->play();             // start or resume
anim->stop();             // stop (keeps current position)
anim->rewind();           // reset elapsed to start

bool playing = anim->isPlaying();
float p      = anim->progress();  // 0.0 = start, 1.0 = end

Block manipulator input (orbit, pan) while the animation plays to avoid conflicts:

anim->setBlockManipulatorDuringPlayback(true);

Camera Shake

shake() applies a brief, exponentially-decaying random jitter to the camera position — useful for explosions, impacts, or dramatic moments.

anim->shake(0.4f, 0.5f);  // 0.4 units intensity, 0.5 seconds duration

Shake works independently of playback: you can shake a stopped camera.

Keyboard Toggle Example

void onKey(int key, int, int action, int) override
{
    if (action != GLFW_PRESS) return;
    if (key == GLFW_KEY_P) {
        if (m_anim->isPlaying()) m_anim->stop();
        else                     m_anim->play();
    } else if (key == GLFW_KEY_S) {
        m_anim->shake(0.4f, 0.5f);
    } else if (key == GLFW_KEY_L) {
        m_looping = !m_looping;
        m_anim->setMode(m_looping ? ivf::SplineAnimMode::Loop : ivf::SplineAnimMode::Once);
    }
}

Orbit Fly-Through Recipe

A wide orbit around a scene centre with altitude variation. Eight keyframes close the loop seamlessly.

auto anim = ivfui::CameraAnimation::create(cameraManipulator());
anim->setMode(ivf::SplineAnimMode::Loop);
anim->setDuration(12.0f);
anim->setAutoLookForward(true);
anim->setBlockManipulatorDuringPlayback(true);

// Eye positions — orbit at varying radius and height
anim->addKeyframe({ 18.0f,  8.0f,  0.0f}, {0, 1, 0});
anim->addKeyframe({  8.0f, 12.0f, 14.0f}, {0, 1, 0});
anim->addKeyframe({ -5.0f,  5.0f, 18.0f}, {0, 1, 0});
anim->addKeyframe({-18.0f,  9.0f,  3.0f}, {0, 1, 0});
anim->addKeyframe({-10.0f,  6.0f,-14.0f}, {0, 1, 0});
anim->addKeyframe({  3.0f, 14.0f,-16.0f}, {0, 1, 0});
anim->addKeyframe({ 14.0f,  7.0f, -8.0f}, {0, 1, 0});
anim->addKeyframe({ 18.0f,  8.0f,  0.0f}, {0, 1, 0});  // close the loop
anim->play();

See the full runnable example at Camera Animation Examples.