A keyFrame Catmull-Rom Frame interpolator.
A KeyFrameInterpolator holds keyFrames (that define a path) and a pointer to a Frame of your application (which will be interpolated). When the user startInterpolation(), the KeyFrameInterpolator regularly updates the frame() position and orientation along the path.
Here is a typical utilization example (see also the keyFrames example):
kfi->addKeyFrame( Frame( Vec(1,0,0), Quaternion() ) );
kfi->addKeyFrame( new Frame( Vec(2,1,0), Quaternion() ) );
glMultMatrixd( kfi->frame()->matrix() );
The keyFrames are defined by a Frame and a time, expressed in seconds. The Frame can be provided as a const reference or as a pointer to a Frame (see the addKeyFrame() methods). In the latter case, the path will automatically be updated when the Frame is modified (using the Frame::modified() signal).
The time has to be monotonously increasing over keyFrames. When interpolationSpeed() equals 1.0 (default value), these times correspond to actual user's seconds during interpolation (provided that your main loop is fast enough). The interpolation is then real-time: the keyFrames will be reached at their keyFrameTime().
When the user startInterpolation(), a timer is started which will update the frame()'s position and orientation every interpolationPeriod() milliseconds. This update increases the interpolationTime() by interpolationPeriod() * interpolationSpeed() milliseconds.
Note that this mechanism ensures that the number of interpolation steps is constant and equal to the total path duration() divided by the interpolationPeriod() * interpolationSpeed(). This is especially useful for benchmarking or movie creation (constant number of snapshots).
During the interpolation, the KeyFrameInterpolator emits an interpolated() signal, which will usually be connected to the QGLViewer::update() slot. The interpolation is stopped when interpolationTime() is greater than the lastTime() (unless loopInterpolation() is
true) and the endReached() signal is then emitted.
Note that a Camera has Camera::keyFrameInterpolator(), that can be used to drive the Camera along a path, or to restore a saved position (a path made of a single keyFrame). Press Alt+Fx to define a new keyFrame for path x. Pressing Fx plays/pauses path interpolation. See QGLViewer::pathKey() and the keyboard page for details.
- If a Constraint is attached to the frame() (see Frame::constraint()), it should be deactivated before interpolationIsStarted(), otherwise the interpolated motion (computed as if there was no constraint) will probably be erroneous.
Retrieving interpolated values
This code defines a KeyFrameInterpolator, and displays the positions that will be followed by the frame() along the path:
const qreal deltaTime = 0.04;
for (qreal time=kfi.firstTime(); time<=kfi.lastTime(); time += deltaTime)
cout << "t=" << time << "\tpos=" << kfi.frame()->position() << endl;
You may want to temporally disconnect the
kfi interpolated() signal from the QGLViewer::update() slot before calling this code.
Draws the path used to interpolate the frame().
mask controls what is drawn: if (mask & 1) (default), the position path is drawn. If (mask & 2), a camera representation is regularly drawn and if (mask & 4), an oriented axis is regularly drawn. Examples:
In the case where camera or axis is drawn,
nbFrames controls the number of objects (axis or camera) drawn between two successive keyFrames. When
nbFrames=1, only the path KeyFrames are drawn.
nbFrames=2 also draws the intermediate orientation, etc. The maximum value is 30.
nbFrames should divide 30 so that an object is drawn for each KeyFrame. Default value is 6.
scale (default=1.0) controls the scaling of the camera and axis drawing. A value of QGLViewer::sceneRadius() should give good results.
See the keyFrames example for an illustration.
The color of the path is the current
- The OpenGL state is modified by this method: GL_LIGHTING is disabled and line width set to 2. Use this code to preserve your current OpenGL state:
drawPathModifyGLState(mask, nbFrames, scale);