- Collada loader now supports node animations

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@375 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
This commit is contained in:
ulfjorensen
2009-04-06 17:00:03 +00:00
parent 29c33760e4
commit e471b966c5
5 changed files with 584 additions and 17 deletions

View File

@@ -160,6 +160,8 @@ void ColladaParser::ReadStructure()
if( mReader->getNodeType() == irr::io::EXN_ELEMENT) {
if( IsElement( "asset"))
ReadAssetInfo();
else if( IsElement( "library_animations"))
ReadAnimationLibrary();
else if( IsElement( "library_controllers"))
ReadControllerLibrary();
else if( IsElement( "library_images"))
@@ -235,6 +237,153 @@ void ColladaParser::ReadAssetInfo()
}
}
// ------------------------------------------------------------------------------------------------
// Reads the animation library
void ColladaParser::ReadAnimationLibrary()
{
while( mReader->read())
{
if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
{
if( IsElement( "animation"))
{
// delegate the reading. Depending on the inner elements it will be a container or a anim channel
ReadAnimation( &mAnims);
} else
{
// ignore the rest
SkipElement();
}
}
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
{
if( strcmp( mReader->getNodeName(), "library_animations") != 0)
ThrowException( "Expected end of \"library_animations\" element.");
break;
}
}
}
// ------------------------------------------------------------------------------------------------
// Reads an animation into the given parent structure
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 anim container in case we're a container
Animation* anim = NULL;
// optional name given as an attribute
std::string animName;
int indexName = TestAttribute( "name");
int indexID = TestAttribute( "id");
if( indexName >= 0)
animName = mReader->getAttributeValue( indexName);
else if( indexID >= 0)
animName = mReader->getAttributeValue( indexID);
else
animName = "animation";
while( mReader->read())
{
if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
{
// we have subanimations
if( IsElement( "animation"))
{
// create container from our element
if( !anim)
{
anim = new Animation;
anim->mName = animName;
pParent->mSubAnims.push_back( anim);
}
// recurse into the subelement
ReadAnimation( anim);
}
else if( IsElement( "source"))
{
// possible animation data - we'll never know. Better store it
ReadSource();
}
else if( IsElement( "sampler"))
{
// have it read into our channel
ReadAnimationSampler( channel);
}
else if( IsElement( "channel"))
{
// the binding element whose whole purpose is to provide the target to animate
// 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);
}
else
{
// ignore the rest
SkipElement();
}
}
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
{
if( strcmp( mReader->getNodeName(), "animation") != 0)
ThrowException( "Expected end of \"animation\" element.");
break;
}
}
// it turned out to be a channel - add it
if( !channel.mTarget.empty())
pParent->mChannels.push_back( channel);
}
// ------------------------------------------------------------------------------------------------
// Reads an animation sampler into the given anim channel
void ColladaParser::ReadAnimationSampler( Collada::AnimationChannel& pChannel)
{
while( mReader->read())
{
if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
{
if( IsElement( "input"))
{
int indexSemantic = GetAttribute( "semantic");
const char* semantic = mReader->getAttributeValue( indexSemantic);
int indexSource = GetAttribute( "source");
const char* source = mReader->getAttributeValue( indexSource);
if( source[0] != '#')
ThrowException( "Unsupported URL format");
source++;
if( strcmp( semantic, "INPUT") == 0)
pChannel.mSourceTimes = source;
else if( strcmp( semantic, "OUTPUT") == 0)
pChannel.mSourceValues = source;
if( !mReader->isEmptyElement())
SkipElement();
}
else
{
// ignore the rest
SkipElement();
}
}
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
{
if( strcmp( mReader->getNodeName(), "sampler") != 0)
ThrowException( "Expected end of \"sampler\" element.");
break;
}
}
}
// ------------------------------------------------------------------------------------------------
// Reads the skeleton controller library
void ColladaParser::ReadControllerLibrary()
@@ -2072,13 +2221,19 @@ void ColladaParser::ReadNodeTransformation( Node* pNode, TransformType pType)
{
std::string tagName = mReader->getNodeName();
Transform tf;
tf.mType = pType;
// read SID
int indexSID = TestAttribute( "sid");
if( indexSID >= 0)
tf.mID = mReader->getAttributeValue( indexSID);
// how many parameters to read per transformation type
static const unsigned int sNumParameters[] = { 9, 4, 3, 3, 7, 16 };
const char* content = GetTextContent();
// read as many parameters and store in the transformation
Transform tf;
tf.mType = pType;
for( unsigned int a = 0; a < sNumParameters[pType]; a++)
{
// read a number