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));
    }
}
예제 #2
0
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));
    }
}
예제 #3
0
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)));
    }
}