/// compute interpolation parameters from keyframes and an iterator /// to the next keyframe (the first with time > t) static void interParams(const KeyFrameSet &keyFrames, double t, const KeyFrameSet::const_iterator &itup, double *tcur, double *vcur, double *vcurDerivRight, Natron::KeyframeType *interp, double *tnext, double *vnext, double *vnextDerivLeft, Natron::KeyframeType *interpNext) { assert(itup == keyFrames.end() || t < itup->getTime()); if (itup == keyFrames.begin()) { //if all keys have a greater time // get the first keyframe *tnext = itup->getTime(); *vnext = itup->getValue(); *vnextDerivLeft = itup->getLeftDerivative(); *interpNext = itup->getInterpolation(); *tcur = *tnext - 1.; *vcur = *vnext; *vcurDerivRight = 0.; *interp = Natron::KEYFRAME_NONE; } else if (itup == keyFrames.end()) { //if we found no key that has a greater time // get the last keyframe KeyFrameSet::const_reverse_iterator itlast = keyFrames.rbegin(); *tcur = itlast->getTime(); *vcur = itlast->getValue(); *vcurDerivRight = itlast->getRightDerivative(); *interp = itlast->getInterpolation(); *tnext = *tcur + 1.; *vnext = *vcur; *vnextDerivLeft = 0.; *interpNext = Natron::KEYFRAME_NONE; } else { // between two keyframes // get the last keyframe with time <= t KeyFrameSet::const_iterator itcur = itup; --itcur; assert(itcur->getTime() <= t); *tcur = itcur->getTime(); *vcur = itcur->getValue(); *vcurDerivRight = itcur->getRightDerivative(); *interp = itcur->getInterpolation(); *tnext = itup->getTime(); *vnext = itup->getValue(); *vnextDerivLeft = itup->getLeftDerivative(); *interpNext = itup->getInterpolation(); } }
KeyFrameSet::iterator Curve::refreshDerivatives(Curve::CurveChangedReason reason, KeyFrameSet::iterator key) { // PRIVATE - should not lock double tcur = key->getTime(); double vcur = key->getValue(); double tprev, vprev, tnext, vnext, vprevDerivRight, vnextDerivLeft; Natron::KeyframeType prevType, nextType; if (key == _imp->keyFrames.begin()) { tprev = tcur; vprev = vcur; vprevDerivRight = 0.; prevType = Natron::KEYFRAME_NONE; } else { KeyFrameSet::const_iterator prev = key; --prev; tprev = prev->getTime(); vprev = prev->getValue(); vprevDerivRight = prev->getRightDerivative(); prevType = prev->getInterpolation(); //if prev is the first keyframe, and not edited by the user then interpolate linearly if (prev == _imp->keyFrames.begin() && prevType != Natron::KEYFRAME_FREE && prevType != Natron::KEYFRAME_BROKEN) { prevType = Natron::KEYFRAME_LINEAR; } } KeyFrameSet::const_iterator next = key; ++next; if (next == _imp->keyFrames.end()) { tnext = tcur; vnext = vcur; vnextDerivLeft = 0.; nextType = Natron::KEYFRAME_NONE; } else { tnext = next->getTime(); vnext = next->getValue(); vnextDerivLeft = next->getLeftDerivative(); nextType = next->getInterpolation(); KeyFrameSet::const_iterator nextnext = next; ++nextnext; //if next is thelast keyframe, and not edited by the user then interpolate linearly if (nextnext == _imp->keyFrames.end() && nextType != Natron::KEYFRAME_FREE && nextType != Natron::KEYFRAME_BROKEN) { nextType = Natron::KEYFRAME_LINEAR; } } double vcurDerivLeft,vcurDerivRight; assert(key->getInterpolation() != Natron::KEYFRAME_NONE && key->getInterpolation() != Natron::KEYFRAME_BROKEN && key->getInterpolation() != Natron::KEYFRAME_FREE); Natron::autoComputeDerivatives(prevType, key->getInterpolation(), nextType, tprev, vprev, tcur, vcur, tnext, vnext, vprevDerivRight, vnextDerivLeft, &vcurDerivLeft, &vcurDerivRight); KeyFrame newKey(*key); newKey.setLeftDerivative(vcurDerivLeft); newKey.setRightDerivative(vcurDerivRight); std::pair<KeyFrameSet::iterator,bool> newKeyIt = _imp->keyFrames.insert(newKey); // keyframe at this time exists, erase and insert again if (!newKeyIt.second) { _imp->keyFrames.erase(newKeyIt.first); newKeyIt = _imp->keyFrames.insert(newKey); assert(newKeyIt.second); } key = newKeyIt.first; if (reason != DERIVATIVES_CHANGED) { key = evaluateCurveChanged(DERIVATIVES_CHANGED,key); } return key; }