Collada: Importer generates animations from <library_animation_clips>, if the node is present.
parent
2466ae6c2e
commit
c34717639e
|
@ -597,6 +597,18 @@ struct Animation
|
|||
for( std::vector<Animation*>::iterator it = mSubAnims.begin(); it != mSubAnims.end(); ++it)
|
||||
delete *it;
|
||||
}
|
||||
|
||||
void CollectChannelsRecursively(std::vector<AnimationChannel> &channels)
|
||||
{
|
||||
channels.insert(channels.end(), mChannels.begin(), mChannels.end());
|
||||
|
||||
for (std::vector<Animation*>::iterator it = mSubAnims.begin(); it != mSubAnims.end(); ++it)
|
||||
{
|
||||
Animation *pAnim = (*it);
|
||||
|
||||
pAnim->CollectChannelsRecursively(channels);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/** Description of a collada animation channel which has been determined to affect the current node */
|
||||
|
|
|
@ -187,6 +187,8 @@ void ColladaParser::ReadStructure()
|
|||
ReadAssetInfo();
|
||||
else if( IsElement( "library_animations"))
|
||||
ReadAnimationLibrary();
|
||||
else if (IsElement("library_animation_clips"))
|
||||
ReadAnimationClipLibrary();
|
||||
else if( IsElement( "library_controllers"))
|
||||
ReadControllerLibrary();
|
||||
else if( IsElement( "library_images"))
|
||||
|
@ -271,6 +273,131 @@ void ColladaParser::ReadAssetInfo()
|
|||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Reads the animation clips
|
||||
void ColladaParser::ReadAnimationClipLibrary()
|
||||
{
|
||||
if (mReader->isEmptyElement())
|
||||
return;
|
||||
|
||||
while (mReader->read())
|
||||
{
|
||||
if (mReader->getNodeType() == irr::io::EXN_ELEMENT)
|
||||
{
|
||||
if (IsElement("animation_clip"))
|
||||
{
|
||||
// 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_" + mAnimationClipLibrary.size();
|
||||
|
||||
std::pair<std::string, std::vector<std::string>> clip;
|
||||
|
||||
clip.first = animName;
|
||||
|
||||
while (mReader->read())
|
||||
{
|
||||
if (mReader->getNodeType() == irr::io::EXN_ELEMENT)
|
||||
{
|
||||
if (IsElement("instance_animation"))
|
||||
{
|
||||
int indexUrl = TestAttribute("url");
|
||||
if (indexUrl >= 0)
|
||||
{
|
||||
const char* url = mReader->getAttributeValue(indexUrl);
|
||||
if (url[0] != '#')
|
||||
ThrowException("Unknown reference format");
|
||||
|
||||
url++;
|
||||
|
||||
clip.second.push_back(url);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// ignore the rest
|
||||
SkipElement();
|
||||
}
|
||||
}
|
||||
else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
|
||||
{
|
||||
if (strcmp(mReader->getNodeName(), "animation_clip") != 0)
|
||||
ThrowException("Expected end of <animation_clip> element.");
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (clip.second.size() > 0)
|
||||
{
|
||||
mAnimationClipLibrary.push_back(clip);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// ignore the rest
|
||||
SkipElement();
|
||||
}
|
||||
}
|
||||
else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
|
||||
{
|
||||
if (strcmp(mReader->getNodeName(), "library_animation_clips") != 0)
|
||||
ThrowException("Expected end of <library_animation_clips> element.");
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Re-build animations from animation clip library, if present.
|
||||
void ColladaParser::RebuildRootAnimationsFromClips()
|
||||
{
|
||||
if (mAnimationClipLibrary.size() > 0)
|
||||
{
|
||||
Animation temp;
|
||||
|
||||
for (AnimationClipLibrary::iterator it = mAnimationClipLibrary.begin(); it != mAnimationClipLibrary.end(); ++it)
|
||||
{
|
||||
std::string clipName = it->first;
|
||||
|
||||
printf("Clip: %s\n", clipName.c_str());
|
||||
|
||||
Animation *clip = new Animation();
|
||||
clip->mName = clipName;
|
||||
|
||||
temp.mSubAnims.push_back(clip);
|
||||
|
||||
for (std::vector<std::string>::iterator a = it->second.begin(); a != it->second.end(); ++a)
|
||||
{
|
||||
std::string animationID = *a;
|
||||
|
||||
printf(" Animation instance: %s\n", animationID.c_str());
|
||||
|
||||
AnimationLibrary::iterator animation = mAnimationLibrary.find(animationID);
|
||||
|
||||
if (animation != mAnimationLibrary.end())
|
||||
{
|
||||
Animation *pSourceAnimation = animation->second;
|
||||
|
||||
pSourceAnimation->CollectChannelsRecursively(clip->mChannels);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mAnims = temp;
|
||||
|
||||
// Ensure no double deletes.
|
||||
temp.mSubAnims.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Reads the animation library
|
||||
void ColladaParser::ReadAnimationLibrary()
|
||||
|
@ -318,12 +445,17 @@ void ColladaParser::ReadAnimation( Collada::Animation* pParent)
|
|||
|
||||
// optional name given as an attribute
|
||||
std::string animName;
|
||||
std::string animID;
|
||||
int indexName = TestAttribute( "name");
|
||||
int indexID = TestAttribute( "id");
|
||||
|
||||
if (indexID >= 0)
|
||||
animID = mReader->getAttributeValue(indexID);
|
||||
|
||||
if( indexName >= 0)
|
||||
animName = mReader->getAttributeValue( indexName);
|
||||
else if( indexID >= 0)
|
||||
animName = mReader->getAttributeValue( indexID);
|
||||
animName = animID;
|
||||
else
|
||||
animName = "animation";
|
||||
|
||||
|
@ -395,11 +527,17 @@ void ColladaParser::ReadAnimation( Collada::Animation* pParent)
|
|||
// it turned out to have channels - add them
|
||||
if( !channels.empty())
|
||||
{
|
||||
// FIXME: Is this essentially doing the same as "single-anim-node" codepath in
|
||||
// ColladaLoader::StoreAnimations? If not, defer this to where animation
|
||||
// clip instances are set up. Due to handling of <library_animation_clips>
|
||||
// this cannot be done here, as the channel owner is lost.
|
||||
/*
|
||||
// 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)
|
||||
|
@ -410,6 +548,11 @@ void ColladaParser::ReadAnimation( Collada::Animation* pParent)
|
|||
}
|
||||
for( ChannelMap::const_iterator it = channels.begin(); it != channels.end(); ++it)
|
||||
anim->mChannels.push_back( it->second);
|
||||
|
||||
if (indexID >= 0)
|
||||
{
|
||||
mAnimationLibrary[animID] = anim;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,6 +82,12 @@ namespace Assimp
|
|||
|
||||
/** Reads the animation library */
|
||||
void ReadAnimationLibrary();
|
||||
|
||||
/** Reads the animation clip library */
|
||||
void ReadAnimationClipLibrary();
|
||||
|
||||
/** Re-build animations from animation clip library, if present */
|
||||
void RebuildRootAnimationsFromClips();
|
||||
|
||||
/** Reads an animation into the given parent structure */
|
||||
void ReadAnimation( Collada::Animation* pParent);
|
||||
|
@ -312,6 +318,14 @@ namespace Assimp
|
|||
/** Controller library: joint controllers by ID */
|
||||
typedef std::map<std::string, Collada::Controller> ControllerLibrary;
|
||||
ControllerLibrary mControllerLibrary;
|
||||
|
||||
/** Animation library: animation references by ID */
|
||||
typedef std::map<std::string, Collada::Animation*> AnimationLibrary;
|
||||
AnimationLibrary mAnimationLibrary;
|
||||
|
||||
/** Animation clip library: clip animation references by ID */
|
||||
typedef std::vector<std::pair<std::string, std::vector<std::string>>> AnimationClipLibrary;
|
||||
AnimationClipLibrary mAnimationClipLibrary;
|
||||
|
||||
/** Pointer to the root node. Don't delete, it just points to one of
|
||||
the nodes in the node library. */
|
||||
|
|
Loading…
Reference in New Issue