fixed: auto_ptr -> unique_ptr
[opensg.git] / Source / System / FileIO / Collada / OSGColladaAnimation.cpp
blob8366d6369196902bb62ee81c9e5456e0a9e5d3dc
1 /*---------------------------------------------------------------------------*\
2 * OpenSG *
3 * *
4 * *
5 * Copyright (C) 2009 by the OpenSG Forum *
6 * *
7 * www.opensg.org *
8 * *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
10 * *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
13 * License *
14 * *
15 * This library is free software; you can redistribute it and/or modify it *
16 * under the terms of the GNU Library General Public License as published *
17 * by the Free Software Foundation, version 2. *
18 * *
19 * This library is distributed in the hope that it will be useful, but *
20 * WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
22 * Library General Public License for more details. *
23 * *
24 * You should have received a copy of the GNU Library General Public *
25 * License along with this library; if not, write to the Free Software *
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
27 * *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
30 * Changes *
31 * *
32 * *
33 * *
34 * *
35 * *
36 * *
37 \*---------------------------------------------------------------------------*/
39 #if __GNUC__ >= 4 || __GNUC_MINOR__ >=3
40 #pragma GCC diagnostic ignored "-Wold-style-cast"
41 #endif
43 #include "OSGColladaAnimation.h"
45 #ifdef OSG_WITH_COLLADA
47 #include "OSGColladaAnimationClip.h"
48 #include "OSGColladaGlobal.h"
49 #include "OSGColladaInstanceAnimation.h"
50 #include "OSGColladaLog.h"
51 #include "OSGColladaNode.h"
52 #include "OSGColladaSource.h"
54 #include "OSGAnimMatrixDataSource.h"
55 #include "OSGAnimQuaternionDataSource.h"
56 #include "OSGAnimVec3fDataSource.h"
57 #include "OSGAnimTargetAttachment.h"
59 #include "OSGNameAttachment.h"
61 #include <dom/domAnimation.h>
63 OSG_BEGIN_NAMESPACE
65 ColladaInstInfoTransitPtr
66 ColladaAnimation::ColladaAnimationInstInfo::create(
67 ColladaAnimationClip *colInstParent,
68 ColladaInstanceAnimation *colInst,
69 ColladaAnimation *colInstTarget,
70 AnimKeyFrameTemplate *animTmpl )
72 return ColladaInstInfoTransitPtr(
73 new ColladaAnimationInstInfo(colInstParent, colInst,
74 colInstTarget, animTmpl));
77 ColladaAnimation *
78 ColladaAnimation::ColladaAnimationInstInfo::getAnim(void) const
80 return _colInstTarget;
83 AnimKeyFrameTemplate *
84 ColladaAnimation::ColladaAnimationInstInfo::getTemplate(void) const
86 return _animTmpl;
89 void
90 ColladaAnimation::ColladaAnimationInstInfo::process(void)
92 #if !defined(OSG_USE_COLLADA_ANIMCLIP_INSTANCE_HACK)
93 ColladaAnimation *colAnim =
94 dynamic_cast<ColladaAnimation *>(getColInst()->getTargetElem());
95 OSG_ASSERT(colAnim != NULL);
97 colAnim->createInstance(this);
98 #else
99 OSG_ASSERT(getAnim() != NULL);
101 getAnim()->createInstance(this);
102 #endif
105 ColladaAnimation::ColladaAnimationInstInfo::ColladaAnimationInstInfo(
106 ColladaAnimationClip *colInstParent,
107 ColladaInstanceAnimation *colInst,
108 ColladaAnimation *colInstTarget,
109 AnimKeyFrameTemplate *animTmpl )
111 : Inherited (colInstParent, colInst)
112 , _colInstTarget(colInstTarget)
113 , _animTmpl (animTmpl)
117 ColladaAnimation::ColladaAnimationInstInfo::~ColladaAnimationInstInfo(void)
121 // ===========================================================================
123 ColladaElementRegistrationHelper ColladaAnimation::_regHelper(
124 &ColladaAnimation::create, "animation");
127 ColladaElementTransitPtr
128 ColladaAnimation::create(daeElement *elem, ColladaGlobal *global)
130 return ColladaElementTransitPtr(new ColladaAnimation(elem, global));
133 void
134 ColladaAnimation::read(ColladaElement *colElemParent)
136 domAnimationRef anim = getDOMElementAs<domAnimation>();
138 OSG_COLLADA_LOG(("ColladaAnimation::read id [%s]\n", anim->getId()));
140 readAnim(anim);
142 const domAnimation_Array &subAnims = anim->getAnimation_array();
144 for(UInt32 i = 0; i < subAnims.getCount(); ++i)
146 readAnim(subAnims[i]);
150 AnimKeyFrameTemplate *
151 ColladaAnimation::createInstance(ColladaInstInfo *colInstInfo)
153 domAnimationRef anim = getDOMElementAs<domAnimation>();
155 OSG_COLLADA_LOG(("ColladaAnimation::createInstance id [%s]\n",
156 anim->getId()));
158 ColladaAnimationInstInfo *colAnimInstInfo =
159 dynamic_cast<ColladaAnimationInstInfo *>(colInstInfo);
160 #if 0
161 ColladaAnimationClip *colAnimClip =
162 dynamic_cast<ColladaAnimationClip *>(colInstInfo->getColInstParent());
163 #endif
164 AnimKeyFrameTemplate *animTmpl =
165 colAnimInstInfo->getTemplate();
167 OSG_ASSERT(animTmpl != NULL);
169 createInstanceAnim(anim,
170 colInstInfo->getColInstParent(),
171 colInstInfo->getColInst (),
172 animTmpl );
174 const domAnimation_Array &subAnims = anim->getAnimation_array();
176 for(UInt32 i = 0; i < subAnims.getCount(); ++i)
178 createInstanceAnim(subAnims[i],
179 colInstInfo->getColInstParent(),
180 colInstInfo->getColInst (),
181 animTmpl );
184 editInstStore().push_back(animTmpl);
186 return animTmpl;
189 ColladaAnimation::ColladaAnimation(daeElement *elem, ColladaGlobal *global)
190 : Inherited (elem, global)
191 , _sourceMap()
195 ColladaAnimation::~ColladaAnimation(void)
199 void
200 ColladaAnimation::readAnim(domAnimation *anim)
202 OSG_COLLADA_LOG(("ColladaAnimation::readAnim id [%s]\n",
203 (anim->getId() != NULL ? anim->getId() : "") ));
205 const domSource_Array &sources = anim->getSource_array();
207 for(UInt32 i = 0; i < sources.getCount(); ++i)
209 ColladaSourceRefPtr colSource =
210 getUserDataAs<ColladaSource>(sources[i]);
212 if(colSource == NULL)
214 colSource = dynamic_pointer_cast<ColladaSource>(
215 ColladaElementFactory::the()->create(sources[i], getGlobal()));
217 colSource->read(this);
220 _sourceMap.insert(
221 SourceMap::value_type(sources[i]->getId(), colSource));
224 const domAnimation_Array &subAnims = anim->getAnimation_array();
226 for(UInt32 i = 0; i < subAnims.getCount(); ++i)
228 readAnim(subAnims[i]);
232 void
233 ColladaAnimation::createInstanceAnim(
234 domAnimation *anim, ColladaElement *colInstParent,
235 ColladaInstanceElement *colInst, AnimKeyFrameTemplate *animTmpl )
237 ColladaAnimationClip *colAnimClip =
238 dynamic_cast<ColladaAnimationClip *>(colInstParent);
239 const domChannel_Array &channels = anim->getChannel_array();
241 for(UInt32 i = 0; i < channels.getCount(); ++i)
243 daeURI samplerURI = channels[i]->getSource();
244 domSamplerRef sampler =
245 daeSafeCast<domSampler>(samplerURI.getElement());
247 if(sampler == NULL)
249 SWARNING << "ColladaAnimation::createInstanceAnim: Could not "
250 << "find <sampler> [" << samplerURI.str()
251 << "] for <channel> [" << i << "] in animation id ["
252 << (anim->getId() != NULL ? anim->getId() : "")
253 << std::endl;
254 continue;
257 DataSourceInfo dsInfo;
259 createDataSource(channels[i], sampler, dsInfo);
261 handleInput (channels[i], sampler, colAnimClip, animTmpl, dsInfo);
262 handleOutput (channels[i], sampler, animTmpl, dsInfo);
263 handleInterpolation(channels[i], sampler, animTmpl, dsInfo);
265 if(dsInfo._dataSource == NULL)
267 SWARNING << "ColladaAnimation::createInstanceAnim: Failed to "
268 << "create a data source for <channel> [" << i
269 << "]. Ignoring." << std::endl;
270 continue;
273 OSG_COLLADA_LOG(("ColladaAnimation::createInstanceAnim: Filled "
274 "data source for channel [%d] target [%s]\n",
275 i, channels[i]->getTarget()));
277 animTmpl->editMFSources ()->push_back(dsInfo._dataSource);
278 animTmpl->editMFTargetIds()->push_back(dsInfo._target );
281 domAnimation_clipRef animClip =
282 colAnimClip->getDOMElementAs<domAnimation_clip>();
284 animTmpl->setName(animClip->getName());
287 void
288 ColladaAnimation::createDataSource(
289 domChannel *channel, domSampler *sampler, DataSourceInfo &dsInfo)
291 domInputLocalRef input = findInput(sampler, "OUTPUT");
293 if(input == NULL)
295 SWARNING << "ColladaAnimation::createDataSource: No <input> "
296 << "with semantic OUTPUT in <sampler> ["
297 << (sampler->getId() != NULL ? sampler->getId() : "")
298 << "]." << std::endl;
299 return;
302 std::string sourceId = input->getSource().id();
303 SourceMapConstIt smIt = _sourceMap.find(sourceId);
305 if(smIt == _sourceMap.end())
307 SWARNING << "ColladaAnimation::createDataSource: No <source> "
308 << "with id [" << sourceId << "] found." << std::endl;
309 return;
312 std::string fieldSuffix;
313 std::string target (channel->getTarget() );
314 daeSidRef targetRef(target, getGlobal()->getDocRoot());
315 daeElement *targetElem = targetRef.resolve().elt;
317 if(targetElem == NULL)
319 SWARNING << "ColladaAnimation::createDataSource: Could not resolve ["
320 << target << "]. Ignoring" << std::endl;
321 return;
324 if(targetElem->typeID() == domMatrix::ID())
326 dsInfo._target = channel->getTarget() + std::string(".matrix");
327 dsInfo._dataSource = AnimMatrixDataSource::create();
329 else if(targetElem->typeID() == domTranslate::ID())
331 dsInfo._target = channel->getTarget() + std::string(".translate");
332 dsInfo._dataSource = AnimVec3fDataSource::create();
334 else if(targetElem->typeID() == domRotate::ID())
336 dsInfo._target = channel->getTarget() + std::string(".rotate");
337 dsInfo._dataSource = AnimQuaternionDataSource::create();
339 else
341 dsInfo._dataSource = NULL;
343 SWARNING << "ColladaAnimation::createDataSource: Target [" << target
344 << "] has unhandled type [" << targetElem->typeID()
345 << "]. Ignoring" << std::endl;
346 return;
349 // make sure the target has a AnimTargetAttachment on it
350 daeElement *targetParentElem = targetElem->getParentElement();
351 domNode *parentNode = daeSafeCast<domNode>(targetParentElem);
353 if(parentNode == NULL)
355 SWARNING << "ColladaAnimation::createDataSource: Target [" << target
356 << "] does not have a parent <node>.\n" << std::endl;
357 return;
360 ColladaNodeRefPtr colNode = getUserDataAs<ColladaNode>(parentNode);
362 if(colNode == NULL)
364 SWARNING << "ColladaAnimation::createDataSource: Parent <node> for "
365 << "target [" << target << "] has no ColladaNode structure."
366 << std::endl;
367 return;
370 std::string::size_type slashPos = target.find('/');
371 std::string targetSID = target.substr(slashPos + 1);
373 Node *targetNode = colNode->getNodeBySid(0, targetSID);
375 if(targetNode == NULL)
377 SWARNING << "ColladaAnimation::createDataSource: Could not find "
378 << "node for sid [" << targetSID << "]." << std::endl;
379 return;
382 NodeCore *targetCore = targetNode->getCore();
383 setTargetId(targetCore, target);
385 OSG_COLLADA_LOG(("ColladaAnimation::createDataSource: Setting "
386 "AnimTargetAttachment targetId [%s] for core [%p] node [%p] [%s]\n",
387 target.c_str(), targetCore, targetNode,
388 (getName(targetNode) != NULL ? getName(targetNode) : "")));
391 void
392 ColladaAnimation::handleInput(
393 domChannel *channel, domSampler *sampler,
394 ColladaAnimationClip *colAnimClip, AnimKeyFrameTemplate *animTmpl,
395 DataSourceInfo &dsInfo )
397 if(dsInfo._dataSource == NULL)
398 return;
400 domInputLocalRef input = findInput(sampler, "INPUT");
402 if(input == NULL)
404 SWARNING << "ColladaAnimation::handleInput: No <input> "
405 << "with semantic INPUT in sampler ["
406 << (sampler->getId() != NULL ? sampler->getId() : "")
407 << "]. Ignoring." << std::endl;
408 return;
411 Real32 startT =
412 colAnimClip->getDOMElementAs<domAnimation_clip>()->getStart();
413 Real32 endT =
414 colAnimClip->getDOMElementAs<domAnimation_clip>()->getEnd ();
416 std::string sourceId = input->getSource().id();
417 SourceMapConstIt smIt = _sourceMap.find(sourceId);
419 if(smIt == _sourceMap.end())
421 SWARNING << "ColladaAnimation::handleInput: No <source> "
422 << "with id [" << sourceId << "] found." << std::endl;
423 return;
426 const ColladaSource::FloatStore &inputStore = smIt->second->getFloatStore();
428 ColladaSource::FloatStoreConstIt startIt =
429 std::lower_bound(inputStore.begin(), inputStore.end(), startT);
430 ColladaSource::FloatStoreConstIt endIt =
431 std::upper_bound(inputStore.begin(), inputStore.end(), endT );
433 dsInfo._firstKey = std::distance(inputStore.begin(), startIt);
434 dsInfo._lastKey = std::distance(inputStore.begin(), endIt );
436 OSG_COLLADA_LOG(("ColladaAnimation::handleInput: "
437 "Using key range [%d %d] [%f %f] [%f %f] of [0 %"
438 PRISize"]\n",
439 dsInfo._firstKey, dsInfo._lastKey,
440 inputStore[dsInfo._firstKey ],
441 inputStore[dsInfo._lastKey - 1],
442 startT, endT, inputStore.size()));
444 for(UInt32 i = dsInfo._firstKey; i < dsInfo._lastKey; ++i)
446 dsInfo._dataSource->editMFInValues()->push_back(inputStore[i]);
451 void
452 ColladaAnimation::handleOutput(
453 domChannel *channel, domSampler *sampler,
454 AnimKeyFrameTemplate *animTmpl, DataSourceInfo &dsInfo )
456 if(dsInfo._dataSource == NULL)
457 return;
459 domInputLocalRef input = findInput(sampler, "OUTPUT");
461 if(input == NULL)
463 SWARNING << "ColladaAnimation::handleOutput: No <input> "
464 << "with semantic OUTPUT in <sampler> ["
465 << (sampler->getId() != NULL ? sampler->getId() : "")
466 << "]." << std::endl;
467 return;
470 std::string sourceId = input->getSource().id();
471 SourceMapConstIt smIt = _sourceMap.find(sourceId);
473 if(smIt == _sourceMap.end())
475 SWARNING << "ColladaAnimation::handleOutput: No <source> "
476 << "with id [" << sourceId << "] found." << std::endl;
477 return;
480 AnimMatrixDataSourceRefPtr matrixDS =
481 dynamic_pointer_cast<AnimMatrixDataSource>(dsInfo._dataSource);
482 AnimVec3fDataSourceRefPtr vec3fDS =
483 dynamic_pointer_cast<AnimVec3fDataSource>(dsInfo._dataSource);
484 AnimQuaternionDataSourceRefPtr quatDS =
485 dynamic_pointer_cast<AnimQuaternionDataSource>(dsInfo._dataSource);
487 if(matrixDS != NULL)
489 #if defined(OSG_USE_COLLADA_ANIMCLIP_INSTANCE_HACK)
490 bool noAnim = true;
491 #endif
493 ColladaSource::MatrixStoreConstIt matIt =
494 smIt->second->getMatrixStore().begin() + dsInfo._firstKey;
495 ColladaSource::MatrixStoreConstIt matEnd =
496 smIt->second->getMatrixStore().begin() + dsInfo._lastKey;
498 #if defined(OSG_USE_COLLADA_ANIMCLIP_INSTANCE_HACK)
499 // remove animations that do not change during the clip we instantiate
500 // them from
502 for(; matIt != matEnd; ++matIt)
504 if(*matIt != smIt->second->getMatrixStore()[dsInfo._firstKey])
506 noAnim = false;
507 break;
512 if(noAnim == true)
514 OSG_COLLADA_LOG(("ColladaAnimation::handleOutput: No anim for "
515 "current clip - skipping animation\n"));
517 dsInfo._dataSource = NULL;
518 return;
521 matIt = smIt->second->getMatrixStore().begin() + dsInfo._firstKey;
522 matEnd = smIt->second->getMatrixStore().begin() + dsInfo._lastKey;
523 #endif
525 for(; matIt != matEnd; ++matIt)
527 matrixDS->editMFValues()->push_back(*matIt);
531 else if(vec3fDS != NULL)
533 SWARNING << "ColladaAnimation::handleOutput: Vec3fDataSource NIY"
534 << std::endl;
536 else if(quatDS != NULL)
538 SWARNING << "ColladaAnimation::handleOutput: QuaternionDataSource NIY"
539 << std::endl;
541 else
543 SWARNING << "ColladaAnimation::handleOutput: Unknown DataSource type."
544 << std::endl;
548 void
549 ColladaAnimation::handleInterpolation(
550 domChannel *channel, domSampler *sampler,
551 AnimKeyFrameTemplate *animTmpl, DataSourceInfo &dsInfo )
553 if(dsInfo._dataSource == NULL)
554 return;
556 domInputLocalRef input = findInput(sampler, "INTERPOLATION");
558 if(input == NULL)
560 SWARNING << "ColladaAnimation::handleInterpolation: No <input> "
561 << "with semantic INTERPOLATION in <sampler> ["
562 << (sampler->getId() != NULL ? sampler->getId() : "")
563 << "]." << std::endl;
564 return;
567 std::string sourceId = input->getSource().id();
568 SourceMapConstIt smIt = _sourceMap.find(sourceId);
570 if(smIt == _sourceMap.end())
572 SWARNING << "ColladaAnimation::handleInterpolation: No <source> "
573 << "with id [" << sourceId << "] found." << std::endl;
574 return;
577 // check if all values are the same
578 bool singleVal = true;
579 const ColladaSource::NameStore &interpol =
580 smIt->second->getNameStore();
581 ColladaSource::NameStoreConstIt iIt = interpol.begin() + dsInfo._firstKey;
582 ColladaSource::NameStoreConstIt iEnd = interpol.begin() + dsInfo._lastKey;
584 for(; iIt != iEnd; ++iIt)
586 if(interpol[dsInfo._firstKey] != *iIt)
588 singleVal = false;
589 break;
593 iIt = interpol.begin() + dsInfo._firstKey;
594 iEnd = interpol.begin() + dsInfo._lastKey;
596 for(; iIt != iEnd; ++iIt)
598 if(*iIt == "STEP")
600 dsInfo._dataSource->editMFInterpolationModes()->push_back(
601 AnimKeyFrameDataSource::IM_Step);
603 else if(*iIt == "LINEAR")
605 dsInfo._dataSource->editMFInterpolationModes()->push_back(
606 AnimKeyFrameDataSource::IM_Linear);
608 else if(*iIt == "BEZIER")
610 dsInfo._dataSource->editMFInterpolationModes()->push_back(
611 AnimKeyFrameDataSource::IM_Bezier);
613 else if(*iIt == "HERMITE")
615 dsInfo._dataSource->editMFInterpolationModes()->push_back(
616 AnimKeyFrameDataSource::IM_Hermite);
618 else
620 SWARNING << "ColladdaAnimation::handleInterpolation: "
621 << "unknown interpolation mode [" << *iIt
622 << "]. Using LINEAR instead." << std::endl;
624 dsInfo._dataSource->editMFInterpolationModes()->push_back(
625 AnimKeyFrameDataSource::IM_Linear);
628 // stop after one value if they are all the same
629 if(singleVal == true)
630 break;
634 /*! Find an <input> with the given semantic in the given sampler.
636 domInputLocal *
637 ColladaAnimation::findInput(domSampler *sampler, const std::string &semantic)
639 domInputLocal *retVal = NULL;
640 const domInputLocal_Array &inputs = sampler->getInput_array();
642 for(UInt32 i = 0; i < inputs.getCount(); ++i)
644 std::string inputSem = inputs[i]->getSemantic();
646 if(semantic == inputSem)
648 retVal = inputs[i];
649 break;
653 return retVal;
656 OSG_END_NAMESPACE
658 #endif // OSG_WITH_COLLADA