//----------------------------------------------------------------------------// // // // ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation // // and distributed under the MIT License (MIT). // // // // Copyright (c) Guillaume Blanc // // // // Permission is hereby granted, free of charge, to any person obtaining a // // copy of this software and associated documentation files (the "Software"), // // to deal in the Software without restriction, including without limitation // // the rights to use, copy, modify, merge, publish, distribute, sublicense, // // and/or sell copies of the Software, and to permit persons to whom the // // Software is furnished to do so, subject to the following conditions: // // // // The above copyright notice and this permission notice shall be included in // // all copies or substantial portions of the Software. // // // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL // // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // // DEALINGS IN THE SOFTWARE. // // // //----------------------------------------------------------------------------// #ifndef OZZ_OZZ_ANIMATION_OFFLINE_RAW_SKELETON_H_ #define OZZ_OZZ_ANIMATION_OFFLINE_RAW_SKELETON_H_ #include "ozz/base/containers/string.h" #include "ozz/base/containers/vector.h" #include "ozz/base/io/archive_traits.h" #include "ozz/base/maths/transform.h" namespace ozz { namespace animation { namespace offline { // Off-line skeleton type. // This skeleton type is not intended to be used in run time. It is used to // define the offline skeleton object that can be converted to the runtime // skeleton using the SkeletonBuilder. This skeleton structure exposes joints' // hierarchy. A joint is defined with a name, a transformation (its bind pose), // and its children. Children are exposed as a public std::vector of joints. // This same type is used for skeleton roots, also exposed from the public API. // The public API exposed through std:vector's of joints can be used freely with // the only restriction that the total number of joints does not exceed // Skeleton::kMaxJoints. struct RawSkeleton { // Construct an empty skeleton. RawSkeleton(); // The destructor is responsible for deleting the roots and their hierarchy. ~RawSkeleton(); // Offline skeleton joint type. struct Joint { // Type of the list of children joints. typedef ozz::vector Children; // Children joints. Children children; // The name of the joint. ozz::string name; // Joint bind pose transformation in local space. math::Transform transform; }; // Tests for *this validity. // Returns true on success or false on failure if the number of joints exceeds // ozz::Skeleton::kMaxJoints. bool Validate() const; // Returns the number of joints of *this animation. // This function is not constant time as it iterates the hierarchy of joints // and counts them. int num_joints() const; // Declares the skeleton's roots. Can be empty if the skeleton has no joint. Joint::Children roots; }; namespace { // Internal function used to iterate through joint hierarchy depth-first. template inline void _IterHierarchyRecurseDF( const RawSkeleton::Joint::Children& _children, const RawSkeleton::Joint* _parent, _Fct& _fct) { for (size_t i = 0; i < _children.size(); ++i) { const RawSkeleton::Joint& current = _children[i]; _fct(current, _parent); _IterHierarchyRecurseDF(current.children, ¤t, _fct); } } // Internal function used to iterate through joint hierarchy breadth-first. template inline void _IterHierarchyRecurseBF( const RawSkeleton::Joint::Children& _children, const RawSkeleton::Joint* _parent, _Fct& _fct) { for (size_t i = 0; i < _children.size(); ++i) { const RawSkeleton::Joint& current = _children[i]; _fct(current, _parent); } for (size_t i = 0; i < _children.size(); ++i) { const RawSkeleton::Joint& current = _children[i]; _IterHierarchyRecurseBF(current.children, ¤t, _fct); } } } // namespace // Applies a specified functor to each joint in a depth-first order. // _Fct is of type void(const Joint& _current, const Joint* _parent) where the // first argument is the child of the second argument. _parent is null if the // _current joint is the root. template inline _Fct IterateJointsDF(const RawSkeleton& _skeleton, _Fct _fct) { _IterHierarchyRecurseDF(_skeleton.roots, nullptr, _fct); return _fct; } // Applies a specified functor to each joint in a breadth-first order. // _Fct is of type void(const Joint& _current, const Joint* _parent) where the // first argument is the child of the second argument. _parent is null if the // _current joint is the root. template inline _Fct IterateJointsBF(const RawSkeleton& _skeleton, _Fct _fct) { _IterHierarchyRecurseBF(_skeleton.roots, nullptr, _fct); return _fct; } } // namespace offline } // namespace animation namespace io { OZZ_IO_TYPE_VERSION(1, animation::offline::RawSkeleton) OZZ_IO_TYPE_TAG("ozz-raw_skeleton", animation::offline::RawSkeleton) // Should not be called directly but through io::Archive << and >> operators. template <> struct Extern { static void Save(OArchive& _archive, const animation::offline::RawSkeleton* _skeletons, size_t _count); static void Load(IArchive& _archive, animation::offline::RawSkeleton* _skeletons, size_t _count, uint32_t _version); }; } // namespace io } // namespace ozz #endif // OZZ_OZZ_ANIMATION_OFFLINE_RAW_SKELETON_H_