root/OpenSceneGraph/trunk/src/osgPlugins/dae/daeRAnimations.cpp @ 13041

Revision 13041, 35.0 kB (checked in by robert, 3 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
Line 
1#include "daeReader.h"
2#include "domSourceReader.h"
3#include <dae.h>
4#include <dae/domAny.h>
5#include <dom/domCOLLADA.h>
6#include <dom/domConstants.h>
7
8#include <osgAnimation/Channel>
9#include <osgAnimation/MorphGeometry>
10#include <osgAnimation/StackedTransform>
11#include <osgAnimation/StackedRotateAxisElement>
12#include <osgAnimation/UpdateBone>
13#include <osgAnimation/UpdateMatrixTransform>
14
15using namespace osgDAE;
16
17
18// Mapping Collada animations to Osg animations
19// domAnimation ->  osgAnimation::Animation
20// domSampler   ->  osgAnimation::Channel
21// domSource    ->  osgAnimation::Channel.Sampler
22// domChannel   ->  osgAnimation::Channel.TargetName
23osgAnimation::BasicAnimationManager* daeReader::processAnimationLibraries(domCOLLADA* document)
24{
25    domLibrary_animation_clips_Array domAnimationClipsLibraries = document->getLibrary_animation_clips_array();
26
27    domLibrary_animations_Array domAnimationsLibraries = document->getLibrary_animations_array();
28    osgAnimation::BasicAnimationManager* pOsgAnimationManager = NULL;
29
30    // Only create an animationmanager if we have  animation clip libraries or animation libraries
31    if ((domAnimationClipsLibraries.getCount() > 0) || (domAnimationsLibraries.getCount() > 0))
32    {
33        pOsgAnimationManager = new osgAnimation::BasicAnimationManager();
34
35        // Process all animation clip libraries
36        for (size_t i=0; i < domAnimationClipsLibraries.getCount(); i++)
37        {
38            domAnimation_clip_Array domAnimationClips = domAnimationClipsLibraries[i]->getAnimation_clip_array();
39            // Process all animation clips in this library
40            for (size_t j=0; j < domAnimationClips.getCount(); j++)
41            {
42                processAnimationClip(pOsgAnimationManager, domAnimationClips[j]);
43            }
44        }
45
46        // If there are no clips then all animations are part of the same clip
47        if (domAnimationClipsLibraries.getCount() == 0 && domAnimationsLibraries.getCount())
48        {
49            osgAnimation::Animation* pOsgAnimation = new osgAnimation::Animation;
50            pOsgAnimation->setName("Default");
51            pOsgAnimationManager->registerAnimation(pOsgAnimation);
52
53            // Process all animation libraries
54            for (size_t i=0; i < domAnimationsLibraries.getCount(); i++)
55            {
56                domAnimation_Array domAnimations = domAnimationsLibraries[i]->getAnimation_array();
57
58                TargetChannelPartMap tcm;
59
60                // Process all animations in this library
61                for (size_t j=0; j < domAnimations.getCount(); j++)
62                {
63                    processAnimationChannels(domAnimations[j], tcm);
64                }
65
66                processAnimationMap(tcm, pOsgAnimation);
67            }
68        }
69    }
70    return pOsgAnimationManager;
71}
72
73// <animation_clip (id) (name) (start) (end)>
74// 0..1 <asset>
75// 1..* <instance_animation>
76// 0..* <extra>
77void daeReader::processAnimationClip(osgAnimation::BasicAnimationManager* pOsgAnimationManager, domAnimation_clip* pDomAnimationClip)
78{
79    // an <animation_clip> groups animations
80    osgAnimation::Animation* pOsgAnimation = new osgAnimation::Animation;
81    std::string name = pDomAnimationClip->getId() ? pDomAnimationClip->getId() : "AnimationClip";
82    pOsgAnimation->setName(name);
83
84    // We register the animation inside the scheduler
85    pOsgAnimationManager->registerAnimation(pOsgAnimation);
86
87    double start = pDomAnimationClip->getStart();
88    double end = pDomAnimationClip->getEnd();
89
90    pOsgAnimation->setStartTime(start);
91    double duration = end - start;
92    if (duration > 0)
93    {
94        pOsgAnimation->setDuration(duration);
95    }
96
97    TargetChannelPartMap tcm;
98
99    // 1..* <instance_animation>
100    domInstanceWithExtra_Array domInstanceArray = pDomAnimationClip->getInstance_animation_array();
101    for (size_t i=0; i < domInstanceArray.getCount(); i++)
102    {
103        domAnimation *pDomAnimation = daeSafeCast<domAnimation>(getElementFromURI(domInstanceArray[i]->getUrl()));
104        if (pDomAnimation)
105        {
106            processAnimationChannels(pDomAnimation, tcm);
107        }
108        else
109        {
110            OSG_WARN << "Failed to locate animation " << domInstanceArray[i]->getUrl().getURI() << std::endl;
111        }
112    }
113
114    processAnimationMap(tcm, pOsgAnimation);
115}
116
117struct KeyFrameComparator
118{
119    bool operator () (const osgAnimation::Keyframe& a, const osgAnimation::Keyframe& b) const
120    {
121        return a.getTime() < b.getTime();
122    }
123    bool operator () (const osgAnimation::Keyframe& a, float t) const
124    {
125        return a.getTime() < t;
126    }
127    bool operator () (float t, const osgAnimation::Keyframe& b) const
128    {
129        return t < b.getTime();
130    }
131};
132
133template <typename T>
134void deCasteljau(osgAnimation::TemplateCubicBezier<T>& l, osgAnimation::TemplateCubicBezier<T>& n, osgAnimation::TemplateCubicBezier<T>& r, float t)
135{
136    T q1 = l.getPosition() + t * (l.getControlPointOut() - l.getPosition());
137    T q2 = l.getControlPointOut() + t * (r.getControlPointIn() - l.getControlPointOut());
138    T q3 = r.getControlPointIn() + t * (r.getPosition() - r.getControlPointIn());
139
140    T r1 = q1 + t * (q2 - q1);
141    T r2 = q2 + t * (q3 - q2);
142
143    T s = r1 + t * (r2 - r1);
144
145    n.setControlPointIn(r1);
146
147    n.setPosition(s);
148
149    n.setControlPointOut(r2);
150
151    l.setControlPointOut(q1);
152
153    r.setControlPointIn(q3);
154}
155
156void mergeKeyframeContainers(osgAnimation::Vec3CubicBezierKeyframeContainer* to,
157                    osgAnimation::FloatCubicBezierKeyframeContainer** from,
158                    daeReader::InterpolationType interpolationType,
159                    const osg::Vec3& defaultValue)
160{
161    assert(to->empty());
162
163    typedef std::set<float> TimeSet;
164    TimeSet times;
165
166    for (int i = 0; i < 3; ++i)
167    {
168        if (!from[i] || from[i]->empty())
169        {
170            continue;
171        }
172
173        for (osgAnimation::FloatCubicBezierKeyframeContainer::const_iterator
174            it = from[i]->begin(), end = from[i]->end(); it != end; ++it)
175        {
176            times.insert(it->getTime());
177        }
178    }
179
180    for (TimeSet::const_iterator it = times.begin(), end = times.end(); it != end; ++it)
181    {
182        const float time = *it;
183
184        osgAnimation::Vec3CubicBezier value(defaultValue);
185
186        for (int i = 0; i < 3; ++i)
187        {
188            if (!from[i] || from[i]->empty())
189            {
190                continue;
191            }
192
193            osgAnimation::FloatCubicBezierKeyframeContainer::iterator next =
194                std::lower_bound(from[i]->begin(), from[i]->end(), time, KeyFrameComparator());
195            if (next == from[i]->end())
196            {
197                --next;
198                value.getPosition().ptr()[i] = next->getValue().getPosition();
199                value.getControlPointIn().ptr()[i] = next->getValue().getControlPointIn();
200                value.getControlPointOut().ptr()[i] = next->getValue().getControlPointOut();
201            }
202            else if (next == from[i]->begin() || next->getTime() == time)
203            {
204                value.getPosition().ptr()[i] = next->getValue().getPosition();
205                value.getControlPointIn().ptr()[i] = next->getValue().getControlPointIn();
206                value.getControlPointOut().ptr()[i] = next->getValue().getControlPointOut();
207            }
208            else
209            {
210                osgAnimation::FloatCubicBezierKeyframeContainer::iterator prev = next;
211                --prev;
212
213                switch (interpolationType)
214                {
215                case daeReader::INTERPOLATION_STEP:
216                    value.getPosition().ptr()[i] = prev->getValue().getPosition();
217                    break;
218                case daeReader::INTERPOLATION_LINEAR:
219                    {
220                        float xp = prev->getTime(), xn = next->getTime();
221                        float yp = prev->getValue().getPosition(), yn = next->getValue().getPosition();
222                        value.getPosition().ptr()[i] = yp + (yn - yp) * (time - xp) / (xn - xp);
223                    }
224                    break;
225                case daeReader::INTERPOLATION_BEZIER:
226                    {
227                        float xp = prev->getTime(), xn = next->getTime();
228
229                        osgAnimation::FloatCubicBezier l(prev->getValue()), n, r(next->getValue());
230                        deCasteljau(l, n, r, (time - xp) / (xn - xp));
231
232                        value.getPosition().ptr()[i] = n.getPosition();
233                        value.getControlPointIn().ptr()[i] = n.getControlPointIn();
234                        value.getControlPointOut().ptr()[i] = n.getControlPointOut();
235
236                        osgAnimation::Vec3CubicBezier prevValue = to->back().getValue();
237                        prevValue.getControlPointOut().ptr()[i] = l.getControlPointOut();
238                        to->back().setValue(prevValue);
239
240                        prev->setValue(l);
241                        next->setValue(r);
242                        from[i]->insert(next, osgAnimation::FloatCubicBezierKeyframe(time, n));
243                    }
244                    break;
245                default:
246                    OSG_WARN << "Unsupported interpolation type." << std::endl;
247                    break;
248                }
249
250                //todo - different types of interpolation
251            }
252        }
253
254        to->push_back(osgAnimation::Vec3CubicBezierKeyframe(time, value));
255    }
256}
257
258void daeReader::processAnimationChannels(
259    domAnimation* pDomAnimation, TargetChannelPartMap& tcm)
260{
261    // 1..* <source>
262    SourceMap sources;
263    domSource_Array domSources = pDomAnimation->getSource_array();
264    for (size_t i=0; i < domSources.getCount(); i++)
265    {
266        sources.insert(std::make_pair((daeElement*)domSources[i], domSourceReader(domSources[i])));
267    }
268
269    domChannel_Array domChannels = pDomAnimation->getChannel_array();
270    for (size_t i=0; i < domChannels.getCount(); i++)
271    {
272        processChannel(domChannels[i], sources, tcm);
273    }
274
275    domAnimation_Array domAnimations = pDomAnimation->getAnimation_array();
276    for (size_t i=0; i < domAnimations.getCount(); i++)
277    {
278        // recursively call
279        processAnimationChannels(domAnimations[i], tcm);
280    }
281}
282
283osgAnimation::Vec3KeyframeContainer* convertKeyframeContainerToLinear(osgAnimation::Vec3CubicBezierKeyframeContainer& from)
284{
285    osgAnimation::Vec3KeyframeContainer* linearKeyframes = new osgAnimation::Vec3KeyframeContainer;
286    for (size_t i = 0; i < from.size(); ++i)
287    {
288        linearKeyframes->push_back(osgAnimation::Vec3Keyframe(
289            from[i].getTime(), from[i].getValue().getPosition()));
290    }
291    return linearKeyframes;
292}
293
294template <typename T>
295void convertHermiteToBezier(osgAnimation::TemplateKeyframeContainer<T>& keyframes)
296{
297    for (size_t i = 0; i < keyframes.size(); ++i)
298    {
299        T val = keyframes[i].getValue();
300        val.setControlPointIn(val.getControlPointIn() / 3.0f + val.getPosition());
301        val.setControlPointOut(val.getControlPointOut() / -3.0f + val.getPosition());
302        keyframes[i].setValue(val);
303    }
304}
305
306// osgAnimation requires control points to be in a weird order. This function
307// reorders them from the conventional order to osgAnimation order.
308template <typename T>
309void reorderControlPoints(osgAnimation::TemplateKeyframeContainer<osgAnimation::TemplateCubicBezier<T> >& vkfCont)
310{
311    if (vkfCont.size() <= 1)
312    {
313        if (vkfCont.size() == 1)
314        {
315            osgAnimation::TemplateCubicBezier<T> tcb = vkfCont.front().getValue();
316            T inCP = tcb.getControlPointIn();
317            tcb.setControlPointIn(tcb.getControlPointOut());
318            tcb.setControlPointOut(inCP);
319            vkfCont.front().setValue(tcb);
320        }
321        return;
322    }
323
324    osgAnimation::TemplateCubicBezier<T> first = vkfCont.front().getValue();
325
326    for (unsigned i = 0; i < vkfCont.size() - 1; ++i)
327    {
328        osgAnimation::TemplateCubicBezier<T> tcb = vkfCont[i].getValue();
329        tcb.setControlPointIn(tcb.getControlPointOut());
330        tcb.setControlPointOut(vkfCont[i + 1].getValue().getControlPointIn());
331        vkfCont[i].setValue(tcb);
332    }
333
334    osgAnimation::TemplateCubicBezier<T> last = vkfCont.back().getValue();
335    last.setControlPointIn(last.getControlPointOut());
336    last.setControlPointOut(first.getControlPointIn());
337    vkfCont.back().setValue(last);
338}
339
340// <animation (id) (name)>
341// 0..1 <asset>
342// option 1
343//        1..* <source>
344//        one of (<sampler>, <channel>, <animation>) or <animation> (see below)
345// option 2
346//        1..* <source>
347//        1..* <sampler>
348//        0..* <animation>
349// option 3
350//        1..* <animation>
351// 0..* <extra>
352void daeReader::processAnimationMap(const TargetChannelPartMap& tcm, osgAnimation::Animation* pOsgAnimation)
353{
354    for (TargetChannelPartMap::const_iterator lb = tcm.begin(), end = tcm.end(); lb != end;)
355    {
356        TargetChannelPartMap::const_iterator ub = tcm.upper_bound(lb->first);
357
358        osgAnimation::Channel* pOsgAnimationChannel = NULL;
359        std::string channelName, targetName, componentName;
360
361        if (osgAnimation::Vec3Target* pTarget = dynamic_cast<osgAnimation::Vec3Target*>(lb->first))
362        {
363            osgAnimation::FloatCubicBezierKeyframeContainer* fkfConts[3] = {NULL, NULL, NULL};
364            osgAnimation::Vec3CubicBezierKeyframeContainer* vkfCont = NULL;
365            InterpolationType interpolationType = INTERPOLATION_DEFAULT;
366
367            for (TargetChannelPartMap::const_iterator it = lb; it != ub; ++it)
368            {
369                ChannelPart* channelPart = it->second.get();
370                extractTargetName(channelPart->name, channelName, targetName, componentName);
371                interpolationType = channelPart->interpolation;
372
373                if (osgAnimation::Vec3CubicBezierKeyframeContainer* v3cnt = dynamic_cast<osgAnimation::Vec3CubicBezierKeyframeContainer*>(channelPart->keyframes.get()))
374                {
375                    vkfCont = v3cnt;
376                    break;
377                }
378                else if (osgAnimation::FloatCubicBezierKeyframeContainer* fcnt = dynamic_cast<osgAnimation::FloatCubicBezierKeyframeContainer*>(channelPart->keyframes.get()))
379                {
380                    if (strchr("xusr0", tolower(componentName[0])))
381                    {
382                        fkfConts[0] = fcnt;
383                    }
384                    else if (strchr("yvtg1", tolower(componentName[0])))
385                    {
386                        fkfConts[1] = fcnt;
387                    }
388                    else if (strchr("zpb2", tolower(componentName[0])))
389                    {
390                        fkfConts[2] = fcnt;
391                    }
392                    else
393                    {
394                        OSG_WARN << "Unrecognised vector component \"" << componentName << "\"" << std::endl;
395                    }
396                }
397                else
398                {
399                    OSG_WARN << "Unrecognised keyframe container \"" << channelPart->name << "\"" << std::endl;
400                }
401            }
402
403            if (!pOsgAnimationChannel && (fkfConts[0] || fkfConts[1] || fkfConts[2]))
404            {
405                vkfCont = new osgAnimation::Vec3CubicBezierKeyframeContainer;
406                mergeKeyframeContainers(vkfCont, fkfConts, interpolationType, pTarget->getValue());
407            }
408
409            if (vkfCont)
410            {
411                if (interpolationType == INTERPOLATION_STEP)
412                {
413                    osgAnimation::Vec3StepChannel* channel = new osgAnimation::Vec3StepChannel;
414                    pOsgAnimationChannel = channel;
415                    channel->getOrCreateSampler()->setKeyframeContainer(convertKeyframeContainerToLinear(*vkfCont));
416                }
417                else if (interpolationType == INTERPOLATION_LINEAR)
418                {
419                    osgAnimation::Vec3LinearChannel* channel = new osgAnimation::Vec3LinearChannel;
420                    pOsgAnimationChannel = channel;
421                    channel->getOrCreateSampler()->setKeyframeContainer(convertKeyframeContainerToLinear(*vkfCont));
422                }
423                else if (interpolationType == INTERPOLATION_BEZIER)
424                {
425                    osgAnimation::Vec3CubicBezierChannel* channel = new osgAnimation::Vec3CubicBezierChannel;
426                    pOsgAnimationChannel = channel;
427                    reorderControlPoints(*vkfCont);
428                    channel->getOrCreateSampler()->setKeyframeContainer(vkfCont);
429                }
430                else if (interpolationType == INTERPOLATION_HERMITE)
431                {
432                    osgAnimation::Vec3CubicBezierChannel* channel = new osgAnimation::Vec3CubicBezierChannel;
433                    pOsgAnimationChannel = channel;
434                    convertHermiteToBezier(*vkfCont);
435                    reorderControlPoints(*vkfCont);
436                    channel->getOrCreateSampler()->setKeyframeContainer(vkfCont);
437                }
438                else
439                {
440                    OSG_WARN << "Unsupported interpolation type" << std::endl;
441                }
442            }
443        }
444        else
445        {
446            ChannelPart* channelPart = lb->second.get();
447            extractTargetName(channelPart->name, channelName, targetName, componentName);
448
449            typedef osgAnimation::TemplateKeyframe<osgAnimation::TemplateCubicBezier<osg::Matrixf> > MatrixCubicBezierKeyframe;
450            typedef osgAnimation::TemplateKeyframeContainer<osgAnimation::TemplateCubicBezier<osg::Matrixf> > MatrixCubicBezierKeyframeContainer;
451
452            if (osgAnimation::FloatCubicBezierKeyframeContainer* kfCntr =
453                dynamic_cast<osgAnimation::FloatCubicBezierKeyframeContainer*>(channelPart->keyframes.get()))
454            {
455                if (dynamic_cast<osgAnimation::MatrixTarget*>(lb->first))
456                {
457                    OSG_WARN << "Animating elements of matrices not supported." << std::endl;
458                }
459                else
460                {
461                    osgAnimation::FloatCubicBezierChannel* channel = new osgAnimation::FloatCubicBezierChannel;
462                    reorderControlPoints(*kfCntr);
463                    channel->getOrCreateSampler()->setKeyframeContainer(kfCntr);
464                    pOsgAnimationChannel = channel;
465                }
466            }
467            else if (MatrixCubicBezierKeyframeContainer* cbkfCntr =
468                dynamic_cast<MatrixCubicBezierKeyframeContainer*>(channelPart->keyframes.get()))
469            {
470                osgAnimation::MatrixKeyframeContainer* kfCntr = new osgAnimation::MatrixKeyframeContainer;
471                for (size_t i = 0; i < cbkfCntr->size(); ++i)
472                {
473                    const MatrixCubicBezierKeyframe& cbkf = cbkfCntr->at(i);
474                    kfCntr->push_back(osgAnimation::MatrixKeyframe(cbkf.getTime(), cbkf.getValue().getPosition()));
475                }
476                osgAnimation::MatrixLinearChannel* channel = new osgAnimation::MatrixLinearChannel;
477                channel->getOrCreateSampler()->setKeyframeContainer(kfCntr);
478                pOsgAnimationChannel = channel;
479            }
480        }
481
482        if (pOsgAnimationChannel)
483        {
484            pOsgAnimationChannel->setTargetName(targetName);
485            pOsgAnimationChannel->setName(channelName);
486            pOsgAnimation->addChannel(pOsgAnimationChannel);
487        }
488        lb = ub;
489    }
490
491    pOsgAnimation->computeDuration();
492}
493
494template <typename T, typename TArray>
495osgAnimation::KeyframeContainer* makeKeyframes(
496    const osg::FloatArray* pOsgTimesArray,
497    TArray* pOsgPointArray,
498    TArray* pOsgInTanArray,
499    TArray* pOsgOutTanArray,
500    daeReader::InterpolationType& interpolationType)
501{
502    osgAnimation::TemplateKeyframeContainer<osgAnimation::TemplateCubicBezier<T> >* keyframes =
503        new osgAnimation::TemplateKeyframeContainer<osgAnimation::TemplateCubicBezier<T> >;
504
505    for (size_t i = 0; i < pOsgTimesArray->size(); i++)
506    {
507        T pt = (*pOsgPointArray)[i];
508        T cpIn = pt, cpOut = pt;
509        if (pOsgInTanArray)
510        {
511            if (interpolationType == daeReader::INTERPOLATION_HERMITE)
512                //convert from hermite to bezier
513                cpIn += (*pOsgInTanArray)[i] / 3;
514            else if (interpolationType == daeReader::INTERPOLATION_BEZIER)
515                cpIn = (*pOsgInTanArray)[i];
516        }
517        if (pOsgOutTanArray)
518        {
519            if (interpolationType == daeReader::INTERPOLATION_HERMITE)
520                //convert from hermite to bezier
521                cpOut += (*pOsgOutTanArray)[i] / 3;
522            else if (interpolationType == daeReader::INTERPOLATION_BEZIER)
523                cpOut = (*pOsgOutTanArray)[i];
524        }
525
526        keyframes->push_back(
527            osgAnimation::TemplateKeyframe<osgAnimation::TemplateCubicBezier<T> >(
528            (*pOsgTimesArray)[i],
529            osgAnimation::TemplateCubicBezier<T>(pt, cpIn, cpOut)));
530    }
531
532    if (interpolationType == daeReader::INTERPOLATION_HERMITE)
533    {
534        interpolationType = daeReader::INTERPOLATION_BEZIER;
535    }
536
537    return keyframes;
538}
539
540// Sampler tells how to use the sources to generate an animated value.
541// <sampler (id)>
542// 1..* <input>
543//        1    semantic
544//        1    source
545daeReader::ChannelPart* daeReader::processSampler(domChannel* pDomChannel, SourceMap &sources)
546{
547    // And we finally define our channel
548    // Note osg can only create time based animations
549
550    //from the channel you know the target, from the target you know the type
551    domSampler *pDomSampler = daeSafeCast<domSampler>(getElementFromURI(pDomChannel->getSource()));
552    if (!pDomSampler)
553    {
554        return NULL;
555    }
556
557    domInputLocal_Array domInputArray = pDomSampler->getInput_array();
558
559    daeElement* input_source = NULL;
560    daeElement* output_source = NULL;
561    daeElement* output_intangent_source = NULL;
562    daeElement* output_outtangent_source = NULL;
563    domInputLocal *tmp;
564
565    osg::FloatArray* pOsgTimesArray = NULL;
566    if (findInputSourceBySemantic(domInputArray, COMMON_PROFILE_INPUT_INPUT, input_source, &tmp))
567    {
568        domSource* pDomSource = daeSafeCast<domSource>(input_source);
569        if (pDomSource)
570        {
571            domSource::domTechnique_common* pDomTechnique = pDomSource->getTechnique_common();
572            if (pDomTechnique)
573            {
574                domAccessor* pDomAccessor = pDomTechnique->getAccessor();
575                domParam_Array domParams = pDomAccessor->getParam_array();
576                if (domParams.getCount() > 0)
577                {
578                    if (!strcmp("TIME", domParams[0]->getName()))
579                    {
580                        pOsgTimesArray = sources[input_source].getArray<osg::FloatArray>();
581                    }
582                    else
583                    {
584                        OSG_WARN << "Only TIME based animations are supported" <<std::endl;
585                        return NULL;
586                    }
587                }
588                else
589                {
590                    OSG_WARN << "No params in accessor" <<std::endl;
591                    return NULL;
592                }
593            }
594            else
595            {
596                OSG_WARN << "Unable to find <technique_common> in <source> " << pDomSource->getName() <<std::endl;
597                return NULL;
598            }
599        }
600        else
601        {
602            OSG_WARN << "Could not get animation 'INPUT' source"<<std::endl;
603            return NULL;
604        }
605    }
606
607    //const bool readDoubleKeyframes = (_precisionHint & osgDB::Options::DOUBLE_PRECISION_KEYFRAMES) != 0;
608    static const bool readDoubleKeyframes = false;
609
610    findInputSourceBySemantic(domInputArray, COMMON_PROFILE_INPUT_OUTPUT, output_source, &tmp);
611    findInputSourceBySemantic(domInputArray, COMMON_PROFILE_INPUT_IN_TANGENT, output_intangent_source, &tmp);
612    findInputSourceBySemantic(domInputArray, COMMON_PROFILE_INPUT_OUT_TANGENT, output_outtangent_source, &tmp);
613    domSourceReader::ArrayType arrayType = sources[output_source].getArrayType(readDoubleKeyframes);
614
615    struct InterpTypeName
616    {
617        InterpolationType interp;
618        const char* str;
619    };
620
621    InterpTypeName interpTypeNames[] = {
622        {INTERPOLATION_STEP, "STEP"},
623        {INTERPOLATION_LINEAR, "LINEAR"},
624        {INTERPOLATION_BEZIER, "BEZIER"},
625        {INTERPOLATION_HERMITE, "HERMITE"},
626        {INTERPOLATION_CARDINAL, "CARDINAL"},
627        {INTERPOLATION_BSPLINE, "BSPLINE"}
628    };
629    const int interpTypeCount = sizeof(interpTypeNames) / sizeof(*interpTypeNames);
630
631    // TODO multiple outputs may be possible?
632
633    InterpolationType interpolationType = INTERPOLATION_DEFAULT;
634
635    if (findInputSourceBySemantic(domInputArray, COMMON_PROFILE_INPUT_INTERPOLATION, input_source, &tmp))
636    {
637        domSource* pDomSource = daeSafeCast<domSource>(input_source);
638        if (pDomSource)
639        {
640            domName_array* pDomNames = pDomSource->getName_array();
641            if (pDomNames)
642            {
643                daeStringArray* stringArray = &(pDomNames->getValue());
644
645                // Take a look at the first element in the array to see what kind of interpolation is needed
646                // multiple interpolation types inside an animation is not supported
647                if (stringArray->getCount() > 0)
648                {
649                    // Collada interpolation types
650                    for (int i = 0; i < interpTypeCount; ++i)
651                    {
652                        if (!strcmp(interpTypeNames[i].str, (*stringArray)[0]))
653                        {
654                            interpolationType = interpTypeNames[i].interp;
655                            break;
656                        }
657                    }
658                }
659                else
660                {
661                    OSG_WARN << "No names in <Name_array>" <<std::endl;
662                    return NULL;
663                }
664            }
665            else
666            {
667                OSG_WARN << "Unable to find <Name_array> in <source> " << pDomSource->getName() <<std::endl;
668                return NULL;
669            }
670        }
671        else
672        {
673            OSG_WARN << "Could not get animation 'INPUT' source"<<std::endl;
674            return NULL;
675        }
676    }
677
678    //work around for files output by the Autodesk FBX converter.
679    if ((interpolationType == INTERPOLATION_BEZIER) &&
680        (_authoringTool == FBX_CONVERTER || _authoringTool == MAYA))
681    {
682        interpolationType = INTERPOLATION_HERMITE;
683    }
684
685    osgAnimation::KeyframeContainer* keyframes = NULL;
686
687    switch (arrayType)
688    {
689    case domSourceReader::Float:
690        keyframes = makeKeyframes<float>(pOsgTimesArray,
691            sources[output_source].getArray<osg::FloatArray>(),
692            sources[output_intangent_source].getArray<osg::FloatArray>(),
693            sources[output_outtangent_source].getArray<osg::FloatArray>(),
694            interpolationType);
695        break;
696    case domSourceReader::Vec2:
697        keyframes = makeKeyframes<osg::Vec2>(pOsgTimesArray,
698            sources[output_source].getArray<osg::Vec2Array>(),
699            sources[output_intangent_source].getArray<osg::Vec2Array>(),
700            sources[output_outtangent_source].getArray<osg::Vec2Array>(),
701            interpolationType);
702        break;
703    case domSourceReader::Vec3:
704        keyframes = makeKeyframes<osg::Vec3>(pOsgTimesArray,
705            sources[output_source].getArray<osg::Vec3Array>(),
706            sources[output_intangent_source].getArray<osg::Vec3Array>(),
707            sources[output_outtangent_source].getArray<osg::Vec3Array>(),
708            interpolationType);
709        break;
710    case domSourceReader::Vec4:
711        keyframes = makeKeyframes<osg::Vec4>(pOsgTimesArray,
712            sources[output_source].getArray<osg::Vec4Array>(),
713            sources[output_intangent_source].getArray<osg::Vec4Array>(),
714            sources[output_outtangent_source].getArray<osg::Vec4Array>(),
715            interpolationType);
716        break;
717    case domSourceReader::Vec2d:
718        keyframes = makeKeyframes<osg::Vec2d>(pOsgTimesArray,
719            sources[output_source].getArray<osg::Vec2dArray>(),
720            sources[output_intangent_source].getArray<osg::Vec2dArray>(),
721            sources[output_outtangent_source].getArray<osg::Vec2dArray>(),
722            interpolationType);
723        break;
724    case domSourceReader::Vec3d:
725        keyframes = makeKeyframes<osg::Vec3d>(pOsgTimesArray,
726            sources[output_source].getArray<osg::Vec3dArray>(),
727            sources[output_intangent_source].getArray<osg::Vec3dArray>(),
728            sources[output_outtangent_source].getArray<osg::Vec3dArray>(),
729            interpolationType);
730        break;
731    case domSourceReader::Vec4d:
732        keyframes = makeKeyframes<osg::Vec4d>(pOsgTimesArray,
733            sources[output_source].getArray<osg::Vec4dArray>(),
734            sources[output_intangent_source].getArray<osg::Vec4dArray>(),
735            sources[output_outtangent_source].getArray<osg::Vec4dArray>(),
736            interpolationType);
737        break;
738    case domSourceReader::Matrix:
739        keyframes = makeKeyframes<osg::Matrixf>(pOsgTimesArray,
740            sources[output_source].getArray<osg::MatrixfArray>(),
741            sources[output_intangent_source].getArray<osg::MatrixfArray>(),
742            sources[output_outtangent_source].getArray<osg::MatrixfArray>(),
743            interpolationType);
744        break;
745    default:
746        ;// Fall through
747    }
748
749    if (keyframes)
750    {
751        ChannelPart* chanPart = new ChannelPart;
752        chanPart->keyframes = keyframes;
753        chanPart->interpolation = interpolationType;
754        chanPart->name = pDomChannel->getTarget();
755        return chanPart;
756    }
757
758    return NULL;
759}
760
761osgAnimation::Target* findChannelTarget(osg::NodeCallback* nc, const std::string& targetName, bool& rotation)
762{
763    if (osgAnimation::UpdateMatrixTransform* umt = dynamic_cast<osgAnimation::UpdateMatrixTransform*>(nc))
764    {
765        for (osgAnimation::StackedTransform::const_iterator
766            it = umt->getStackedTransforms().begin(), end = umt->getStackedTransforms().end(); it != end; ++it)
767        {
768            osgAnimation::StackedTransformElement* te = it->get();
769            if (te->getName() == targetName)
770            {
771                rotation = dynamic_cast<osgAnimation::StackedRotateAxisElement*>(te) != NULL;
772                return te->getOrCreateTarget();
773            }
774        }
775    }
776    else if (!dynamic_cast<osgAnimation::UpdateMorph*>(nc))
777    {
778        OSG_WARN << "Unrecognised AnimationUpdateCallback" << std::endl;
779    }
780
781    return NULL;
782}
783
784void convertDegreesToRadians(osgAnimation::KeyframeContainer* pKeyframeContainer)
785{
786    if (osgAnimation::FloatKeyframeContainer* fkc =
787        dynamic_cast<osgAnimation::FloatKeyframeContainer*>(pKeyframeContainer))
788    {
789        for (size_t i = 0; i < fkc->size(); ++i)
790        {
791            osgAnimation::FloatKeyframe& fk = (*fkc)[i];
792            fk.setValue(osg::DegreesToRadians(fk.getValue()));
793        }
794    }
795    else if (osgAnimation::FloatCubicBezierKeyframeContainer* fcbkc =
796        dynamic_cast<osgAnimation::FloatCubicBezierKeyframeContainer*>(pKeyframeContainer))
797    {
798        for (size_t i = 0; i < fcbkc->size(); ++i)
799        {
800            osgAnimation::FloatCubicBezierKeyframe& fcbk = (*fcbkc)[i];
801            osgAnimation::FloatCubicBezier fcb = fcbk.getValue();
802            fcb.setPosition(osg::DegreesToRadians(fcb.getPosition()));
803            fcb.setControlPointIn(osg::DegreesToRadians(fcb.getControlPointIn()));
804            fcb.setControlPointOut(osg::DegreesToRadians(fcb.getControlPointOut()));
805            fcbk.setValue(fcb);
806        }
807    }
808    else
809    {
810        OSG_WARN << "Warning: rotation keyframes not converted to radians." << std::endl;
811    }
812}
813
814// Channel connects animation output to parameter to animate
815// <channel>
816// 1 source
817// 1 target
818void daeReader::processChannel(domChannel* pDomChannel, SourceMap& sources, TargetChannelPartMap& tcm)
819{
820    domSampler *pDomSampler = daeSafeCast<domSampler>(getElementFromURI(pDomChannel->getSource()));
821    if (pDomSampler)
822    {
823        ChannelPart* pChannelPart = processSampler(pDomChannel, sources);
824
825        if (pChannelPart)
826        {
827            domChannelOsgAnimationUpdateCallbackMap::iterator iter = _domChannelOsgAnimationUpdateCallbackMap.find(pDomChannel);
828            if (iter != _domChannelOsgAnimationUpdateCallbackMap.end())
829            {
830                osg::NodeCallback* nc = iter->second.get();
831
832                std::string channelName, targetName, componentName;
833                extractTargetName(pDomChannel->getTarget(), channelName, targetName, componentName);
834                //assert(targetName == nc->getName());
835                bool bRotationChannel = false;
836                if (osgAnimation::Target* pTarget = findChannelTarget(nc, channelName, bRotationChannel))
837                {
838                    if (bRotationChannel)
839                    {
840                        convertDegreesToRadians(pChannelPart->keyframes.get());
841                    }
842                    tcm.insert(TargetChannelPartMap::value_type(pTarget, pChannelPart));
843                }
844                else
845                {
846                    OSG_WARN << "Target \"" << channelName << "\" not found." << std::endl;
847                }
848            }
849            else
850            {
851                OSG_WARN << "Could not locate UpdateCallback for <channel> target "  << pDomChannel->getTarget()<< std::endl;
852            }
853        }
854        else
855        {
856            OSG_WARN << "<channel> source "  << pDomChannel->getSource().getURI() << " has no corresponding osgAnimation::Channel" << std::endl;
857        }
858    }
859    else
860    {
861        OSG_WARN << "Could not locate <channel> source "  << pDomChannel->getSource().getURI() << std::endl;
862    }
863}
864
865void daeReader::extractTargetName(const std::string& daeTarget, std::string& channelName, std::string& targetName, std::string& component)
866{
867    size_t slash = daeTarget.find_last_of("/");
868    if (slash != std::string::npos)
869    {
870        // Handle /translation
871        targetName = daeTarget.substr(0, slash);
872        channelName = daeTarget.substr(slash+1, std::string::npos);
873    }
874    else
875    {
876        size_t parenthesis = daeTarget.find_last_of("(");
877        size_t endpos = daeTarget.find_last_of(")");
878        if (parenthesis != std::string::npos && endpos != std::string::npos)
879        {
880            // Handle (1)
881            targetName = daeTarget.substr(0, parenthesis);
882            channelName = daeTarget.substr(parenthesis+1, endpos - parenthesis - 1);
883        }
884        else
885        {
886            OSG_WARN << "Couldn't extract a proper name for <channel> target " << daeTarget << std::endl;
887        }
888    }
889
890    size_t period = channelName.find_last_of(".");
891    if (period != std::string::npos)
892    {
893        component = channelName.substr(period+1, std::string::npos);
894        channelName = channelName.substr(0, period);
895    }
896    else
897    {
898        component.clear();
899
900        size_t first_parenthesis = channelName.find_first_of("(");
901        if (first_parenthesis != std::string::npos)
902        {
903            size_t open_parenthesis = first_parenthesis;
904
905            do
906            {
907                if (open_parenthesis != first_parenthesis) component += ",";
908
909                size_t close_parenthesis = channelName.find_first_of(")", open_parenthesis);
910                component += channelName.substr(open_parenthesis+1, close_parenthesis-open_parenthesis-1);
911                open_parenthesis = channelName.find_first_of("(", close_parenthesis);
912            }
913            while (open_parenthesis != std::string::npos);
914
915            channelName = channelName.substr(0, first_parenthesis);
916        }
917    }
918}
Note: See TracBrowser for help on using the browser.