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)
|
for( std::vector<Animation*>::iterator it = mSubAnims.begin(); it != mSubAnims.end(); ++it)
|
||||||
delete *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 */
|
/** Description of a collada animation channel which has been determined to affect the current node */
|
||||||
|
|
|
@ -187,6 +187,8 @@ void ColladaParser::ReadStructure()
|
||||||
ReadAssetInfo();
|
ReadAssetInfo();
|
||||||
else if( IsElement( "library_animations"))
|
else if( IsElement( "library_animations"))
|
||||||
ReadAnimationLibrary();
|
ReadAnimationLibrary();
|
||||||
|
else if (IsElement("library_animation_clips"))
|
||||||
|
ReadAnimationClipLibrary();
|
||||||
else if( IsElement( "library_controllers"))
|
else if( IsElement( "library_controllers"))
|
||||||
ReadControllerLibrary();
|
ReadControllerLibrary();
|
||||||
else if( IsElement( "library_images"))
|
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
|
// Reads the animation library
|
||||||
void ColladaParser::ReadAnimationLibrary()
|
void ColladaParser::ReadAnimationLibrary()
|
||||||
|
@ -318,12 +445,17 @@ void ColladaParser::ReadAnimation( Collada::Animation* pParent)
|
||||||
|
|
||||||
// optional name given as an attribute
|
// optional name given as an attribute
|
||||||
std::string animName;
|
std::string animName;
|
||||||
|
std::string animID;
|
||||||
int indexName = TestAttribute( "name");
|
int indexName = TestAttribute( "name");
|
||||||
int indexID = TestAttribute( "id");
|
int indexID = TestAttribute( "id");
|
||||||
|
|
||||||
|
if (indexID >= 0)
|
||||||
|
animID = mReader->getAttributeValue(indexID);
|
||||||
|
|
||||||
if( indexName >= 0)
|
if( indexName >= 0)
|
||||||
animName = mReader->getAttributeValue( indexName);
|
animName = mReader->getAttributeValue( indexName);
|
||||||
else if( indexID >= 0)
|
else if( indexID >= 0)
|
||||||
animName = mReader->getAttributeValue( indexID);
|
animName = animID;
|
||||||
else
|
else
|
||||||
animName = "animation";
|
animName = "animation";
|
||||||
|
|
||||||
|
@ -395,11 +527,17 @@ void ColladaParser::ReadAnimation( Collada::Animation* pParent)
|
||||||
// it turned out to have channels - add them
|
// it turned out to have channels - add them
|
||||||
if( !channels.empty())
|
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
|
// special filtering for stupid exporters packing each channel into a separate animation
|
||||||
if( channels.size() == 1)
|
if( channels.size() == 1)
|
||||||
{
|
{
|
||||||
pParent->mChannels.push_back( channels.begin()->second);
|
pParent->mChannels.push_back( channels.begin()->second);
|
||||||
} else
|
} else
|
||||||
|
*/
|
||||||
{
|
{
|
||||||
// else create the animation, if not done yet, and store the channels
|
// else create the animation, if not done yet, and store the channels
|
||||||
if( !anim)
|
if( !anim)
|
||||||
|
@ -410,6 +548,11 @@ void ColladaParser::ReadAnimation( Collada::Animation* pParent)
|
||||||
}
|
}
|
||||||
for( ChannelMap::const_iterator it = channels.begin(); it != channels.end(); ++it)
|
for( ChannelMap::const_iterator it = channels.begin(); it != channels.end(); ++it)
|
||||||
anim->mChannels.push_back( it->second);
|
anim->mChannels.push_back( it->second);
|
||||||
|
|
||||||
|
if (indexID >= 0)
|
||||||
|
{
|
||||||
|
mAnimationLibrary[animID] = anim;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,6 +83,12 @@ namespace Assimp
|
||||||
/** Reads the animation library */
|
/** Reads the animation library */
|
||||||
void ReadAnimationLibrary();
|
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 */
|
/** Reads an animation into the given parent structure */
|
||||||
void ReadAnimation( Collada::Animation* pParent);
|
void ReadAnimation( Collada::Animation* pParent);
|
||||||
|
|
||||||
|
@ -313,6 +319,14 @@ namespace Assimp
|
||||||
typedef std::map<std::string, Collada::Controller> ControllerLibrary;
|
typedef std::map<std::string, Collada::Controller> ControllerLibrary;
|
||||||
ControllerLibrary mControllerLibrary;
|
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
|
/** Pointer to the root node. Don't delete, it just points to one of
|
||||||
the nodes in the node library. */
|
the nodes in the node library. */
|
||||||
Collada::Node* mRootNode;
|
Collada::Node* mRootNode;
|
||||||
|
|
Loading…
Reference in New Issue