diff --git a/code/Collada/ColladaHelper.h b/code/Collada/ColladaHelper.h index b7d47da15..6c2154102 100644 --- a/code/Collada/ColladaHelper.h +++ b/code/Collada/ColladaHelper.h @@ -647,23 +647,37 @@ struct Animation void CombineSingleChannelAnimationsRecursively(Animation *pParent) { + std::set childrenTargets; + bool childrenAnimationsHaveDifferentChannels = true; + for (std::vector::iterator it = pParent->mSubAnims.begin(); it != pParent->mSubAnims.end();) { Animation *anim = *it; - CombineSingleChannelAnimationsRecursively(anim); - if (anim->mChannels.size() == 1) + if (childrenAnimationsHaveDifferentChannels && anim->mChannels.size() == 1 && + childrenTargets.find(anim->mChannels[0].mTarget) == childrenTargets.end()) { + childrenTargets.insert(anim->mChannels[0].mTarget); + } else { + childrenAnimationsHaveDifferentChannels = false; + } + + ++it; + } + + // We only want to combine animations if they have different channels + if (childrenAnimationsHaveDifferentChannels) + { + for (std::vector::iterator it = pParent->mSubAnims.begin(); it != pParent->mSubAnims.end();) { + Animation *anim = *it; + pParent->mChannels.push_back(anim->mChannels[0]); it = pParent->mSubAnims.erase(it); delete anim; - } - else - { - ++it; + continue; } } } diff --git a/code/Collada/ColladaLoader.cpp b/code/Collada/ColladaLoader.cpp index 37529bc98..0d8aa47c4 100644 --- a/code/Collada/ColladaLoader.cpp +++ b/code/Collada/ColladaLoader.cpp @@ -963,18 +963,38 @@ void ColladaLoader::StoreAnimations( aiScene* pScene, const ColladaParser& pPars // catch special case: many animations with the same length, each affecting only a single node. // we need to unite all those single-node-anims to a proper combined animation - for( size_t a = 0; a < mAnims.size(); ++a) { + for(size_t a = 0; a < mAnims.size(); ++a) { aiAnimation* templateAnim = mAnims[a]; - if( templateAnim->mNumChannels == 1) { + + if (templateAnim->mNumChannels == 1) { // search for other single-channel-anims with the same duration std::vector collectedAnimIndices; for( size_t b = a+1; b < mAnims.size(); ++b) { aiAnimation* other = mAnims[b]; if (other->mNumChannels == 1 && other->mDuration == templateAnim->mDuration && other->mTicksPerSecond == templateAnim->mTicksPerSecond) - collectedAnimIndices.push_back(b); + collectedAnimIndices.push_back(b); } + // We only want to combine the animations if they have different channels + std::set animTargets; + animTargets.insert(templateAnim->mChannels[0]->mNodeName.C_Str()); + bool collectedAnimationsHaveDifferentChannels = true; + for (size_t b = 0; b < collectedAnimIndices.size(); ++b) + { + aiAnimation* srcAnimation = mAnims[collectedAnimIndices[b]]; + std::string channelName = std::string(srcAnimation->mChannels[0]->mNodeName.C_Str()); + if (animTargets.find(channelName) == animTargets.end()) { + animTargets.insert(channelName); + } else { + collectedAnimationsHaveDifferentChannels = false; + break; + } + } + + if (!collectedAnimationsHaveDifferentChannels) + continue; + // if there are other animations which fit the template anim, combine all channels into a single anim if (!collectedAnimIndices.empty()) {