keyFrameInterpolator.cpp
Go to the documentation of this file.
00001 /****************************************************************************
00002 
00003  Copyright (C) 2002-2013 Gilles Debunne. All rights reserved.
00004 
00005  This file is part of the QGLViewer library version 2.4.0.
00006 
00007  http://www.libqglviewer.com - contact@libqglviewer.com
00008 
00009  This file may be used under the terms of the GNU General Public License 
00010  versions 2.0 or 3.0 as published by the Free Software Foundation and
00011  appearing in the LICENSE file included in the packaging of this file.
00012  In addition, as a special exception, Gilles Debunne gives you certain 
00013  additional rights, described in the file GPL_EXCEPTION in this package.
00014 
00015  libQGLViewer uses dual licensing. Commercial/proprietary software must
00016  purchase a libQGLViewer Commercial License.
00017 
00018  This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00019  WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00020 
00021 *****************************************************************************/
00022 
00023 #include "domUtils.h"
00024 #include "qglviewer.h" // for QGLViewer::drawAxis and Camera::drawCamera
00025 
00026 using namespace qglviewer;
00027 using namespace std;
00028 
00029 #if QT_VERSION < 0x040000
00030 // Patch for QPtrList / QList syntax difference
00031 # define peekNext current
00032 #endif
00033 
00040 KeyFrameInterpolator::KeyFrameInterpolator(Frame* frame)
00041   : frame_(NULL), period_(40), interpolationTime_(0.0), interpolationSpeed_(1.0), interpolationStarted_(false),
00042     closedPath_(false), loopInterpolation_(false), pathIsValid_(false), valuesAreValid_(true), currentFrameValid_(false)
00043   // #CONNECTION# Values cut pasted initFromDOMElement()
00044 {
00045   setFrame(frame);
00046 #if QT_VERSION < 0x040000
00047   keyFrame_.setAutoDelete(true);
00048 #endif
00049   for (int i=0; i<4; ++i)
00050 #if QT_VERSION >= 0x040000
00051     currentFrame_[i] = new QMutableListIterator<KeyFrame*>(keyFrame_);
00052 #else
00053     currentFrame_[i] = new QPtrListIterator<KeyFrame>(keyFrame_);
00054 #endif
00055   connect(&timer_, SIGNAL(timeout()), SLOT(update()));
00056 }
00057 
00059 KeyFrameInterpolator::~KeyFrameInterpolator()
00060 {
00061   deletePath();
00062   for (int i=0; i<4; ++i)
00063     delete currentFrame_[i];
00064 }
00065 
00067 void KeyFrameInterpolator::setFrame(Frame* const frame)
00068 {
00069   if (this->frame())
00070     disconnect(this, SIGNAL( interpolated() ), this->frame(), SIGNAL( interpolated() ));
00071 
00072   frame_ = frame;
00073 
00074   if (this->frame())
00075     connect(this, SIGNAL( interpolated() ), this->frame(), SIGNAL( interpolated() ));
00076 }
00077 
00084 void KeyFrameInterpolator::update()
00085 {
00086   interpolateAtTime(interpolationTime());
00087 
00088   interpolationTime_ += interpolationSpeed() * interpolationPeriod() / 1000.0;
00089 
00090   if (interpolationTime() > keyFrame_.last()->time())
00091     {
00092       if (loopInterpolation())
00093         setInterpolationTime(keyFrame_.first()->time() + interpolationTime_ - keyFrame_.last()->time());
00094       else
00095         {
00096           // Make sure last KeyFrame is reached and displayed
00097           interpolateAtTime(keyFrame_.last()->time());
00098           stopInterpolation();
00099         }
00100       Q_EMIT endReached();
00101     }
00102   else
00103     if (interpolationTime() < keyFrame_.first()->time())
00104       {
00105         if (loopInterpolation())
00106           setInterpolationTime(keyFrame_.last()->time() - keyFrame_.first()->time() + interpolationTime_);
00107         else
00108           {
00109             // Make sure first KeyFrame is reached and displayed
00110             interpolateAtTime(keyFrame_.first()->time());
00111             stopInterpolation();
00112           }
00113         Q_EMIT endReached();
00114       }
00115 }
00116 
00117 
00138 void KeyFrameInterpolator::startInterpolation(int period)
00139 {
00140   if (period >= 0)
00141     setInterpolationPeriod(period);
00142 
00143   if (!keyFrame_.isEmpty())
00144     {
00145       if ((interpolationSpeed() > 0.0) && (interpolationTime() >= keyFrame_.last()->time()))
00146         setInterpolationTime(keyFrame_.first()->time());
00147       if ((interpolationSpeed() < 0.0) && (interpolationTime() <= keyFrame_.first()->time()))
00148         setInterpolationTime(keyFrame_.last()->time());
00149       timer_.start(interpolationPeriod());
00150       interpolationStarted_ = true;
00151       update();
00152     }
00153 }
00154 
00155 
00157 void KeyFrameInterpolator::stopInterpolation()
00158 {
00159   timer_.stop();
00160   interpolationStarted_ = false;
00161 }
00162 
00163 
00168 void KeyFrameInterpolator::resetInterpolation()
00169 {
00170   stopInterpolation();
00171   setInterpolationTime(firstTime());
00172 }
00173 
00186 void KeyFrameInterpolator::addKeyFrame(const Frame* const frame, float time)
00187 {
00188   if (!frame)
00189     return;
00190 
00191   if (keyFrame_.isEmpty())
00192     interpolationTime_ = time;
00193 
00194   if ( (!keyFrame_.isEmpty()) && (keyFrame_.last()->time() > time) )
00195     qWarning("Error in KeyFrameInterpolator::addKeyFrame: time is not monotone");
00196   else
00197     keyFrame_.append(new KeyFrame(frame, time));
00198   connect(frame, SIGNAL(modified()), SLOT(invalidateValues()));
00199   valuesAreValid_ = false;
00200   pathIsValid_ = false;
00201   currentFrameValid_ = false;
00202   resetInterpolation();
00203 }
00204 
00212 void KeyFrameInterpolator::addKeyFrame(const Frame& frame, float time)
00213 {
00214   if (keyFrame_.isEmpty())
00215     interpolationTime_ = time;
00216 
00217   if ( (!keyFrame_.isEmpty()) && (keyFrame_.last()->time() > time) )
00218     qWarning("Error in KeyFrameInterpolator::addKeyFrame: time is not monotone");
00219   else
00220     keyFrame_.append(new KeyFrame(frame, time));
00221 
00222   valuesAreValid_ = false;
00223   pathIsValid_ = false;
00224   currentFrameValid_ = false;
00225   resetInterpolation();
00226 }
00227 
00228 
00233 void KeyFrameInterpolator::addKeyFrame(const Frame* const frame)
00234 {
00235   float time;
00236   if (keyFrame_.isEmpty())
00237     time = 0.0;
00238   else
00239     time = lastTime() + 1.0;
00240 
00241   addKeyFrame(frame, time);
00242 }
00243 
00248 void KeyFrameInterpolator::addKeyFrame(const Frame& frame)
00249 {
00250   float time;
00251   if (keyFrame_.isEmpty())
00252     time = 0.0;
00253   else
00254     time = keyFrame_.last()->time() + 1.0;
00255 
00256   addKeyFrame(frame, time);
00257 }
00258 
00260 void KeyFrameInterpolator::deletePath()
00261 {
00262   stopInterpolation();
00263 #if QT_VERSION >= 0x040000
00264   qDeleteAll(keyFrame_);
00265 #endif
00266   keyFrame_.clear();
00267   pathIsValid_ = false;
00268   valuesAreValid_ = false;
00269   currentFrameValid_ = false;
00270 }
00271 
00272 static void drawCamera(float scale)
00273 {
00274   glDisable(GL_LIGHTING);
00275 
00276   const float halfHeight = scale * 0.07;
00277   const float halfWidth  = halfHeight * 1.3;
00278   const float dist = halfHeight / tan(M_PI/8.0);
00279 
00280   const float arrowHeight    = 1.5f * halfHeight;
00281   const float baseHeight     = 1.2f * halfHeight;
00282   const float arrowHalfWidth = 0.5f * halfWidth;
00283   const float baseHalfWidth  = 0.3f * halfWidth;
00284 
00285   // Frustum outline
00286   glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
00287   glBegin(GL_LINE_STRIP);
00288   glVertex3f(-halfWidth, halfHeight,-dist);
00289   glVertex3f(-halfWidth,-halfHeight,-dist);
00290   glVertex3f( 0.0f, 0.0f, 0.0f);
00291   glVertex3f( halfWidth,-halfHeight,-dist);
00292   glVertex3f(-halfWidth,-halfHeight,-dist);
00293   glEnd();
00294   glBegin(GL_LINE_STRIP);
00295   glVertex3f( halfWidth,-halfHeight,-dist);
00296   glVertex3f( halfWidth, halfHeight,-dist);
00297   glVertex3f( 0.0f, 0.0f, 0.0f);
00298   glVertex3f(-halfWidth, halfHeight,-dist);
00299   glVertex3f( halfWidth, halfHeight,-dist);
00300   glEnd();
00301 
00302   // Up arrow
00303   glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00304   // Base
00305   glBegin(GL_QUADS);
00306   glVertex3f(-baseHalfWidth, halfHeight,-dist);
00307   glVertex3f( baseHalfWidth, halfHeight,-dist);
00308   glVertex3f( baseHalfWidth, baseHeight,-dist);
00309   glVertex3f(-baseHalfWidth, baseHeight,-dist);
00310   glEnd();
00311 
00312   // Arrow
00313   glBegin(GL_TRIANGLES);
00314   glVertex3f( 0.0f,           arrowHeight,-dist);
00315   glVertex3f(-arrowHalfWidth, baseHeight, -dist);
00316   glVertex3f( arrowHalfWidth, baseHeight, -dist);
00317   glEnd();
00318 }
00319 
00351 void KeyFrameInterpolator::drawPath(int mask, int nbFrames, float scale)
00352 {
00353   const int nbSteps = 30;
00354   if (!pathIsValid_)
00355     {
00356       path_.clear();
00357 #if QT_VERSION < 0x040000
00358       path_.reserve(nbSteps*keyFrame_.count());
00359 #endif
00360 
00361       if (keyFrame_.isEmpty())
00362         return;
00363 
00364       if (!valuesAreValid_)
00365         updateModifiedFrameValues();
00366 
00367       if (keyFrame_.first() == keyFrame_.last())
00368         path_.push_back(Frame(keyFrame_.first()->position(), keyFrame_.first()->orientation()));
00369       else
00370         {
00371           static Frame fr;
00372           KeyFrame* kf_[4];
00373           kf_[0] = keyFrame_.first();
00374           kf_[1] = kf_[0];
00375 #if QT_VERSION >= 0x040000
00376           int index = 1;
00377           kf_[2] = (index < keyFrame_.size()) ? keyFrame_.at(index) : NULL;
00378           index++;
00379           kf_[3] = (index < keyFrame_.size()) ? keyFrame_.at(index) : NULL;
00380 #else
00381           kf_[2] = keyFrame_.next();
00382           kf_[3] = keyFrame_.next();
00383 #endif
00384 
00385           while (kf_[2])
00386             {
00387               Vec diff = kf_[2]->position() - kf_[1]->position();
00388               Vec v1 = 3.0 * diff - 2.0 * kf_[1]->tgP() - kf_[2]->tgP();
00389               Vec v2 = -2.0 * diff + kf_[1]->tgP() + kf_[2]->tgP();
00390 
00391               // cout << kf_[0]->time() << " , " << kf_[1]->time() << " , " << kf_[2]->time() << " , " << kf_[3]->time() << endl;
00392               for (int step=0; step<nbSteps; ++step)
00393                 {
00394                   float alpha = step / static_cast<float>(nbSteps);
00395                   fr.setPosition(kf_[1]->position() + alpha * (kf_[1]->tgP() + alpha * (v1+alpha*v2)));
00396                   fr.setOrientation(Quaternion::squad(kf_[1]->orientation(), kf_[1]->tgQ(), kf_[2]->tgQ(), kf_[2]->orientation(), alpha));
00397                   path_.push_back(fr);
00398                 }
00399 
00400               // Shift
00401               kf_[0] = kf_[1];
00402               kf_[1] = kf_[2];
00403               kf_[2] = kf_[3];
00404 #if QT_VERSION >= 0x040000
00405               index++;
00406               kf_[3] = (index < keyFrame_.size()) ? keyFrame_.at(index) : NULL;
00407 #else
00408               kf_[3] = keyFrame_.next();
00409 #endif
00410             }
00411           // Add last KeyFrame
00412           path_.push_back(Frame(kf_[1]->position(), kf_[1]->orientation()));
00413         }
00414       pathIsValid_ = true;
00415     }
00416 
00417   if (mask)
00418     {
00419       glDisable(GL_LIGHTING);
00420       glLineWidth(2);
00421 
00422       if (mask & 1)
00423         {
00424           glBegin(GL_LINE_STRIP);
00425 #if QT_VERSION >= 0x040000
00426           Q_FOREACH (Frame fr, path_)
00427             glVertex3fv(fr.position());
00428 #else
00429 # if QT_VERSION < 0x030000
00430           for (int i=0; i < path_.size(); ++i)
00431             glVertex3fv((path_.at(i)).position());
00432 # else
00433           for (QValueVector<Frame>::const_iterator pnt=path_.begin(), end=path_.end(); pnt!=end; ++pnt)
00434             glVertex3fv((*pnt).position());
00435 # endif
00436 #endif
00437           glEnd();
00438         }
00439       if (mask & 6)
00440         {
00441           int count = 0;
00442           if (nbFrames > nbSteps)
00443             nbFrames = nbSteps;
00444           float goal = 0.0f;
00445 #if QT_VERSION >= 0x040000
00446           Q_FOREACH (Frame fr, path_)
00447 #else
00448 # if QT_VERSION < 0x030000
00449           for (int i=0; i < path_.size(); ++i)
00450 # else
00451           for (QValueVector<Frame>::const_iterator pnt=path_.begin(), end=path_.end(); pnt!=end; ++pnt)
00452 # endif
00453 #endif
00454               if ((count++) >= goal)
00455                 {
00456                   goal += nbSteps / static_cast<float>(nbFrames);
00457                   glPushMatrix();
00458 #if QT_VERSION >= 0x040000
00459                   glMultMatrixd(fr.matrix());
00460 #else
00461 # if QT_VERSION < 0x030000
00462                   glMultMatrixd((path_.at(i)).matrix());
00463 # else
00464                   glMultMatrixd((*pnt).matrix());
00465 # endif
00466 #endif
00467                   if (mask & 2) drawCamera(scale);
00468                   if (mask & 4) QGLViewer::drawAxis(scale/10.0);
00469                   glPopMatrix();
00470                 }
00471         }
00472     }
00473 }
00474 
00475 void KeyFrameInterpolator::updateModifiedFrameValues()
00476 {
00477   Quaternion prevQ = keyFrame_.first()->orientation();
00478   KeyFrame* kf;
00479 #if QT_VERSION >= 0x040000
00480   for (int i=0; i<keyFrame_.size(); ++i)
00481     {
00482       kf = keyFrame_.at(i);
00483 #else
00484   for (kf = keyFrame_.first(); kf; kf=keyFrame_.next())
00485     {
00486 #endif
00487       if (kf->frame())
00488         kf->updateValuesFromPointer();
00489       kf->flipOrientationIfNeeded(prevQ);
00490       prevQ = kf->orientation();
00491     }
00492 
00493   KeyFrame* prev = keyFrame_.first();
00494   kf = keyFrame_.first();
00495 #if QT_VERSION >= 0x040000
00496   int index = 1;
00497 #endif
00498   while (kf)
00499     {
00500 #if QT_VERSION >= 0x040000
00501       KeyFrame* next = (index < keyFrame_.size()) ? keyFrame_.at(index) : NULL;
00502       index++;
00503 #else
00504       KeyFrame* next = keyFrame_.next();
00505 #endif
00506       if (next)
00507         kf->computeTangent(prev, next);
00508       else
00509         kf->computeTangent(prev, kf);
00510       prev = kf;
00511       kf = next;
00512     }
00513   valuesAreValid_ = true;
00514 }
00515 
00522 Frame KeyFrameInterpolator::keyFrame(int index) const
00523 {
00524   const KeyFrame* const kf = keyFrame_.at(index);
00525   return Frame(kf->position(), kf->orientation());
00526 }
00527 
00531 float KeyFrameInterpolator::keyFrameTime(int index) const
00532 {
00533   return keyFrame_.at(index)->time();
00534 }
00535 
00540 float KeyFrameInterpolator::duration() const
00541 {
00542   return lastTime() - firstTime();
00543 }
00544 
00548 float KeyFrameInterpolator::firstTime() const
00549 {
00550   if (keyFrame_.isEmpty())
00551     return 0.0;
00552   else
00553     return keyFrame_.first()->time();
00554 }
00555 
00559 float KeyFrameInterpolator::lastTime() const
00560 {
00561   if (keyFrame_.isEmpty())
00562     return 0.0;
00563   else
00564     return keyFrame_.last()->time();
00565 }
00566 
00567 void KeyFrameInterpolator::updateCurrentKeyFrameForTime(float time)
00568 {
00569   // Assertion: times are sorted in monotone order.
00570   // Assertion: keyFrame_ is not empty
00571 
00572   // TODO: Special case for loops when closed path is implemented !!
00573   if (!currentFrameValid_)
00574     // Recompute everything from scrach
00575 #if QT_VERSION >= 0x040000
00576     currentFrame_[1]->toFront();
00577 #else
00578     currentFrame_[1]->toFirst();
00579 #endif
00580 
00581   while (currentFrame_[1]->peekNext()->time() > time)
00582     {
00583       currentFrameValid_ = false;
00584 #if QT_VERSION >= 0x040000
00585       if (!currentFrame_[1]->hasPrevious())
00586 #else
00587       if (currentFrame_[1]->atFirst())
00588 #endif
00589         break;
00590 #if QT_VERSION >= 0x040000
00591       currentFrame_[1]->previous();
00592 #else
00593       --(*currentFrame_[1]);
00594 #endif
00595     }
00596 
00597   if (!currentFrameValid_)
00598     *currentFrame_[2] = *currentFrame_[1];
00599 
00600   while (currentFrame_[2]->peekNext()->time() < time)
00601     {
00602       currentFrameValid_ = false;
00603 #if QT_VERSION >= 0x040000
00604       if (!currentFrame_[2]->hasNext())
00605 #else
00606       if (currentFrame_[2]->atLast())
00607 #endif
00608         break;
00609 #if QT_VERSION >= 0x040000
00610       currentFrame_[2]->next();
00611 #else
00612       ++(*currentFrame_[2]);
00613 #endif
00614     }
00615 
00616   if (!currentFrameValid_)
00617     {
00618       *currentFrame_[1] = *currentFrame_[2];
00619 #if QT_VERSION >= 0x040000
00620       if ((currentFrame_[1]->hasPrevious()) && (time < currentFrame_[2]->peekNext()->time()))
00621         currentFrame_[1]->previous();
00622 #else
00623       if ((!currentFrame_[1]->atFirst()) && (time < currentFrame_[2]->current()->time()))
00624         --(*currentFrame_[1]);
00625 #endif
00626 
00627       *currentFrame_[0] = *currentFrame_[1];
00628 #if QT_VERSION >= 0x040000
00629       if (currentFrame_[0]->hasPrevious())
00630         currentFrame_[0]->previous();
00631 #else
00632       if (!currentFrame_[0]->atFirst())
00633         --(*currentFrame_[0]);
00634 #endif
00635 
00636       *currentFrame_[3] = *currentFrame_[2];
00637 #if QT_VERSION >= 0x040000
00638       if (currentFrame_[3]->hasNext())
00639         currentFrame_[3]->next();
00640 #else
00641       if (!currentFrame_[3]->atLast())
00642         ++(*currentFrame_[3]);
00643 #endif
00644 
00645       currentFrameValid_ = true;
00646       splineCacheIsValid_ = false;
00647     }
00648 
00649   // cout << "Time = " << time << " : " << currentFrame_[0]->peekNext()->time() << " , " <<
00650   // currentFrame_[1]->peekNext()->time() << " , " << currentFrame_[2]->peekNext()->time() << " , " <<  currentFrame_[3]->peekNext()->time() << endl;
00651 }
00652 
00653 void KeyFrameInterpolator::updateSplineCache()
00654 {
00655   Vec delta = currentFrame_[2]->peekNext()->position() - currentFrame_[1]->peekNext()->position();
00656   v1 = 3.0 * delta - 2.0 * currentFrame_[1]->peekNext()->tgP() - currentFrame_[2]->peekNext()->tgP();
00657   v2 = -2.0 * delta + currentFrame_[1]->peekNext()->tgP() + currentFrame_[2]->peekNext()->tgP();
00658   splineCacheIsValid_ = true;
00659 }
00660 
00668 void KeyFrameInterpolator::interpolateAtTime(float time)
00669 {
00670   setInterpolationTime(time);
00671 
00672   if ((keyFrame_.isEmpty()) || (!frame()))
00673     return;
00674 
00675   if (!valuesAreValid_)
00676     updateModifiedFrameValues();
00677 
00678   updateCurrentKeyFrameForTime(time);
00679 
00680   if (!splineCacheIsValid_)
00681     updateSplineCache();
00682 
00683   float alpha;
00684   float dt = currentFrame_[2]->peekNext()->time() - currentFrame_[1]->peekNext()->time();
00685   if (dt == 0.0)
00686     alpha = 0.0;
00687   else
00688     alpha = (time - currentFrame_[1]->peekNext()->time()) / dt;
00689 
00690   // Linear interpolation - debug
00691   // Vec pos = alpha*(currentFrame_[2]->peekNext()->position()) + (1.0-alpha)*(currentFrame_[1]->peekNext()->position());
00692   Vec pos = currentFrame_[1]->peekNext()->position() + alpha * (currentFrame_[1]->peekNext()->tgP() + alpha * (v1+alpha*v2));
00693   Quaternion q = Quaternion::squad(currentFrame_[1]->peekNext()->orientation(), currentFrame_[1]->peekNext()->tgQ(),
00694                                    currentFrame_[2]->peekNext()->tgQ(), currentFrame_[2]->peekNext()->orientation(), alpha);
00695   frame()->setPositionAndOrientationWithConstraint(pos, q);
00696 
00697   Q_EMIT interpolated();
00698 }
00699 
00715 QDomElement KeyFrameInterpolator::domElement(const QString& name, QDomDocument& document) const
00716 {
00717   QDomElement de = document.createElement(name);
00718   int count = 0;
00719 #if QT_VERSION >= 0x040000
00720   Q_FOREACH (KeyFrame* kf, keyFrame_)
00721 #else
00722   for (KeyFrame* kf = keyFrame_.first(); kf; kf = keyFrame_.next() )
00723 #endif
00724     {
00725       Frame fr(kf->position(), kf->orientation());
00726       QDomElement kfNode = fr.domElement("KeyFrame", document);
00727       kfNode.setAttribute("index", QString::number(count));
00728       kfNode.setAttribute("time",  QString::number(kf->time()));
00729       de.appendChild(kfNode);
00730       ++count;
00731     }
00732   de.setAttribute("nbKF", QString::number(keyFrame_.count()));
00733   de.setAttribute("time", QString::number(interpolationTime()));
00734   de.setAttribute("speed", QString::number(interpolationSpeed()));
00735   de.setAttribute("period", QString::number(interpolationPeriod()));
00736   de.setAttribute("closedPath", (closedPath()?"true":"false"));
00737   de.setAttribute("loop", (loopInterpolation()?"true":"false"));
00738   return de;
00739 }
00740 
00749 void KeyFrameInterpolator::initFromDOMElement(const QDomElement& element)
00750 {
00751 #if QT_VERSION >= 0x040000
00752   qDeleteAll(keyFrame_);
00753 #endif
00754   keyFrame_.clear();
00755   QDomElement child=element.firstChild().toElement();
00756   while (!child.isNull())
00757     {
00758       if (child.tagName() == "KeyFrame")
00759         {
00760           Frame fr;
00761           fr.initFromDOMElement(child);
00762           float time = DomUtils::floatFromDom(child, "time", 0.0);
00763           addKeyFrame(fr, time);
00764         }
00765 
00766       child = child.nextSibling().toElement();
00767     }
00768 
00769   // #CONNECTION# Values cut pasted from constructor
00770   setInterpolationTime(DomUtils::floatFromDom(element, "time", 0.0));
00771   setInterpolationSpeed(DomUtils::floatFromDom(element, "speed", 1.0));
00772   setInterpolationPeriod(DomUtils::intFromDom(element, "period", 40));
00773   setClosedPath(DomUtils::boolFromDom(element, "closedPath", false));
00774   setLoopInterpolation(DomUtils::boolFromDom(element, "loop", false));
00775 
00776   // setFrame(NULL);
00777   pathIsValid_ = false;
00778   valuesAreValid_ = false;
00779   currentFrameValid_ = false;
00780 
00781   stopInterpolation();
00782 }
00783 
00784 #ifndef DOXYGEN
00785 
00787 KeyFrameInterpolator::KeyFrame::KeyFrame(const Frame& fr, float t)
00788   : time_(t), frame_(NULL)
00789 {
00790   p_ = fr.position();
00791   q_ = fr.orientation();
00792 }
00793 
00794 KeyFrameInterpolator::KeyFrame::KeyFrame(const Frame* fr, float t)
00795   : time_(t), frame_(fr)
00796 {
00797   updateValuesFromPointer();
00798 }
00799 
00800 void KeyFrameInterpolator::KeyFrame::updateValuesFromPointer()
00801 {
00802   p_ = frame()->position();
00803   q_ = frame()->orientation();
00804 }
00805 
00806 void KeyFrameInterpolator::KeyFrame::computeTangent(const KeyFrame* const prev, const KeyFrame* const next)
00807 {
00808   tgP_ = 0.5 * (next->position() - prev->position());
00809   tgQ_ = Quaternion::squadTangent(prev->orientation(), q_, next->orientation());
00810 }
00811 
00812 void KeyFrameInterpolator::KeyFrame::flipOrientationIfNeeded(const Quaternion& prev)
00813 {
00814   if (Quaternion::dot(prev, q_) < 0.0)
00815     q_.negate();
00816 }
00817 
00818 #endif //DOXYGEN


octovis
Author(s): Kai M. Wurm , Armin Hornung
autogenerated on Thu Jun 6 2019 17:31:58