ソースを参照

- Bugfix: Collada-Loader now also reads animations containing multiple channels
- Bugfix: Collada-Loader new resolves subelement animation channels correctly
- silenced some warnings in the B3DImporter code. There are a lot more over there, though.

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@459 67173fc5-114c-0410-ac8e-9d2fd5bffc1f

ulfjorensen 16 年 前
コミット
3f2fa97f18
3 ファイル変更52 行追加13 行削除
  1. 4 0
      code/B3DImporter.cpp
  2. 8 2
      code/ColladaLoader.cpp
  3. 40 11
      code/ColladaParser.cpp

+ 4 - 0
code/B3DImporter.cpp

@@ -123,6 +123,7 @@ void B3DImporter::Fail( string str ){
 int B3DImporter::ReadByte(){
 	if( _pos<_buf.size() ) return _buf[_pos++];
 	Fail( "EOF" );
+	return 0;
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -133,6 +134,7 @@ int B3DImporter::ReadInt(){
 		return n;
 	}
 	Fail( "EOF" );
+	return 0;
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -143,6 +145,7 @@ float B3DImporter::ReadFloat(){
 		return n;
 	}
 	Fail( "EOF" );
+	return 0.0f;
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -178,6 +181,7 @@ string B3DImporter::ReadString(){
 		str+=c;
 	}
 	Fail( "EOF" );
+	return string();
 }
 
 // ------------------------------------------------------------------------------------------------

+ 8 - 2
code/ColladaLoader.cpp

@@ -844,8 +844,8 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
 				continue;
 			if( srcChannel.mTarget.find( '/', slashPos+1) != std::string::npos)
 				continue;
-			std::string targetName = srcChannel.mTarget.substr( 0, slashPos);
-			if( targetName != nodeName)
+			std::string targetID = srcChannel.mTarget.substr( 0, slashPos);
+			if( targetID != srcNode->mID)
 				continue;
 
 			// find the dot that separates the transformID - there should be only one or zero
@@ -860,6 +860,12 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
 				std::string subElement = srcChannel.mTarget.substr( dotPos+1);
 				if( subElement == "ANGLE")
 					entry.mSubElement = 3; // last number in an Axis-Angle-Transform is the angle
+				else if( subElement == "X")
+					entry.mSubElement = 0;
+				else if( subElement == "Y")
+					entry.mSubElement = 1;
+				else if( subElement == "Z")
+					entry.mSubElement = 2;
 				else 
 					DefaultLogger::get()->warn( boost::str( boost::format( "Unknown anim subelement \"%s\". Ignoring") % subElement));
 			} else

+ 40 - 11
code/ColladaParser.cpp

@@ -270,8 +270,9 @@ void ColladaParser::ReadAnimationLibrary()
 void ColladaParser::ReadAnimation( Collada::Animation* pParent)
 {
 	// an <animation> element may be a container for grouping sub-elements or an animation channel
-	// this is the channel we're writing to, in case it's a channel
-	AnimationChannel channel;
+	// this is the channel collection by ID, in case it has channels
+	typedef std::map<std::string, AnimationChannel> ChannelMap;
+	ChannelMap channels;
 	// this is the anim container in case we're a container
 	Animation* anim = NULL;
 
@@ -311,8 +312,13 @@ void ColladaParser::ReadAnimation( Collada::Animation* pParent)
 			} 
 			else if( IsElement( "sampler"))
 			{
-				// have it read into our channel
-				ReadAnimationSampler( channel);
+				// read the ID to assign the corresponding collada channel afterwards.
+				int indexID = GetAttribute( "id");
+				std::string id = mReader->getAttributeValue( indexID);
+				ChannelMap::iterator newChannel = channels.insert( std::make_pair( id, AnimationChannel())).first;
+
+				// have it read into a channel
+				ReadAnimationSampler( newChannel->second);
 			} 
 			else if( IsElement( "channel"))
 			{
@@ -320,7 +326,13 @@ void ColladaParser::ReadAnimation( Collada::Animation* pParent)
 				// Thanks, Collada! A directly posted information would have been too simple, I guess.
 				// Better add another indirection to that! Can't have enough of those.
 				int indexTarget = GetAttribute( "target");
-				channel.mTarget = mReader->getAttributeValue( indexTarget);
+				int indexSource = GetAttribute( "source");
+				const char* sourceId = mReader->getAttributeValue( indexSource);
+				if( sourceId[0] == '#')
+					sourceId++;
+				ChannelMap::iterator cit = channels.find( sourceId);
+				if( cit != channels.end())
+					cit->second.mTarget = mReader->getAttributeValue( indexTarget);
 
 				if( !mReader->isEmptyElement())
 					SkipElement();
@@ -340,9 +352,26 @@ void ColladaParser::ReadAnimation( Collada::Animation* pParent)
 		}
 	}
 
-	// it turned out to be a channel - add it
-	if( !channel.mTarget.empty())
-		pParent->mChannels.push_back( channel);
+	// it turned out to have channels - add them
+	if( !channels.empty())
+	{
+		// special filtering for stupid exporters packing each channel into a separate animation
+		if( channels.size() == 1)
+		{
+			pParent->mChannels.push_back( channels.begin()->second);
+		} else
+		{
+			// else create the animation, if not done yet, and store the channels
+			if( !anim)
+			{
+				anim = new Animation;
+				anim->mName = animName;
+				pParent->mSubAnims.push_back( anim);
+			}
+			for( ChannelMap::const_iterator it = channels.begin(); it != channels.end(); ++it)
+				anim->mChannels.push_back( it->second);
+		}
+	}
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -2364,10 +2393,10 @@ void ColladaParser::ReadNodeGeometry( Node* pNode)
 					int attrMaterial = GetAttribute( "target");
 					const char* urlMat = mReader->getAttributeValue( attrMaterial);
 					Collada::SemanticMappingTable s;
-					if( urlMat[0] != '#')
-						ThrowException( "Unknown reference format");
+					if( urlMat[0] == '#')
+            urlMat++;
 
-					s.mMatName = urlMat+1;
+					s.mMatName = urlMat;
 
 					// resolve further material details + THIS UGLY AND NASTY semantic mapping stuff
 					if( !mReader->isEmptyElement())