void readKeys(KFbxAnimCurve* curveX, KFbxAnimCurve* curveY, KFbxAnimCurve* curveZ, const fbxDouble3& defaultValue, std::vector<osgAnimation::TemplateKeyframe<osg::Vec3> >& keyFrameCntr, float scalar = 1.0f) { KFbxAnimCurve* curves[3] = {curveX, curveY, curveZ}; typedef std::set<double> TimeSet; typedef std::map<double, float> TimeFloatMap; TimeSet times; TimeFloatMap curveTimeMap[3]; for (int nCurve = 0; nCurve < 3; ++nCurve) { KFbxAnimCurve* pCurve = curves[nCurve]; int nKeys = pCurve ? pCurve->KeyGetCount() : 0; if (!nKeys) { times.insert(0.0); curveTimeMap[nCurve][0.0] = defaultValue[nCurve] * scalar; } for (int i = 0; i < nKeys; ++i) { KFbxAnimCurveKey key = pCurve->KeyGet(i); double fTime = key.GetTime().GetSecondDouble(); times.insert(fTime); curveTimeMap[nCurve][fTime] = static_cast<float>(key.GetValue()) * scalar; } } for (TimeSet::iterator it = times.begin(); it != times.end(); ++it) { double fTime = *it; osg::Vec3 val; for (int i = 0; i < 3; ++i) { if (curveTimeMap[i].empty()) continue; TimeFloatMap::iterator lb = curveTimeMap[i].lower_bound(fTime); if (lb == curveTimeMap[i].end()) --lb; val[i] = lb->second; } keyFrameCntr.push_back(osgAnimation::Vec3Keyframe(fTime, val)); } }
void mergeKeyframeContainers(osgAnimation::Vec3CubicBezierKeyframeContainer* to, osgAnimation::FloatCubicBezierKeyframeContainer** from, daeReader::InterpolationType interpolationType, const osg::Vec3& defaultValue) { assert(to->empty()); typedef std::set<float> TimeSet; TimeSet times; for (int i = 0; i < 3; ++i) { if (!from[i] || from[i]->empty()) { continue; } for (osgAnimation::FloatCubicBezierKeyframeContainer::const_iterator it = from[i]->begin(), end = from[i]->end(); it != end; ++it) { times.insert(it->getTime()); } } for (TimeSet::const_iterator it = times.begin(), end = times.end(); it != end; ++it) { const float time = *it; osgAnimation::Vec3CubicBezier value(defaultValue); for (int i = 0; i < 3; ++i) { if (!from[i] || from[i]->empty()) { continue; } osgAnimation::FloatCubicBezierKeyframeContainer::iterator next = std::lower_bound(from[i]->begin(), from[i]->end(), time, KeyFrameComparator()); if (next == from[i]->end()) { --next; value.getPosition().ptr()[i] = next->getValue().getPosition(); value.getControlPointIn().ptr()[i] = next->getValue().getControlPointIn(); value.getControlPointOut().ptr()[i] = next->getValue().getControlPointOut(); } else if (next == from[i]->begin() || next->getTime() == time) { value.getPosition().ptr()[i] = next->getValue().getPosition(); value.getControlPointIn().ptr()[i] = next->getValue().getControlPointIn(); value.getControlPointOut().ptr()[i] = next->getValue().getControlPointOut(); } else { osgAnimation::FloatCubicBezierKeyframeContainer::iterator prev = next; --prev; switch (interpolationType) { case daeReader::INTERPOLATION_STEP: value.getPosition().ptr()[i] = prev->getValue().getPosition(); break; case daeReader::INTERPOLATION_LINEAR: { float xp = prev->getTime(), xn = next->getTime(); float yp = prev->getValue().getPosition(), yn = next->getValue().getPosition(); value.getPosition().ptr()[i] = yp + (yn - yp) * (time - xp) / (xn - xp); } break; case daeReader::INTERPOLATION_BEZIER: { float xp = prev->getTime(), xn = next->getTime(); osgAnimation::FloatCubicBezier l(prev->getValue()), n, r(next->getValue()); deCasteljau(l, n, r, (time - xp) / (xn - xp)); value.getPosition().ptr()[i] = n.getPosition(); value.getControlPointIn().ptr()[i] = n.getControlPointIn(); value.getControlPointOut().ptr()[i] = n.getControlPointOut(); osgAnimation::Vec3CubicBezier prevValue = to->back().getValue(); prevValue.getControlPointOut().ptr()[i] = l.getControlPointOut(); to->back().setValue(prevValue); prev->setValue(l); next->setValue(r); from[i]->insert(next, osgAnimation::FloatCubicBezierKeyframe(time, n)); } break; default: OSG_WARN << "Unsupported interpolation type." << std::endl; break; } //todo - different types of interpolation } } to->push_back(osgAnimation::Vec3CubicBezierKeyframe(time, value)); } }
void readKeys(FbxAnimCurve* curveX, FbxAnimCurve* curveY, FbxAnimCurve* curveZ, const FbxDouble3& defaultValue, std::vector<osgAnimation::Vec3CubicBezierKeyframe>& keyFrameCntr, float scalar = 1.0f) { FbxAnimCurve* curves[3] = {curveX, curveY, curveZ}; typedef std::set<double> TimeSet; typedef std::map<double, osgAnimation::FloatCubicBezier> TimeValueMap; TimeSet times; TimeValueMap curveTimeMap[3]; for (int nCurve = 0; nCurve < 3; ++nCurve) { FbxAnimCurve* pCurve = curves[nCurve]; int nKeys = pCurve ? pCurve->KeyGetCount() : 0; if (!nKeys) { times.insert(0.0); curveTimeMap[nCurve][0.0] = osgAnimation::FloatCubicBezier(defaultValue[nCurve] * scalar); } for (int i = 0; i < nKeys; ++i) { double fTime = pCurve->KeyGetTime(i).GetSecondDouble(); float val = pCurve->KeyGetValue(i); times.insert(fTime); FbxAnimCurveTangentInfo leftTangent = pCurve->KeyGetLeftDerivativeInfo(i); FbxAnimCurveTangentInfo rightTangent = pCurve->KeyGetRightDerivativeInfo(i); if (i > 0) { leftTangent.mDerivative *= fTime - pCurve->KeyGetTime(i - 1).GetSecondDouble(); } if (i + 1 < pCurve->KeyGetCount()) { rightTangent.mDerivative *= pCurve->KeyGetTime(i + 1).GetSecondDouble() - fTime; } osgAnimation::FloatCubicBezier key( val * scalar, (val - leftTangent.mDerivative / 3.0) * scalar, (val + rightTangent.mDerivative / 3.0) * scalar); curveTimeMap[nCurve][fTime] = key; } } for (TimeSet::iterator it = times.begin(); it != times.end(); ++it) { double fTime = *it; osg::Vec3 val, cpIn, cpOut; for (int i = 0; i < 3; ++i) { if (curveTimeMap[i].empty()) continue; TimeValueMap::iterator lb = curveTimeMap[i].lower_bound(fTime); if (lb == curveTimeMap[i].end()) --lb; val[i] = lb->second.getPosition(); cpIn[i] = lb->second.getControlPointIn(); cpOut[i] = lb->second.getControlPointOut(); } keyFrameCntr.push_back(osgAnimation::Vec3CubicBezierKeyframe(fTime, osgAnimation::Vec3CubicBezier(val, cpIn, cpOut))); } }