00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "domUtils.h"
00024 #include "qglviewer.h"
00025
00026 using namespace qglviewer;
00027 using namespace std;
00028
00029 #if QT_VERSION < 0x040000
00030
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
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
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
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
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
00303 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00304
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
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
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
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
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
00570
00571
00572
00573 if (!currentFrameValid_)
00574
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
00650
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
00691
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
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
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