Home Download Gallery Documentation Developer

# The keyFrames example

The `KeyFrameInterpolator` test example.

KeyFrameInterpolator smoothly interpolate their attached Frame over time on a path defined by Frames. The interpolation can be started/stopped/reset, played in loop, played at a different speed, etc...

In this examples, the path is defined by four ManipulatedFrame which all can be moved with the mouse. The interpolating path is updated accordingly.

The path and the interpolating axis are drawn using KeyFrameInterpolator::drawPath().

By default, the Camera holds 12 KeyFrameInterpolator, binded to the F1-12 keys. Use Alt-Fx to define a new keyFrame for path x, and simply press Fx to play/pause the path x. See the keyboard page for details.

## keyFrames.h

    #include <QGLViewer/qglviewer.h>

    class Viewer : public QGLViewer {
    public:
      Viewer();

    protected:
      virtual void draw();
      virtual void keyPressEvent(QKeyEvent *e);
      virtual QString helpString() const;

    private:
      qglviewer::ManipulatedFrame **keyFrame_;
      qglviewer::KeyFrameInterpolator kfi_;
      const int nbKeyFrames;
      int currentKF_;
    };

## keyFrames.cpp

    #include "keyFrames.h"

    #include <QGLViewer/manipulatedFrame.h>
    #include <QKeyEvent>

    using namespace qglviewer;
    using namespace std;

    Viewer::Viewer() : nbKeyFrames(4) {
      restoreStateFromFile();

      // myFrame is the Frame that will be interpolated.
      Frame *myFrame = new Frame();

      // Set myFrame as the KeyFrameInterpolator interpolated Frame.
      kfi_.setFrame(myFrame);
      kfi_.setLoopInterpolation();

      // An array of manipulated (key) frames.
      keyFrame_ = new ManipulatedFrame *[nbKeyFrames];

      // Create an initial path
      for (int i = 0; i < nbKeyFrames; i++) {
        keyFrame_[i] = new ManipulatedFrame();
        keyFrame_[i]->setPosition(-1.0 + 2.0 * i / (nbKeyFrames - 1), 0.0, 0.0);
        kfi_.addKeyFrame(keyFrame_[i]);
      }

      currentKF_ = 0;
      setManipulatedFrame(keyFrame_[currentKF_]);

      // Enable direct frame manipulation when the mouse hovers.
      setMouseTracking(true);

      setKeyDescription(Qt::Key_Plus, "Increases interpolation speed");
      setKeyDescription(Qt::Key_Minus, "Decreases interpolation speed");
      setKeyDescription(Qt::Key_Left, "Selects previous key frame");
      setKeyDescription(Qt::Key_Right, "Selects next key frame");
      setKeyDescription(Qt::Key_Return, "Starts/stops interpolation");

      help();

      connect(&kfi_, SIGNAL(interpolated()), SLOT(update()));
      kfi_.startInterpolation();
    }

    QString Viewer::helpString() const {
      QString text("<h2>K e y F r a m e s</h2>");
      text += "A <i>KeyFrameInterpolator</i> holds an interpolated path defined by "
              "key frames. ";
      text += "It can then smoothly make its associed frame follow that path. Key "
              "frames can interactively be manipulated, even ";
      text += "during interpolation.<br><br>";
      text += "Note that the camera holds 12 such keyFrameInterpolators, binded to "
              "F1-F12. Press <b>Alt+Fx</b> to define new key ";
      text += "frames, and then press <b>Fx</b> to make the camera follow the "
              "path. Press <b>C</b> to visualize these paths.<br><br>";
      text += "<b>+/-</b> changes the interpolation speed. Negative values are "
              "allowed.<br><br>";
      text += "<b>Return</b> starts-stops the interpolation.<br><br>";
      text += "Use the left and right arrows to change the manipulated KeyFrame. ";
      text += "Press <b>Control</b> to move it or simply hover over it.";
      return text;
    }

    void Viewer::keyPressEvent(QKeyEvent *e) {
      switch (e->key()) {
      case Qt::Key_Left:
        currentKF_ = (currentKF_ + nbKeyFrames - 1) % nbKeyFrames;
        setManipulatedFrame(keyFrame_[currentKF_]);
        update();
        break;
      case Qt::Key_Right:
        currentKF_ = (currentKF_ + 1) % nbKeyFrames;
        setManipulatedFrame(keyFrame_[currentKF_]);
        update();
        break;
      case Qt::Key_Return:
        kfi_.toggleInterpolation();
        break;
      case Qt::Key_Plus:
        kfi_.setInterpolationSpeed(kfi_.interpolationSpeed() + 0.25);
        break;
      case Qt::Key_Minus:
        kfi_.setInterpolationSpeed(kfi_.interpolationSpeed() - 0.25);
        break;
      // case Qt::Key_C :
      // kfi_.setClosedPath(!kfi_.closedPath());
      // break;
      default:
        QGLViewer::keyPressEvent(e);
      }
    }

    void Viewer::draw() {
      // Draw interpolated frame
      glPushMatrix();
      glMultMatrixd(kfi_.frame()->matrix());
      drawAxis(0.3f);
      glPopMatrix();

      kfi_.drawPath(5, 10);

      for (int i = 0; i < nbKeyFrames; ++i) {
        glPushMatrix();
        glMultMatrixd(kfi_.keyFrame(i).matrix());

        if ((i == currentKF_) || (keyFrame_[i]->grabsMouse()))
          drawAxis(0.4f);
        else
          drawAxis(0.2f);

        glPopMatrix();
      }
    }

## main.cpp

    #include "keyFrames.h"
    #include <qapplication.h>

    int main(int argc, char **argv) {
      QApplication application(argc, argv);

      Viewer viewer;

      viewer.setWindowTitle("keyFrames");

      viewer.show();

      return application.exec();
    }

Back to the examples main page.