diff options
Diffstat (limited to 'libs/assimp/tools/assimp_view/SceneAnimator.h')
-rw-r--r-- | libs/assimp/tools/assimp_view/SceneAnimator.h | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/libs/assimp/tools/assimp_view/SceneAnimator.h b/libs/assimp/tools/assimp_view/SceneAnimator.h new file mode 100644 index 0000000..454357f --- /dev/null +++ b/libs/assimp/tools/assimp_view/SceneAnimator.h @@ -0,0 +1,237 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2022, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +/** @file SceneAnimator.h + * Manages animations for a given scene and calculates present + * transformations for all nodes + */ + +#ifndef AV_SCENEANIMATOR_H_INCLUDED +#define AV_SCENEANIMATOR_H_INCLUDED + +#include <map> + +namespace AssimpView { + +// --------------------------------------------------------------------------------- +/** A little tree structure to match the scene's node structure, but holding + * additional data. Needs to be public to allow using it in templates at + * certain compilers. + */ +struct SceneAnimNode { + std::string mName; + SceneAnimNode *mParent; + std::vector<SceneAnimNode *> mChildren; + + //! most recently calculated local transform + aiMatrix4x4 mLocalTransform; + + //! same, but in world space + aiMatrix4x4 mGlobalTransform; + + //! index in the current animation's channel array. -1 if not animated. + int mChannelIndex; + + //! Default construction + SceneAnimNode() : + mName(), mParent(nullptr), mChildren(), mLocalTransform(), mGlobalTransform(), mChannelIndex(-1) { + // empty + } + + //! Construction from a given name + SceneAnimNode(const std::string &pName) : + mName(pName), mParent(nullptr), mChildren(), mLocalTransform(), mGlobalTransform(), mChannelIndex(-1) { + // empty + } + + //! Destruct all children recursively + ~SceneAnimNode() { + for (std::vector<SceneAnimNode *>::iterator it = mChildren.begin(); it != mChildren.end(); ++it) { + delete *it; + } + } +}; + +// --------------------------------------------------------------------------------- +/** Calculates the animated node transformations for a given scene and timestamp. + * + * Create an instance for a aiScene you want to animate and set the current animation + * to play. You can then have the instance calculate the current pose for all nodes + * by calling Calculate() for a given timestamp. After this you can retrieve the + * present transformation for a given node by calling GetLocalTransform() or + * GetGlobalTransform(). A full set of bone matrices can be retrieved by + * GetBoneMatrices() for a given mesh. + */ +class SceneAnimator { +public: + // ---------------------------------------------------------------------------- + /** Constructor for a given scene. + * + * The object keeps a reference to the scene during its lifetime, but + * ownership stays at the caller. + * @param pScene The scene to animate. + * @param pAnimIndex [optional] Index of the animation to play. Assumed to + * be 0 if not given. + */ + SceneAnimator(const aiScene *pScene, size_t pAnimIndex = 0); + + /** Destructor */ + ~SceneAnimator(); + + // ---------------------------------------------------------------------------- + /** Sets the animation to use for playback. This also recreates the internal + * mapping structures, which might take a few cycles. + * @param pAnimIndex Index of the animation in the scene's animation array + */ + void SetAnimIndex(size_t pAnimIndex); + + // ---------------------------------------------------------------------------- + /** Calculates the node transformations for the scene. Call this to get + * up-to-date results before calling one of the getters. + * @param pTime Current time. Can be an arbitrary range. + */ + void Calculate(double pTime); + + // ---------------------------------------------------------------------------- + /** Retrieves the most recent local transformation matrix for the given node. + * + * The returned matrix is in the node's parent's local space, just like the + * original node's transformation matrix. If the node is not animated, the + * node's original transformation is returned so that you can safely use or + * assign it to the node itsself. If there is no node with the given name, + * the identity matrix is returned. All transformations are updated whenever + * Calculate() is called. + * @param pNodeName Name of the node + * @return A reference to the node's most recently calculated local + * transformation matrix. + */ + const aiMatrix4x4 &GetLocalTransform(const aiNode *node) const; + + // ---------------------------------------------------------------------------- + /** Retrieves the most recent global transformation matrix for the given node. + * + * The returned matrix is in world space, which is the same coordinate space + * as the transformation of the scene's root node. If the node is not animated, + * the node's original transformation is returned so that you can safely use or + * assign it to the node itsself. If there is no node with the given name, the + * identity matrix is returned. All transformations are updated whenever + * Calculate() is called. + * @param pNodeName Name of the node + * @return A reference to the node's most recently calculated global + * transformation matrix. + */ + const aiMatrix4x4 &GetGlobalTransform(const aiNode *node) const; + + // ---------------------------------------------------------------------------- + /** Calculates the bone matrices for the given mesh. + * + * Each bone matrix transforms from mesh space in bind pose to mesh space in + * skinned pose, it does not contain the mesh's world matrix. Thus the usual + * matrix chain for using in the vertex shader is + * @code + * boneMatrix * worldMatrix * viewMatrix * projMatrix + * @endcode + * @param pNode The node carrying the mesh. + * @param pMeshIndex Index of the mesh in the node's mesh array. The NODE's + * mesh array, not the scene's mesh array! Leave out to use the first mesh + * of the node, which is usually also the only one. + * @return A reference to a vector of bone matrices. Stays stable till the + * next call to GetBoneMatrices(); + */ + const std::vector<aiMatrix4x4> &GetBoneMatrices(const aiNode *pNode, + size_t pMeshIndex = 0); + + // ---------------------------------------------------------------------------- + /** @brief Get the current animation index + */ + size_t CurrentAnimIndex() const { + return mCurrentAnimIndex; + } + + // ---------------------------------------------------------------------------- + /** @brief Get the current animation or NULL + */ + aiAnimation *CurrentAnim() const { + return static_cast<unsigned int>(mCurrentAnimIndex) < mScene->mNumAnimations ? mScene->mAnimations[mCurrentAnimIndex] : NULL; + } + +protected: + /** Recursively creates an internal node structure matching the + * current scene and animation. + */ + SceneAnimNode *CreateNodeTree(aiNode *pNode, SceneAnimNode *pParent); + + /** Recursively updates the internal node transformations from the + * given matrix array + */ + void UpdateTransforms(SceneAnimNode *pNode, const std::vector<aiMatrix4x4> &pTransforms); + + /** Calculates the global transformation matrix for the given internal node */ + void CalculateGlobalTransform(SceneAnimNode *pInternalNode); + +protected: + /** The scene we're operating on */ + const aiScene *mScene; + + /** Current animation index */ + int mCurrentAnimIndex; + + /** The AnimEvaluator we use to calculate the current pose for the current animation */ + AnimEvaluator *mAnimEvaluator; + + /** Root node of the internal scene structure */ + SceneAnimNode *mRootNode; + + /** Name to node map to quickly find nodes by their name */ + typedef std::map<const aiNode *, SceneAnimNode *> NodeMap; + NodeMap mNodesByName; + + /** Name to node map to quickly find nodes for given bones by their name */ + typedef std::map<const char *, const aiNode *> BoneMap; + BoneMap mBoneNodesByName; + + /** Array to return transformations results inside. */ + std::vector<aiMatrix4x4> mTransforms; +}; + +} // end of namespace AssimpView + +#endif // AV_SCENEANIMATOR_H_INCLUDED |