root/OpenSceneGraph/trunk/src/osgPlugins/fbx/fbxRAnimation.cpp @ 13041

Revision 13041, 17.8 kB (checked in by robert, 2 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
Line 
1#include <osg/MatrixTransform>
2
3#include <osgAnimation/Animation>
4#include <osgAnimation/BasicAnimationManager>
5#include <osgAnimation/Channel>
6#include <osgAnimation/Sampler>
7
8#if defined(_MSC_VER)
9    #pragma warning( disable : 4505 )
10    #pragma warning( default : 4996 )
11#endif
12#include <fbxsdk.h>
13#include <fbxfilesdk/fbxfilesdk_nsuse.h>
14
15#include "fbxReader.h"
16
17osg::Quat makeQuat(const fbxDouble3&, ERotationOrder);
18
19osg::Quat makeQuat(const osg::Vec3& radians, ERotationOrder fbxRotOrder)
20{
21    fbxDouble3 degrees(
22        osg::RadiansToDegrees(radians.x()),
23        osg::RadiansToDegrees(radians.y()),
24        osg::RadiansToDegrees(radians.z()));
25    return makeQuat(degrees, fbxRotOrder);
26}
27
28void readKeys(KFbxAnimCurve* curveX, KFbxAnimCurve* curveY, KFbxAnimCurve* curveZ,
29              const fbxDouble3& defaultValue,
30              std::vector<osgAnimation::TemplateKeyframe<osg::Vec3> >& keyFrameCntr, float scalar = 1.0f)
31{
32    KFbxAnimCurve* curves[3] = {curveX, curveY, curveZ};
33
34    typedef std::set<double> TimeSet;
35    typedef std::map<double, float> TimeFloatMap;
36    TimeSet times;
37    TimeFloatMap curveTimeMap[3];
38
39    for (int nCurve = 0; nCurve < 3; ++nCurve)
40    {
41        KFbxAnimCurve* pCurve = curves[nCurve];
42
43        int nKeys = pCurve ? pCurve->KeyGetCount() : 0;
44
45        if (!nKeys)
46        {
47            times.insert(0.0);
48            curveTimeMap[nCurve][0.0] = defaultValue[nCurve] * scalar;
49        }
50
51        for (int i = 0; i < nKeys; ++i)
52        {
53            KFbxAnimCurveKey key = pCurve->KeyGet(i);
54            double fTime = key.GetTime().GetSecondDouble();
55            times.insert(fTime);
56            curveTimeMap[nCurve][fTime] = static_cast<float>(key.GetValue()) * scalar;
57        }
58    }
59
60    for (TimeSet::iterator it = times.begin(); it != times.end(); ++it)
61    {
62        double fTime = *it;
63        osg::Vec3 val;
64        for (int i = 0; i < 3; ++i)
65        {
66            if (curveTimeMap[i].empty()) continue;
67
68            TimeFloatMap::iterator lb = curveTimeMap[i].lower_bound(fTime);
69            if (lb == curveTimeMap[i].end()) --lb;
70            val[i] = lb->second;
71        }
72        keyFrameCntr.push_back(osgAnimation::Vec3Keyframe(fTime, val));
73    }
74}
75
76void readKeys(KFbxAnimCurve* curveX, KFbxAnimCurve* curveY, KFbxAnimCurve* curveZ,
77              const fbxDouble3& defaultValue,
78              std::vector<osgAnimation::Vec3CubicBezierKeyframe>& keyFrameCntr, float scalar = 1.0f)
79{
80    KFbxAnimCurve* curves[3] = {curveX, curveY, curveZ};
81
82    typedef std::set<double> TimeSet;
83    typedef std::map<double, osgAnimation::FloatCubicBezier> TimeValueMap;
84    TimeSet times;
85    TimeValueMap curveTimeMap[3];
86
87    for (int nCurve = 0; nCurve < 3; ++nCurve)
88    {
89        KFbxAnimCurve* pCurve = curves[nCurve];
90
91        int nKeys = pCurve ? pCurve->KeyGetCount() : 0;
92
93        if (!nKeys)
94        {
95            times.insert(0.0);
96            curveTimeMap[nCurve][0.0] = osgAnimation::FloatCubicBezier(defaultValue[nCurve] * scalar);
97        }
98
99        for (int i = 0; i < nKeys; ++i)
100        {
101            double fTime = pCurve->KeyGetTime(i).GetSecondDouble();
102            float val = pCurve->KeyGetValue(i);
103            times.insert(fTime);
104            KFCurveTangeantInfo leftTangent = pCurve->KeyGetLeftDerivativeInfo(i);
105            KFCurveTangeantInfo rightTangent = pCurve->KeyGetRightDerivativeInfo(i);
106
107            if (i > 0)
108            {
109                leftTangent.mDerivative *= fTime - pCurve->KeyGetTime(i - 1).GetSecondDouble();
110            }
111            if (i + 1 < pCurve->KeyGetCount())
112            {
113                rightTangent.mDerivative *= pCurve->KeyGetTime(i + 1).GetSecondDouble() - fTime;
114            }
115
116            osgAnimation::FloatCubicBezier key(
117                val * scalar,
118                (val - leftTangent.mDerivative / 3.0) * scalar,
119                (val + rightTangent.mDerivative / 3.0) * scalar);
120
121            curveTimeMap[nCurve][fTime] = key;
122        }
123    }
124
125    for (TimeSet::iterator it = times.begin(); it != times.end(); ++it)
126    {
127        double fTime = *it;
128        osg::Vec3 val, cpIn, cpOut;
129        for (int i = 0; i < 3; ++i)
130        {
131            if (curveTimeMap[i].empty()) continue;
132
133            TimeValueMap::iterator lb = curveTimeMap[i].lower_bound(fTime);
134            if (lb == curveTimeMap[i].end()) --lb;
135            val[i] = lb->second.getPosition();
136            cpIn[i] = lb->second.getControlPointIn();
137            cpOut[i] = lb->second.getControlPointOut();
138        }
139
140        keyFrameCntr.push_back(osgAnimation::Vec3CubicBezierKeyframe(fTime,
141            osgAnimation::Vec3CubicBezier(val, cpIn, cpOut)));
142    }
143}
144
145// osgAnimation requires control points to be in a weird order. This function
146// reorders them from the conventional order to osgAnimation order.
147template <typename T>
148void reorderControlPoints(osgAnimation::TemplateKeyframeContainer<osgAnimation::TemplateCubicBezier<T> >& vkfCont)
149{
150    if (vkfCont.size() <= 1)
151    {
152        if (vkfCont.size() == 1)
153        {
154            osgAnimation::TemplateCubicBezier<T> tcb = vkfCont.front().getValue();
155            T inCP = tcb.getControlPointIn();
156            tcb.setControlPointIn(tcb.getControlPointOut());
157            tcb.setControlPointOut(inCP);
158            vkfCont.front().setValue(tcb);
159        }
160        return;
161    }
162
163    osgAnimation::TemplateCubicBezier<T> first = vkfCont.front().getValue();
164
165    for (unsigned i = 0; i < vkfCont.size() - 1; ++i)
166    {
167        osgAnimation::TemplateCubicBezier<T> tcb = vkfCont[i].getValue();
168        tcb.setControlPointIn(tcb.getControlPointOut());
169        tcb.setControlPointOut(vkfCont[i + 1].getValue().getControlPointIn());
170        vkfCont[i].setValue(tcb);
171    }
172
173    osgAnimation::TemplateCubicBezier<T> last = vkfCont.back().getValue();
174    last.setControlPointIn(last.getControlPointOut());
175    last.setControlPointOut(first.getControlPointIn());
176    vkfCont.back().setValue(last);
177}
178
179osgAnimation::Channel* readFbxChannels(KFbxAnimCurve* curveX, KFbxAnimCurve* curveY,
180    KFbxAnimCurve* curveZ,
181    const fbxDouble3& defaultValue,
182    const char* targetName, const char* channelName)
183{
184    if (!(curveX && curveX->KeyGetCount()) &&
185        !(curveY && curveY->KeyGetCount()) &&
186        !(curveZ && curveZ->KeyGetCount()))
187    {
188        return 0;
189    }
190
191    KFbxAnimCurveDef::EInterpolationType interpolationType = KFbxAnimCurveDef::eINTERPOLATION_CONSTANT;
192    if (curveX && curveX->KeyGetCount()) interpolationType = curveX->KeyGetInterpolation(0);
193    else if (curveY && curveY->KeyGetCount()) interpolationType = curveY->KeyGetInterpolation(0);
194    else if (curveZ && curveZ->KeyGetCount()) interpolationType = curveZ->KeyGetInterpolation(0);
195
196    osgAnimation::Channel* pChannel = 0;
197
198    if (interpolationType == KFbxAnimCurveDef::eINTERPOLATION_CUBIC)
199    {
200        osgAnimation::Vec3CubicBezierKeyframeContainer* pKeyFrameCntr = new osgAnimation::Vec3CubicBezierKeyframeContainer;
201        readKeys(curveX, curveY, curveZ, defaultValue, *pKeyFrameCntr);
202        reorderControlPoints(*pKeyFrameCntr);
203
204        osgAnimation::Vec3CubicBezierChannel* pCubicChannel = new osgAnimation::Vec3CubicBezierChannel;
205        pCubicChannel->getOrCreateSampler()->setKeyframeContainer(pKeyFrameCntr);
206        pChannel = pCubicChannel;
207    }
208    else
209    {
210        osgAnimation::Vec3KeyframeContainer* pKeyFrameCntr = new osgAnimation::Vec3KeyframeContainer;
211        readKeys(curveX, curveY, curveZ, defaultValue, *pKeyFrameCntr);
212
213        if (interpolationType == KFbxAnimCurveDef::eINTERPOLATION_CONSTANT)
214        {
215            osgAnimation::Vec3StepChannel* pStepChannel = new osgAnimation::Vec3StepChannel;
216            pStepChannel->getOrCreateSampler()->setKeyframeContainer(pKeyFrameCntr);
217            pChannel = pStepChannel;
218        }
219        else
220        {
221            osgAnimation::Vec3LinearChannel* pLinearChannel = new osgAnimation::Vec3LinearChannel;
222            pLinearChannel->getOrCreateSampler()->setKeyframeContainer(pKeyFrameCntr);
223            pChannel = pLinearChannel;
224        }
225    }
226
227    pChannel->setTargetName(targetName);
228    pChannel->setName(channelName);
229
230    return pChannel;
231}
232
233osgAnimation::Channel* readFbxChannels(
234    KFbxTypedProperty<fbxDouble3>& fbxProp, KFbxAnimLayer* pAnimLayer,
235    const char* targetName, const char* channelName)
236{
237    if (!fbxProp.IsValid()) return 0;
238
239    return readFbxChannels(
240        fbxProp.GetCurve<KFbxAnimCurve>(pAnimLayer, "X"),
241        fbxProp.GetCurve<KFbxAnimCurve>(pAnimLayer, "Y"),
242        fbxProp.GetCurve<KFbxAnimCurve>(pAnimLayer, "Z"),
243        fbxProp.Get(),
244        targetName, channelName);
245}
246
247osgAnimation::Channel* readFbxChannelsQuat(
248    KFbxAnimCurve* curveX, KFbxAnimCurve* curveY, KFbxAnimCurve* curveZ,
249    const fbxDouble3& defaultValue,
250    const char* targetName, ERotationOrder rotOrder)
251{
252    if (!(curveX && curveX->KeyGetCount()) &&
253        !(curveY && curveY->KeyGetCount()) &&
254        !(curveZ && curveZ->KeyGetCount()))
255    {
256        return 0;
257    }
258
259    osgAnimation::QuatSphericalLinearChannel* pChannel = new osgAnimation::QuatSphericalLinearChannel;
260    pChannel->setTargetName(targetName);
261    pChannel->setName("quaternion");
262    typedef std::vector<osgAnimation::TemplateKeyframe<osg::Vec3> > KeyFrameCntr;
263    KeyFrameCntr eulerFrameCntr;
264    readKeys(curveX, curveY, curveZ, defaultValue, eulerFrameCntr, static_cast<float>(osg::PI / 180.0));
265
266    osgAnimation::QuatSphericalLinearSampler::KeyframeContainerType& quatFrameCntr =
267        *pChannel->getOrCreateSampler()->getOrCreateKeyframeContainer();
268    quatFrameCntr.reserve(eulerFrameCntr.size());
269
270    for (KeyFrameCntr::iterator it = eulerFrameCntr.begin(), end = eulerFrameCntr.end();
271        it != end; ++it)
272    {
273        const osg::Vec3& euler = it->getValue();
274        quatFrameCntr.push_back(osgAnimation::QuatKeyframe(
275            it->getTime(), makeQuat(euler, rotOrder)));
276    }
277
278    return pChannel;
279}
280
281osgAnimation::Animation* addChannels(
282    osgAnimation::Channel* pTranslationChannel,
283    osgAnimation::Channel* pRotationChannels[],
284    osgAnimation::Channel* pScaleChannel,
285    osg::ref_ptr<osgAnimation::AnimationManagerBase>& pAnimManager,
286    const char* pTakeName)
287{
288    if (pTranslationChannel ||
289        pRotationChannels[0] ||
290        pRotationChannels[1] ||
291        pRotationChannels[2] ||
292        pScaleChannel)
293    {
294        if (!pAnimManager) pAnimManager = new osgAnimation::BasicAnimationManager;
295
296        osgAnimation::Animation* pAnimation = 0;
297        const osgAnimation::AnimationList& anims = pAnimManager->getAnimationList();
298        for (size_t i = 0; i < anims.size(); ++i)
299        {
300            if (anims[i]->getName() == pTakeName)
301            {
302                pAnimation = anims[i].get();
303            }
304        }
305
306        if (!pAnimation)
307        {
308            pAnimation = new osgAnimation::Animation;
309            pAnimation->setName(pTakeName);
310            pAnimManager->registerAnimation(pAnimation);
311        }
312
313        if (pTranslationChannel) pAnimation->addChannel(pTranslationChannel);
314        if (pRotationChannels[0]) pAnimation->addChannel(pRotationChannels[0]);
315        if (pRotationChannels[1]) pAnimation->addChannel(pRotationChannels[1]);
316        if (pRotationChannels[2]) pAnimation->addChannel(pRotationChannels[2]);
317        if (pScaleChannel) pAnimation->addChannel(pScaleChannel);
318
319
320        return pAnimation;
321    }
322
323    return 0;
324}
325
326void readFbxRotationAnimation(osgAnimation::Channel* channels[3],
327    KFbxNode* pNode,
328    KFbxAnimLayer* pAnimLayer, const char* targetName)
329{
330    if (!pNode->LclRotation.IsValid())
331    {
332        return;
333    }
334
335    ERotationOrder rotOrder = pNode->RotationOrder.IsValid() ? pNode->RotationOrder.Get() : eEULER_XYZ;
336
337    if (pNode->QuaternionInterpolate.IsValid() && pNode->QuaternionInterpolate.Get())
338    {
339        channels[0] = readFbxChannelsQuat(
340            pNode->LclRotation.GetCurve<KFbxAnimCurve>(pAnimLayer, KFCURVENODE_R_X),
341            pNode->LclRotation.GetCurve<KFbxAnimCurve>(pAnimLayer, KFCURVENODE_R_Y),
342            pNode->LclRotation.GetCurve<KFbxAnimCurve>(pAnimLayer, KFCURVENODE_R_Z),
343            pNode->LclRotation.Get(),
344            targetName, rotOrder);
345    }
346    else
347    {
348        const char* curveNames[3] = {KFCURVENODE_R_X, KFCURVENODE_R_Y, KFCURVENODE_R_Z};
349
350        fbxDouble3 fbxPropValue = pNode->LclRotation.Get();
351        fbxPropValue[0] = osg::DegreesToRadians(fbxPropValue[0]);
352        fbxPropValue[1] = osg::DegreesToRadians(fbxPropValue[1]);
353        fbxPropValue[2] = osg::DegreesToRadians(fbxPropValue[2]);
354
355        for (int i = 0; i < 3; ++i)
356        {
357            KFbxAnimCurve* curve = pNode->LclRotation.GetCurve<KFbxAnimCurve>(pAnimLayer, curveNames[i]);
358            if (!curve)
359            {
360                continue;
361            }
362
363            KFbxAnimCurveDef::EInterpolationType interpolationType = KFbxAnimCurveDef::eINTERPOLATION_CONSTANT;
364            if (curve && curve->KeyGetCount()) interpolationType = curve->KeyGetInterpolation(0);
365
366            if (interpolationType == KFbxAnimCurveDef::eINTERPOLATION_CUBIC)
367            {
368                osgAnimation::FloatCubicBezierKeyframeContainer* pKeyFrameCntr = new osgAnimation::FloatCubicBezierKeyframeContainer;
369
370                for (int j = 0; j < curve->KeyGetCount(); ++j)
371                {
372                    double fTime = curve->KeyGetTime(j).GetSecondDouble();
373                    float angle = curve->KeyGetValue(j);
374                    //KFbxAnimCurveDef::EWeightedMode tangentWeightMode = curve->KeyGet(j).GetTangentWeightMode();
375
376                    KFCurveTangeantInfo leftTangent = curve->KeyGetLeftDerivativeInfo(j);
377                    KFCurveTangeantInfo rightTangent = curve->KeyGetRightDerivativeInfo(j);
378                    if (j > 0)
379                    {
380                        leftTangent.mDerivative *= fTime - curve->KeyGetTime(j - 1).GetSecondDouble();
381                    }
382                    if (j + 1 < curve->KeyGetCount())
383                    {
384                        rightTangent.mDerivative *= curve->KeyGetTime(j + 1).GetSecondDouble() - fTime;
385                    }
386                    osgAnimation::FloatCubicBezier key(
387                        osg::DegreesToRadians(angle),
388                        osg::DegreesToRadians(angle - leftTangent.mDerivative / 3.0),
389                        osg::DegreesToRadians(angle + rightTangent.mDerivative / 3.0));
390
391                    pKeyFrameCntr->push_back(osgAnimation::FloatCubicBezierKeyframe(
392                        fTime,
393                        key));
394                }
395
396                reorderControlPoints(*pKeyFrameCntr);
397
398                osgAnimation::FloatCubicBezierChannel* pCubicChannel = new osgAnimation::FloatCubicBezierChannel;
399                pCubicChannel->getOrCreateSampler()->setKeyframeContainer(pKeyFrameCntr);
400                channels[i] = pCubicChannel;
401            }
402            else
403            {
404                osgAnimation::FloatKeyframeContainer* keys = new osgAnimation::FloatKeyframeContainer;
405
406                for (int j = 0; j < curve->KeyGetCount(); ++j)
407                {
408                    KFbxAnimCurveKey key = curve->KeyGet(j);
409                    keys->push_back(osgAnimation::FloatKeyframe(
410                        key.GetTime().GetSecondDouble(),
411                        static_cast<float>(osg::DegreesToRadians(key.GetValue()))));
412                }
413
414                if (interpolationType == KFbxAnimCurveDef::eINTERPOLATION_CONSTANT)
415                {
416                    osgAnimation::FloatStepChannel* pStepChannel = new osgAnimation::FloatStepChannel();
417                    pStepChannel->getOrCreateSampler()->setKeyframeContainer(keys);
418                    channels[i] = pStepChannel;
419                }
420                else
421                {
422                    osgAnimation::FloatLinearChannel* pLinearChannel = new osgAnimation::FloatLinearChannel();
423                    pLinearChannel->getOrCreateSampler()->setKeyframeContainer(keys);
424                    channels[i] = pLinearChannel;
425                }
426            }
427
428            channels[i]->setTargetName(targetName);
429            channels[i]->setName(std::string("rotate") + curveNames[i]);
430        }
431    }
432}
433
434osgAnimation::Animation* readFbxAnimation(KFbxNode* pNode,
435    KFbxAnimLayer* pAnimLayer, const char* pTakeName, const char* targetName,
436    osg::ref_ptr<osgAnimation::AnimationManagerBase>& pAnimManager)
437{
438    osgAnimation::Channel* pTranslationChannel = 0;
439    osgAnimation::Channel* pRotationChannels[3] = {0};
440    readFbxRotationAnimation(pRotationChannels, pNode, pAnimLayer, targetName);
441
442
443    if (pNode->LclTranslation.IsValid())
444    {
445        pTranslationChannel = readFbxChannels(
446            pNode->LclTranslation.GetCurve<KFbxAnimCurve>(pAnimLayer, KFCURVENODE_T_X),
447            pNode->LclTranslation.GetCurve<KFbxAnimCurve>(pAnimLayer, KFCURVENODE_T_Y),
448            pNode->LclTranslation.GetCurve<KFbxAnimCurve>(pAnimLayer, KFCURVENODE_T_Z),
449            pNode->LclTranslation.Get(),
450            targetName, "translate");
451    }
452
453    osgAnimation::Channel* pScaleChannel = readFbxChannels(
454        pNode->LclScaling, pAnimLayer, targetName, "scale");
455
456    return addChannels(pTranslationChannel, pRotationChannels, pScaleChannel, pAnimManager, pTakeName);
457}
458
459std::string OsgFbxReader::readFbxAnimation(KFbxNode* pNode, const char* targetName)
460{
461    std::string result;
462    for (int i = 0; i < fbxScene.GetSrcObjectCount(FBX_TYPE(KFbxAnimStack)); ++i)
463    {
464        KFbxAnimStack* pAnimStack = KFbxCast<KFbxAnimStack>(fbxScene.GetSrcObject(FBX_TYPE(KFbxAnimStack), i));
465
466        int nbAnimLayers = pAnimStack->GetMemberCount(FBX_TYPE(KFbxAnimLayer));
467
468        const char* pTakeName = pAnimStack->GetName();
469
470        if (!pTakeName || !*pTakeName)
471            continue;
472
473        for (int j = 0; j < nbAnimLayers; j++)
474        {
475            KFbxAnimLayer* pAnimLayer = pAnimStack->GetMember(FBX_TYPE(KFbxAnimLayer), j);
476            osgAnimation::Animation* pAnimation = ::readFbxAnimation(pNode, pAnimLayer, pTakeName, targetName, pAnimationManager);
477            if (pAnimation)
478            {
479                result = targetName;
480            }
481        }
482    }
483    return result;
484}
Note: See TracBrowser for help on using the browser.