2
0
Эх сурвалжийг харах

Merge pull request #2855 from felipeek/fix/collada-combining-animations

fix: Don't combine Collada animations when channels are shared
Kim Kulling 5 жил өмнө
parent
commit
185c2fde3c

+ 21 - 6
code/Collada/ColladaHelper.h

@@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <map>
 #include <vector>
+#include <set>
 #include <stdint.h>
 #include <assimp/light.h>
 #include <assimp/mesh.h>
@@ -658,23 +659,37 @@ struct Animation
 
 	void CombineSingleChannelAnimationsRecursively(Animation *pParent)
 	{
+		std::set<std::string> childrenTargets;
+		bool childrenAnimationsHaveDifferentChannels = true;
+
 		for (std::vector<Animation*>::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<Animation*>::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;
 			}
 		}
 	}

+ 23 - 3
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<size_t> 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<std::string> 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())
             {