Initial commit

This commit is contained in:
Martin Felis
2021-11-11 21:22:24 +01:00
commit b78045ffe7
812 changed files with 421882 additions and 0 deletions
@@ -0,0 +1,76 @@
//----------------------------------------------------------------------------//
// //
// 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_ADDITIVE_ANIMATION_BUILDER_H_
#define OZZ_OZZ_ANIMATION_OFFLINE_ADDITIVE_ANIMATION_BUILDER_H_
#include "ozz/base/platform.h"
#include "ozz/base/span.h"
namespace ozz {
namespace math {
struct Transform;
}
namespace animation {
namespace offline {
// Forward declare offline animation type.
struct RawAnimation;
// Defines the class responsible for building a delta animation from an offline
// raw animation. This is used to create animations compatible with additive
// blending.
class AdditiveAnimationBuilder {
public:
// Initializes the builder.
AdditiveAnimationBuilder();
// Builds delta animation from _input..
// Returns true on success and fills _output_animation with the delta
// version of _input animation.
// *_output must be a valid RawAnimation instance. Uses first frame as
// reference pose Returns false on failure and resets _output to an empty
// animation. See RawAnimation::Validate() for more details about failure
// reasons.
bool operator()(const RawAnimation& _input, RawAnimation* _output) const;
// Builds delta animation from _input..
// Returns true on success and fills _output_animation with the delta
// *_output must be a valid RawAnimation instance.
// version of _input animation.
// *_reference_pose used as the base pose to calculate deltas from
// Returns false on failure and resets _output to an empty animation.
bool operator()(const RawAnimation& _input,
const span<const math::Transform>& _reference_pose,
RawAnimation* _output) const;
};
} // namespace offline
} // namespace animation
} // namespace ozz
#endif // OZZ_OZZ_ANIMATION_OFFLINE_ADDITIVE_ANIMATION_BUILDER_H_
@@ -0,0 +1,59 @@
//----------------------------------------------------------------------------//
// //
// 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_ANIMATION_BUILDER_H_
#define OZZ_OZZ_ANIMATION_OFFLINE_ANIMATION_BUILDER_H_
#include "ozz/base/memory/unique_ptr.h"
namespace ozz {
namespace animation {
// Forward declares the runtime animation type.
class Animation;
namespace offline {
// Forward declares the offline animation type.
struct RawAnimation;
// Defines the class responsible of building runtime animation instances from
// offline raw animations.
// No optimization at all is performed on the raw animation.
class AnimationBuilder {
public:
// Creates an Animation based on _raw_animation and *this builder parameters.
// Returns a valid Animation on success.
// See RawAnimation::Validate() for more details about failure reasons.
// The animation is returned as an unique_ptr as ownership is given back to
// the caller.
unique_ptr<Animation> operator()(const RawAnimation& _raw_animation) const;
};
} // namespace offline
} // namespace animation
} // namespace ozz
#endif // OZZ_OZZ_ANIMATION_OFFLINE_ANIMATION_BUILDER_H_
@@ -0,0 +1,103 @@
//----------------------------------------------------------------------------//
// //
// 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_ANIMATION_OPTIMIZER_H_
#define OZZ_OZZ_ANIMATION_OFFLINE_ANIMATION_OPTIMIZER_H_
#include "ozz/base/containers/map.h"
namespace ozz {
namespace animation {
// Forward declare runtime skeleton type.
class Skeleton;
namespace offline {
// Forward declare offline animation type.
struct RawAnimation;
// Defines the class responsible of optimizing an offline raw animation
// instance. Optimization is performed using a key frame reduction technique. It
// deciamtes redundant / interpolable key frames, within error tolerances given
// as input. The optimizer takes into account for each joint the error
// generated on its whole child hierarchy. This allows for example to take into
// consideration the error generated on a finger when optimizing the shoulder. A
// small error on the shoulder can be magnified when propagated to the finger
// indeed.
// It's possible to override optimization settings for a joint. This implicitely
// have an effect on the whole chain, up to that joint. This allows for example
// to have aggressive optimization for a whole skeleton, except for the chain
// that leads to the hand if user wants it to be precise. Default optimization
// tolerances are set in order to favor quality over runtime performances and
// memory footprint.
class AnimationOptimizer {
public:
// Initializes the optimizer with default tolerances (favoring quality).
AnimationOptimizer();
// Optimizes _input using *this parameters. _skeleton is required to evaluate
// optimization error along joint hierarchy (see hierarchical_tolerance).
// Returns true on success and fills _output animation with the optimized
// version of _input animation.
// *_output must be a valid RawAnimation instance.
// Returns false on failure and resets _output to an empty animation.
// See RawAnimation::Validate() for more details about failure reasons.
bool operator()(const RawAnimation& _input, const Skeleton& _skeleton,
RawAnimation* _output) const;
// Optimization settings.
struct Setting {
// Default settings
Setting()
: tolerance(1e-3f), // 1mm
distance(1e-1f) // 10cm
{}
Setting(float _tolerance, float _distance)
: tolerance(_tolerance), distance(_distance) {}
// The maximum error that an optimization is allowed to generate on a whole
// joint hierarchy.
float tolerance;
// The distance (from the joint) at which error is measured (if bigger that
// joint hierarchy). This allows to emulate effect on skinning.
float distance;
};
// Golbal optimization settings. These settings apply to all joints of the
// hierarchy, unless overriden by joint specific settings.
Setting setting;
// Per joint override of optimization settings.
typedef ozz::map<int, Setting> JointsSetting;
JointsSetting joints_setting_override;
};
} // namespace offline
} // namespace animation
} // namespace ozz
#endif // OZZ_OZZ_ANIMATION_OFFLINE_ANIMATION_OPTIMIZER_H_
@@ -0,0 +1,170 @@
//----------------------------------------------------------------------------//
// //
// 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_FBX_FBX_H_
#define OZZ_OZZ_ANIMATION_OFFLINE_FBX_FBX_H_
#include <fbxsdk.h>
#include "ozz/base/maths/simd_math.h"
#include "ozz/base/maths/transform.h"
namespace ozz {
namespace math {
struct Transform;
} // namespace math
namespace animation {
namespace offline {
namespace fbx {
// Manages FbxManager instance.
class FbxManagerInstance {
public:
// Instantiates FbxManager.
FbxManagerInstance();
// Destroys FbxManager.
~FbxManagerInstance();
// Cast operator to get internal FbxManager instance.
operator FbxManager*() const { return fbx_manager_; }
private:
FbxManager* fbx_manager_;
};
// Default io settings used to import a scene.
class FbxDefaultIOSettings {
public:
// Instantiates default settings.
explicit FbxDefaultIOSettings(const FbxManagerInstance& _manager);
// De-instantiates default settings.
virtual ~FbxDefaultIOSettings();
// Get FbxIOSettings instance.
FbxIOSettings* settings() const { return io_settings_; }
// Cast operator to get internal FbxIOSettings instance.
operator FbxIOSettings*() const { return io_settings_; }
private:
FbxIOSettings* io_settings_;
};
// Io settings used to import an animation from a scene.
class FbxAnimationIOSettings : public FbxDefaultIOSettings {
public:
FbxAnimationIOSettings(const FbxManagerInstance& _manager);
};
// Io settings used to import a skeleton from a scene.
class FbxSkeletonIOSettings : public FbxDefaultIOSettings {
public:
FbxSkeletonIOSettings(const FbxManagerInstance& _manager);
};
// Implements axis system and unit system conversion helper, from any Fbx system
// to ozz system (FbxAxisSystem::eYAxis, FbxAxisSystem::eParityOdd,
// FbxAxisSystem::eRightHanded, meter).
// While Fbx sdk FbxAxisSystem::ConvertScene and FbxSystem::ConvertScene only
// affect scene root, this class functions can be used to bake nodes, vertices,
// animations transformations...
class FbxSystemConverter {
public:
// Initialize converter with fbx scene systems.
FbxSystemConverter(const FbxAxisSystem& _from_axis,
const FbxSystemUnit& _from_unit);
// Converts a fbx matrix to an ozz Float4x4 matrix, in ozz axis and unit
// systems, using _m' = C * _m * (C-1) operation.
math::Float4x4 ConvertMatrix(const FbxAMatrix& _m) const;
// Converts fbx matrix to an ozz transform, in ozz axis and unit systems,
// using _m' = C * _m * (C-1) operation.
// Can return false if matrix isn't affine.
bool ConvertTransform(const FbxAMatrix& _m,
math::Transform* _transform) const;
// Converts fbx FbxVector4 point to an ozz Float3, in ozz axis and unit
// systems, using _p' = C * _p operation.
math::Float3 ConvertPoint(const FbxVector4& _p) const;
// Converts fbx FbxVector4 vector to an ozz Float3, in ozz axis and unit
// systems, using _p' = ((C-1)-T) * _p operation. Normals are converted
// using the inverse transpose matrix to support non-uniform scale
// transformations.
math::Float3 ConvertVector(const FbxVector4& _p) const;
private:
// The matrix used to convert from "from" axis/unit to ozz coordinate system
// base.
math::Float4x4 convert_;
// The inverse of convert_ matrix.
math::Float4x4 inverse_convert_;
// The transpose inverse of convert_ matrix.
math::Float4x4 inverse_transpose_convert_;
};
// Loads a scene from a Fbx file.
class FbxSceneLoader {
public:
// Loads the scene that can then be obtained with scene() function.
FbxSceneLoader(const char* _filename, const char* _password,
const FbxManagerInstance& _manager,
const FbxDefaultIOSettings& _io_settings);
FbxSceneLoader(FbxStream* _stream, const char* _password,
const FbxManagerInstance& _manager,
const FbxDefaultIOSettings& _io_settings);
~FbxSceneLoader();
// Returns a valid scene if fbx import was successful, nullptr otherwise.
FbxScene* scene() const { return scene_; }
// Returns a valid converter if fbx import was successful, nullptr otherwise.
FbxSystemConverter* converter() { return converter_; }
private:
void ImportScene(FbxImporter* _importer, const bool _initialized,
const char* _password, const FbxManagerInstance& _manager,
const FbxDefaultIOSettings& _io_settings);
// Scene instance that was loaded from the file.
FbxScene* scene_;
// Axis and unit conversion helper.
FbxSystemConverter* converter_;
};
} // namespace fbx
} // namespace offline
} // namespace animation
} // namespace ozz
#endif // OZZ_OZZ_ANIMATION_OFFLINE_FBX_FBX_H_
@@ -0,0 +1,90 @@
//----------------------------------------------------------------------------//
// //
// 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_FBX_FBX_ANIMATION_H_
#define OZZ_OZZ_ANIMATION_OFFLINE_FBX_FBX_ANIMATION_H_
#include "ozz/animation/offline/fbx/fbx.h"
#include "ozz/animation/offline/tools/import2ozz.h"
#include "ozz/base/containers/string.h"
#include "ozz/base/containers/vector.h"
namespace ozz {
namespace animation {
class Skeleton;
namespace offline {
struct RawAnimation;
struct RawFloatTrack;
struct RawFloat2Track;
struct RawFloat3Track;
struct RawFloat4Track;
struct RawquaternionTrack;
namespace fbx {
OzzImporter::AnimationNames GetAnimationNames(FbxSceneLoader& _scene_loader);
bool ExtractAnimation(const char* _animation_name,
FbxSceneLoader& _scene_loader, const Skeleton& _skeleton,
float _sampling_rate, RawAnimation* _animation);
OzzImporter::NodeProperties GetNodeProperties(FbxSceneLoader& _scene_loader,
const char* _node_name);
bool ExtractTrack(const char* _animation_name, const char* _node_name,
const char* _track_name,
OzzImporter::NodeProperty::Type _type,
FbxSceneLoader& _scene_loader, float _sampling_rate,
RawFloatTrack* _track);
bool ExtractTrack(const char* _animation_name, const char* _node_name,
const char* _track_name,
OzzImporter::NodeProperty::Type _type,
FbxSceneLoader& _scene_loader, float _sampling_rate,
RawFloat2Track* _track);
bool ExtractTrack(const char* _animation_name, const char* _node_name,
const char* _track_name,
OzzImporter::NodeProperty::Type _type,
FbxSceneLoader& _scene_loader, float _sampling_rate,
RawFloat3Track* _track);
bool ExtractTrack(const char* _animation_name, const char* _node_name,
const char* _track_name,
OzzImporter::NodeProperty::Type _type,
FbxSceneLoader& _scene_loader, float _sampling_rate,
RawFloat4Track* _track);
} // namespace fbx
} // namespace offline
} // namespace animation
} // namespace ozz
#endif // OZZ_OZZ_ANIMATION_OFFLINE_FBX_FBX_ANIMATION_H_
@@ -0,0 +1,50 @@
//----------------------------------------------------------------------------//
// //
// 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_FBX_FBX_SKELETON_H_
#define OZZ_OZZ_ANIMATION_OFFLINE_FBX_FBX_SKELETON_H_
#include "ozz/animation/offline/fbx/fbx.h"
#include "ozz/animation/offline/tools/import2ozz.h"
namespace ozz {
namespace animation {
namespace offline {
struct RawSkeleton;
namespace fbx {
bool ExtractSkeleton(FbxSceneLoader& _loader,
const OzzImporter::NodeType& _types,
RawSkeleton* _skeleton);
} // namespace fbx
} // namespace offline
} // namespace animation
} // namespace ozz
#endif // OZZ_OZZ_ANIMATION_OFFLINE_FBX_FBX_SKELETON_H_
@@ -0,0 +1,159 @@
//----------------------------------------------------------------------------//
// //
// 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_ANIMATION_H_
#define OZZ_OZZ_ANIMATION_OFFLINE_RAW_ANIMATION_H_
#include "ozz/base/containers/string.h"
#include "ozz/base/containers/vector.h"
#include "ozz/base/io/archive_traits.h"
#include "ozz/base/maths/quaternion.h"
#include "ozz/base/maths/vec_float.h"
namespace ozz {
namespace animation {
namespace offline {
// Offline animation type.
// This animation type is not intended to be used in run time. It is used to
// define the offline animation object that can be converted to the runtime
// animation using the AnimationBuilder.
// This animation structure exposes tracks of keyframes. Keyframes are defined
// with a time and a value which can either be a translation (3 float x, y, z),
// a rotation (a quaternion) or scale coefficient (3 floats x, y, z). Tracks are
// defined as a set of three different std::vectors (translation, rotation and
// scales). Animation structure is then a vector of tracks, along with a
// duration value.
// Finally the RawAnimation structure exposes Validate() function to check that
// it is valid, meaning that all the following rules are respected:
// 1. Animation duration is greater than 0.
// 2. Keyframes' time are sorted in a strict ascending order.
// 3. Keyframes' time are all within [0,animation duration] range.
// Animations that would fail this validation will fail to be converted by the
// AnimationBuilder.
struct RawAnimation {
// Constructs a valid RawAnimation with a 1s default duration.
RawAnimation();
// Tests for *this validity.
// Returns true if animation data (duration, tracks) is valid:
// 1. Animation duration is greater than 0.
// 2. Keyframes' time are sorted in a strict ascending order.
// 3. Keyframes' time are all within [0,animation duration] range.
bool Validate() const;
// Get the estimated animation's size in bytes.
size_t size() const;
// Defines a raw translation key frame.
struct TranslationKey {
// Key frame time.
float time;
// Key frame value.
typedef math::Float3 Value;
Value value;
// Provides identity transformation for a translation key.
static math::Float3 identity() { return math::Float3::zero(); }
};
// Defines a raw rotation key frame.
struct RotationKey {
// Key frame time.
float time;
// Key frame value.
typedef math::Quaternion Value;
math::Quaternion value;
// Provides identity transformation for a rotation key.
static math::Quaternion identity() { return math::Quaternion::identity(); }
};
// Defines a raw scaling key frame.
struct ScaleKey {
// Key frame time.
float time;
// Key frame value.
typedef math::Float3 Value;
math::Float3 value;
// Provides identity transformation for a scale key.
static math::Float3 identity() { return math::Float3::one(); }
};
// Defines a track of key frames for a bone, including translation, rotation
// and scale.
struct JointTrack {
typedef ozz::vector<TranslationKey> Translations;
Translations translations;
typedef ozz::vector<RotationKey> Rotations;
Rotations rotations;
typedef ozz::vector<ScaleKey> Scales;
Scales scales;
// Validates track. See RawAnimation::Validate for more details.
// Use an infinite value for _duration if unknown. This will validate
// keyframe orders, but not maximum duration.
bool Validate(float _duration) const;
};
// Returns the number of tracks of this animation.
int num_tracks() const { return static_cast<int>(tracks.size()); }
// Stores per joint JointTrack, ie: per joint animation key-frames.
// tracks_.size() gives the number of animated joints.
ozz::vector<JointTrack> tracks;
// The duration of the animation. All the keys of a valid RawAnimation are in
// the range [0,duration].
float duration;
// Name of the animation.
ozz::string name;
};
} // namespace offline
} // namespace animation
namespace io {
OZZ_IO_TYPE_VERSION(3, animation::offline::RawAnimation)
OZZ_IO_TYPE_TAG("ozz-raw_animation", animation::offline::RawAnimation)
// Should not be called directly but through io::Archive << and >> operators.
template <>
struct Extern<animation::offline::RawAnimation> {
static void Save(OArchive& _archive,
const animation::offline::RawAnimation* _animations,
size_t _count);
static void Load(IArchive& _archive,
animation::offline::RawAnimation* _animations, size_t _count,
uint32_t _version);
};
} // namespace io
} // namespace ozz
#endif // OZZ_OZZ_ANIMATION_OFFLINE_RAW_ANIMATION_H_
@@ -0,0 +1,91 @@
//----------------------------------------------------------------------------//
// //
// 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_ANIMATION_UTILS_H_
#define OZZ_OZZ_ANIMATION_OFFLINE_RAW_ANIMATION_UTILS_H_
#include "ozz/animation/offline/raw_animation.h"
#include "ozz/base/maths/transform.h"
#include "ozz/base/span.h"
namespace ozz {
namespace animation {
namespace offline {
// Translation interpolation method.
math::Float3 LerpTranslation(const math::Float3& _a, const math::Float3& _b,
float _alpha);
// Rotation interpolation method.
math::Quaternion LerpRotation(const math::Quaternion& _a,
const math::Quaternion& _b, float _alpha);
// Scale interpolation method.
math::Float3 LerpScale(const math::Float3& _a, const math::Float3& _b,
float _alpha);
// Samples a RawAnimation track. This function shall be used for offline
// purpose. Use ozz::animation::Animation and ozz::animation::SamplingJob for
// runtime purpose.
// Returns false if track is invalid.
bool SampleTrack(const RawAnimation::JointTrack& _track, float _time,
ozz::math::Transform* _transform);
// Samples a RawAnimation. This function shall be used for offline
// purpose. Use ozz::animation::Animation and ozz::animation::SamplingJob for
// runtime purpose.
// _animation must be valid.
// Returns false output range is too small or animation is invalid.
bool SampleAnimation(const RawAnimation& _animation, float _time,
const span<ozz::math::Transform>& _transforms);
// Implement fixed rate keyframe time iteration. This utility purpose is to
// ensure that sampling goes strictly from 0 to duration, and that period
// between consecutive time samples have a fixed period.
// This sounds trivial, but floating point error could occur if keyframe time
// was accumulated for a long duration.
class FixedRateSamplingTime {
public:
FixedRateSamplingTime(float _duration, float _frequency);
float time(size_t _key) const {
assert(_key < num_keys_);
return ozz::math::Min(_key * period_, duration_);
}
size_t num_keys() const { return num_keys_; }
private:
float duration_;
float period_;
size_t num_keys_;
};
} // namespace offline
} // namespace animation
} // namespace ozz
#endif // OZZ_OZZ_ANIMATION_OFFLINE_RAW_ANIMATION_UTILS_H_
@@ -0,0 +1,152 @@
//----------------------------------------------------------------------------//
// //
// 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<Joint> 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 <typename _Fct>
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, &current, _fct);
}
}
// Internal function used to iterate through joint hierarchy breadth-first.
template <typename _Fct>
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, &current, _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 <typename _Fct>
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 <typename _Fct>
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<animation::offline::RawSkeleton> {
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_
@@ -0,0 +1,133 @@
//----------------------------------------------------------------------------//
// //
// 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_TRACK_H_
#define OZZ_OZZ_ANIMATION_OFFLINE_RAW_TRACK_H_
#include "ozz/base/containers/string.h"
#include "ozz/base/containers/vector.h"
#include "ozz/base/io/archive_traits.h"
#include "ozz/base/maths/quaternion.h"
#include "ozz/base/maths/vec_float.h"
namespace ozz {
namespace animation {
namespace offline {
// Interpolation mode.
struct RawTrackInterpolation {
enum Value {
kStep, // All values following this key, up to the next key, are equal.
kLinear, // All value between this key and the next are linearly
// interpolated.
};
};
// Keyframe data structure.
template <typename _ValueType>
struct RawTrackKeyframe {
typedef _ValueType ValueType;
RawTrackInterpolation::Value interpolation;
float ratio;
ValueType value;
};
namespace internal {
// Offline user-channel animation track type implementation.
// This offline track data structure is meant to be used for user-channel
// tracks, aka animation of variables that aren't joint transformation. It is
// available for tracks of 1 to 4 floats (RawFloatTrack, RawFloat2Track, ...,
// RawFloat4Track) and quaternions (RawQuaternionTrack). Quaternions differ from
// float4 because of the specific interpolation and comparison treatment they
// require. As all other Raw data types, they are not intended to be used in run
// time. They are used to define the offline track object that can be converted
// to the runtime one using the a ozz::animation::offline::TrackBuilder. This
// animation structure exposes a single sequence of keyframes. Keyframes are
// defined with a ratio, a value and an interpolation mode:
// - Ratio: A track has no duration, so it uses ratios between 0 (beginning of
// the track) and 1 (the end), instead of times. This allows to avoid any
// discrepancy between the durations of tracks and the animation they match
// with.
// - Value: The animated value (float, ... float4, quaternion).
// - Interpolation mode (`ozz::animation::offline::RawTrackInterpolation`):
// Defines how value is interpolated with the next key. Track structure is then
// a sorted vector of keyframes. RawTrack structure exposes a Validate()
// function to check that all the following rules are respected:
// 1. Keyframes' ratios are sorted in a strict ascending order.
// 2. Keyframes' ratios are all within [0,1] range.
// RawTrack that would fail this validation will fail to be converted by
// the RawTrackBuilder.
template <typename _ValueType>
struct RawTrack {
typedef _ValueType ValueType;
typedef RawTrackKeyframe<ValueType> Keyframe;
// Validates that all the following rules are respected:
// 1. Keyframes' ratios are sorted in a strict ascending order.
// 2. Keyframes' ratios are all within [0,1] range.
bool Validate() const;
// Uses intrusive serialization option, as a way to factorize code.
// Version and Tag should still be defined for each specialization.
void Save(io::OArchive& _archive) const;
void Load(io::IArchive& _archive, uint32_t _version);
// Sequence of keyframes, expected to be sorted.
typedef typename ozz::vector<Keyframe> Keyframes;
Keyframes keyframes;
// Name of the track.
string name;
};
} // namespace internal
// Offline user-channel animation track type instantiation.
struct RawFloatTrack : public internal::RawTrack<float> {};
struct RawFloat2Track : public internal::RawTrack<math::Float2> {};
struct RawFloat3Track : public internal::RawTrack<math::Float3> {};
struct RawFloat4Track : public internal::RawTrack<math::Float4> {};
struct RawQuaternionTrack : public internal::RawTrack<math::Quaternion> {};
} // namespace offline
} // namespace animation
namespace io {
OZZ_IO_TYPE_VERSION(1, animation::offline::RawFloatTrack)
OZZ_IO_TYPE_TAG("ozz-raw_float_track", animation::offline::RawFloatTrack)
OZZ_IO_TYPE_VERSION(1, animation::offline::RawFloat2Track)
OZZ_IO_TYPE_TAG("ozz-raw_float2_track", animation::offline::RawFloat2Track)
OZZ_IO_TYPE_VERSION(1, animation::offline::RawFloat3Track)
OZZ_IO_TYPE_TAG("ozz-raw_float3_track", animation::offline::RawFloat3Track)
OZZ_IO_TYPE_VERSION(1, animation::offline::RawFloat4Track)
OZZ_IO_TYPE_TAG("ozz-raw_float4_track", animation::offline::RawFloat4Track)
OZZ_IO_TYPE_VERSION(1, animation::offline::RawQuaternionTrack)
OZZ_IO_TYPE_TAG("ozz-raw_quat_track", animation::offline::RawQuaternionTrack)
} // namespace io
} // namespace ozz
#endif // OZZ_OZZ_ANIMATION_OFFLINE_RAW_TRACK_H_
@@ -0,0 +1,59 @@
//----------------------------------------------------------------------------//
// //
// 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_SKELETON_BUILDER_H_
#define OZZ_OZZ_ANIMATION_OFFLINE_SKELETON_BUILDER_H_
#include "ozz/base/maths/transform.h"
#include "ozz/base/memory/unique_ptr.h"
namespace ozz {
namespace animation {
// Forward declares the runtime skeleton type.
class Skeleton;
namespace offline {
// Forward declares the offline skeleton type.
struct RawSkeleton;
// Defines the class responsible of building Skeleton instances.
class SkeletonBuilder {
public:
// Creates a Skeleton based on _raw_skeleton and *this builder parameters.
// Returns a Skeleton instance on success, an empty unique_ptr on failure. See
// RawSkeleton::Validate() for more details about failure reasons.
// The skeleton is returned as an unique_ptr as ownership is given back to the
// caller.
ozz::unique_ptr<ozz::animation::Skeleton> operator()(
const RawSkeleton& _raw_skeleton) const;
};
} // namespace offline
} // namespace animation
} // namespace ozz
#endif // OZZ_OZZ_ANIMATION_OFFLINE_SKELETON_BUILDER_H_
@@ -0,0 +1,137 @@
//----------------------------------------------------------------------------//
// //
// 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_TOOLS_IMPORT2OZZ_H_
#define OZZ_OZZ_ANIMATION_OFFLINE_TOOLS_IMPORT2OZZ_H_
#include "ozz/base/containers/string.h"
#include "ozz/base/containers/vector.h"
#include "ozz/animation/offline/raw_animation.h"
#include "ozz/animation/offline/raw_skeleton.h"
#include "ozz/animation/offline/raw_track.h"
namespace ozz {
namespace animation {
class Skeleton;
namespace offline {
// Defines ozz converter/importer interface.
// OzzImporter implements a command line tool to convert any source data format
// to ozz skeletons and animations. The tool exposes a set of global options
// through the command line, and a json configuration file to tune import
// settings. Reference json configuration is generated at
// src\animation\offline\tools\reference.json.
// To import a new source data format, one will implement the pure virtual
// functions of this interface. All the conversions end error processing are
// done by the tool.
class OzzImporter {
public:
virtual ~OzzImporter() {}
// Function operator that must be called with main() arguments to start import
// process.
int operator()(int _argc, const char** _argv);
// Loads source data file.
// Returning false will report and error.
virtual bool Load(const char* _filename) = 0;
// Skeleton management.
// Defines node types that should be considered as skeleton joints.
struct NodeType {
bool skeleton : 1; // Uses skeleton nodes as skeleton joints.
bool marker : 1; // Uses marker nodes as skeleton joints.
bool camera : 1; // Uses camera nodes as skeleton joints.
bool geometry : 1; // Uses geometry nodes as skeleton joints.
bool light : 1; // Uses light nodes as skeleton joints.
bool any : 1; // Uses any node type as skeleton joints, including those
// listed above and any other.
};
// Import a skeleton from the source data file.
// Returning false will report and error.
virtual bool Import(ozz::animation::offline::RawSkeleton* _skeleton,
const NodeType& _types) = 0;
// Animations management.
// Gets the name of all the animations/clips/takes available from the source
// data file.
typedef ozz::vector<ozz::string> AnimationNames;
virtual AnimationNames GetAnimationNames() = 0;
// Import animation "_animation_name" from the source data file.
// The skeleton is provided such that implementation can look for its joints
// animations.
// Returning false will report and error.
virtual bool Import(const char* _animation_name,
const ozz::animation::Skeleton& _skeleton,
float _sampling_rate, RawAnimation* _animation) = 0;
// Tracks / properties management.
// Defines properties, aka user-channel data: animations that aren't only
// joint transforms.
struct NodeProperty {
ozz::string name;
enum Type { kFloat1, kFloat2, kFloat3, kFloat4, kPoint, kVector };
Type type;
};
// Get all properties available for a node.
typedef ozz::vector<NodeProperty> NodeProperties;
virtual NodeProperties GetNodeProperties(const char* _node_name) = 0;
// Imports a track of type 1, 2, 3 or 4 floats, for the triplet
// _animation_name/_node_name/_track_name.
// Returning false will report and error.
virtual bool Import(const char* _animation_name, const char* _node_name,
const char* _track_name, NodeProperty::Type _track_type,
float _sampling_rate, RawFloatTrack* _track) = 0;
virtual bool Import(const char* _animation_name, const char* _node_name,
const char* _track_name, NodeProperty::Type _track_type,
float _sampling_rate, RawFloat2Track* _track) = 0;
virtual bool Import(const char* _animation_name, const char* _node_name,
const char* _track_name, NodeProperty::Type _track_type,
float _sampling_rate, RawFloat3Track* _track) = 0;
virtual bool Import(const char* _animation_name, const char* _node_name,
const char* _track_name, NodeProperty::Type _track_type,
float _sampling_rate, RawFloat4Track* _track) = 0;
// Build a filename from a wildcard string.
ozz::string BuildFilename(const char* _filename,
const char* _data_name) const;
};
} // namespace offline
} // namespace animation
} // namespace ozz
#endif // OZZ_OZZ_ANIMATION_OFFLINE_TOOLS_IMPORT2OZZ_H_
@@ -0,0 +1,77 @@
//----------------------------------------------------------------------------//
// //
// 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_TRACK_BUILDER_H_
#define OZZ_OZZ_ANIMATION_OFFLINE_TRACK_BUILDER_H_
#include "ozz/base/memory/unique_ptr.h"
namespace ozz {
namespace animation {
// Forward declares the runtime tracks type.
class FloatTrack;
class Float2Track;
class Float3Track;
class Float4Track;
class QuaternionTrack;
namespace offline {
// Forward declares the offline tracks type.
struct RawFloatTrack;
struct RawFloat2Track;
struct RawFloat3Track;
struct RawFloat4Track;
struct RawQuaternionTrack;
// Defines the class responsible of building runtime track instances from
// offline tracks.The input raw track is first validated. Runtime conversion of
// a validated raw track cannot fail. Note that no optimization is performed on
// the data at all.
class TrackBuilder {
public:
// Creates a Track based on _raw_track and *this builder parameters.
// Returns a track instance on success, an empty unique_ptr on failure. See
// Raw*Track::Validate() for more details about failure reasons.
// The track is returned as an unique_ptr as ownership is given back to the
// caller.
ozz::unique_ptr<FloatTrack> operator()(const RawFloatTrack& _input) const;
ozz::unique_ptr<Float2Track> operator()(const RawFloat2Track& _input) const;
ozz::unique_ptr<Float3Track> operator()(const RawFloat3Track& _input) const;
ozz::unique_ptr<Float4Track> operator()(const RawFloat4Track& _input) const;
ozz::unique_ptr<QuaternionTrack> operator()(
const RawQuaternionTrack& _input) const;
private:
template <typename _RawTrack, typename _Track>
ozz::unique_ptr<_Track> Build(const _RawTrack& _input) const;
};
} // namespace offline
} // namespace animation
} // namespace ozz
#endif // OZZ_OZZ_ANIMATION_OFFLINE_TRACK_BUILDER_H_
@@ -0,0 +1,71 @@
//----------------------------------------------------------------------------//
// //
// 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_TRACK_OPTIMIZER_H_
#define OZZ_OZZ_ANIMATION_OFFLINE_TRACK_OPTIMIZER_H_
namespace ozz {
namespace animation {
namespace offline {
// Forward declare offline track types.
struct RawFloatTrack;
struct RawFloat2Track;
struct RawFloat3Track;
struct RawFloat4Track;
struct RawQuaternionTrack;
// TrackOptimizer is responsible for optimizing an offline raw track instance.
// Optimization is a keyframe reduction process. Redundant and interpolable
// keyframes (within a tolerance value) are removed from the track. Default
// optimization tolerances are set in order to favor quality over runtime
// performances and memory footprint.
class TrackOptimizer {
public:
// Initializes the optimizer with default tolerances (favoring quality).
TrackOptimizer();
// Optimizes _input using *this parameters.
// Returns true on success and fills _output track with the optimized
// version of _input track.
// *_output must be a valid Raw*Track instance.
// Returns false on failure and resets _output to an empty track.
// See Raw*Track::Validate() for more details about failure reasons.
bool operator()(const RawFloatTrack& _input, RawFloatTrack* _output) const;
bool operator()(const RawFloat2Track& _input, RawFloat2Track* _output) const;
bool operator()(const RawFloat3Track& _input, RawFloat3Track* _output) const;
bool operator()(const RawFloat4Track& _input, RawFloat4Track* _output) const;
bool operator()(const RawQuaternionTrack& _input,
RawQuaternionTrack* _output) const;
// Optimization tolerance.
float tolerance;
};
} // namespace offline
} // namespace animation
} // namespace ozz
#endif // OZZ_OZZ_ANIMATION_OFFLINE_TRACK_OPTIMIZER_H_
@@ -0,0 +1,137 @@
//----------------------------------------------------------------------------//
// //
// 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_RUNTIME_ANIMATION_H_
#define OZZ_OZZ_ANIMATION_RUNTIME_ANIMATION_H_
#include "ozz/base/io/archive_traits.h"
#include "ozz/base/platform.h"
#include "ozz/base/span.h"
namespace ozz {
namespace io {
class IArchive;
class OArchive;
} // namespace io
namespace animation {
// Forward declares the AnimationBuilder, used to instantiate an Animation.
namespace offline {
class AnimationBuilder;
}
// Forward declaration of key frame's type.
struct Float3Key;
struct QuaternionKey;
// Defines a runtime skeletal animation clip.
// The runtime animation data structure stores animation keyframes, for all the
// joints of a skeleton. This structure is usually filled by the
// AnimationBuilder and deserialized/loaded at runtime.
// For each transformation type (translation, rotation and scale), Animation
// structure stores a single array of keyframes that contains all the tracks
// required to animate all the joints of a skeleton, matching breadth-first
// joints order of the runtime skeleton structure. In order to optimize cache
// coherency when sampling the animation, Keyframes in this array are sorted by
// time, then by track number.
class Animation {
public:
// Builds a default animation.
Animation();
// Declares the public non-virtual destructor.
~Animation();
// Gets the animation clip duration.
float duration() const { return duration_; }
// Gets the number of animated tracks.
int num_tracks() const { return num_tracks_; }
// Returns the number of SoA elements matching the number of tracks of *this
// animation. This value is useful to allocate SoA runtime data structures.
int num_soa_tracks() const { return (num_tracks_ + 3) / 4; }
// Gets animation name.
const char* name() const { return name_ ? name_ : ""; }
// Gets the buffer of translations keys.
span<const Float3Key> translations() const {
return translations_;
}
// Gets the buffer of rotation keys.
span<const QuaternionKey> rotations() const { return rotations_; }
// Gets the buffer of scale keys.
span<const Float3Key> scales() const { return scales_; }
// Get the estimated animation's size in bytes.
size_t size() const;
// Serialization functions.
// Should not be called directly but through io::Archive << and >> operators.
void Save(ozz::io::OArchive& _archive) const;
void Load(ozz::io::IArchive& _archive, uint32_t _version);
protected:
private:
// Disables copy and assignation.
Animation(Animation const&);
void operator=(Animation const&);
// AnimationBuilder class is allowed to instantiate an Animation.
friend class offline::AnimationBuilder;
// Internal destruction function.
void Allocate(size_t _name_len, size_t _translation_count,
size_t _rotation_count, size_t _scale_count);
void Deallocate();
// Duration of the animation clip.
float duration_;
// The number of joint tracks. Can differ from the data stored in translation/
// rotation/scale buffers because of SoA requirements.
int num_tracks_;
// Animation name.
char* name_;
// Stores all translation/rotation/scale keys begin and end of buffers.
span<Float3Key> translations_;
span<QuaternionKey> rotations_;
span<Float3Key> scales_;
};
} // namespace animation
namespace io {
OZZ_IO_TYPE_VERSION(6, animation::Animation)
OZZ_IO_TYPE_TAG("ozz-animation", animation::Animation)
} // namespace io
} // namespace ozz
#endif // OZZ_OZZ_ANIMATION_RUNTIME_ANIMATION_H_
@@ -0,0 +1,43 @@
//----------------------------------------------------------------------------//
// //
// 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_RUNTIME_ANIMATION_UTILS_H_
#define OZZ_OZZ_ANIMATION_RUNTIME_ANIMATION_UTILS_H_
#include "ozz/animation/runtime/animation.h"
namespace ozz {
namespace animation {
// Count translation, rotation or scale keyframes for a given track number. Use
// a negative _track value to count all tracks.
int CountTranslationKeyframes(const Animation& _animation, int _track = -1);
int CountRotationKeyframes(const Animation& _animation, int _track = -1);
int CountScaleKeyframes(const Animation& _animation, int _track = -1);
} // namespace animation
} // namespace ozz
#endif // OZZ_OZZ_ANIMATION_RUNTIME_ANIMATION_UTILS_H_
@@ -0,0 +1,138 @@
//----------------------------------------------------------------------------//
// //
// 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_RUNTIME_BLENDING_JOB_H_
#define OZZ_OZZ_ANIMATION_RUNTIME_BLENDING_JOB_H_
#include "ozz/base/maths/simd_math.h"
#include "ozz/base/span.h"
namespace ozz {
// Forward declaration of math structures.
namespace math {
struct SoaTransform;
}
namespace animation {
// ozz::animation::BlendingJob is in charge of blending (mixing) multiple poses
// (the result of a sampled animation) according to their respective weight,
// into one output pose.
// The number of transforms/joints blended by the job is defined by the number
// of transforms of the bind pose (note that this is a SoA format). This means
// that all buffers must be at least as big as the bind pose buffer.
// Partial animation blending is supported through optional joint weights that
// can be specified with layers joint_weights buffer. Unspecified joint weights
// are considered as a unit weight of 1.f, allowing to mix full and partial
// blend operations in a single pass.
// The job does not owned any buffers (input/output) and will thus not delete
// them during job's destruction.
struct BlendingJob {
// Default constructor, initializes default values.
BlendingJob();
// Validates job parameters.
// Returns true for a valid job, false otherwise:
// -if layer range is not valid (can be empty though).
// -if additive layer range is not valid (can be empty though).
// -if any layer is not valid.
// -if output range is not valid.
// -if any buffer (including layers' content : transform, joint weights...) is
// smaller than the bind pose buffer.
// -if the threshold value is less than or equal to 0.f.
bool Validate() const;
// Runs job's blending task.
// The job is validated before any operation is performed, see Validate() for
// more details.
// Returns false if *this job is not valid.
bool Run() const;
// Defines a layer of blending input data (local space transforms) and
// parameters (weights).
struct Layer {
// Default constructor, initializes default values.
Layer();
// Blending weight of this layer. Negative values are considered as 0.
// Normalization is performed during the blending stage so weight can be in
// any range, even though range [0:1] is optimal.
float weight;
// The range [begin,end[ of input layer posture. This buffer expect to store
// local space transforms, that are usually outputted from a sampling job.
// This range must be at least as big as the bind pose buffer, even though
// only the number of transforms defined by the bind pose buffer will be
// processed.
span<const math::SoaTransform> transform;
// Optional range [begin,end[ of blending weight for each joint in this
// layer.
// If both pointers are nullptr (default case) then per joint weight
// blending is disabled. A valid range is defined as being at least as big
// as the bind pose buffer, even though only the number of transforms
// defined by the bind pose buffer will be processed. When a layer doesn't
// specifies per joint weights, then it is implicitly considered as
// being 1.f. This default value is a reference value for the normalization
// process, which implies that the range of values for joint weights should
// be [0,1]. Negative weight values are considered as 0, but positive ones
// aren't clamped because they could exceed 1.f if all layers contains valid
// joint weights.
span<const math::SimdFloat4> joint_weights;
};
// The job blends the bind pose to the output when the accumulated weight of
// all layers is less than this threshold value.
// Must be greater than 0.f.
float threshold;
// Job input layers, can be empty or nullptr.
// The range of layers that must be blended.
span<const Layer> layers;
// Job input additive layers, can be empty or nullptr.
// The range of layers that must be added to the output.
span<const Layer> additive_layers;
// The skeleton bind pose. The size of this buffer defines the number of
// transforms to blend. This is the reference because this buffer is defined
// by the skeleton that all the animations belongs to.
// It is used when the accumulated weight for a bone on all layers is
// less than the threshold value, in order to fall back on valid transforms.
span<const ozz::math::SoaTransform> bind_pose;
// Job output.
// The range of output transforms to be filled with blended layer
// transforms during job execution.
// Must be at least as big as the bind pose buffer, but only the number of
// transforms defined by the bind pose buffer size will be processed.
span<ozz::math::SoaTransform> output;
};
} // namespace animation
} // namespace ozz
#endif // OZZ_OZZ_ANIMATION_RUNTIME_BLENDING_JOB_H_
@@ -0,0 +1,114 @@
//----------------------------------------------------------------------------//
// //
// 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_RUNTIME_IK_AIM_JOB_H_
#define OZZ_OZZ_ANIMATION_RUNTIME_IK_AIM_JOB_H_
#include "ozz/base/platform.h"
#include "ozz/base/maths/simd_math.h"
namespace ozz {
// Forward declaration of math structures.
namespace math {
struct SimdQuaternion;
}
namespace animation {
// ozz::animation::IKAimJob rotates a joint so it aims at a target. Joint aim
// direction and up vectors can be different from joint axis. The job computes
// the transformation (rotation) that needs to be applied to the joints such
// that a provided forward vector (in joint local-space) aims at the target
// position (in skeleton model-space). Up vector (in joint local-space) is also
// used to keep the joint oriented in the same direction as the pole vector.
// The job also exposes an offset (in joint local-space) from where the forward
// vector should aim the target.
// Result is unstable if joint-to-target direction is parallel to pole vector,
// or if target is too close to joint position.
struct IKAimJob {
// Default constructor, initializes default values.
IKAimJob();
// Validates job parameters. Returns true for a valid job, or false otherwise:
// -if output quaternion pointer is nullptr
bool Validate() const;
// Runs job's execution task.
// The job is validated before any operation is performed, see Validate() for
// more details.
// Returns false if *this job is not valid.
bool Run() const;
// Job input.
// Target position to aim at, in model-space
math::SimdFloat4 target;
// Joint forward axis, in joint local-space, to be aimed at target position.
// This vector shall be normalized, otherwise validation will fail.
// Default is x axis.
math::SimdFloat4 forward;
// Offset position from the joint in local-space, that will aim at target.
math::SimdFloat4 offset;
// Joint up axis, in joint local-space, used to keep the joint oriented in the
// same direction as the pole vector. Default is y axis.
math::SimdFloat4 up;
// Pole vector, in model-space. The pole vector defines the direction
// the up should point to. Note that IK chain orientation will flip when
// target vector and the pole vector are aligned/crossing each other. It's
// caller responsibility to ensure that this doesn't happen.
math::SimdFloat4 pole_vector;
// Twist_angle rotates joint around the target vector.
// Default is 0.
float twist_angle;
// Weight given to the IK correction clamped in range [0,1]. This allows to
// blend / interpolate from no IK applied (0 weight) to full IK (1).
float weight;
// Joint model-space matrix.
const math::Float4x4* joint;
// Job output.
// Output local-space joint correction quaternion. It needs to be multiplied
// with joint local-space quaternion.
math::SimdQuaternion* joint_correction;
// Optional boolean output value, set to true if target can be reached with IK
// computations. Target is considered not reachable when target is between
// joint and offset position.
bool* reached;
};
} // namespace animation
} // namespace ozz
#endif // OZZ_OZZ_ANIMATION_RUNTIME_IK_AIM_JOB_H_
@@ -0,0 +1,128 @@
//----------------------------------------------------------------------------//
// //
// 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_RUNTIME_IK_TWO_BONE_JOB_H_
#define OZZ_OZZ_ANIMATION_RUNTIME_IK_TWO_BONE_JOB_H_
#include "ozz/base/platform.h"
#include "ozz/base/maths/simd_math.h"
namespace ozz {
// Forward declaration of math structures.
namespace math {
struct SimdQuaternion;
}
namespace animation {
// ozz::animation::IKTwoBoneJob performs inverse kinematic on a three joints
// chain (two bones).
// The job computes the transformations (rotations) that needs to be applied to
// the first two joints of the chain (named start and middle joints) such that
// the third joint (named end) reaches the provided target position (if
// possible). The job outputs start and middle joint rotation corrections as
// quaternions.
// The three joints must be ancestors, but don't need to be direct
// ancestors (joints in-between will simply remain fixed).
// Implementation is inspired by Autodesk Maya 2 bone IK, improved stability
// wise and extended with Soften IK.
struct IKTwoBoneJob {
// Constructor, initializes default values.
IKTwoBoneJob();
// Validates job parameters. Returns true for a valid job, or false otherwise:
// -if any input pointer is nullptr
// -if mid_axis isn't normalized.
bool Validate() const;
// Runs job's execution task.
// The job is validated before any operation is performed, see Validate() for
// more details.
// Returns false if *this job is not valid.
bool Run() const;
// Job input.
// Target IK position, in model-space. This is the position the end of the
// joint chain will try to reach.
math::SimdFloat4 target;
// Normalized middle joint rotation axis, in middle joint local-space. Default
// value is z axis. This axis is usually fixed for a given skeleton (as it's
// in middle joint space). Its direction is defined like this: a positive
// rotation around this axis will open the angle between the two bones. This
// in turn also to define which side the two joints must bend. Job validation
// will fail if mid_axis isn't normalized.
math::SimdFloat4 mid_axis;
// Pole vector, in model-space. The pole vector defines the direction the
// middle joint should point to, allowing to control IK chain orientation.
// Note that IK chain orientation will flip when target vector and the pole
// vector are aligned/crossing each other. It's caller responsibility to
// ensure that this doesn't happen.
math::SimdFloat4 pole_vector;
// Twist_angle rotates IK chain around the vector define by start-to-target
// vector. Default is 0.
float twist_angle;
// Soften ratio allows the chain to gradually fall behind the target
// position. This prevents the joint chain from snapping into the final
// position, softening the final degrees before the joint chain becomes flat.
// This ratio represents the distance to the end, from which softening is
// starting.
float soften;
// Weight given to the IK correction clamped in range [0,1]. This allows to
// blend / interpolate from no IK applied (0 weight) to full IK (1).
float weight;
// Model-space matrices of the start, middle and end joints of the chain.
// The 3 joints should be ancestors. They don't need to be direct
// ancestors though.
const math::Float4x4* start_joint;
const math::Float4x4* mid_joint;
const math::Float4x4* end_joint;
// Job output.
// Local-space corrections to apply to start and middle joints in order for
// end joint to reach target position.
// These quaternions must be multiplied to the local-space quaternion of their
// respective joints.
math::SimdQuaternion* start_joint_correction;
math::SimdQuaternion* mid_joint_correction;
// Optional boolean output value, set to true if target can be reached with IK
// computations. Reachability is driven by bone chain length, soften ratio and
// target distance. Target is considered unreached if weight is less than 1.
bool* reached;
};
} // namespace animation
} // namespace ozz
#endif // OZZ_OZZ_ANIMATION_RUNTIME_IK_TWO_BONE_JOB_H_
@@ -0,0 +1,120 @@
//----------------------------------------------------------------------------//
// //
// 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_RUNTIME_LOCAL_TO_MODEL_JOB_H_
#define OZZ_OZZ_ANIMATION_RUNTIME_LOCAL_TO_MODEL_JOB_H_
#include "ozz/base/platform.h"
#include "ozz/base/span.h"
namespace ozz {
// Forward declaration math structures.
namespace math {
struct SoaTransform;
}
namespace math {
struct Float4x4;
}
namespace animation {
// Forward declares the Skeleton object used to describe joint hierarchy.
class Skeleton;
// Computes model-space joint matrices from local-space SoaTransform.
// This job uses the skeleton to define joints parent-child hierarchy. The job
// iterates through all joints to compute their transform relatively to the
// skeleton root.
// Job inputs is an array of SoaTransform objects (in local-space), ordered like
// skeleton's joints. Job output is an array of matrices (in model-space),
// ordered like skeleton's joints. Output are matrices, because the combination
// of affine transformations can contain shearing or complex transformation
// that cannot be represented as Transform object.
struct LocalToModelJob {
// Default constructor, initializes default values.
LocalToModelJob();
// Validates job parameters. Returns true for a valid job, or false otherwise:
// -if any input pointer, including ranges, is nullptr.
// -if the size of the input is smaller than the skeleton's number of joints.
// Note that this input has a SoA format.
// -if the size of of the output is smaller than the skeleton's number of
// joints.
bool Validate() const;
// Runs job's local-to-model task.
// The job is validated before any operation is performed, see Validate() for
// more details.
// Returns false if job is not valid. See Validate() function.
bool Run() const;
// Job input.
// The Skeleton object describing the joint hierarchy used for local to
// model space conversion.
const Skeleton* skeleton;
// The root matrix will multiply to every model space matrices, default nullptr
// means an identity matrix. This can be used to directly compute world-space
// transforms for example.
const ozz::math::Float4x4* root;
// Defines "from" which joint the local-to-model conversion should start.
// Default value is ozz::Skeleton::kNoParent, meaning the whole hierarchy is
// updated. This parameter can be used to optimize update by limiting
// conversion to part of the joint hierarchy. Note that "from" parent should
// be a valid matrix, as it is going to be used as part of "from" joint
// hierarchy update.
int from;
// Defines "to" which joint the local-to-model conversion should go, "to"
// included. Update will end before "to" joint is reached if "to" is not part
// of the hierarchy starting from "from". Default value is
// ozz::animation::Skeleton::kMaxJoints, meaning the hierarchy (starting from
// "from") is updated to the last joint.
int to;
// If true, "from" joint is not updated during job execution. Update starts
// with all children of "from". This can be used to update a model-space
// transform independently from the local-space one. To do so: set "from"
// joint model-space transform matrix, and run this Job with "from_excluded"
// to update all "from" children.
// Default value is false.
bool from_excluded;
// The input range that store local transforms.
span<const ozz::math::SoaTransform> input;
// Job output.
// The output range to be filled with model-space matrices.
span<ozz::math::Float4x4> output;
};
} // namespace animation
} // namespace ozz
#endif // OZZ_OZZ_ANIMATION_RUNTIME_LOCAL_TO_MODEL_JOB_H_
@@ -0,0 +1,181 @@
//----------------------------------------------------------------------------//
// //
// 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_RUNTIME_SAMPLING_JOB_H_
#define OZZ_OZZ_ANIMATION_RUNTIME_SAMPLING_JOB_H_
#include "ozz/base/platform.h"
#include "ozz/base/span.h"
namespace ozz {
// Forward declaration of math structures.
namespace math {
struct SoaTransform;
}
namespace animation {
// Forward declares the animation type to sample.
class Animation;
// Forward declares the cache object used by the SamplingJob.
class SamplingCache;
// Samples an animation at a given time ratio in the unit interval [0,1] (where
// 0 is the beginning of the animation, 1 is the end), to output the
// corresponding posture in local-space.
// SamplingJob uses a cache (aka SamplingCache) to store intermediate values
// (decompressed animation keyframes...) while sampling. This cache also stores
// pre-computed values that allows drastic optimization while playing/sampling
// the animation forward. Backward sampling works, but isn't optimized through
// the cache. The job does not owned the buffers (in/output) and will thus not
// delete them during job's destruction.
struct SamplingJob {
// Default constructor, initializes default values.
SamplingJob();
// Validates job parameters. Returns true for a valid job, or false otherwise:
// -if any input pointer is nullptr
// -if output range is invalid.
bool Validate() const;
// Runs job's sampling task.
// The job is validated before any operation is performed, see Validate() for
// more details.
// Returns false if *this job is not valid.
bool Run() const;
// Time ratio in the unit interval [0,1] used to sample animation (where 0 is
// the beginning of the animation, 1 is the end). It should be computed as the
// current time in the animation , divided by animation duration.
// This ratio is clamped before job execution in order to resolves any
// approximation issue on range bounds.
float ratio;
// The animation to sample.
const Animation* animation;
// A cache object that must be big enough to sample *this animation.
SamplingCache* cache;
// Job output.
// The output range to be filled with sampled joints during job execution.
// If there are less joints in the animation compared to the output range,
// then remaining SoaTransform are left unchanged.
// If there are more joints in the animation, then the last joints are not
// sampled.
span<ozz::math::SoaTransform> output;
};
namespace internal {
// Soa hot data to interpolate.
struct InterpSoaFloat3;
struct InterpSoaQuaternion;
} // namespace internal
// Declares the cache object used by the workload to take advantage of the
// frame coherency of animation sampling.
class SamplingCache {
public:
// Constructs an empty cache. The cache needs to be resized with the
// appropriate number of tracks before it can be used with a SamplingJob.
SamplingCache();
// Constructs a cache that can be used to sample any animation with at most
// _max_tracks tracks. _num_tracks is internally aligned to a multiple of
// soa size, which means max_tracks() can return a different (but bigger)
// value than _max_tracks.
explicit SamplingCache(int _max_tracks);
// Deallocates cache.
~SamplingCache();
// Resize the number of joints that the cache can support.
// This also implicitly invalidate the cache.
void Resize(int _max_tracks);
// Invalidate the cache.
// The SamplingJob automatically invalidates a cache when required
// during sampling. This automatic mechanism is based on the animation
// address and sampling time ratio. The weak point is that it can result in a
// crash if ever the address of an animation is used again with another
// animation (could be the result of successive call to delete / new).
// Therefore it is recommended to manually invalidate a cache when it is
// known that this cache will not be used for with an animation again.
void Invalidate();
// The maximum number of tracks that the cache can handle.
int max_tracks() const { return max_soa_tracks_ * 4; }
int max_soa_tracks() const { return max_soa_tracks_; }
private:
// Disables copy and assignation.
SamplingCache(SamplingCache const&);
void operator=(SamplingCache const&);
friend struct SamplingJob;
// Steps the cache in order to use it for a potentially new animation and
// ratio. If the _animation is different from the animation currently cached,
// or if the _ratio shows that the animation is played backward, then the
// cache is invalidated and reseted for the new _animation and _ratio.
void Step(const Animation& _animation, float _ratio);
// The animation this cache refers to. nullptr means that the cache is invalid.
const Animation* animation_;
// The current time ratio in the animation.
float ratio_;
// The number of soa tracks that can store this cache.
int max_soa_tracks_;
// Soa hot data to interpolate.
internal::InterpSoaFloat3* soa_translations_;
internal::InterpSoaQuaternion* soa_rotations_;
internal::InterpSoaFloat3* soa_scales_;
// Points to the keys in the animation that are valid for the current time
// ratio.
int* translation_keys_;
int* rotation_keys_;
int* scale_keys_;
// Current cursors in the animation. 0 means that the cache is invalid.
int translation_cursor_;
int rotation_cursor_;
int scale_cursor_;
// Outdated soa entries. One bit per soa entry (32 joints per byte).
uint8_t* outdated_translations_;
uint8_t* outdated_rotations_;
uint8_t* outdated_scales_;
};
} // namespace animation
} // namespace ozz
#endif // OZZ_OZZ_ANIMATION_RUNTIME_SAMPLING_JOB_H_
@@ -0,0 +1,144 @@
//----------------------------------------------------------------------------//
// //
// 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_RUNTIME_SKELETON_H_
#define OZZ_OZZ_ANIMATION_RUNTIME_SKELETON_H_
#include "ozz/base/io/archive_traits.h"
#include "ozz/base/platform.h"
#include "ozz/base/span.h"
namespace ozz {
namespace io {
class IArchive;
class OArchive;
} // namespace io
namespace math {
struct SoaTransform;
}
namespace animation {
// Forward declaration of SkeletonBuilder, used to instantiate a skeleton.
namespace offline {
class SkeletonBuilder;
}
// This runtime skeleton data structure provides a const-only access to joint
// hierarchy, joint names and bind-pose. This structure is filled by the
// SkeletonBuilder and can be serialize/deserialized.
// Joint names, bind-poses and hierarchy information are all stored in separate
// arrays of data (as opposed to joint structures for the RawSkeleton), in order
// to closely match with the way runtime algorithms use them. Joint hierarchy is
// packed as an array of parent jont indices (16 bits), stored in depth-first
// order. This is enough to traverse the whole joint hierarchy. See
// IterateJointsDF() from skeleton_utils.h that implements a depth-first
// traversal utility.
class Skeleton {
public:
// Defines Skeleton constant values.
enum Constants {
// Defines the maximum number of joints.
// This is limited in order to control the number of bits required to store
// a joint index. Limiting the number of joints also helps handling worst
// size cases, like when it is required to allocate an array of joints on
// the stack.
kMaxJoints = 1024,
// Defines the maximum number of SoA elements required to store the maximum
// number of joints.
kMaxSoAJoints = (kMaxJoints + 3) / 4,
// Defines the index of the parent of the root joint (which has no parent in
// fact).
kNoParent = -1,
};
// Builds a default skeleton.
Skeleton();
// Declares the public non-virtual destructor.
~Skeleton();
// Returns the number of joints of *this skeleton.
int num_joints() const { return static_cast<int>(joint_parents_.size()); }
// Returns the number of soa elements matching the number of joints of *this
// skeleton. This value is useful to allocate SoA runtime data structures.
int num_soa_joints() const { return (num_joints() + 3) / 4; }
// Returns joint's bind poses. Bind poses are stored in soa format.
span<const math::SoaTransform> joint_bind_poses() const {
return joint_bind_poses_;
}
// Returns joint's parent indices range.
span<const int16_t> joint_parents() const { return joint_parents_; }
// Returns joint's name collection.
span<const char* const> joint_names() const {
return span<const char* const>(joint_names_.begin(), joint_names_.end());
}
// Serialization functions.
// Should not be called directly but through io::Archive << and >> operators.
void Save(ozz::io::OArchive& _archive) const;
void Load(ozz::io::IArchive& _archive, uint32_t _version);
private:
// Disables copy and assignation.
Skeleton(Skeleton const&);
void operator=(Skeleton const&);
// Internal allocation/deallocation function.
// Allocate returns the beginning of the contiguous buffer of names.
char* Allocate(size_t _char_count, size_t _num_joints);
void Deallocate();
// SkeletonBuilder class is allowed to instantiate an Skeleton.
friend class offline::SkeletonBuilder;
// Buffers below store joint informations in joing depth first order. Their
// size is equal to the number of joints of the skeleton.
// Bind pose of every joint in local space.
span<math::SoaTransform> joint_bind_poses_;
// Array of joint parent indexes.
span<int16_t> joint_parents_;
// Stores the name of every joint in an array of c-strings.
span<char*> joint_names_;
};
} // namespace animation
namespace io {
OZZ_IO_TYPE_VERSION(2, animation::Skeleton)
OZZ_IO_TYPE_TAG("ozz-skeleton", animation::Skeleton)
} // namespace io
} // namespace ozz
#endif // OZZ_OZZ_ANIMATION_RUNTIME_SKELETON_H_
@@ -0,0 +1,90 @@
//----------------------------------------------------------------------------//
// //
// 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_RUNTIME_SKELETON_UTILS_H_
#define OZZ_OZZ_ANIMATION_RUNTIME_SKELETON_UTILS_H_
#include "ozz/animation/runtime/skeleton.h"
#include "ozz/base/maths/transform.h"
#include <cassert>
namespace ozz {
namespace animation {
// Get bind-pose of a skeleton joint.
ozz::math::Transform GetJointLocalBindPose(const Skeleton& _skeleton,
int _joint);
// Test if a joint is a leaf. _joint number must be in range [0, num joints].
// "_joint" is a leaf if it's the last joint, or next joint's parent isn't
// "_joint".
inline bool IsLeaf(const Skeleton& _skeleton, int _joint) {
const int num_joints = _skeleton.num_joints();
assert(_joint >= 0 && _joint < num_joints && "_joint index out of range");
const span<const int16_t>& parents = _skeleton.joint_parents();
const int next = _joint + 1;
return next == num_joints || parents[next] != _joint;
}
// Applies a specified functor to each joint in a depth-first order.
// _Fct is of type void(int _current, int _parent) where the first argument is
// the child of the second argument. _parent is kNoParent if the
// _current joint is a root. _from indicates the joint from which the joint
// hierarchy traversal begins. Use Skeleton::kNoParent to traverse the
// whole hierarchy, in case there are multiple roots.
template <typename _Fct>
inline _Fct IterateJointsDF(const Skeleton& _skeleton, _Fct _fct,
int _from = Skeleton::kNoParent) {
const span<const int16_t>& parents = _skeleton.joint_parents();
const int num_joints = _skeleton.num_joints();
//
// parents[i] >= _from is true as long as "i" is a child of "_from".
static_assert(Skeleton::kNoParent < 0,
"Algorithm relies on kNoParent being negative");
for (int i = _from < 0 ? 0 : _from, process = i < num_joints; process;
++i, process = i < num_joints && parents[i] >= _from) {
_fct(i, parents[i]);
}
return _fct;
}
// Applies a specified functor to each joint in a reverse (from leaves to root)
// depth-first order. _Fct is of type void(int _current, int _parent) where the
// first argument is the child of the second argument. _parent is kNoParent if
// the _current joint is a root.
template <typename _Fct>
inline _Fct IterateJointsDFReverse(const Skeleton& _skeleton, _Fct _fct) {
const span<const int16_t>& parents = _skeleton.joint_parents();
for (int i = _skeleton.num_joints() - 1; i >= 0; --i) {
_fct(i, parents[i]);
}
return _fct;
}
} // namespace animation
} // namespace ozz
#endif // OZZ_OZZ_ANIMATION_RUNTIME_SKELETON_UTILS_H_
@@ -0,0 +1,169 @@
//----------------------------------------------------------------------------//
// //
// 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_RUNTIME_TRACK_H_
#define OZZ_OZZ_ANIMATION_RUNTIME_TRACK_H_
#include "ozz/base/io/archive_traits.h"
#include "ozz/base/platform.h"
#include "ozz/base/span.h"
#include "ozz/base/maths/quaternion.h"
#include "ozz/base/maths/vec_float.h"
namespace ozz {
namespace animation {
// Forward declares the TrackBuilder, used to instantiate a Track.
namespace offline {
class TrackBuilder;
}
namespace internal {
// Runtime user-channel track internal implementation.
// The runtime track data structure exists for 1 to 4 float types (FloatTrack,
// ..., Float4Track) and quaternions (QuaternionTrack). See RawTrack for more
// details on track content. The runtime track data structure is optimized for
// the processing of ozz::animation::TrackSamplingJob and
// ozz::animation::TrackTriggeringJob. Keyframe ratios, values and interpolation
// mode are all store as separate buffers in order to access the cache
// coherently. Ratios are usually accessed/read alone from the jobs that all
// start by looking up the keyframes to interpolate indeed.
template <typename _ValueType>
class Track {
public:
typedef _ValueType ValueType;
Track();
~Track();
// Keyframe accessors.
span<const float> ratios() const { return ratios_; }
span<const _ValueType> values() const { return values_; }
span<const uint8_t> steps() const { return steps_; }
// Get the estimated track's size in bytes.
size_t size() const;
// Get track name.
const char* name() const { return name_ ? name_ : ""; }
// Serialization functions.
// Should not be called directly but through io::Archive << and >> operators.
void Save(ozz::io::OArchive& _archive) const;
void Load(ozz::io::IArchive& _archive, uint32_t _version);
private:
// Disables copy and assignation.
Track(Track const&);
void operator=(Track const&);
// TrackBuilder class is allowed to allocate a Track.
friend class offline::TrackBuilder;
// Internal destruction function.
void Allocate(size_t _keys_count, size_t _name_len);
void Deallocate();
// Keyframe ratios (0 is the beginning of the track, 1 is the end).
span<float> ratios_;
// Keyframe values.
span<_ValueType> values_;
// Keyframe modes (1 bit per key): 1 for step, 0 for linear.
span<uint8_t> steps_;
// Track name.
char* name_;
};
// Definition of operations policies per track value type.
template <typename _ValueType>
struct TrackPolicy {
inline static _ValueType Lerp(const _ValueType& _a, const _ValueType& _b,
float _alpha) {
return math::Lerp(_a, _b, _alpha);
}
inline static float Distance(const _ValueType& _a, const _ValueType& _b) {
return math::Length(_a - _b);
}
inline static _ValueType identity() { return _ValueType(0.f); }
};
// Specialization for float policy.
template <>
inline float TrackPolicy<float>::Distance(const float& _a, const float& _b) {
return std::abs(_a - _b);
}
// Specialization for quaternions policy.
template <>
inline math::Quaternion TrackPolicy<math::Quaternion>::Lerp(
const math::Quaternion& _a, const math::Quaternion& _b, float _alpha) {
// Uses NLerp to favor speed. This same function is used when optimizing the
// curve (key frame reduction), so "constant speed" interpolation can still be
// approximated with a lower tolerance value if it matters.
return math::NLerp(_a, _b, _alpha);
}
template <>
inline float TrackPolicy<math::Quaternion>::Distance(
const math::Quaternion& _a, const math::Quaternion& _b) {
const float cos_half_angle =
_a.x * _b.x + _a.y * _b.y + _a.z * _b.z + _a.w * _b.w;
// Return value is 1 - half cosine, so the closer the quaternions, the closer
// to 0.
return 1.f - math::Min(1.f, std::abs(cos_half_angle));
}
template <>
inline math::Quaternion TrackPolicy<math::Quaternion>::identity() {
return math::Quaternion::identity();
}
} // namespace internal
// Runtime track data structure instantiation.
class FloatTrack : public internal::Track<float> {};
class Float2Track : public internal::Track<math::Float2> {};
class Float3Track : public internal::Track<math::Float3> {};
class Float4Track : public internal::Track<math::Float4> {};
class QuaternionTrack : public internal::Track<math::Quaternion> {};
} // namespace animation
namespace io {
OZZ_IO_TYPE_VERSION(1, animation::FloatTrack)
OZZ_IO_TYPE_TAG("ozz-float_track", animation::FloatTrack)
OZZ_IO_TYPE_VERSION(1, animation::Float2Track)
OZZ_IO_TYPE_TAG("ozz-float2_track", animation::Float2Track)
OZZ_IO_TYPE_VERSION(1, animation::Float3Track)
OZZ_IO_TYPE_TAG("ozz-float3_track", animation::Float3Track)
OZZ_IO_TYPE_VERSION(1, animation::Float4Track)
OZZ_IO_TYPE_TAG("ozz-float4_track", animation::Float4Track)
OZZ_IO_TYPE_VERSION(1, animation::QuaternionTrack)
OZZ_IO_TYPE_TAG("ozz-quat_track", animation::QuaternionTrack)
} // namespace io
} // namespace ozz
#endif // OZZ_OZZ_ANIMATION_RUNTIME_TRACK_H_
@@ -0,0 +1,80 @@
//----------------------------------------------------------------------------//
// //
// 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_RUNTIME_TRACK_SAMPLING_JOB_H_
#define OZZ_OZZ_ANIMATION_RUNTIME_TRACK_SAMPLING_JOB_H_
#include "ozz/animation/runtime/track.h"
namespace ozz {
namespace animation {
namespace internal {
// TrackSamplingJob internal implementation. See *TrackSamplingJob for more
// details.
template <typename _Track>
struct TrackSamplingJob {
typedef typename _Track::ValueType ValueType;
TrackSamplingJob();
// Validates all parameters.
bool Validate() const;
// Validates and executes sampling.
bool Run() const;
// Ratio used to sample track, clamped in range [0,1] before job execution. 0
// is the beginning of the track, 1 is the end. This is a ratio rather than a
// ratio because tracks have no duration.
float ratio;
// Track to sample.
const _Track* track;
// Job output.
typename _Track::ValueType* result;
};
} // namespace internal
// Track sampling job implementation. Track sampling allows to query a track
// value for a specified ratio. This is a ratio rather than a time because
// tracks have no duration.
struct FloatTrackSamplingJob : public internal::TrackSamplingJob<FloatTrack> {};
struct Float2TrackSamplingJob : public internal::TrackSamplingJob<Float2Track> {
};
struct Float3TrackSamplingJob : public internal::TrackSamplingJob<Float3Track> {
};
struct Float4TrackSamplingJob : public internal::TrackSamplingJob<Float4Track> {
};
struct QuaternionTrackSamplingJob
: public internal::TrackSamplingJob<QuaternionTrack> {};
} // namespace animation
} // namespace ozz
#endif // OZZ_OZZ_ANIMATION_RUNTIME_TRACK_SAMPLING_JOB_H_
@@ -0,0 +1,161 @@
//----------------------------------------------------------------------------//
// //
// 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_RUNTIME_TRACK_TRIGGERING_JOB_H_
#define OZZ_OZZ_ANIMATION_RUNTIME_TRACK_TRIGGERING_JOB_H_
#include "ozz/base/platform.h"
namespace ozz {
namespace animation {
class FloatTrack;
// Track edge triggering job implementation. Edge triggering wording refers to
// signal processing, where a signal edge is a transition from low to high or
// from high to low. It is called an "edge" because of the square wave which
// represents a signal has edges at those points. A rising edge is the
// transition from low to high, a falling edge is from high to low.
// TrackTriggeringJob detects when track curve crosses a threshold value,
// triggering dated events that can be processed as state changes.
// Only FloatTrack is supported, because comparing to a threshold for other
// track types isn't possible.
// The job execution actually performs a lazy evaluation of edges. It builds an
// iterator that will process the next edge on each call to ++ operator.
struct TrackTriggeringJob {
TrackTriggeringJob();
// Validates job parameters.
bool Validate() const;
// Validates and executes job. Execution is lazy. Iterator operator ++ is
// actually doing the processing work.
bool Run() const;
// Input range. 0 is the beginning of the track, 1 is the end.
// from and to can be of any sign, any order, and any range. The job will
// perform accordingly:
// - if difference between from and to is greater than 1, the iterator will
// loop multiple times on the track.
// - if from is greater than to, then the track is processed backward (rising
// edges in forward become falling ones).
float from;
float to;
// Edge detection threshold value.
// A rising edge is detected as soon as the track value becomes greater than
// the threshold.
// A falling edge is detected as soon as the track value becomes smaller or
// equal than the threshold.
float threshold;
// Track to sample.
const FloatTrack* track;
// Job output iterator.
class Iterator;
Iterator* iterator;
// Returns an iterator referring to the past-the-end element. It should only
// be used to test if iterator loop reached the end (using operator !=), and
// shall not be dereferenced.
Iterator end() const;
// Structure of an edge as detected by the job.
struct Edge {
float ratio; // Ratio at which track value crossed threshold.
bool rising; // true is edge is rising (getting higher than threshold).
};
};
// Iterator implementation. Calls to ++ operator will compute the next edge. It
// should be compared (using operator !=) to job's end iterator to test if the
// last edge has been reached.
class TrackTriggeringJob::Iterator {
public:
Iterator() : job_(nullptr), outer_(0.f), inner_(0) {}
// Evaluate next edge.
// Calling this function on an end iterator results in an assertion in debug,
// an undefined behavior otherwise.
const Iterator& operator++();
Iterator operator++(int) {
Iterator prev = *this;
++*this;
return prev;
}
// Compare with other iterators.
bool operator!=(const Iterator& _it) const {
return inner_ != _it.inner_ || outer_ != _it.outer_ || job_ != _it.job_;
}
bool operator==(const Iterator& _it) const {
return job_ == _it.job_ && outer_ == _it.outer_ && inner_ == _it.inner_;
}
// Dereferencing operators.
const Edge& operator*() const {
assert(*this != job_->end() && "Can't dereference end iterator.");
return edge_;
}
const Edge* operator->() const {
assert(*this != job_->end() && "Can't dereference end iterator.");
return &edge_;
}
private:
friend struct TrackTriggeringJob;
// Constructors used by the job.
explicit Iterator(const TrackTriggeringJob* _job);
struct End {};
Iterator(const TrackTriggeringJob* _job, End)
: job_(_job),
outer_(0.f),
inner_(-2) { // Can never be reached while looping.
}
// Job this iterator works on.
const TrackTriggeringJob* job_;
// Current value of the outer loop, aka a ratio cursor between from and to.
float outer_;
// Current value of the inner loop, aka a key frame index.
ptrdiff_t inner_;
// Latest evaluated edge.
Edge edge_;
};
// end() job function inline implementation.
inline TrackTriggeringJob::Iterator TrackTriggeringJob::end() const {
return Iterator(this, Iterator::End());
}
} // namespace animation
} // namespace ozz
#endif // OZZ_OZZ_ANIMATION_RUNTIME_TRACK_TRIGGERING_JOB_H_
@@ -0,0 +1,51 @@
//----------------------------------------------------------------------------//
// //
// 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_RUNTIME_TRACK_TRIGGERING_JOB_TRAIT_H_
#define OZZ_OZZ_ANIMATION_RUNTIME_TRACK_TRIGGERING_JOB_TRAIT_H_
// Defines iterator traits required to use TrackTriggeringJob::Iterator
// with stl algorithms.
// This is a separate file from "track_triggering_job.h" to prevent everyone
// from including stl file <iterator>.
#include "ozz/animation/runtime/track_triggering_job.h"
#include <iterator>
// Specializes std::iterator_traits.
namespace std {
template <>
struct iterator_traits<ozz::animation::TrackTriggeringJob::Iterator> {
typedef ptrdiff_t difference_type;
typedef ozz::animation::TrackTriggeringJob::Edge value_type;
typedef const ozz::animation::TrackTriggeringJob::Edge* pointer;
typedef const ozz::animation::TrackTriggeringJob::Edge& reference;
typedef forward_iterator_tag iterator_category;
};
} // namespace std
#endif // OZZ_OZZ_ANIMATION_RUNTIME_TRACK_TRIGGERING_JOB_TRAIT_H_
@@ -0,0 +1,41 @@
//----------------------------------------------------------------------------//
// //
// 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_BASE_CONTAINERS_DEQUE_H_
#define OZZ_OZZ_BASE_CONTAINERS_DEQUE_H_
#include <deque>
#include "ozz/base/containers/std_allocator.h"
namespace ozz {
// Redirects std::deque to ozz::deque in order to replace std default allocator
// by ozz::StdAllocator.
template <class _Ty, class _Allocator = ozz::StdAllocator<_Ty>>
using deque = std::deque<_Ty, _Allocator>;
} // namespace ozz
#endif // OZZ_OZZ_BASE_CONTAINERS_DEQUE_H_
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,51 @@
//----------------------------------------------------------------------------//
// //
// 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_BASE_CONTAINERS_LIST_H_
#define OZZ_OZZ_BASE_CONTAINERS_LIST_H_
#ifdef _MSC_VER
#pragma warning(push)
// Removes constant conditional expression warning.
#pragma warning(disable : 4127)
#endif // _MSC_VER
#include <list>
#ifdef _MSC_VER
#pragma warning(pop)
#endif // _MSC_VER
#include "ozz/base/containers/std_allocator.h"
namespace ozz {
// Redirects std::list to ozz::list in order to replace std default allocator by
// ozz::StdAllocator.
template <class _Ty, class _Allocator = ozz::StdAllocator<_Ty>>
using list = std::list<_Ty, _Allocator>;
} // namespace ozz
#endif // OZZ_OZZ_BASE_CONTAINERS_LIST_H_
@@ -0,0 +1,70 @@
//----------------------------------------------------------------------------//
// //
// 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_BASE_CONTAINERS_MAP_H_
#define OZZ_OZZ_BASE_CONTAINERS_MAP_H_
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4702) // warning C4702: unreachable code
#endif // _MSC_VER
#include <cstring>
#include <map>
#ifdef _MSC_VER
#pragma warning(pop)
#endif // _MSC_VER
#include "ozz/base/containers/std_allocator.h"
namespace ozz {
// Redirects std::map to ozz::map in order to replace std default allocator by
// ozz::StdAllocator.
template <class _Key, class _Ty, class _Pred = std::less<_Key>,
class _Allocator = ozz::StdAllocator<std::pair<const _Key, _Ty>>>
using map = std::map<_Key, _Ty, _Pred, _Allocator>;
// Implements a string comparator that can be used by std algorithm like maps.
struct str_less {
bool operator()(const char* const& _left, const char* const& _right) const {
return strcmp(_left, _right) < 0;
}
};
// Specializes std::map to use c-string as a key.
template <class _Ty, class _Allocator =
ozz::StdAllocator<std::pair<const char* const, _Ty>>>
using cstring_map = std::map<const char*, _Ty, str_less, _Allocator>;
// Redirects std::multimap to ozz::MultiMap in order to replace std default
// allocator by ozz::StdAllocator.
template <class _Key, class _Ty, class _Pred = std::less<_Key>,
class _Allocator = ozz::StdAllocator<std::pair<const _Key, _Ty>>>
using multimap = std::multimap<_Key, _Ty, _Pred, _Allocator>;
} // namespace ozz
#endif // OZZ_OZZ_BASE_CONTAINERS_MAP_H_
@@ -0,0 +1,47 @@
//----------------------------------------------------------------------------//
// //
// 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_BASE_CONTAINERS_QUEUE_H_
#define OZZ_OZZ_BASE_CONTAINERS_QUEUE_H_
#include <queue>
#include "deque.h"
namespace ozz {
// Redirects std::queue to ozz::queue in order to replace std default allocator
// by ozz::StdAllocator.
template <class _Ty, class _Container = deque<_Ty>>
using queue = std::queue<_Ty, _Container>;
// Redirects std::priority_queue to ozz::priority_queue in order to replace std
// default allocator by ozz::StdAllocator.
template <class _Ty, class _Container = deque<_Ty>,
class _Pred = std::less<typename _Container::value_type>>
using priority_queue = std::priority_queue<_Ty, _Container, _Pred>;
} // namespace ozz
#endif // OZZ_OZZ_BASE_CONTAINERS_QUEUE_H_
@@ -0,0 +1,48 @@
//----------------------------------------------------------------------------//
// //
// 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_BASE_CONTAINERS_SET_H_
#define OZZ_OZZ_BASE_CONTAINERS_SET_H_
#include <set>
#include "ozz/base/containers/std_allocator.h"
namespace ozz {
// Redirects std::set to ozz::set in order to replace std default allocator by
// ozz::StdAllocator.
template <class _Key, class _Pred = std::less<_Key>,
class _Allocator = ozz::StdAllocator<_Key>>
using set = std::set<_Key, _Pred, _Allocator>;
// Redirects std::multiset to ozz::multiset in order to replace std default
// allocator by ozz::StdAllocator.
template <class _Key, class _Pred = std::less<_Key>,
class _Allocator = ozz::StdAllocator<_Key>>
using multiset = std::multiset<_Key, _Pred, _Allocator>;
} // namespace ozz
#endif // OZZ_OZZ_BASE_CONTAINERS_SET_H_
@@ -0,0 +1,41 @@
//----------------------------------------------------------------------------//
// //
// 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_BASE_CONTAINERS_STACK_H_
#define OZZ_OZZ_BASE_CONTAINERS_STACK_H_
#include <stack>
#include "deque.h"
namespace ozz {
// Redirects std::stack to ozz::stack in order to replace std default allocator
// by ozz::StdAllocator.
template <class _Ty, class _Container = typename ozz::deque<_Ty>>
using stack = std::stack<_Ty, _Container>;
} // namespace ozz
#endif // OZZ_OZZ_BASE_CONTAINERS_STACK_H_
@@ -0,0 +1,105 @@
//----------------------------------------------------------------------------//
// //
// 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_BASE_CONTAINERS_STD_ALLOCATOR_H_
#define OZZ_OZZ_BASE_CONTAINERS_STD_ALLOCATOR_H_
#include <new>
#include "ozz/base/memory/allocator.h"
namespace ozz {
// Define a STL allocator compliant allocator->
template <typename _Ty>
class StdAllocator {
public:
typedef _Ty value_type; // Element type.
typedef value_type* pointer; // Pointer to element.
typedef value_type& reference; // Reference to element.
typedef const value_type* const_pointer; // Constant pointer to element.
typedef const value_type& const_reference; // Constant reference to element.
typedef size_t size_type; // Quantities of elements.
typedef ptrdiff_t difference_type; // Difference between two pointers.
StdAllocator() noexcept {}
StdAllocator(const StdAllocator&) noexcept {}
template <class _Other>
StdAllocator<value_type>(const StdAllocator<_Other>&) noexcept {}
template <class _Other>
struct rebind {
typedef StdAllocator<_Other> other;
};
pointer address(reference _ref) const noexcept { return &_ref; }
const_pointer address(const_reference _ref) const noexcept { return &_ref; }
template <class _Other, class... _Args>
void construct(_Other* _ptr, _Args&&... _args) {
::new (static_cast<void*>(_ptr)) _Other(std::forward<_Args>(_args)...);
}
template <class _Other>
void destroy(_Other* _ptr) {
(void)_ptr;
_ptr->~_Other();
}
// Allocates array of _Count elements.
pointer allocate(size_t _count) noexcept {
// Makes sure to a use c like allocator, to avoid duplicated constructor
// calls.
return reinterpret_cast<pointer>(memory::default_allocator()->Allocate(
sizeof(value_type) * _count, alignof(value_type)));
}
// Deallocates object at _Ptr, ignores size.
void deallocate(pointer _ptr, size_type) noexcept {
memory::default_allocator()->Deallocate(_ptr);
}
size_type max_size() const noexcept {
return (~size_type(0)) / sizeof(value_type);
}
};
// Tests for allocator equality (always true).
template <class _Ty, class _Other>
inline bool operator==(const StdAllocator<_Ty>&,
const StdAllocator<_Other>&) noexcept {
return true;
}
// Tests for allocator inequality (always false).
template <class _Ty, class _Other>
inline bool operator!=(const StdAllocator<_Ty>&,
const StdAllocator<_Other>&) noexcept {
return false;
}
} // namespace ozz
#endif // OZZ_OZZ_BASE_CONTAINERS_STD_ALLOCATOR_H_
@@ -0,0 +1,41 @@
//----------------------------------------------------------------------------//
// //
// 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_BASE_CONTAINERS_STRING_H_
#define OZZ_OZZ_BASE_CONTAINERS_STRING_H_
#include <string>
#include "ozz/base/containers/std_allocator.h"
namespace ozz {
// Redirects std::basic_string to ozz::string in order to replace std default
// allocator by ozz::StdAllocator.
using string =
std::basic_string<char, std::char_traits<char>, ozz::StdAllocator<char>>;
} // namespace ozz
#endif // OZZ_OZZ_BASE_CONTAINERS_STRING_H_
@@ -0,0 +1,49 @@
//----------------------------------------------------------------------------//
// //
// 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_BASE_CONTAINERS_STRING_ARCHIVE_H_
#define OZZ_OZZ_BASE_CONTAINERS_STRING_ARCHIVE_H_
#include "ozz/base/containers/string.h"
#include "ozz/base/io/archive_traits.h"
#include "ozz/base/platform.h"
namespace ozz {
namespace io {
OZZ_IO_TYPE_NOT_VERSIONABLE(ozz::string)
template <>
struct Extern<ozz::string> {
static void Save(OArchive& _archive, const ozz::string* _values,
size_t _count);
static void Load(IArchive& _archive, ozz::string* _values, size_t _count,
uint32_t _version);
};
} // namespace io
} // namespace ozz
#endif // OZZ_OZZ_BASE_CONTAINERS_STRING_ARCHIVE_H_
@@ -0,0 +1,62 @@
//----------------------------------------------------------------------------//
// //
// 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_BASE_CONTAINERS_UNORDERED_MAP_H_
#define OZZ_OZZ_BASE_CONTAINERS_UNORDERED_MAP_H_
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4702) // warning C4702: unreachable code
#endif // _MSC_VER
#include <unordered_map>
#ifdef _MSC_VER
#pragma warning(pop)
#endif // _MSC_VER
#include "ozz/base/containers/std_allocator.h"
namespace ozz {
// Redirects std::unordered_map to ozz::unordered_map in order to replace std
// default allocator by ozz::StdAllocator.
template <class _Key, class _Ty, class _Hash = std::hash<_Key>,
class _KeyEqual = std::equal_to<_Key>,
class _Allocator = ozz::StdAllocator<std::pair<const _Key, _Ty>>>
using unordered_map =
std::unordered_map<_Key, _Ty, _Hash, _KeyEqual, _Allocator>;
// Redirects std::unordered_multimap to ozz::UnorderedMultiMap in order to
// replace std default allocator by ozz::StdAllocator.
template <class _Key, class _Ty, class _Hash = std::hash<_Key>,
class _KeyEqual = std::equal_to<_Key>,
class _Allocator = ozz::StdAllocator<std::pair<const _Key, _Ty>>>
using unordered_multimap =
std::unordered_multimap<_Key, _Ty, _Hash, _KeyEqual, _Allocator>;
} // namespace ozz
#endif // OZZ_OZZ_BASE_CONTAINERS_UNORDERED_MAP_H_
@@ -0,0 +1,52 @@
//----------------------------------------------------------------------------//
// //
// 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_BASE_CONTAINERS_UNORDERED_SET_H_
#define OZZ_OZZ_BASE_CONTAINERS_UNORDERED_SET_H_
#include <unordered_set>
#include "ozz/base/containers/std_allocator.h"
namespace ozz {
// Redirects std::unordered_set to ozz::UnorderedSet in order to replace std
// default allocator by ozz::StdAllocator.
template <class _Key, class _Hash = std::hash<_Key>,
class _KeyEqual = std::equal_to<_Key>,
class _Allocator = ozz::StdAllocator<_Key> >
using unordered_set =
std::unordered_set<_Key, _Hash, _KeyEqual, _Allocator>;
// Redirects std::unordered_multiset to ozz::UnorderedMultiSet in order to
// replace std default allocator by ozz::StdAllocator.
template <class _Key, class _Hash = std::hash<_Key>,
class _KeyEqual = std::equal_to<_Key>,
class _Allocator = ozz::StdAllocator<_Key> >
using unordered_multiset =
std::unordered_multiset<_Key, _Hash, _KeyEqual, _Allocator>;
} // namespace ozz
#endif // OZZ_OZZ_BASE_CONTAINERS_UNORDERED_SET_H_
@@ -0,0 +1,74 @@
//----------------------------------------------------------------------------//
// //
// 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_BASE_CONTAINERS_VECTOR_H_
#define OZZ_OZZ_BASE_CONTAINERS_VECTOR_H_
#include <vector>
#include "ozz/base/containers/std_allocator.h"
namespace ozz {
// Redirects std::vector to ozz::vector in order to replace std default
// allocator by ozz::StdAllocator.
template <class _Ty, class _Allocator = ozz::StdAllocator<_Ty>>
using vector = std::vector<_Ty, _Allocator>;
// Extends std::vector with two functions that gives access to the begin and the
// end of its array of elements.
// Returns the mutable begin of the array of elements, or nullptr if
// vector's empty.
template <class _Ty, class _Allocator>
inline _Ty* array_begin(std::vector<_Ty, _Allocator>& _vector) {
return _vector.data();
}
// Returns the non-mutable begin of the array of elements, or nullptr if
// vector's empty.
template <class _Ty, class _Allocator>
inline const _Ty* array_begin(const std::vector<_Ty, _Allocator>& _vector) {
return _vector.data();
}
// Returns the mutable end of the array of elements, or nullptr if
// vector's empty. Array end is one element past the last element of the
// array, it cannot be dereferenced.
template <class _Ty, class _Allocator>
inline _Ty* array_end(std::vector<_Ty, _Allocator>& _vector) {
return _vector.data() + _vector.size();
}
// Returns the non-mutable end of the array of elements, or nullptr if
// vector's empty. Array end is one element past the last element of the
// array, it cannot be dereferenced.
template <class _Ty, class _Allocator>
inline const _Ty* array_end(const std::vector<_Ty, _Allocator>& _vector) {
return _vector.data() + _vector.size();
}
} // namespace ozz
#endif // OZZ_OZZ_BASE_CONTAINERS_VECTOR_H_
@@ -0,0 +1,72 @@
//----------------------------------------------------------------------------//
// //
// 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_BASE_CONTAINERS_VECTOR_ARCHIVE_H_
#define OZZ_OZZ_BASE_CONTAINERS_VECTOR_ARCHIVE_H_
#include "ozz/base/containers/vector.h"
#include "ozz/base/io/archive.h"
#include "ozz/base/platform.h"
namespace ozz {
namespace io {
OZZ_IO_TYPE_NOT_VERSIONABLE_T2(class _Ty, class _Allocator,
std::vector<_Ty, _Allocator>)
template <class _Ty, class _Allocator>
struct Extern<std::vector<_Ty, _Allocator>> {
inline static void Save(OArchive& _archive,
const std::vector<_Ty, _Allocator>* _values,
size_t _count) {
for (size_t i = 0; i < _count; i++) {
const std::vector<_Ty, _Allocator>& vector = _values[i];
const uint32_t size = static_cast<uint32_t>(vector.size());
_archive << size;
if (size > 0) {
_archive << ozz::io::MakeArray(&vector[0], size);
}
}
}
inline static void Load(IArchive& _archive,
std::vector<_Ty, _Allocator>* _values, size_t _count,
uint32_t _version) {
(void)_version;
for (size_t i = 0; i < _count; i++) {
std::vector<_Ty, _Allocator>& vector = _values[i];
uint32_t size;
_archive >> size;
vector.resize(size);
if (size > 0) {
_archive >> ozz::io::MakeArray(&vector[0], size);
}
}
}
};
} // namespace io
} // namespace ozz
#endif // OZZ_OZZ_BASE_CONTAINERS_VECTOR_ARCHIVE_H_
+157
View File
@@ -0,0 +1,157 @@
//----------------------------------------------------------------------------//
// //
// 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_BASE_ENDIANNESS_H_
#define OZZ_OZZ_BASE_ENDIANNESS_H_
// Declares endianness modes and functions to swap data from a mode to another.
#include <cstddef>
#include "ozz/base/platform.h"
namespace ozz {
// Declares supported endianness.
enum Endianness {
kBigEndian,
kLittleEndian,
};
// Get the native endianness of the targeted processor.
// This function does not rely on a pre-processor definition as no standard
// definition exists. It is rather implemented as a portable runtime function.
inline Endianness GetNativeEndianness() {
const union {
uint16_t s;
uint8_t c[2];
} u = {1}; // Initializes u.s -> then read u.c.
return Endianness(u.c[0]);
}
// Declare the endian swapper struct that is aimed to be specialized (template
// meaning) for every type sizes.
// The swapper provides two functions:
// - void Swap(_Ty* _ty, size_t _count) swaps the array _ty of _count
// elements in-place.
// - _Ty Swap(_Ty _ty) returns a swapped copy of _ty.
// It can be used directly if _Ty is known or through EndianSwap function.
// The default value of template attribute _size enables automatic
// specialization selection.
template <typename _Ty, size_t _size = sizeof(_Ty)>
struct EndianSwapper;
// Internal macro used to swap two bytes.
#define OZZ_BYTE_SWAP(_a, _b) \
do { \
const char temp = _a; \
_a = _b; \
_b = temp; \
} while (0)
// EndianSwapper specialization for 1 byte types.
template <typename _Ty>
struct EndianSwapper<_Ty, 1> {
OZZ_INLINE static void Swap(_Ty* _ty, size_t _count) {
(void)_ty;
(void)_count;
}
OZZ_INLINE static _Ty Swap(_Ty _ty) { return _ty; }
};
// EndianSwapper specialization for 2 bytes types.
template <typename _Ty>
struct EndianSwapper<_Ty, 2> {
OZZ_INLINE static void Swap(_Ty* _ty, size_t _count) {
char* alias = reinterpret_cast<char*>(_ty);
for (size_t i = 0; i < _count * 2; i += 2) {
OZZ_BYTE_SWAP(alias[i + 0], alias[i + 1]);
}
}
OZZ_INLINE static _Ty Swap(_Ty _ty) { // Pass by copy to swap _ty in-place.
char* alias = reinterpret_cast<char*>(&_ty);
OZZ_BYTE_SWAP(alias[0], alias[1]);
return _ty;
}
};
// EndianSwapper specialization for 4 bytes types.
template <typename _Ty>
struct EndianSwapper<_Ty, 4> {
OZZ_INLINE static void Swap(_Ty* _ty, size_t _count) {
char* alias = reinterpret_cast<char*>(_ty);
for (size_t i = 0; i < _count * 4; i += 4) {
OZZ_BYTE_SWAP(alias[i + 0], alias[i + 3]);
OZZ_BYTE_SWAP(alias[i + 1], alias[i + 2]);
}
}
OZZ_INLINE static _Ty Swap(_Ty _ty) { // Pass by copy to swap _ty in-place.
char* alias = reinterpret_cast<char*>(&_ty);
OZZ_BYTE_SWAP(alias[0], alias[3]);
OZZ_BYTE_SWAP(alias[1], alias[2]);
return _ty;
}
};
// EndianSwapper specialization for 8 bytes types.
template <typename _Ty>
struct EndianSwapper<_Ty, 8> {
OZZ_INLINE static void Swap(_Ty* _ty, size_t _count) {
char* alias = reinterpret_cast<char*>(_ty);
for (size_t i = 0; i < _count * 8; i += 8) {
OZZ_BYTE_SWAP(alias[i + 0], alias[i + 7]);
OZZ_BYTE_SWAP(alias[i + 1], alias[i + 6]);
OZZ_BYTE_SWAP(alias[i + 2], alias[i + 5]);
OZZ_BYTE_SWAP(alias[i + 3], alias[i + 4]);
}
}
OZZ_INLINE static _Ty Swap(_Ty _ty) { // Pass by copy to swap _ty in-place.
char* alias = reinterpret_cast<char*>(&_ty);
OZZ_BYTE_SWAP(alias[0], alias[7]);
OZZ_BYTE_SWAP(alias[1], alias[6]);
OZZ_BYTE_SWAP(alias[2], alias[5]);
OZZ_BYTE_SWAP(alias[3], alias[4]);
return _ty;
}
};
// OZZ_BYTE_SWAP is not useful anymore.
#undef OZZ_BYTE_SWAP
// Helper function that swaps _count elements of the array _ty in place.
template <typename _Ty>
OZZ_INLINE void EndianSwap(_Ty* _ty, size_t _count) {
EndianSwapper<_Ty>::Swap(_ty, _count);
}
// Helper function that swaps _ty in place.
template <typename _Ty>
OZZ_INLINE _Ty EndianSwap(_Ty _ty) {
return EndianSwapper<_Ty>::Swap(_ty);
}
} // namespace ozz
#endif // OZZ_OZZ_BASE_ENDIANNESS_H_
+175
View File
@@ -0,0 +1,175 @@
//----------------------------------------------------------------------------//
// //
// 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_BASE_GTEST_HELPER_H_
#define OZZ_OZZ_BASE_GTEST_HELPER_H_
#include <sstream>
#include "gtest/gtest.h"
// EXPECT_ASSERTION expands to real death test if assertions are enabled.
// Parameters:
// statement - A statement that a macro such as EXPECT_DEATH would test
// for program termination.
// regex - A regex that a macro such as EXPECT_DEATH would use to test
// the output of statement.
#ifdef NDEBUG
// Expands to nothing if asserts aren't enabled (ie: NDEBUG is defined)
#define EXPECT_ASSERTION(_statement, _regex) \
do { \
} while (void(0), false);
#else // NDEBUG
#ifdef _WIN32
#include <crtdbg.h>
#include <cstdlib>
namespace internal {
// Provides a hook during abort to ensure EXIT_FAILURE is returned.
inline int AbortHook(int, char*, int*) { exit(EXIT_FAILURE); }
} // namespace internal
#define EXPECT_ASSERTION(_statement, _regex) \
do { \
/* During death tests executions:*/ \
/* Disables popping message boxes during crt and stl assertions*/ \
int old_mode = 0; \
(void)old_mode; \
_CRT_REPORT_HOOK old_hook = nullptr; \
(void)old_hook; \
if (testing::internal::GTEST_FLAG(internal_run_death_test).length() > 0) { \
old_mode = _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG); \
old_hook = _CrtSetReportHook(&internal::AbortHook); \
} \
EXPECT_DEATH((void)(_statement), _regex); \
if (testing::internal::GTEST_FLAG(internal_run_death_test).length() > 0) { \
_CrtSetReportMode(_CRT_ASSERT, old_mode); \
(void)_CrtSetReportHook(old_hook); \
} \
\
} while (void(0), 0)
#else // _WIN32
#define EXPECT_ASSERTION(_statement, _regex) EXPECT_DEATH(_statement, _regex)
#endif // _WIN32
#endif // NDEBUG
// EXPECT_EQ_LOG* executes _expression and compares its result with _eq.
// While executing _expression, EXPECT_EQ_LOG redirects _output (ex:
// std::clog) and then expects that the output matched the regular expression
// _re.
#define EXPECT_EQ_LOG(_expression, _eq, _output, _re) \
do { \
internal::RedirectOuputTester tester(_output, _re); \
EXPECT_EQ(_expression, _eq); \
\
} while (void(0), 0)
// There are multiple declinations EXPECT_EQ_LOG*, to match with clog, cerr and
// cout outputs, and verbose level option.
// Specialises EXPECT_EQ_LOG* for verbose clog output type.
#define EXPECT_EQ_LOG_LOGV(_expression, _eq, _re) \
EXPECT_EQ_LOG(_expression, _eq, std::clog, \
ozz::log::kVerbose <= ozz::log::GetLevel() ? _re : nullptr)
// Specialises EXPECT_EQ_LOG* for standard clog output type.
#define EXPECT_EQ_LOG_LOG(_expression, _eq, _re) \
EXPECT_EQ_LOG(_expression, _eq, std::clog, \
ozz::log::kStandard <= ozz::log::GetLevel() ? _re : nullptr)
// Specialises EXPECT_EQ_LOG* for standard cout output type.
#define EXPECT_EQ_LOG_OUT(_expression, _eq, _re) \
EXPECT_EQ_LOG(_expression, _eq, std::cout, \
ozz::log::kStandard <= ozz::log::GetLevel() ? _re : nullptr)
// Specialises EXPECT_EQ_LOG* for standard cerr output type.
#define EXPECT_EQ_LOG_ERR(_expression, _eq, _re) \
EXPECT_EQ_LOG(_expression, _eq, std::cerr, \
ozz::log::kStandard <= ozz::log::GetLevel() ? _re : nullptr)
// EXPECT_EQ_LOG* executes _expression while redirecting _output (ex:
// std::clog) and then expects that the output matched the regular expression
// _re.
#define EXPECT_LOG(_expression, _output, _re) \
do { \
internal::RedirectOuputTester tester(_output, _re); \
(_expression); \
\
} while (void(0), 0)
// There are multiple declinations EXPECT_LOG*, to match with clog, cerr and
// cout outputs, and verbose level option.
// Specialises EXPECT_LOG* for verbose clog output type.
#define EXPECT_LOG_LOGV(_expression, _re) \
EXPECT_LOG(_expression, std::clog, \
ozz::log::kVerbose <= ozz::log::GetLevel() ? _re : nullptr)
// Specialises EXPECT_LOG* for standard clog output type.
#define EXPECT_LOG_LOG(_expression, _re) \
EXPECT_LOG(_expression, std::clog, \
ozz::log::kStandard <= ozz::log::GetLevel() ? _re : nullptr)
// Specialises EXPECT_LOG* for standard cout output type.
#define EXPECT_LOG_OUT(_expression, _re) \
EXPECT_LOG(_expression, std::cout, \
ozz::log::kStandard <= ozz::log::GetLevel() ? _re : nullptr)
// Specialises EXPECT_LOG* for standard cerr output type.
#define EXPECT_LOG_ERR(_expression, _re) \
EXPECT_LOG(_expression, std::cerr, \
ozz::log::kStandard <= ozz::log::GetLevel() ? _re : nullptr)
namespace internal {
class RedirectOuputTester {
public:
// Specify a nullptr _regex to test an empty output
RedirectOuputTester(std::ostream& _ostream, const char* _regex)
: ostream_(_ostream), old_(_ostream.rdbuf()), regex_(_regex) {
// Redirect ostream_ buffer.
ostream_.rdbuf(redirect_.rdbuf());
}
~RedirectOuputTester() {
if (regex_) {
EXPECT_TRUE(::testing::internal::RE::PartialMatch(redirect_.str().c_str(),
regex_));
} else {
EXPECT_EQ(redirect_.str().size(), 0u);
}
// Restore ostream_ buffer.
ostream_.rdbuf(old_);
// finally outputs everything temporary redirected.
ostream_ << redirect_.str();
}
private:
std::ostream& ostream_;
std::streambuf* old_;
const char* regex_;
std::stringstream redirect_;
};
} // namespace internal
#endif // OZZ_OZZ_BASE_GTEST_HELPER_H_
+440
View File
@@ -0,0 +1,440 @@
//----------------------------------------------------------------------------//
// //
// 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_BASE_IO_ARCHIVE_H_
#define OZZ_OZZ_BASE_IO_ARCHIVE_H_
// Provides input (IArchive) and output (OArchive) serialization containers.
// Archive are similar to c++ iostream. Data can be saved to a OArchive with
// the << operator, or loaded from a IArchive with the >> operator.
// Primitive data types are simply saved/loaded to/from archives, while struct
// and class are saved/loaded through Save/Load intrusive or non-intrusive
// functions:
// - The intrusive function prototypes are "void Save(ozz::io::OArchive*) const"
// and "void Load(ozz::io::IArchive*)".
// - The non-intrusive functions allow to work on arrays of objects. They must
// be implemented in ozz::io namespace, by specializing the following template
// struct:
// template <typename _Ty>
// struct Extern {
// static void Save(OArchive& _archive, const _Ty* _ty, size_t _count);
// static void Load(IArchive& _archive, _Ty* _ty, size_t _count,
// uint32_t _version);
// };
//
// Arrays of struct/class or primitive types can be saved/loaded with the
// helper function ozz::io::MakeArray() that is then streamed in or out using
// << and >> archive operators: archive << ozz::io::MakeArray(my_array, count);
//
// Versioning can be done using OZZ_IO_TYPE_VERSION macros. Type version
// is saved in the OArchive, and is given back to Load functions to allow to
// manually handle version modifications. Versioning can be disabled using
// OZZ_IO_TYPE_NOT_VERSIONABLE like macros. It can not be re-enabled afterward.
//
// Objects can be assigned a tag using OZZ_IO_TYPE_TAG macros. A tag allows to
// check the type of the next object to read from an archive. An automatic
// assertion check is performed for each object that has a tag. It can also be
// done manually to ensure an archive has the expected content.
//
// Endianness (big-endian or little-endian) can be specified while constructing
// an output archive (ozz::io::OArchive). Input archives automatically handle
// endianness conversion if the native platform endian mode differs from the
// archive one.
//
// IArchive and OArchive expect valid streams as argument, respectively opened
// for reading and writing. Archives do NOT perform error detection while
// reading or writing. All errors are considered programming errors. This leads
// to the following assertions on the user side:
// - When writing: the stream must be big (or grow-able) enough to support the
// data being written.
// - When reading: Stream's tell (position in the stream) must match the object
// being read. To help with this requirement, archives provide a tag mechanism
// that allows to check the tag (ie the type) of the next object to read. Stream
// integrity, like data corruption or file truncation, must also be validated on
// the user side.
#include "ozz/base/endianness.h"
#include "ozz/base/io/stream.h"
#include "ozz/base/platform.h"
#include "ozz/base/span.h"
#include <stdint.h>
#include <cassert>
#include "ozz/base/io/archive_traits.h"
namespace ozz {
namespace io {
namespace internal {
// Defines Tagger helper object struct.
// The boolean template argument is used to automatically select a template
// specialization, whether _Ty has a tag or not.
template <typename _Ty,
bool _HasTag = internal::Tag<const _Ty>::kTagLength != 0>
struct Tagger;
} // namespace internal
// Implements output archive concept used to save/serialize data from a Stream.
// The output endianness mode is set at construction time. It is written to the
// stream to allow the IArchive to perform the required conversion to the native
// endianness mode while reading.
class OArchive {
public:
// Constructs an output archive from the Stream _stream that must be valid
// and opened for writing.
explicit OArchive(Stream* _stream,
Endianness _endianness = GetNativeEndianness());
// Returns true if an endian swap is required while writing.
bool endian_swap() const { return endian_swap_; }
// Saves _size bytes of binary data from _data.
size_t SaveBinary(const void* _data, size_t _size) {
return stream_->Write(_data, _size);
}
// Class type saving.
template <typename _Ty>
void operator<<(const _Ty& _ty) {
internal::Tagger<const _Ty>::Write(*this);
SaveVersion<_Ty>();
Extern<_Ty>::Save(*this, &_ty, 1);
}
// Primitive type saving.
#define OZZ_IO_PRIMITIVE_TYPE(_type) \
void operator<<(_type _v) { \
_type v = endian_swap_ ? EndianSwapper<_type>::Swap(_v) : _v; \
OZZ_IF_DEBUG(size_t size =) stream_->Write(&v, sizeof(v)); \
assert(size == sizeof(v)); \
}
OZZ_IO_PRIMITIVE_TYPE(char)
OZZ_IO_PRIMITIVE_TYPE(int8_t)
OZZ_IO_PRIMITIVE_TYPE(uint8_t)
OZZ_IO_PRIMITIVE_TYPE(int16_t)
OZZ_IO_PRIMITIVE_TYPE(uint16_t)
OZZ_IO_PRIMITIVE_TYPE(int32_t)
OZZ_IO_PRIMITIVE_TYPE(uint32_t)
OZZ_IO_PRIMITIVE_TYPE(int64_t)
OZZ_IO_PRIMITIVE_TYPE(uint64_t)
OZZ_IO_PRIMITIVE_TYPE(bool)
OZZ_IO_PRIMITIVE_TYPE(float)
#undef OZZ_IO_PRIMITIVE_TYPE
// Returns output stream.
Stream* stream() const { return stream_; }
private:
template <typename _Ty>
void SaveVersion() {
// Compilation could fail here if the version is not defined for _Ty, or if
// the .h file containing its definition is not included by the caller of
// this function.
if (void(0), internal::Version<const _Ty>::kValue != 0) {
uint32_t version = internal::Version<const _Ty>::kValue;
*this << version;
}
}
// The output stream.
Stream* stream_;
// Endian swap state, true if a conversion is required while writing.
bool endian_swap_;
};
// Implements input archive concept used to load/de-serialize data to a Stream.
// Endianness conversions are automatically performed according to the Archive
// and the native formats.
class IArchive {
public:
// Constructs an input archive from the Stream _stream that must be opened for
// reading, at the same tell (position in the stream) as when it was passed to
// the OArchive.
explicit IArchive(Stream* _stream);
// Returns true if an endian swap is required while reading.
bool endian_swap() const { return endian_swap_; }
// Loads _size bytes of binary data to _data.
size_t LoadBinary(void* _data, size_t _size) {
return stream_->Read(_data, _size);
}
// Class type loading.
template <typename _Ty>
void operator>>(_Ty& _ty) {
// Only uses tag validation for assertions, as reading cannot fail.
OZZ_IF_DEBUG(bool valid =) internal::Tagger<const _Ty>::Validate(*this);
assert(valid && "Type tag does not match archive content.");
// Loads instance.
uint32_t version = LoadVersion<_Ty>();
Extern<_Ty>::Load(*this, &_ty, 1, version);
}
// Primitive type loading.
#define OZZ_IO_PRIMITIVE_TYPE(_type) \
void operator>>(_type& _v) { \
_type v; \
OZZ_IF_DEBUG(size_t size =) stream_->Read(&v, sizeof(v)); \
assert(size == sizeof(v)); \
_v = endian_swap_ ? EndianSwapper<_type>::Swap(v) : v; \
}
OZZ_IO_PRIMITIVE_TYPE(char)
OZZ_IO_PRIMITIVE_TYPE(int8_t)
OZZ_IO_PRIMITIVE_TYPE(uint8_t)
OZZ_IO_PRIMITIVE_TYPE(int16_t)
OZZ_IO_PRIMITIVE_TYPE(uint16_t)
OZZ_IO_PRIMITIVE_TYPE(int32_t)
OZZ_IO_PRIMITIVE_TYPE(uint32_t)
OZZ_IO_PRIMITIVE_TYPE(int64_t)
OZZ_IO_PRIMITIVE_TYPE(uint64_t)
OZZ_IO_PRIMITIVE_TYPE(bool)
OZZ_IO_PRIMITIVE_TYPE(float)
#undef OZZ_IO_PRIMITIVE_TYPE
template <typename _Ty>
bool TestTag() {
// Only tagged types can be tested. If compilations fails here, it can
// mean the file containing tag declaration is not included.
static_assert(internal::Tag<const _Ty>::kTagLength != 0,
"Tag unknown for type.");
const int tell = stream_->Tell();
bool valid = internal::Tagger<const _Ty>::Validate(*this);
stream_->Seek(tell, Stream::kSet); // Rewinds before the tag test.
return valid;
}
// Returns input stream.
Stream* stream() const { return stream_; }
private:
template <typename _Ty>
uint32_t LoadVersion() {
uint32_t version = 0;
if (void(0), internal::Version<const _Ty>::kValue != 0) {
*this >> version;
}
return version;
}
// The input stream.
Stream* stream_;
// Endian swap state, true if a conversion is required while reading.
bool endian_swap_;
};
// Primitive type are not versionable.
OZZ_IO_TYPE_NOT_VERSIONABLE(char)
OZZ_IO_TYPE_NOT_VERSIONABLE(int8_t)
OZZ_IO_TYPE_NOT_VERSIONABLE(uint8_t)
OZZ_IO_TYPE_NOT_VERSIONABLE(int16_t)
OZZ_IO_TYPE_NOT_VERSIONABLE(uint16_t)
OZZ_IO_TYPE_NOT_VERSIONABLE(int32_t)
OZZ_IO_TYPE_NOT_VERSIONABLE(uint32_t)
OZZ_IO_TYPE_NOT_VERSIONABLE(int64_t)
OZZ_IO_TYPE_NOT_VERSIONABLE(uint64_t)
OZZ_IO_TYPE_NOT_VERSIONABLE(bool)
OZZ_IO_TYPE_NOT_VERSIONABLE(float)
// Default loading and saving external implementation.
template <typename _Ty>
struct Extern {
inline static void Save(OArchive& _archive, const _Ty* _ty, size_t _count) {
for (size_t i = 0; i < _count; ++i) {
_ty[i].Save(_archive);
}
}
inline static void Load(IArchive& _archive, _Ty* _ty, size_t _count,
uint32_t _version) {
for (size_t i = 0; i < _count; ++i) {
_ty[i].Load(_archive, _version);
}
}
};
// Wrapper for dynamic array serialization.
// Must be used through ozz::io::MakeArray.
namespace internal {
template <typename _Ty>
struct Array {
OZZ_INLINE void Save(OArchive& _archive) const {
ozz::io::Extern<_Ty>::Save(_archive, array, count);
}
OZZ_INLINE void Load(IArchive& _archive, uint32_t _version) const {
ozz::io::Extern<_Ty>::Load(_archive, array, count, _version);
}
_Ty* array;
size_t count;
};
// Specialize for const _Ty which can only be saved.
template <typename _Ty>
struct Array<const _Ty> {
OZZ_INLINE void Save(OArchive& _archive) const {
ozz::io::Extern<_Ty>::Save(_archive, array, count);
}
const _Ty* array;
size_t count;
};
// Array copies version from the type it contains.
// Definition of Array of _Ty version: _Ty version.
template <typename _Ty>
struct Version<const Array<_Ty>> {
enum { kValue = Version<const _Ty>::kValue };
};
// Specializes Array Save/Load for primitive types.
#define OZZ_IO_PRIMITIVE_TYPE(_type) \
template <> \
inline void Array<const _type>::Save(OArchive& _archive) const { \
if (_archive.endian_swap()) { \
/* Save element by element as swapping in place the whole buffer is*/ \
/* not possible.*/ \
for (size_t i = 0; i < count; ++i) { \
_archive << array[i]; \
} \
} else { \
OZZ_IF_DEBUG(size_t size =) \
_archive.SaveBinary(array, count * sizeof(_type)); \
assert(size == count * sizeof(_type)); \
} \
} \
\
template <> \
inline void Array<_type>::Save(OArchive& _archive) const { \
if (_archive.endian_swap()) { \
/* Save element by element as swapping in place the whole buffer is*/ \
/* not possible.*/ \
for (size_t i = 0; i < count; ++i) { \
_archive << array[i]; \
} \
} else { \
OZZ_IF_DEBUG(size_t size =) \
_archive.SaveBinary(array, count * sizeof(_type)); \
assert(size == count * sizeof(_type)); \
} \
} \
\
template <> \
inline void Array<_type>::Load(IArchive& _archive, uint32_t /*_version*/) \
const { \
OZZ_IF_DEBUG(size_t size =) \
_archive.LoadBinary(array, count * sizeof(_type)); \
assert(size == count * sizeof(_type)); \
if (_archive.endian_swap()) { /*Can swap in-place.*/ \
EndianSwapper<_type>::Swap(array, count); \
} \
}
OZZ_IO_PRIMITIVE_TYPE(char)
OZZ_IO_PRIMITIVE_TYPE(int8_t)
OZZ_IO_PRIMITIVE_TYPE(uint8_t)
OZZ_IO_PRIMITIVE_TYPE(int16_t)
OZZ_IO_PRIMITIVE_TYPE(uint16_t)
OZZ_IO_PRIMITIVE_TYPE(int32_t)
OZZ_IO_PRIMITIVE_TYPE(uint32_t)
OZZ_IO_PRIMITIVE_TYPE(int64_t)
OZZ_IO_PRIMITIVE_TYPE(uint64_t)
OZZ_IO_PRIMITIVE_TYPE(bool)
OZZ_IO_PRIMITIVE_TYPE(float)
#undef OZZ_IO_PRIMITIVE_TYPE
} // namespace internal
// Utility function that instantiates Array wrapper.
template <typename _Ty>
OZZ_INLINE const internal::Array<_Ty> MakeArray(_Ty* _array, size_t _count) {
const internal::Array<_Ty> array = {_array, _count};
return array;
}
template <typename _Ty>
OZZ_INLINE const internal::Array<const _Ty> MakeArray(const _Ty* _array,
size_t _count) {
const internal::Array<const _Ty> array = {_array, _count};
return array;
}
template <typename _Ty>
OZZ_INLINE const internal::Array<_Ty> MakeArray(span<_Ty> _array) {
const internal::Array<_Ty> array = {_array.data(), _array.size()};
return array;
}
template <typename _Ty>
OZZ_INLINE const internal::Array<const _Ty> MakeArray(span<const _Ty> _array) {
const internal::Array<const _Ty> array = {_array.data(), _array.size()};
return array;
}
template <typename _Ty, size_t _count>
OZZ_INLINE const internal::Array<_Ty> MakeArray(_Ty (&_array)[_count]) {
const internal::Array<_Ty> array = {_array, _count};
return array;
}
template <typename _Ty, size_t _count>
OZZ_INLINE const internal::Array<const _Ty> MakeArray(
const _Ty (&_array)[_count]) {
const internal::Array<const _Ty> array = {_array, _count};
return array;
}
namespace internal {
// Specialization of the Tagger helper for tagged types.
template <typename _Ty>
struct Tagger<_Ty, true> {
static void Write(OArchive& _archive) {
typedef internal::Tag<const _Ty> Tag;
OZZ_IF_DEBUG(size_t size =)
_archive.SaveBinary(Tag::Get(), Tag::kTagLength);
assert(size == Tag::kTagLength);
}
static bool Validate(IArchive& _archive) {
typedef internal::Tag<const _Ty> Tag;
char buf[Tag::kTagLength];
if (Tag::kTagLength != _archive.LoadBinary(buf, Tag::kTagLength)) {
return false;
}
const char* tag = Tag::Get();
size_t i = 0;
for (; i < Tag::kTagLength && buf[i] == tag[i]; ++i) {
}
return i == Tag::kTagLength;
}
};
// Specialization of the Tagger helper for types with no tag.
template <typename _Ty>
struct Tagger<_Ty, false> {
static void Write(OArchive& /*_archive*/) {}
static bool Validate(IArchive& /*_archive*/) { return true; }
};
} // namespace internal
} // namespace io
} // namespace ozz
#endif // OZZ_OZZ_BASE_IO_ARCHIVE_H_
@@ -0,0 +1,220 @@
//----------------------------------------------------------------------------//
// //
// 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_BASE_IO_ARCHIVE_TRAITS_H_
#define OZZ_OZZ_BASE_IO_ARCHIVE_TRAITS_H_
// Provides traits for customizing archive serialization properties: version,
// tag... See archive.h for more details.
#include <stdint.h>
#include <cstddef>
namespace ozz {
namespace io {
// Forward declaration of archive types.
class OArchive;
class IArchive;
// Default loading and saving external declaration.
// Those template implementations aim to be specialized at compilation time by
// non-member Load and save functions. For example the specialization of the
// Save() function for a type Type is:
// void Save(OArchive& _archive, const Extrusive* _test, size_t _count) {
// }
// The Load() function receives the version _version of type _Ty at the time the
// archive was saved.
// This uses polymorphism rather than template specialization to avoid
// including the file that contains the template definition.
//
// This default function call member _Ty::Load/Save function.
template <typename _Ty>
struct Extern;
// Declares the current (compile time) version of _type.
// This macro must be used inside namespace ozz::io.
// Syntax is: OZZ_IO_TYPE_VERSION(46, Foo).
#define OZZ_IO_TYPE_VERSION(_version, _type) \
static_assert(_version > 0, "Version number must be > 0"); \
namespace internal { \
template <> \
struct Version<const _type> { \
enum { kValue = _version }; \
}; \
} // internal
// Declares the current (compile time) version of a template _type.
// This macro must be used inside namespace ozz::io.
// OZZ_IO_TYPE_VERSION_T1(46, typename _T1, Foo<_T1>).
#define OZZ_IO_TYPE_VERSION_T1(_version, _arg0, ...) \
static_assert(_version > 0, "Version number must be > 0"); \
namespace internal { \
template <_arg0> \
struct Version<const __VA_ARGS__> { \
enum { kValue = _version }; \
}; \
} // internal
// Declares the current (compile time) version of a template _type.
// This macro must be used inside namespace ozz::io.
// OZZ_IO_TYPE_VERSION_T2(46, typename _T1, typename _T2, Foo<_T1, _T2>).
#define OZZ_IO_TYPE_VERSION_T2(_version, _arg0, _arg1, ...) \
static_assert(_version > 0, "Version number must be > 0"); \
namespace internal { \
template <_arg0, _arg1> \
struct Version<const __VA_ARGS__> { \
enum { kValue = _version }; \
}; \
\
} // internal
// Declares the current (compile time) version of a template _type.
// This macro must be used inside namespace ozz::io.
// OZZ_IO_TYPE_VERSION_T3(
// 46, typename _T1, typename _T2, typename _T3, Foo<_T1, _T2, _T3>).
#define OZZ_IO_TYPE_VERSION_T3(_version, _arg0, _arg1, _arg2, ...) \
static_assert(_version > 0, "Version number must be > 0"); \
namespace internal { \
template <_arg0, _arg1, _arg2> \
struct Version<const __VA_ARGS__> { \
enum { kValue = _version }; \
}; \
\
} // internal
// Declares the current (compile time) version of a template _type.
// This macro must be used inside namespace ozz::io.
// OZZ_IO_TYPE_VERSION_T4(
// 46, typename _T1, typename _T2, typename _T3, typename _T4,
// Foo<_T1, _T2, _T3, _T4>).
#define OZZ_IO_TYPE_VERSION_T4(_version, _arg0, _arg1, _arg2, _arg3, ...) \
static_assert(_version > 0, "Version number must be > 0"); \
namespace internal { \
template <_arg0, _arg1, _arg2, _arg3> \
struct Version<const __VA_ARGS__> { \
enum { kValue = _version }; \
}; \
} // internal
// Declares that _type is not versionable. Its version number is 0.
// Once a type has been declared not versionable, it cannot be changed without
// braking versioning.
// This macro must be used inside namespace ozz::io.
// Syntax is: OZZ_IO_TYPE_NOT_VERSIONABLE(Foo).
#define OZZ_IO_TYPE_NOT_VERSIONABLE(_type) \
namespace internal { \
template <> \
struct Version<const _type> { \
enum { kValue = 0 }; \
}; \
} // internal
// Declares that a template _type is not versionable. Its version number is 0.
// Once a type has been declared not versionable, it cannot be changed without
// braking versioning.
// This macro must be used inside namespace ozz::io.
// Syntax is:
// OZZ_IO_TYPE_NOT_VERSIONABLE_T1(typename _T1, Foo<_T1>).
#define OZZ_IO_TYPE_NOT_VERSIONABLE_T1(_arg0, ...) \
namespace internal { \
template <_arg0> \
struct Version<const __VA_ARGS__> { \
enum { kValue = 0 }; \
}; \
} // internal
// Decline non-versionable template declaration to 2 template arguments.
// Syntax is:
// OZZ_IO_TYPE_NOT_VERSIONABLE_T2(typename _T1, typename _T2, Foo<_T1, _T2>).
#define OZZ_IO_TYPE_NOT_VERSIONABLE_T2(_arg0, _arg1, ...) \
namespace internal { \
template <_arg0, _arg1> \
struct Version<const __VA_ARGS__> { \
enum { kValue = 0 }; \
}; \
} // internal
// Decline non-versionable template declaration to 3 template arguments.
// Syntax is:
// OZZ_IO_TYPE_NOT_VERSIONABLE_T3(
// typename _T1, typename _T2, typename _T3, Foo<_T1, _T2, _T3>).
#define OZZ_IO_TYPE_NOT_VERSIONABLE_T3(_arg0, _arg1, _arg2, ...) \
namespace internal { \
template <_arg0, _arg1, _arg2> \
struct Version<const __VA_ARGS__> { \
enum { kValue = 0 }; \
}; \
} // internal
// Decline non-versionable template declaration to 4 template arguments.
// Syntax is:
// OZZ_IO_TYPE_NOT_VERSIONABLE_T4(
// typename _T1, typename _T2, typename _T3, typename _T4,
// Foo<_T1, _T2, _T3, _T4>).
#define OZZ_IO_TYPE_NOT_VERSIONABLE_T4(_arg0, _arg1, _arg2, _arg3, ...) \
namespace internal { \
template <_arg0, _arg1, _arg2, _arg3> \
struct Version<const __VA_ARGS__> { \
enum { kValue = 0 }; \
}; \
} // internal
// Declares the tag of a template _type.
// A tag is a c-string that can be used to check the type (through its tag) of
// the next object to be read from an archive. If no tag is defined, then no
// check is performed.
// This macro must be used inside namespace ozz::io.
// OZZ_IO_TYPE_TAG("Foo", Foo).
#define OZZ_IO_TYPE_TAG(_tag, _type) \
namespace internal { \
template <> \
struct Tag<const _type> { \
/* Length includes null terminated character to detect partial */ \
/* tag mapping.*/ \
enum { kTagLength = OZZ_ARRAY_SIZE(_tag) }; \
static const char* Get() { return _tag; } \
}; \
} // internal
namespace internal {
// Definition of version specializable template struct.
// There's no default implementation in order to force user to define it, which
// in turn forces those who want to serialize an object to include the file that
// defines it's version. This helps with detecting issues at compile time.
template <typename _Ty>
struct Version;
// Defines default tag value, which is disabled.
template <typename _Ty>
struct Tag {
enum { kTagLength = 0 };
};
} // namespace internal
} // namespace io
} // namespace ozz
#endif // OZZ_OZZ_BASE_IO_ARCHIVE_TRAITS_H_
+189
View File
@@ -0,0 +1,189 @@
//----------------------------------------------------------------------------//
// //
// 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_BASE_IO_STREAM_H_
#define OZZ_OZZ_BASE_IO_STREAM_H_
// Provides Stream interface used to read/write a memory buffer or a file with
// Crt fread/fwrite/fseek/ftell like functions.
#include "ozz/base/platform.h"
#include <cstddef>
namespace ozz {
namespace io {
// Declares a stream access interface that conforms with CRT FILE API.
// This interface should be used to remap io operations.
class Stream {
public:
// Tests whether a file is opened.
virtual bool opened() const = 0;
// Reads _size bytes of data to _buffer from the stream. _buffer must be big
// enough to store _size bytes. The position indicator of the stream is
// advanced by the total amount of bytes read.
// Returns the number of bytes actually read, which may be less than _size.
virtual size_t Read(void* _buffer, size_t _size) = 0;
// Writes _size bytes of data from _buffer to the stream. The position
// indicator of the stream is advanced by the total number of bytes written.
// Returns the number of bytes actually written, which may be less than _size.
virtual size_t Write(const void* _buffer, size_t _size) = 0;
// Declares seeking origin enumeration.
enum Origin {
kCurrent, // Current position of the stream pointer.
kEnd, // End of stream.
kSet, // Beginning of stream.
};
// Sets the position indicator associated with the stream to a new position
// defined by adding _offset to a reference position specified by _origin.
// Returns a zero value if successful, otherwise returns a non-zero value.
virtual int Seek(int _offset, Origin _origin) = 0;
// Returns the current value of the position indicator of the stream.
// Returns -1 if an error occurs.
virtual int Tell() const = 0;
// Returns the current size of the stream.
virtual size_t Size() const = 0;
protected:
Stream() {}
// Required virtual destructor.
virtual ~Stream() {}
private:
Stream(const Stream&);
void operator=(const Stream&);
};
// Implements Stream of type File.
class File : public Stream {
public:
// Test if a file at path _filename exists.
// Note that this function is costly. If you aim to open the file right after,
// then open it and use File::opened() to test if it's actually existing.
static bool Exist(const char* _filename);
// Open a file at path _filename with mode * _mode, in conformance with fopen
// specifications.
// Use opened() function to test opening result.
File(const char* _filename, const char* _mode);
// Gives _file ownership to the FileStream, which will be in charge of closing
// it. _file must be nullptr or a valid std::FILE pointer.
explicit File(void* _file);
// Close the file if it is opened.
virtual ~File();
// Close the file if it is opened.
void Close();
// See Stream::opened for details.
virtual bool opened() const;
// See Stream::Read for details.
virtual size_t Read(void* _buffer, size_t _size);
// See Stream::Write for details.
virtual size_t Write(const void* _buffer, size_t _size);
// See Stream::Seek for details.
virtual int Seek(int _offset, Origin _origin);
// See Stream::Tell for details.
virtual int Tell() const;
// See Stream::Tell for details.
virtual size_t Size() const;
private:
// The CRT file pointer.
void* file_;
};
// Implements an in-memory Stream. Allows to use a memory buffer as a Stream.
// The opening mode is equivalent to fopen w+b (binary read/write).
class MemoryStream : public Stream {
public:
// Construct an empty memory stream opened in w+b mode.
MemoryStream();
// Closes the stream and deallocates memory buffer.
virtual ~MemoryStream();
// See Stream::opened for details.
virtual bool opened() const;
// See Stream::Read for details.
virtual size_t Read(void* _buffer, size_t _size);
// See Stream::Write for details.
virtual size_t Write(const void* _buffer, size_t _size);
// See Stream::Seek for details.
virtual int Seek(int _offset, Origin _origin);
// See Stream::Tell for details.
virtual int Tell() const;
// See Stream::Tell for details.
virtual size_t Size() const;
private:
// Resizes buffers size to _size bytes. If _size is less than the actual
// buffer size, then it remains unchanged.
// Returns true if the buffer can contains _size bytes.
bool Resize(size_t _size);
// Size of the buffer increment.
static const size_t kBufferSizeIncrement;
// Maximum stream size.
static const size_t kMaxSize;
// Buffer of data.
char* buffer_;
// The size of the buffer, which is greater or equal to the size of the data
// it contains (end_).
size_t alloc_size_;
// The effective size of the data in the buffer.
int end_;
// The cursor position in the buffer of data.
int tell_;
};
} // namespace io
} // namespace ozz
#endif // OZZ_OZZ_BASE_IO_STREAM_H_
+152
View File
@@ -0,0 +1,152 @@
//----------------------------------------------------------------------------//
// //
// 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_BASE_LOG_H_
#define OZZ_OZZ_BASE_LOG_H_
#include <iostream>
// MSVC includes <cstring> from <iostream> but not gcc.
// So it is included here to ensure a portable behavior.
#include <cstring>
// Proposes a logging interface that redirects logs to std::cout, clog and cerr
// output streams. This interface adds a logging level functionality (kSilent,
// kStandard, kVerbose) to the std API, which can be set using
// ozz::log::GetLevel function.
// Usage conforms to std stream usage: ozz::log::Log() << "something to log."...
namespace ozz {
namespace log {
enum Level {
kSilent, // No output at all, even errors are muted.
kStandard, // Default output level.
kVerbose, // Most verbose output level.
};
// Sets the global logging level.
Level SetLevel(Level _level);
// Gets the global logging level.
Level GetLevel();
// Implements logging base class.
// This class is not intended to be used publicly, it is derived by user
// classes LogV, Log, Out, Err...
// Forwards ostream::operator << to a standard ostream or a silent
// ostringstream according to the logging level at construction time.
class Logger {
public:
// Forwards ostream::operator << for any type.
template <typename _T>
std::ostream& operator<<(const _T& _t) {
return stream_ << _t;
}
// Forwards ostream::operator << for modifiers.
std::ostream& operator<<(std::ostream& (*_Pfn)(std::ostream&)) {
return ((*_Pfn)(stream_));
}
// Implicit cast operator.
operator std::ostream&() const { return stream_; }
// Explicit cast function.
std::ostream& stream() const { return stream_; }
protected:
// Specifies the global stream and the output level.
// Logging levels allows to select _stream or a "silent" stream according to
// the current global logging level.
Logger(std::ostream& _stream, Level _level);
// Destructor, deletes the internal "silent" stream.
~Logger();
private:
// Disables copy and assignment.
Logger(const Logger&);
void operator=(Logger&);
// Selected output stream.
std::ostream& stream_;
// Stores whether the stream is local one, in which case it must be deleted
// in the destructor.
bool local_stream_;
};
// Logs verbose output to the standard error stream (std::clog).
// Enabled if logging level is Verbose.
class LogV : public Logger {
public:
LogV();
};
// Logs output to the standard error stream (std::clog).
// Enabled if logging level is not Silent.
class Log : public Logger {
public:
Log();
};
// Logs output to the standard output (std::cout).
// Enabled if logging level is not Silent.
class Out : public Logger {
public:
Out();
};
// Logs error to the standard error stream (std::cerr).
// Enabled if logging level is not Silent.
class Err : public Logger {
public:
Err();
};
// RAII helper that modifies float logging precision, and restores default
// settings when exiting scope.
// User is reponsible for making sure stream still exist upon RAII destruction.
// See std::setprecision() for more details.
class FloatPrecision {
public:
FloatPrecision(const Logger& _logger, int _precision);
~FloatPrecision();
private:
FloatPrecision(FloatPrecision const&);
void operator=(FloatPrecision const&);
// Original precision and format.
const std::streamsize precision_;
const std::ios_base::fmtflags format_;
// Stream on which original precision must be restored.
std::ostream& stream_;
};
} // namespace log
} // namespace ozz
#endif // OZZ_OZZ_BASE_LOG_H_
+84
View File
@@ -0,0 +1,84 @@
//----------------------------------------------------------------------------//
// //
// 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_BASE_MATHS_BOX_H_
#define OZZ_OZZ_BASE_MATHS_BOX_H_
#include <cstddef>
#include "ozz/base/maths/vec_float.h"
namespace ozz {
namespace math {
// Matrix forward declaration.
struct Float4x4;
// Defines an axis aligned box.
struct Box {
// Constructs an invalid box.
Box();
// Constructs a box with the specified _min and _max bounds.
Box(const Float3& _min, const Float3& _max) : min(_min), max(_max) {}
// Constructs the smallest box that contains the _count points _points.
// _stride is the number of bytes between points.
explicit Box(const Float3& _point) : min(_point), max(_point) {}
// Constructs the smallest box that contains the _count points _points.
// _stride is the number of bytes between points, it must be greater or
// equal to sizeof(Float3).
Box(const Float3* _points, size_t _stride, size_t _count);
// Tests whether *this is a valid box.
bool is_valid() const { return min <= max; }
// Tests whether _p is within box bounds.
bool is_inside(const Float3& _p) const { return _p >= min && _p <= max; }
// Box's min and max bounds.
Float3 min;
Float3 max;
};
// Merges two boxes _a and _b.
// Both _a and _b can be invalid.
OZZ_INLINE Box Merge(const Box& _a, const Box& _b) {
if (!_a.is_valid()) {
return _b;
} else if (!_b.is_valid()) {
return _a;
}
return Box(Min(_a.min, _b.min), Max(_a.max, _b.max));
}
// Compute box transformation by a matrix.
Box TransformBox(const Float4x4& _matrix, const Box& _box);
} // namespace math
} // namespace ozz
#endif // OZZ_OZZ_BASE_MATHS_BOX_H_
@@ -0,0 +1,463 @@
//----------------------------------------------------------------------------//
// //
// 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_BASE_MATHS_GTEST_MATH_HELPER_H_
#define OZZ_OZZ_BASE_MATHS_GTEST_MATH_HELPER_H_
static const float kFloatNearTolerance = 1e-5f;
static const float kFloatNearEstTolerance = 1e-3f;
// Implements "float near" test as a function. Avoids overloading compiler
// optimizer when too much EXPECT_NEAR are used in a single compilation unit.
inline void ExpectFloatNear(float _a, float _b,
float _tol = kFloatNearTolerance) {
EXPECT_NEAR(_a, _b, _tol);
}
// Implements "int equality" test as a function. Avoids overloading compiler
// optimizer when too much EXPECT_TRUE are used in a single compilation unit.
inline void ExpectIntEq(int _a, int _b) { EXPECT_EQ(_a, _b); }
// Implements "bool equality" test as a function. Avoids overloading compiler
// optimizer when too much EXPECT_TRUE are used in a single compilation unit.
inline void ExpectTrue(bool _b) { EXPECT_TRUE(_b); }
// Macro for testing floats, dedicated to estimated functions with a lower
// precision.
#define EXPECT_FLOAT_EQ_EST(_expected, _x) \
EXPECT_NEAR(_expected, _x, kFloatNearEstTolerance)
// Macro for testing ozz::math::Float4 members with x, y, z, w float values,
// using EXPECT_FLOAT_EQ internally.
#define EXPECT_FLOAT4_EQ(_expected, _x, _y, _z, _w) \
\
do { \
SCOPED_TRACE(""); \
const ozz::math::Float4 expected(_expected); \
ExpectFloatNear(expected.x, _x); \
ExpectFloatNear(expected.y, _y); \
ExpectFloatNear(expected.z, _z); \
ExpectFloatNear(expected.w, _w); \
\
} while (void(0), 0)
// Macro for testing ozz::math::Float3 members with x, y, z float values,
// using EXPECT_FLOAT_EQ internally.
#define EXPECT_FLOAT3_EQ(_expected, _x, _y, _z) \
\
do { \
SCOPED_TRACE(""); \
const ozz::math::Float3 expected(_expected); \
ExpectFloatNear(expected.x, _x); \
ExpectFloatNear(expected.y, _y); \
ExpectFloatNear(expected.z, _z); \
\
} while (void(0), 0)
// Macro for testing ozz::math::Float2 members with x, y float values,
// using EXPECT_NEAR internally.
#define EXPECT_FLOAT2_EQ(_expected, _x, _y) \
\
do { \
SCOPED_TRACE(""); \
const ozz::math::Float2 expected(_expected); \
ExpectFloatNear(expected.x, _x); \
ExpectFloatNear(expected.y, _y); \
\
} while (void(0), 0)
// Macro for testing ozz::math::Quaternion members with x, y, z, w float value.
#define EXPECT_QUATERNION_EQ(_expected, _x, _y, _z, _w) \
\
do { \
SCOPED_TRACE(""); \
const ozz::math::Quaternion expected(_expected); \
ExpectFloatNear(expected.x, _x); \
ExpectFloatNear(expected.y, _y); \
ExpectFloatNear(expected.z, _z); \
ExpectFloatNear(expected.w, _w); \
\
} while (void(0), 0)
#define _IMPL_EXPECT_SIMDFLOAT_EQ_TOL(_expected, _x, _y, _z, _w, _tol) \
\
do { \
union { \
ozz::math::SimdFloat4 ret; \
float af[4]; \
} u = {_expected}; \
ExpectFloatNear(u.af[0], _x, _tol); \
ExpectFloatNear(u.af[1], _y, _tol); \
ExpectFloatNear(u.af[2], _z, _tol); \
ExpectFloatNear(u.af[3], _w, _tol); \
\
} while (void(0), 0)
#define _IMPL_EXPECT_SIMDFLOAT_EQ(_expected, _x, _y, _z, _w) \
_IMPL_EXPECT_SIMDFLOAT_EQ_TOL(_expected, _x, _y, _z, _w, kFloatNearTolerance)
#define _IMPL_EXPECT_SIMDFLOAT_EQ_EST(_expected, _x, _y, _z, _w) \
_IMPL_EXPECT_SIMDFLOAT_EQ_TOL(_expected, _x, _y, _z, _w, \
kFloatNearEstTolerance)
// Macro for testing ozz::math::simd::SimdFloat members with x, y, z, w values.
#define EXPECT_SIMDFLOAT_EQ(_expected, _x, _y, _z, _w) \
\
do { \
SCOPED_TRACE(""); \
_IMPL_EXPECT_SIMDFLOAT_EQ(_expected, _x, _y, _z, _w); \
\
} while (void(0), 0)
// Macro for testing ozz::math::simd::SimdFloat members with x, y, z, w values.
// Dedicated to estimated functions with a lower precision.
#define EXPECT_SIMDFLOAT_EQ_EST(_expected, _x, _y, _z, _w) \
\
do { \
SCOPED_TRACE(""); \
_IMPL_EXPECT_SIMDFLOAT_EQ_EST(_expected, _x, _y, _z, _w); \
\
} while (void(0), 0)
// Macro for testing ozz::math::simd::SimdFloat members with x, y values with
// a user defined precision.
#define _IMPL_EXPECT_SIMDFLOAT2_EQ_TOL(_expected, _x, _y, _tol) \
\
do { \
union { \
ozz::math::SimdFloat4 ret; \
float af[4]; \
} u = {_expected}; \
ExpectFloatNear(u.af[0], _x, _tol); \
ExpectFloatNear(u.af[1], _y, _tol); \
\
} while (void(0), 0)
// Macro for testing ozz::math::simd::SimdFloat members with x, y values.
#define EXPECT_SIMDFLOAT2_EQ(_expected, _x, _y) \
\
do { \
SCOPED_TRACE(""); \
_IMPL_EXPECT_SIMDFLOAT2_EQ_TOL(_expected, _x, _y, kFloatNearTolerance); \
\
} while (void(0), 0)
// Macro for testing ozz::math::simd::SimdFloat members with x, y values.
// Dedicated to estimated functions with a lower precision.
#define EXPECT_SIMDFLOAT2_EQ_EST(_expected, _x, _y) \
\
do { \
SCOPED_TRACE(""); \
_IMPL_EXPECT_SIMDFLOAT2_EQ_TOL(_expected, _x, _y, kFloatNearEstTolerance); \
\
} while (void(0), 0)
// Macro for testing ozz::math::simd::SimdFloat members with x, y, z values.
// Dedicated to estimated functions with a user defined precision.
#define EXPECT_SIMDFLOAT3_EQ_TOL(_expected, _x, _y, _z, _tol) \
\
do { \
SCOPED_TRACE(""); \
_IMPL_EXPECT_SIMDFLOAT3_EQ_TOL(_expected, _x, _y, _z, _tol); \
\
} while (void(0), 0)
// Macro for testing ozz::math::simd::SimdFloat members with x, y, z values with
// a user defined precision.
#define _IMPL_EXPECT_SIMDFLOAT3_EQ_TOL(_expected, _x, _y, _z, _tol) \
\
do { \
union { \
ozz::math::SimdFloat4 ret; \
float af[4]; \
} u = {_expected}; \
ExpectFloatNear(u.af[0], _x, _tol); \
ExpectFloatNear(u.af[1], _y, _tol); \
ExpectFloatNear(u.af[2], _z, _tol); \
\
} while (void(0), 0)
// Macro for testing ozz::math::simd::SimdFloat members with x, y, z values.
#define EXPECT_SIMDFLOAT3_EQ(_expected, _x, _y, _z) \
\
do { \
SCOPED_TRACE(""); \
_IMPL_EXPECT_SIMDFLOAT3_EQ_TOL(_expected, _x, _y, _z, \
kFloatNearTolerance); \
\
} while (void(0), 0)
// Macro for testing ozz::math::simd::SimdFloat members with x, y, z values.
// Dedicated to estimated functions with a lower precision.
#define EXPECT_SIMDFLOAT3_EQ_EST(_expected, _x, _y, _z) \
\
do { \
SCOPED_TRACE(""); \
_IMPL_EXPECT_SIMDFLOAT3_EQ_TOL(_expected, _x, _y, _z, \
kFloatNearEstTolerance); \
\
} while (void(0), 0)
// Macro for testing ozz::math::simd::SimdFloat members with x, y, z values.
// Dedicated to estimated functions with a user defined precision.
#define EXPECT_SIMDFLOAT3_EQ_TOL(_expected, _x, _y, _z, _tol) \
\
do { \
SCOPED_TRACE(""); \
_IMPL_EXPECT_SIMDFLOAT3_EQ_TOL(_expected, _x, _y, _z, _tol); \
\
} while (void(0), 0)
// Macro for testing ozz::math::simd::SimdInt members with x, y, z, w values.
#define EXPECT_SIMDINT_EQ(_expected, _x, _y, _z, _w) \
\
do { \
SCOPED_TRACE(""); \
union { \
ozz::math::SimdInt4 ret; \
int ai[4]; \
} u = {_expected}; \
ExpectIntEq(u.ai[0], static_cast<int>(_x)); \
ExpectIntEq(u.ai[1], static_cast<int>(_y)); \
ExpectIntEq(u.ai[2], static_cast<int>(_z)); \
ExpectIntEq(u.ai[3], static_cast<int>(_w)); \
\
} while (void(0), 0)
// Macro for testing ozz::math::SoaFloat4 members with x, y, z, w float values.
#define EXPECT_FLOAT4x4_EQ(_expected, _x0, _x1, _x2, _x3, _y0, _y1, _y2, _y3, \
_z0, _z1, _z2, _z3, _w0, _w1, _w2, _w3) \
\
do { \
SCOPED_TRACE(""); \
const ozz::math::Float4x4 expected(_expected); \
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.cols[0], _x0, _x1, _x2, _x3); \
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.cols[1], _y0, _y1, _y2, _y3); \
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.cols[2], _z0, _z1, _z2, _z3); \
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.cols[3], _w0, _w1, _w2, _w3); \
\
} while (void(0), 0)
// Macro for testing ozz::math::simd::SimdQuaternion members with x, y, z, w
// values.
#define EXPECT_SIMDQUATERNION_EQ(_expected, _x, _y, _z, _w) \
\
do { \
SCOPED_TRACE(""); \
_IMPL_EXPECT_SIMDFLOAT_EQ(_expected.xyzw, _x, _y, _z, _w); \
\
} while (void(0), 0)
// Macro for testing ozz::math::simd::SimdQuaternion members with x, y, z, w
// values.
#define EXPECT_SIMDQUATERNION_EQ_EST(_expected, _x, _y, _z, _w) \
\
do { \
SCOPED_TRACE(""); \
_IMPL_EXPECT_SIMDFLOAT_EQ_EST(_expected.xyzw, _x, _y, _z, _w); \
\
} while (void(0), 0)
// Macro for testing ozz::math::simd::SimdQuaternion members with x, y, z, w
// values.
#define EXPECT_SIMDQUATERNION_EQ_TOL(_expected, _x, _y, _z, _w, _tol) \
\
do { \
SCOPED_TRACE(""); \
_IMPL_EXPECT_SIMDFLOAT_EQ_TOL(_expected.xyzw, _x, _y, _z, _w, _tol); \
\
} while (void(0), 0)
// Macro for testing ozz::math::SoaFloat4 members with x, y, z, w float values.
#define EXPECT_SOAFLOAT4_EQ(_expected, _x0, _x1, _x2, _x3, _y0, _y1, _y2, _y3, \
_z0, _z1, _z2, _z3, _w0, _w1, _w2, _w3) \
\
do { \
SCOPED_TRACE(""); \
const ozz::math::SoaFloat4 expected(_expected); \
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.x, _x0, _x1, _x2, _x3); \
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.y, _y0, _y1, _y2, _y3); \
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.z, _z0, _z1, _z2, _z3); \
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.w, _w0, _w1, _w2, _w3); \
\
} while (void(0), 0)
// Macro for testing ozz::math::SoaFloat4 members with x, y, z, w float values.
// Dedicated to estimated functions with a lower precision.
#define EXPECT_SOAFLOAT4_EQ_EST(_expected, _x0, _x1, _x2, _x3, _y0, _y1, _y2, \
_y3, _z0, _z1, _z2, _z3, _w0, _w1, _w2, _w3) \
\
do { \
SCOPED_TRACE(""); \
const ozz::math::SoaFloat4 expected(_expected); \
_IMPL_EXPECT_SIMDFLOAT_EQ_EST(expected.x, _x0, _x1, _x2, _x3); \
_IMPL_EXPECT_SIMDFLOAT_EQ_EST(expected.y, _y0, _y1, _y2, _y3); \
_IMPL_EXPECT_SIMDFLOAT_EQ_EST(expected.z, _z0, _z1, _z2, _z3); \
_IMPL_EXPECT_SIMDFLOAT_EQ_EST(expected.w, _w0, _w1, _w2, _w3); \
\
} while (void(0), 0)
// Macro for testing ozz::math::SoaFloat3 members with x, y, z float values.
#define EXPECT_SOAFLOAT3_EQ(_expected, _x0, _x1, _x2, _x3, _y0, _y1, _y2, _y3, \
_z0, _z1, _z2, _z3) \
\
do { \
SCOPED_TRACE(""); \
const ozz::math::SoaFloat3 expected(_expected); \
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.x, _x0, _x1, _x2, _x3); \
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.y, _y0, _y1, _y2, _y3); \
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.z, _z0, _z1, _z2, _z3); \
\
} while (void(0), 0)
// Macro for testing ozz::math::SoaFloat3 members with x, y, z float values.
// Dedicated to estimated functions with a lower precision.
#define EXPECT_SOAFLOAT3_EQ_EST(_expected, _x0, _x1, _x2, _x3, _y0, _y1, _y2, \
_y3, _z0, _z1, _z2, _z3) \
\
do { \
SCOPED_TRACE(""); \
const ozz::math::SoaFloat3 expected(_expected); \
_IMPL_EXPECT_SIMDFLOAT_EQ_EST(expected.x, _x0, _x1, _x2, _x3); \
_IMPL_EXPECT_SIMDFLOAT_EQ_EST(expected.y, _y0, _y1, _y2, _y3); \
_IMPL_EXPECT_SIMDFLOAT_EQ_EST(expected.z, _z0, _z1, _z2, _z3); \
\
} while (void(0), 0)
// Macro for testing ozz::math::SoaFloat2 members with x, y float values.
#define EXPECT_SOAFLOAT2_EQ(_expected, _x0, _x1, _x2, _x3, _y0, _y1, _y2, _y3) \
\
do { \
SCOPED_TRACE(""); \
const ozz::math::SoaFloat2 expected(_expected); \
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.x, _x0, _x1, _x2, _x3); \
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.y, _y0, _y1, _y2, _y3); \
\
} while (void(0), 0)
// Macro for testing ozz::math::SoaFloat2 members with x, y float values.
// Dedicated to estimated functions with a lower precision.
#define EXPECT_SOAFLOAT2_EQ_EST(_expected, _x0, _x1, _x2, _x3, _y0, _y1, _y2, \
_y3) \
\
do { \
SCOPED_TRACE(""); \
const ozz::math::SoaFloat2 expected(_expected); \
_IMPL_EXPECT_SIMDFLOAT_EQ_EST(expected.x, _x0, _x1, _x2, _x3); \
_IMPL_EXPECT_SIMDFLOAT_EQ_EST(expected.y, _y0, _y1, _y2, _y3); \
\
} while (void(0), 0)
// Macro for testing ozz::math::SoaFloat2 members with x, y float values.
#define EXPECT_SOAFLOAT1_EQ(_expected, _x0, _x1, _x2, _x3) \
_IMPL_EXPECT_SIMDFLOAT_EQ(_expected, _x0, _x1, _x2, _x3);
// Macro for testing ozz::math::SoaFloat2 members with x, y float values.
// Dedicated to estimated functions with a lower precision.
#define EXPECT_SOAFLOAT1_EQ_EST(_expected, _x0, _x1, _x2, _x3) \
_IMPL_EXPECT_SIMDFLOAT_EQ_EST(_expected, _x0, _x1, _x2, _x3);
// Macro for testing ozz::math::SoaQuaternion members with x, y, z, w float
// values.
#define EXPECT_SOAQUATERNION_EQ(_expected, _x0, _x1, _x2, _x3, _y0, _y1, _y2, \
_y3, _z0, _z1, _z2, _z3, _w0, _w1, _w2, _w3) \
\
do { \
SCOPED_TRACE(""); \
const ozz::math::SoaQuaternion expected(_expected); \
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.x, _x0, _x1, _x2, _x3); \
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.y, _y0, _y1, _y2, _y3); \
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.z, _z0, _z1, _z2, _z3); \
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.w, _w0, _w1, _w2, _w3); \
\
} while (void(0), 0)
// Macro for testing ozz::math::SoaQuaternion members with x, y, z, w float
// values.
// Dedicated to estimated functions with a lower precision.
#define EXPECT_SOAQUATERNION_EQ_EST(_expected, _x0, _x1, _x2, _x3, _y0, _y1, \
_y2, _y3, _z0, _z1, _z2, _z3, _w0, _w1, \
_w2, _w3) \
\
do { \
SCOPED_TRACE(""); \
const ozz::math::SoaQuaternion expected(_expected); \
_IMPL_EXPECT_SIMDFLOAT_EQ_EST(expected.x, _x0, _x1, _x2, _x3); \
_IMPL_EXPECT_SIMDFLOAT_EQ_EST(expected.y, _y0, _y1, _y2, _y3); \
_IMPL_EXPECT_SIMDFLOAT_EQ_EST(expected.z, _z0, _z1, _z2, _z3); \
_IMPL_EXPECT_SIMDFLOAT_EQ_EST(expected.w, _w0, _w1, _w2, _w3); \
\
} while (void(0), 0)
#define EXPECT_SOAFLOAT4x4_EQ( \
_expected, col0xx, col0xy, col0xz, col0xw, col0yx, col0yy, col0yz, col0yw, \
col0zx, col0zy, col0zz, col0zw, col0wx, col0wy, col0wz, col0ww, col1xx, \
col1xy, col1xz, col1xw, col1yx, col1yy, col1yz, col1yw, col1zx, col1zy, \
col1zz, col1zw, col1wx, col1wy, col1wz, col1ww, col2xx, col2xy, col2xz, \
col2xw, col2yx, col2yy, col2yz, col2yw, col2zx, col2zy, col2zz, col2zw, \
col2wx, col2wy, col2wz, col2ww, col3xx, col3xy, col3xz, col3xw, col3yx, \
col3yy, col3yz, col3yw, col3zx, col3zy, col3zz, col3zw, col3wx, col3wy, \
col3wz, col3ww) \
\
do { \
SCOPED_TRACE(""); \
const ozz::math::SoaFloat4x4 expected(_expected); \
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.cols[0].x, col0xx, col0xy, col0xz, \
col0xw); \
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.cols[0].y, col0yx, col0yy, col0yz, \
col0yw); \
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.cols[0].z, col0zx, col0zy, col0zz, \
col0zw); \
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.cols[0].w, col0wx, col0wy, col0wz, \
col0ww); \
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.cols[1].x, col1xx, col1xy, col1xz, \
col1xw); \
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.cols[1].y, col1yx, col1yy, col1yz, \
col1yw); \
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.cols[1].z, col1zx, col1zy, col1zz, \
col1zw); \
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.cols[1].w, col1wx, col1wy, col1wz, \
col1ww); \
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.cols[2].x, col2xx, col2xy, col2xz, \
col2xw); \
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.cols[2].y, col2yx, col2yy, col2yz, \
col2yw); \
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.cols[2].z, col2zx, col2zy, col2zz, \
col2zw); \
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.cols[2].w, col2wx, col2wy, col2wz, \
col2ww); \
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.cols[3].x, col3xx, col3xy, col3xz, \
col3xw); \
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.cols[3].y, col3yx, col3yy, col3yz, \
col3yw); \
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.cols[3].z, col3zx, col3zy, col3zz, \
col3zw); \
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.cols[3].w, col3wx, col3wy, col3wz, \
col3ww); \
\
} while (void(0), 0)
#endif // OZZ_OZZ_BASE_MATHS_GTEST_MATH_HELPER_H_
@@ -0,0 +1,159 @@
//----------------------------------------------------------------------------//
// //
// 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_BASE_MATHS_INTERNAL_SIMD_MATH_CONFIG_H_
#define OZZ_OZZ_BASE_MATHS_INTERNAL_SIMD_MATH_CONFIG_H_
#include "ozz/base/platform.h"
// Avoid SIMD instruction detection if reference (aka scalar) implementation is
// forced.
#if !defined(OZZ_BUILD_SIMD_REF)
// Try to match a SSE2+ version.
#if defined(__AVX2__) || defined(OZZ_SIMD_AVX2)
#include <immintrin.h>
#define OZZ_SIMD_AVX2
#define OZZ_SIMD_AVX // avx is available if avx2 is.
#endif
#if defined(__FMA__) || defined(OZZ_SIMD_FMA)
#include <immintrin.h>
#define OZZ_SIMD_FMA
#endif
#if defined(__AVX__) || defined(OZZ_SIMD_AVX)
#include <immintrin.h>
#define OZZ_SIMD_AVX
#define OZZ_SIMD_SSE4_2 // SSE4.2 is available if avx is.
#endif
#if defined(__SSE4_2__) || defined(OZZ_SIMD_SSE4_2)
#include <nmmintrin.h>
#define OZZ_SIMD_SSE4_2
#define OZZ_SIMD_SSE4_1 // SSE4.1 is available if SSE4.2 is.
#endif
#if defined(__SSE4_1__) || defined(OZZ_SIMD_SSE4_1)
#include <smmintrin.h>
#define OZZ_SIMD_SSE4_1
#define OZZ_SIMD_SSSE3 // SSSE3 is available if SSE4.1 is.
#endif
#if defined(__SSSE3__) || defined(OZZ_SIMD_SSSE3)
#include <tmmintrin.h>
#define OZZ_SIMD_SSSE3
#define OZZ_SIMD_SSE3 // SSE3 is available if SSSE3 is.
#endif
#if defined(__SSE3__) || defined(OZZ_SIMD_SSE3)
#include <pmmintrin.h>
#define OZZ_SIMD_SSE3
#define OZZ_SIMD_SSE2 // SSE2 is available if SSE3 is.
#endif
// x64/amd64 have SSE2 instructions
// _M_IX86_FP is 2 if /arch:SSE2, /arch:AVX or /arch:AVX2 was used.
#if defined(__SSE2__) || defined(_M_AMD64) || defined(_M_X64) || \
(_M_IX86_FP >= 2) || defined(OZZ_SIMD_SSE2)
#include <emmintrin.h>
#define OZZ_SIMD_SSE2
#define OZZ_SIMD_SSEx // OZZ_SIMD_SSEx is the generic flag for SSE support
#endif
// End of SIMD instruction detection
#endif // !OZZ_BUILD_SIMD_REF
// SEE* intrinsics available
#if defined(OZZ_SIMD_SSEx)
namespace ozz {
namespace math {
// Vector of four floating point values.
typedef __m128 SimdFloat4;
// Argument type for Float4.
typedef const __m128 _SimdFloat4;
// Vector of four integer values.
typedef __m128i SimdInt4;
// Argument type for Int4.
typedef const __m128i _SimdInt4;
} // namespace math
} // namespace ozz
#else // No builtin simd available
// No simd instruction set detected, switch back to reference implementation.
// OZZ_SIMD_REF is the generic flag for SIMD reference implementation.
#define OZZ_SIMD_REF
// Declares reference simd float and integer vectors outside of ozz::math, in
// order to match non-reference implementation details.
// Vector of four floating point values.
struct SimdFloat4Def {
alignas(16) float x;
float y;
float z;
float w;
};
// Vector of four integer values.
struct SimdInt4Def {
alignas(16) int x;
int y;
int z;
int w;
};
namespace ozz {
namespace math {
// Vector of four floating point values.
typedef SimdFloat4Def SimdFloat4;
// Argument type for SimdFloat4
typedef const SimdFloat4& _SimdFloat4;
// Vector of four integer values.
typedef SimdInt4Def SimdInt4;
// Argument type for SimdInt4.
typedef const SimdInt4& _SimdInt4;
} // namespace math
} // namespace ozz
#endif // OZZ_SIMD_x
// Native SIMD operator already exist on some compilers, so they have to be disable from ozz implementation
#if !defined(OZZ_SIMD_REF) && (defined(__GNUC__) || defined(__llvm__))
#define OZZ_DISABLE_SSE_NATIVE_OPERATORS
#endif
#endif // OZZ_OZZ_BASE_MATHS_INTERNAL_SIMD_MATH_CONFIG_H_
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,118 @@
//----------------------------------------------------------------------------//
// //
// 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_BASE_MATHS_MATH_ARCHIVE_H_
#define OZZ_OZZ_BASE_MATHS_MATH_ARCHIVE_H_
#include "ozz/base/io/archive_traits.h"
#include "ozz/base/platform.h"
namespace ozz {
namespace math {
struct Float2;
struct Float3;
struct Float4;
struct Quaternion;
struct Transform;
struct Box;
struct RectFloat;
struct RectInt;
} // namespace math
namespace io {
OZZ_IO_TYPE_NOT_VERSIONABLE(math::Float2)
template <>
struct Extern<math::Float2> {
static void Save(OArchive& _archive, const math::Float2* _values,
size_t _count);
static void Load(IArchive& _archive, math::Float2* _values, size_t _count,
uint32_t _version);
};
OZZ_IO_TYPE_NOT_VERSIONABLE(math::Float3)
template <>
struct Extern<math::Float3> {
static void Save(OArchive& _archive, const math::Float3* _values,
size_t _count);
static void Load(IArchive& _archive, math::Float3* _values, size_t _count,
uint32_t _version);
};
OZZ_IO_TYPE_NOT_VERSIONABLE(math::Float4)
template <>
struct Extern<math::Float4> {
static void Save(OArchive& _archive, const math::Float4* _values,
size_t _count);
static void Load(IArchive& _archive, math::Float4* _values, size_t _count,
uint32_t _version);
};
OZZ_IO_TYPE_NOT_VERSIONABLE(math::Quaternion)
template <>
struct Extern<math::Quaternion> {
static void Save(OArchive& _archive, const math::Quaternion* _values,
size_t _count);
static void Load(IArchive& _archive, math::Quaternion* _values, size_t _count,
uint32_t _version);
};
OZZ_IO_TYPE_NOT_VERSIONABLE(math::Transform)
template <>
struct Extern<math::Transform> {
static void Save(OArchive& _archive, const math::Transform* _values,
size_t _count);
static void Load(IArchive& _archive, math::Transform* _values, size_t _count,
uint32_t _version);
};
OZZ_IO_TYPE_NOT_VERSIONABLE(math::Box)
template <>
struct Extern<math::Box> {
static void Save(OArchive& _archive, const math::Box* _values, size_t _count);
static void Load(IArchive& _archive, math::Box* _values, size_t _count,
uint32_t _version);
};
OZZ_IO_TYPE_NOT_VERSIONABLE(math::RectFloat)
template <>
struct Extern<math::RectFloat> {
static void Save(OArchive& _archive, const math::RectFloat* _values,
size_t _count);
static void Load(IArchive& _archive, math::RectFloat* _values, size_t _count,
uint32_t _version);
};
OZZ_IO_TYPE_NOT_VERSIONABLE(math::RectInt)
template <>
struct Extern<math::RectInt> {
static void Save(OArchive& _archive, const math::RectInt* _values,
size_t _count);
static void Load(IArchive& _archive, math::RectInt* _values, size_t _count,
uint32_t _version);
};
} // namespace io
} // namespace ozz
#endif // OZZ_OZZ_BASE_MATHS_MATH_ARCHIVE_H_
@@ -0,0 +1,61 @@
//----------------------------------------------------------------------------//
// //
// 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_BASE_MATHS_MATH_CONSTANT_H_
#define OZZ_OZZ_BASE_MATHS_MATH_CONSTANT_H_
#ifndef INCLUDE_OZZ_MATH_CONSTANT_H_
#define INCLUDE_OZZ_MATH_CONSTANT_H_
namespace ozz {
namespace math {
// Defines math trigonometric constants.
static const float k2Pi = 6.283185307179586476925286766559f;
static const float kPi = 3.1415926535897932384626433832795f;
static const float kPi_2 = 1.5707963267948966192313216916398f;
static const float kPi_4 = .78539816339744830961566084581988f;
static const float kSqrt3 = 1.7320508075688772935274463415059f;
static const float kSqrt3_2 = 0.86602540378443864676372317075294f;
static const float kSqrt2 = 1.4142135623730950488016887242097f;
static const float kSqrt2_2 = 0.70710678118654752440084436210485f;
// Angle unit conversion constants.
static const float kDegreeToRadian = kPi / 180.f;
static const float kRadianToDegree = 180.f / kPi;
// Defines the square normalization tolerance value.
static const float kNormalizationToleranceSq = 1e-6f;
static const float kNormalizationToleranceEstSq = 2e-3f;
// Defines the square orthogonalisation tolerance value.
static const float kOrthogonalisationToleranceSq = 1e-16f;
} // namespace math
} // namespace ozz
#endif // INCLUDE_OZZ_MATH_CONSTANT_H_
#endif // OZZ_OZZ_BASE_MATHS_MATH_CONSTANT_H_
+125
View File
@@ -0,0 +1,125 @@
//----------------------------------------------------------------------------//
// //
// 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_BASE_MATHS_MATH_EX_H_
#define OZZ_OZZ_BASE_MATHS_MATH_EX_H_
#include <cassert>
#include <cmath>
#include "ozz/base/platform.h"
namespace ozz {
namespace math {
// Returns the linear interpolation of _a and _b with coefficient _f.
// _f is not limited to range [0,1].
OZZ_INLINE float Lerp(float _a, float _b, float _f) {
return (_b - _a) * _f + _a;
}
// Returns the minimum of _a and _b. Comparison's based on operator <.
template <typename _Ty>
OZZ_INLINE _Ty Min(_Ty _a, _Ty _b) {
return (_a < _b) ? _a : _b;
}
// Returns the maximum of _a and _b. Comparison's based on operator <.
template <typename _Ty>
OZZ_INLINE _Ty Max(_Ty _a, _Ty _b) {
return (_b < _a) ? _a : _b;
}
// Clamps _x between _a and _b. Comparison's based on operator <.
// Result is unknown if _a is not less or equal to _b.
template <typename _Ty>
OZZ_INLINE _Ty Clamp(_Ty _a, _Ty _x, _Ty _b) {
const _Ty min = _x < _b ? _x : _b;
return min < _a ? _a : min;
}
// Implements int selection, avoiding branching.
OZZ_INLINE int Select(bool _b, int _true, int _false) {
return _false ^ (-static_cast<int>(_b) & (_true ^ _false));
}
// Implements float selection, avoiding branching.
OZZ_INLINE float Select(bool _b, float _true, float _false) {
union {
float f;
int32_t i;
} t = {_true};
union {
float f;
int32_t i;
} f = {_false};
union {
int32_t i;
float f;
} r = {f.i ^ (-static_cast<int32_t>(_b) & (t.i ^ f.i))};
return r.f;
}
// Implements pointer selection, avoiding branching.
template <typename _Ty>
OZZ_INLINE _Ty* Select(bool _b, _Ty* _true, _Ty* _false) {
union {
_Ty* p;
intptr_t i;
} t = {_true};
union {
_Ty* p;
intptr_t i;
} f = {_false};
union {
intptr_t i;
_Ty* p;
} r = {f.i ^ (-static_cast<intptr_t>(_b) & (t.i ^ f.i))};
return r.p;
}
// Implements const pointer selection, avoiding branching.
template <typename _Ty>
OZZ_INLINE const _Ty* Select(bool _b, const _Ty* _true, const _Ty* _false) {
union {
const _Ty* p;
intptr_t i;
} t = {_true};
union {
const _Ty* p;
intptr_t i;
} f = {_false};
union {
intptr_t i;
const _Ty* p;
} r = {f.i ^ (-static_cast<intptr_t>(_b) & (t.i ^ f.i))};
return r.p;
}
} // namespace math
} // namespace ozz
#endif // OZZ_OZZ_BASE_MATHS_MATH_EX_H_
@@ -0,0 +1,370 @@
//----------------------------------------------------------------------------//
// //
// 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_BASE_MATHS_QUATERNION_H_
#define OZZ_OZZ_BASE_MATHS_QUATERNION_H_
#include <cassert>
#include "ozz/base/maths/math_constant.h"
#include "ozz/base/maths/math_ex.h"
#include "ozz/base/maths/vec_float.h"
#include "ozz/base/platform.h"
namespace ozz {
namespace math {
struct Quaternion {
float x, y, z, w;
// Constructs an uninitialized quaternion.
OZZ_INLINE Quaternion() {}
// Constructs a quaternion from 4 floating point values.
OZZ_INLINE Quaternion(float _x, float _y, float _z, float _w)
: x(_x), y(_y), z(_z), w(_w) {}
// Returns a normalized quaternion initialized from an axis angle
// representation.
// Assumes the axis part (x, y, z) of _axis_angle is normalized.
// _angle.x is the angle in radian.
static OZZ_INLINE Quaternion FromAxisAngle(const Float3& _axis, float _angle);
// Returns a normalized quaternion initialized from an axis and angle cosine
// representation.
// Assumes the axis part (x, y, z) of _axis_angle is normalized.
// _angle.x is the angle cosine in radian, it must be within [-1,1] range.
static OZZ_INLINE Quaternion FromAxisCosAngle(const Float3& _axis,
float _cos);
// Returns a normalized quaternion initialized from an Euler representation.
// Euler angles are ordered Heading, Elevation and Bank, or Yaw, Pitch and
// Roll.
static OZZ_INLINE Quaternion FromEuler(float _yaw, float _pitch,
float _roll);
// Returns the quaternion that will rotate vector _from into vector _to,
// around their plan perpendicular axis.The input vectors don't need to be
// normalized, they can be null as well.
static OZZ_INLINE Quaternion FromVectors(const Float3& _from,
const Float3& _to);
// Returns the quaternion that will rotate vector _from into vector _to,
// around their plan perpendicular axis. The input vectors must be normalized.
static OZZ_INLINE Quaternion FromUnitVectors(const Float3& _from,
const Float3& _to);
// Returns the identity quaternion.
static OZZ_INLINE Quaternion identity() {
return Quaternion(0.f, 0.f, 0.f, 1.f);
}
};
// Returns true if each element of a is equal to each element of _b.
OZZ_INLINE bool operator==(const Quaternion& _a, const Quaternion& _b) {
return _a.x == _b.x && _a.y == _b.y && _a.z == _b.z && _a.w == _b.w;
}
// Returns true if one element of a differs from one element of _b.
OZZ_INLINE bool operator!=(const Quaternion& _a, const Quaternion& _b) {
return _a.x != _b.x || _a.y != _b.y || _a.z != _b.z || _a.w != _b.w;
}
// Returns the conjugate of _q. This is the same as the inverse if _q is
// normalized. Otherwise the magnitude of the inverse is 1.f/|_q|.
OZZ_INLINE Quaternion Conjugate(const Quaternion& _q) {
return Quaternion(-_q.x, -_q.y, -_q.z, _q.w);
}
// Returns the addition of _a and _b.
OZZ_INLINE Quaternion operator+(const Quaternion& _a, const Quaternion& _b) {
return Quaternion(_a.x + _b.x, _a.y + _b.y, _a.z + _b.z, _a.w + _b.w);
}
// Returns the multiplication of _q and a scalar _f.
OZZ_INLINE Quaternion operator*(const Quaternion& _q, float _f) {
return Quaternion(_q.x * _f, _q.y * _f, _q.z * _f, _q.w * _f);
}
// Returns the multiplication of _a and _b. If both _a and _b are normalized,
// then the result is normalized.
OZZ_INLINE Quaternion operator*(const Quaternion& _a, const Quaternion& _b) {
return Quaternion(_a.w * _b.x + _a.x * _b.w + _a.y * _b.z - _a.z * _b.y,
_a.w * _b.y + _a.y * _b.w + _a.z * _b.x - _a.x * _b.z,
_a.w * _b.z + _a.z * _b.w + _a.x * _b.y - _a.y * _b.x,
_a.w * _b.w - _a.x * _b.x - _a.y * _b.y - _a.z * _b.z);
}
// Returns the negate of _q. This represent the same rotation as q.
OZZ_INLINE Quaternion operator-(const Quaternion& _q) {
return Quaternion(-_q.x, -_q.y, -_q.z, -_q.w);
}
// Returns true if the angle between _a and _b is less than _tolerance.
OZZ_INLINE bool Compare(const math::Quaternion& _a, const math::Quaternion& _b,
float _cos_half_tolerance) {
// Computes w component of a-1 * b.
const float cos_half_angle =
_a.x * _b.x + _a.y * _b.y + _a.z * _b.z + _a.w * _b.w;
return std::abs(cos_half_angle) >= _cos_half_tolerance;
}
// Returns true if _q is a normalized quaternion.
OZZ_INLINE bool IsNormalized(const Quaternion& _q) {
const float sq_len = _q.x * _q.x + _q.y * _q.y + _q.z * _q.z + _q.w * _q.w;
return std::abs(sq_len - 1.f) < kNormalizationToleranceSq;
}
// Returns the normalized quaternion _q.
OZZ_INLINE Quaternion Normalize(const Quaternion& _q) {
const float sq_len = _q.x * _q.x + _q.y * _q.y + _q.z * _q.z + _q.w * _q.w;
assert(sq_len != 0.f && "_q is not normalizable");
const float inv_len = 1.f / std::sqrt(sq_len);
return Quaternion(_q.x * inv_len, _q.y * inv_len, _q.z * inv_len,
_q.w * inv_len);
}
// Returns the normalized quaternion _q if the norm of _q is not 0.
// Otherwise returns _safer.
OZZ_INLINE Quaternion NormalizeSafe(const Quaternion& _q,
const Quaternion& _safer) {
assert(IsNormalized(_safer) && "_safer is not normalized");
const float sq_len = _q.x * _q.x + _q.y * _q.y + _q.z * _q.z + _q.w * _q.w;
if (sq_len == 0) {
return _safer;
}
const float inv_len = 1.f / std::sqrt(sq_len);
return Quaternion(_q.x * inv_len, _q.y * inv_len, _q.z * inv_len,
_q.w * inv_len);
}
OZZ_INLINE Quaternion Quaternion::FromAxisAngle(const Float3& _axis,
float _angle) {
assert(IsNormalized(_axis) && "axis is not normalized.");
const float half_angle = _angle * .5f;
const float half_sin = std::sin(half_angle);
const float half_cos = std::cos(half_angle);
return Quaternion(_axis.x * half_sin, _axis.y * half_sin, _axis.z * half_sin,
half_cos);
}
OZZ_INLINE Quaternion Quaternion::FromAxisCosAngle(const Float3& _axis,
float _cos) {
assert(IsNormalized(_axis) && "axis is not normalized.");
assert(_cos >= -1.f && _cos <= 1.f && "cos is not in [-1,1] range.");
const float half_cos2 = (1.f + _cos) * 0.5f;
const float half_sin = std::sqrt(1.f - half_cos2);
return Quaternion(_axis.x * half_sin, _axis.y * half_sin, _axis.z * half_sin,
std::sqrt(half_cos2));
}
// Returns to an axis angle representation of quaternion _q.
// Assumes quaternion _q is normalized.
OZZ_INLINE Float4 ToAxisAngle(const Quaternion& _q) {
assert(IsNormalized(_q));
const float clamped_w = Clamp(-1.f, _q.w, 1.f);
const float angle = 2.f * std::acos(clamped_w);
const float s = std::sqrt(1.f - clamped_w * clamped_w);
// Assuming quaternion normalized then s always positive.
if (s < .001f) { // Tests to avoid divide by zero.
// If s close to zero then direction of axis is not important.
return Float4(1.f, 0.f, 0.f, angle);
} else {
// Normalize axis
const float inv_s = 1.f / s;
return Float4(_q.x * inv_s, _q.y * inv_s, _q.z * inv_s, angle);
}
}
OZZ_INLINE Quaternion Quaternion::FromEuler(float _yaw, float _pitch,
float _roll) {
const float half_yaw = _yaw * .5f;
const float c1 = std::cos(half_yaw);
const float s1 = std::sin(half_yaw);
const float half_pitch = _pitch * .5f;
const float c2 = std::cos(half_pitch);
const float s2 = std::sin(half_pitch);
const float half_roll = _roll * .5f;
const float c3 = std::cos(half_roll);
const float s3 = std::sin(half_roll);
const float c1c2 = c1 * c2;
const float s1s2 = s1 * s2;
return Quaternion(c1c2 * s3 + s1s2 * c3, s1 * c2 * c3 + c1 * s2 * s3,
c1 * s2 * c3 - s1 * c2 * s3, c1c2 * c3 - s1s2 * s3);
}
// Returns to an Euler representation of quaternion _q.
// Quaternion _q does not require to be normalized.
OZZ_INLINE Float3 ToEuler(const Quaternion& _q) {
const float sqw = _q.w * _q.w;
const float sqx = _q.x * _q.x;
const float sqy = _q.y * _q.y;
const float sqz = _q.z * _q.z;
// If normalized is one, otherwise is correction factor.
const float unit = sqx + sqy + sqz + sqw;
const float test = _q.x * _q.y + _q.z * _q.w;
Float3 euler;
if (test > .499f * unit) { // Singularity at north pole
euler.x = 2.f * std::atan2(_q.x, _q.w);
euler.y = ozz::math::kPi_2;
euler.z = 0;
} else if (test < -.499f * unit) { // Singularity at south pole
euler.x = -2 * std::atan2(_q.x, _q.w);
euler.y = -kPi_2;
euler.z = 0;
} else {
euler.x = std::atan2(2.f * _q.y * _q.w - 2.f * _q.x * _q.z,
sqx - sqy - sqz + sqw);
euler.y = std::asin(2.f * test / unit);
euler.z = std::atan2(2.f * _q.x * _q.w - 2.f * _q.y * _q.z,
-sqx + sqy - sqz + sqw);
}
return euler;
}
OZZ_INLINE Quaternion Quaternion::FromVectors(const Float3& _from,
const Float3& _to) {
// http://lolengine.net/blog/2014/02/24/quaternion-from-two-vectors-final
const float norm_from_norm_to = std::sqrt(LengthSqr(_from) * LengthSqr(_to));
if (norm_from_norm_to < 1.e-5f) {
return Quaternion::identity();
}
const float real_part = norm_from_norm_to + Dot(_from, _to);
Quaternion quat;
if (real_part < 1.e-6f * norm_from_norm_to) {
// If _from and _to are exactly opposite, rotate 180 degrees around an
// arbitrary orthogonal axis. Axis normalization can happen later, when we
// normalize the quaternion.
quat = std::abs(_from.x) > std::abs(_from.z)
? Quaternion(-_from.y, _from.x, 0.f, 0.f)
: Quaternion(0.f, -_from.z, _from.y, 0.f);
} else {
const Float3 cross = Cross(_from, _to);
quat = Quaternion(cross.x, cross.y, cross.z, real_part);
}
return Normalize(quat);
}
OZZ_INLINE Quaternion Quaternion::FromUnitVectors(const Float3& _from,
const Float3& _to) {
assert(IsNormalized(_from) && IsNormalized(_to) &&
"Input vectors must be normalized.");
// http://lolengine.net/blog/2014/02/24/quaternion-from-two-vectors-final
const float real_part = 1.f + Dot(_from, _to);
if (real_part < 1.e-6f) {
// If _from and _to are exactly opposite, rotate 180 degrees around an
// arbitrary orthogonal axis.
// Normalisation isn't needed, as from is already.
return std::abs(_from.x) > std::abs(_from.z)
? Quaternion(-_from.y, _from.x, 0.f, 0.f)
: Quaternion(0.f, -_from.z, _from.y, 0.f);
} else {
const Float3 cross = Cross(_from, _to);
return Normalize(Quaternion(cross.x, cross.y, cross.z, real_part));
}
}
// Returns the dot product of _a and _b.
OZZ_INLINE float Dot(const Quaternion& _a, const Quaternion& _b) {
return _a.x * _b.x + _a.y * _b.y + _a.z * _b.z + _a.w * _b.w;
}
// Returns the linear interpolation of quaternion _a and _b with coefficient
// _f.
OZZ_INLINE Quaternion Lerp(const Quaternion& _a, const Quaternion& _b,
float _f) {
return Quaternion((_b.x - _a.x) * _f + _a.x, (_b.y - _a.y) * _f + _a.y,
(_b.z - _a.z) * _f + _a.z, (_b.w - _a.w) * _f + _a.w);
}
// Returns the linear interpolation of quaternion _a and _b with coefficient
// _f. _a and _n must be from the same hemisphere (aka dot(_a, _b) >= 0).
OZZ_INLINE Quaternion NLerp(const Quaternion& _a, const Quaternion& _b,
float _f) {
const Float4 lerp((_b.x - _a.x) * _f + _a.x, (_b.y - _a.y) * _f + _a.y,
(_b.z - _a.z) * _f + _a.z, (_b.w - _a.w) * _f + _a.w);
const float sq_len =
lerp.x * lerp.x + lerp.y * lerp.y + lerp.z * lerp.z + lerp.w * lerp.w;
const float inv_len = 1.f / std::sqrt(sq_len);
return Quaternion(lerp.x * inv_len, lerp.y * inv_len, lerp.z * inv_len,
lerp.w * inv_len);
}
// Returns the spherical interpolation of quaternion _a and _b with
// coefficient _f.
OZZ_INLINE Quaternion SLerp(const Quaternion& _a, const Quaternion& _b,
float _f) {
assert(IsNormalized(_a));
assert(IsNormalized(_b));
// Calculate angle between them.
float cos_half_theta = _a.x * _b.x + _a.y * _b.y + _a.z * _b.z + _a.w * _b.w;
// If _a=_b or _a=-_b then theta = 0 and we can return _a.
if (std::abs(cos_half_theta) >= .999f) {
return _a;
}
// Calculate temporary values.
const float half_theta = std::acos(cos_half_theta);
const float sin_half_theta = std::sqrt(1.f - cos_half_theta * cos_half_theta);
// If theta = pi then result is not fully defined, we could rotate around
// any axis normal to _a or _b.
if (sin_half_theta < .001f) {
return Quaternion((_a.x + _b.x) * .5f, (_a.y + _b.y) * .5f,
(_a.z + _b.z) * .5f, (_a.w + _b.w) * .5f);
}
const float ratio_a = std::sin((1.f - _f) * half_theta) / sin_half_theta;
const float ratio_b = std::sin(_f * half_theta) / sin_half_theta;
// Calculate Quaternion.
return Quaternion(
ratio_a * _a.x + ratio_b * _b.x, ratio_a * _a.y + ratio_b * _b.y,
ratio_a * _a.z + ratio_b * _b.z, ratio_a * _a.w + ratio_b * _b.w);
}
// Computes the transformation of a Quaternion and a vector _v.
// This is equivalent to carrying out the quaternion multiplications:
// _q.conjugate() * (*this) * _q
OZZ_INLINE Float3 TransformVector(const Quaternion& _q, const Float3& _v) {
// http://www.neil.dantam.name/note/dantam-quaternion.pdf
// _v + 2.f * cross(_q.xyz, cross(_q.xyz, _v) + _q.w * _v);
const Float3 a(_q.y * _v.z - _q.z * _v.y + _v.x * _q.w,
_q.z * _v.x - _q.x * _v.z + _v.y * _q.w,
_q.x * _v.y - _q.y * _v.x + _v.z * _q.w);
const Float3 b(_q.y * a.z - _q.z * a.y, _q.z * a.x - _q.x * a.z,
_q.x * a.y - _q.y * a.x);
return Float3(_v.x + b.x + b.x, _v.y + b.y + b.y, _v.z + b.z + b.z);
}
} // namespace math
} // namespace ozz
#endif // OZZ_OZZ_BASE_MATHS_QUATERNION_H_
+99
View File
@@ -0,0 +1,99 @@
//----------------------------------------------------------------------------//
// //
// 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_BASE_MATHS_RECT_H_
#define OZZ_OZZ_BASE_MATHS_RECT_H_
namespace ozz {
namespace math {
// Defines a rectangle by the integer coordinates of its lower-left and
// width-height.
struct RectInt {
// Constructs a uninitialized rectangle.
RectInt() {}
// Constructs a rectangle with the specified arguments.
RectInt(int _left, int _bottom, int _width, int _height)
: left(_left), bottom(_bottom), width(_width), height(_height) {}
// Tests whether _x and _y coordinates are within rectangle bounds.
bool is_inside(int _x, int _y) const {
return _x >= left && _x < left + width && _y >= bottom &&
_y < bottom + height;
}
// Gets the rectangle x coordinate of the right rectangle side.
int right() const { return left + width; }
// Gets the rectangle y coordinate of the top rectangle side.
int top() const { return bottom + height; }
// Specifies the x-coordinate of the lower side.
int left;
// Specifies the x-coordinate of the left side.
int bottom;
// Specifies the width of the rectangle.
int width;
// Specifies the height of the rectangle..
int height;
};
// Defines a rectangle by the floating point coordinates of its lower-left
// and width-height.
struct RectFloat {
// Constructs a uninitialized rectangle.
RectFloat() {}
// Constructs a rectangle with the specified arguments.
RectFloat(float _left, float _bottom, float _width, float _height)
: left(_left), bottom(_bottom), width(_width), height(_height) {}
// Tests whether _x and _y coordinates are within rectangle bounds
bool is_inside(float _x, float _y) const {
return _x >= left && _x < left + width && _y >= bottom &&
_y < bottom + height;
}
// Gets the rectangle x coordinate of the right rectangle side.
float right() const { return left + width; }
// Gets the rectangle y coordinate of the top rectangle side.
float top() const { return bottom + height; }
// Specifies the x-coordinate of the lower side.
float left;
// Specifies the x-coordinate of the left side.
float bottom;
// Specifies the width of the rectangle.
float width;
// Specifies the height of the rectangle.
float height;
};
} // namespace math
} // namespace ozz
#endif // OZZ_OZZ_BASE_MATHS_RECT_H_
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,65 @@
//----------------------------------------------------------------------------//
// //
// 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_BASE_MATHS_SIMD_MATH_ARCHIVE_H_
#define OZZ_OZZ_BASE_MATHS_SIMD_MATH_ARCHIVE_H_
#include "ozz/base/io/archive_traits.h"
#include "ozz/base/maths/simd_math.h"
#include "ozz/base/platform.h"
namespace ozz {
namespace io {
OZZ_IO_TYPE_NOT_VERSIONABLE(math::SimdFloat4)
template <>
struct Extern<math::SimdFloat4> {
static void Save(OArchive& _archive, const math::SimdFloat4* _values,
size_t _count);
static void Load(IArchive& _archive, math::SimdFloat4* _values, size_t _count,
uint32_t _version);
};
OZZ_IO_TYPE_NOT_VERSIONABLE(math::SimdInt4)
template <>
struct Extern<math::SimdInt4> {
static void Save(OArchive& _archive, const math::SimdInt4* _values,
size_t _count);
static void Load(IArchive& _archive, math::SimdInt4* _values, size_t _count,
uint32_t _version);
};
OZZ_IO_TYPE_NOT_VERSIONABLE(math::Float4x4)
template <>
struct Extern<math::Float4x4> {
static void Save(OArchive& _archive, const math::Float4x4* _values,
size_t _count);
static void Load(IArchive& _archive, math::Float4x4* _values, size_t _count,
uint32_t _version);
};
} // namespace io
} // namespace ozz
#endif // OZZ_OZZ_BASE_MATHS_SIMD_MATH_ARCHIVE_H_
@@ -0,0 +1,274 @@
//----------------------------------------------------------------------------//
// //
// 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_BASE_MATHS_SIMD_QUATERNION_H_
#define OZZ_OZZ_BASE_MATHS_SIMD_QUATERNION_H_
#include "ozz/base/maths/simd_math.h"
#include <cmath>
// Implement simd quaternion.
namespace ozz {
namespace math {
// Declare the Quaternion type.
struct SimdQuaternion {
SimdFloat4 xyzw;
// Returns the identity quaternion.
static OZZ_INLINE SimdQuaternion identity() {
const SimdQuaternion quat = {simd_float4::w_axis()};
return quat;
}
// the angle in radian.
static OZZ_INLINE SimdQuaternion FromAxisAngle(_SimdFloat4 _axis,
_SimdFloat4 _angle);
// Returns a normalized quaternion initialized from an axis and angle cosine
// representation.
// Assumes the axis part (x, y, z) of _axis_angle is normalized.
// _angle.x is the angle cosine in radian, it must be within [-1,1] range.
static OZZ_INLINE SimdQuaternion FromAxisCosAngle(_SimdFloat4 _axis,
_SimdFloat4 _cos);
// Returns the quaternion that will rotate vector _from into vector _to,
// around their plan perpendicular axis.The input vectors don't need to be
// normalized, they can be null also.
static OZZ_INLINE SimdQuaternion FromVectors(_SimdFloat4 _from,
_SimdFloat4 _to);
// Returns the quaternion that will rotate vector _from into vector _to,
// around their plan perpendicular axis. The input vectors must be normalized.
static OZZ_INLINE SimdQuaternion FromUnitVectors(_SimdFloat4 _from,
_SimdFloat4 _to);
// Returns a normalized quaternion initialized from an axis angle
// representation.
// Assumes the axis part (x, y, z) of _axis_angle is normalized. _angle.x is
};
// Returns the multiplication of _a and _b. If both _a and _b are normalized,
// then the result is normalized.
OZZ_INLINE SimdQuaternion operator*(const SimdQuaternion& _a,
const SimdQuaternion& _b) {
// Original quaternion multiplication can be swizzled in a simd friendly way
// if w is negated, and some w multiplications parts (1st/last) are swaped.
//
// p1 p2 p3 p4
// _a.w * _b.x + _a.x * _b.w + _a.y * _b.z - _a.z * _b.y
// _a.w * _b.y + _a.y * _b.w + _a.z * _b.x - _a.x * _b.z
// _a.w * _b.z + _a.z * _b.w + _a.x * _b.y - _a.y * _b.x
// _a.w * _b.w - _a.x * _b.x - _a.y * _b.y - _a.z * _b.z
// ... becomes ->
// _a.w * _b.x + _a.x * _b.w + _a.y * _b.z - _a.z * _b.y
// _a.w * _b.y + _a.y * _b.w + _a.z * _b.x - _a.x * _b.z
// _a.w * _b.z + _a.z * _b.w + _a.x * _b.y - _a.y * _b.x
// - (_a.z * _b.z + _a.x * _b.x + _a.y * _b.y - _a.w * _b.w)
const SimdFloat4 p1 =
Swizzle<3, 3, 3, 2>(_a.xyzw) * Swizzle<0, 1, 2, 2>(_b.xyzw);
const SimdFloat4 p2 =
Swizzle<0, 1, 2, 0>(_a.xyzw) * Swizzle<3, 3, 3, 0>(_b.xyzw);
const SimdFloat4 p13 =
MAdd(Swizzle<1, 2, 0, 1>(_a.xyzw), Swizzle<2, 0, 1, 1>(_b.xyzw), p1);
const SimdFloat4 p24 =
NMAdd(Swizzle<2, 0, 1, 3>(_a.xyzw), Swizzle<1, 2, 0, 3>(_b.xyzw), p2);
const SimdQuaternion quat = {Xor(p13 + p24, simd_int4::mask_sign_w())};
return quat;
}
// Returns the conjugate of _q. This is the same as the inverse if _q is
// normalized. Otherwise the magnitude of the inverse is 1.f/|_q|.
OZZ_INLINE SimdQuaternion Conjugate(const SimdQuaternion& _q) {
const SimdQuaternion quat = {Xor(_q.xyzw, simd_int4::mask_sign_xyz())};
return quat;
}
// Returns the negate of _q. This represent the same rotation as q.
OZZ_INLINE SimdQuaternion operator-(const SimdQuaternion& _q) {
const SimdQuaternion quat = {Xor(_q.xyzw, simd_int4::mask_sign())};
return quat;
}
// Returns the normalized quaternion _q.
OZZ_INLINE SimdQuaternion Normalize(const SimdQuaternion& _q) {
const SimdQuaternion quat = {Normalize4(_q.xyzw)};
return quat;
}
// Returns the normalized quaternion _q if the norm of _q is not 0.
// Otherwise returns _safer.
OZZ_INLINE SimdQuaternion NormalizeSafe(const SimdQuaternion& _q,
const SimdQuaternion& _safer) {
const SimdQuaternion quat = {NormalizeSafe4(_q.xyzw, _safer.xyzw)};
return quat;
}
// Returns the estimated normalized quaternion _q.
OZZ_INLINE SimdQuaternion NormalizeEst(const SimdQuaternion& _q) {
const SimdQuaternion quat = {NormalizeEst4(_q.xyzw)};
return quat;
}
// Returns the estimated normalized quaternion _q if the norm of _q is not 0.
// Otherwise returns _safer.
OZZ_INLINE SimdQuaternion NormalizeSafeEst(const SimdQuaternion& _q,
const SimdQuaternion& _safer) {
const SimdQuaternion quat = {NormalizeSafeEst4(_q.xyzw, _safer.xyzw)};
return quat;
}
// Tests if the _q is a normalized quaternion.
// Returns the result in the x component of the returned vector. y, z and w are
// set to 0.
OZZ_INLINE SimdInt4 IsNormalized(const SimdQuaternion& _q) {
return IsNormalized4(_q.xyzw);
}
// Tests if the _q is a normalized quaternion.
// Uses the estimated normalization coefficient, that matches estimated math
// functions (RecpEst, MormalizeEst...).
// Returns the result in the x component of the returned vector. y, z and w are
// set to 0.
OZZ_INLINE SimdInt4 IsNormalizedEst(const SimdQuaternion& _q) {
return IsNormalizedEst4(_q.xyzw);
}
OZZ_INLINE SimdQuaternion SimdQuaternion::FromAxisAngle(_SimdFloat4 _axis,
_SimdFloat4 _angle) {
assert(AreAllTrue1(IsNormalizedEst3(_axis)) && "axis is not normalized.");
const SimdFloat4 half_angle = _angle * simd_float4::Load1(.5f);
const SimdFloat4 half_sin = SinX(half_angle);
const SimdFloat4 half_cos = CosX(half_angle);
const SimdQuaternion quat = {SetW(_axis * SplatX(half_sin), half_cos)};
return quat;
}
OZZ_INLINE SimdQuaternion SimdQuaternion::FromAxisCosAngle(_SimdFloat4 _axis,
_SimdFloat4 _cos) {
const SimdFloat4 one = simd_float4::one();
const SimdFloat4 half = simd_float4::Load1(.5f);
assert(AreAllTrue1(IsNormalizedEst3(_axis)) && "axis is not normalized.");
assert(AreAllTrue1(And(CmpGe(_cos, -one), CmpLe(_cos, one))) &&
"cos is not in [-1,1] range.");
const SimdFloat4 half_cos2 = (one + _cos) * half;
const SimdFloat4 half_sin2 = one - half_cos2;
const SimdFloat4 half_sincos2 = SetY(half_cos2, half_sin2);
const SimdFloat4 half_sincos = Sqrt(half_sincos2);
const SimdFloat4 half_sin = SplatY(half_sincos);
const SimdQuaternion quat = {SetW(_axis * half_sin, half_sincos)};
return quat;
}
// Returns to an axis angle representation of quaternion _q.
// Assumes quaternion _q is normalized.
OZZ_INLINE SimdFloat4 ToAxisAngle(const SimdQuaternion& _q) {
assert(AreAllTrue1(IsNormalizedEst4(_q.xyzw)) && "_q is not normalized.");
const SimdFloat4 x_axis = simd_float4::x_axis();
const SimdFloat4 clamped_w = Clamp(-x_axis, SplatW(_q.xyzw), x_axis);
const SimdFloat4 half_angle = ACosX(clamped_w);
// Assuming quaternion is normalized then s always positive.
const SimdFloat4 s = SplatX(SqrtX(NMAdd(clamped_w, clamped_w, x_axis)));
// If s is close to zero then direction of axis is not important.
const SimdInt4 low = CmpLt(s, simd_float4::Load1(1e-3f));
return Select(low, x_axis,
SetW(_q.xyzw * RcpEstNR(s), half_angle + half_angle));
}
OZZ_INLINE SimdQuaternion SimdQuaternion::FromVectors(_SimdFloat4 _from,
_SimdFloat4 _to) {
// http://lolengine.net/blog/2014/02/24/quaternion-from-two-vectors-final
const SimdFloat4 norm_from_norm_to =
SqrtX(Length3Sqr(_from) * Length3Sqr(_to));
const float norm_from_norm_to_x = GetX(norm_from_norm_to);
if (norm_from_norm_to_x < 1.e-6f) {
return SimdQuaternion::identity();
}
const SimdFloat4 real_part = norm_from_norm_to + Dot3(_from, _to);
SimdQuaternion quat;
if (GetX(real_part) < 1.e-6f * norm_from_norm_to_x) {
// If _from and _to are exactly opposite, rotate 180 degrees around an
// arbitrary orthogonal axis. Axis normalization can happen later, when we
// normalize the quaternion.
float from[4];
ozz::math::StorePtrU(_from, from);
quat.xyzw = std::abs(from[0]) > std::abs(from[2])
? ozz::math::simd_float4::Load(-from[1], from[0], 0.f, 0.f)
: ozz::math::simd_float4::Load(0.f, -from[2], from[1], 0.f);
} else {
// This is the general code path.
quat.xyzw = SetW(Cross3(_from, _to), real_part);
}
return Normalize(quat);
}
OZZ_INLINE SimdQuaternion SimdQuaternion::FromUnitVectors(_SimdFloat4 _from,
_SimdFloat4 _to) {
// http://lolengine.net/blog/2014/02/24/quaternion-from-two-vectors-final
assert(ozz::math::AreAllTrue1(
And(IsNormalizedEst3(_from), IsNormalizedEst3(_to))) &&
"Input vectors must be normalized.");
const SimdFloat4 real_part =
ozz::math::simd_float4::x_axis() + Dot3(_from, _to);
if (GetX(real_part) < 1.e-6f) {
// If _from and _to are exactly opposite, rotate 180 degrees around an
// arbitrary orthogonal axis.
// Normalization isn't needed, as from is already.
float from[4];
ozz::math::StorePtrU(_from, from);
SimdQuaternion quat = {
std::abs(from[0]) > std::abs(from[2])
? ozz::math::simd_float4::Load(-from[1], from[0], 0.f, 0.f)
: ozz::math::simd_float4::Load(0.f, -from[2], from[1], 0.f)};
return quat;
} else {
// This is the general code path.
SimdQuaternion quat = {SetW(Cross3(_from, _to), real_part)};
return Normalize(quat);
}
}
// Computes the transformation of a Quaternion and a vector _v.
// This is equivalent to carrying out the quaternion multiplications:
// _q.conjugate() * (*this) * _q
// w component of the returned vector is undefined.
OZZ_INLINE SimdFloat4 TransformVector(const SimdQuaternion& _q,
_SimdFloat4 _v) {
// http://www.neil.dantam.name/note/dantam-quaternion.pdf
// _v + 2.f * cross(_q.xyz, cross(_q.xyz, _v) + _q.w * _v)
const SimdFloat4 cross1 = MAdd(SplatW(_q.xyzw), _v, Cross3(_q.xyzw, _v));
const SimdFloat4 cross2 = Cross3(_q.xyzw, cross1);
return _v + cross2 + cross2;
}
} // namespace math
} // namespace ozz
#endif // OZZ_OZZ_BASE_MATHS_SIMD_QUATERNION_H_
@@ -0,0 +1,676 @@
//----------------------------------------------------------------------------//
// //
// 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_BASE_MATHS_SOA_FLOAT_H_
#define OZZ_OZZ_BASE_MATHS_SOA_FLOAT_H_
#include <cassert>
#include "ozz/base/maths/math_constant.h"
#include "ozz/base/maths/simd_math.h"
#include "ozz/base/platform.h"
namespace ozz {
namespace math {
struct SoaFloat2 {
SimdFloat4 x, y;
static OZZ_INLINE SoaFloat2 Load(_SimdFloat4 _x, _SimdFloat4 _y) {
const SoaFloat2 r = {_x, _y};
return r;
}
static OZZ_INLINE SoaFloat2 zero() {
const SoaFloat2 r = {simd_float4::zero(), simd_float4::zero()};
return r;
}
static OZZ_INLINE SoaFloat2 one() {
const SoaFloat2 r = {simd_float4::one(), simd_float4::one()};
return r;
}
static OZZ_INLINE SoaFloat2 x_axis() {
const SoaFloat2 r = {simd_float4::one(), simd_float4::zero()};
return r;
}
static OZZ_INLINE SoaFloat2 y_axis() {
const SoaFloat2 r = {simd_float4::zero(), simd_float4::one()};
return r;
}
};
struct SoaFloat3 {
SimdFloat4 x, y, z;
static OZZ_INLINE SoaFloat3 Load(_SimdFloat4 _x, _SimdFloat4 _y,
_SimdFloat4 _z) {
const SoaFloat3 r = {_x, _y, _z};
return r;
}
static OZZ_INLINE SoaFloat3 Load(const SoaFloat2& _v, _SimdFloat4 _z) {
const SoaFloat3 r = {_v.x, _v.y, _z};
return r;
}
static OZZ_INLINE SoaFloat3 zero() {
const SoaFloat3 r = {simd_float4::zero(), simd_float4::zero(),
simd_float4::zero()};
return r;
}
static OZZ_INLINE SoaFloat3 one() {
const SoaFloat3 r = {simd_float4::one(), simd_float4::one(),
simd_float4::one()};
return r;
}
static OZZ_INLINE SoaFloat3 x_axis() {
const SoaFloat3 r = {simd_float4::one(), simd_float4::zero(),
simd_float4::zero()};
return r;
}
static OZZ_INLINE SoaFloat3 y_axis() {
const SoaFloat3 r = {simd_float4::zero(), simd_float4::one(),
simd_float4::zero()};
return r;
}
static OZZ_INLINE SoaFloat3 z_axis() {
const SoaFloat3 r = {simd_float4::zero(), simd_float4::zero(),
simd_float4::one()};
return r;
}
};
struct SoaFloat4 {
SimdFloat4 x, y, z, w;
static OZZ_INLINE SoaFloat4 Load(_SimdFloat4 _x, _SimdFloat4 _y,
_SimdFloat4 _z, const SimdFloat4& _w) {
const SoaFloat4 r = {_x, _y, _z, _w};
return r;
}
static OZZ_INLINE SoaFloat4 Load(const SoaFloat3& _v, _SimdFloat4 _w) {
const SoaFloat4 r = {_v.x, _v.y, _v.z, _w};
return r;
}
static OZZ_INLINE SoaFloat4 Load(const SoaFloat2& _v, _SimdFloat4 _z,
_SimdFloat4 _w) {
const SoaFloat4 r = {_v.x, _v.y, _z, _w};
return r;
}
static OZZ_INLINE SoaFloat4 zero() {
const SimdFloat4 zero = simd_float4::zero();
const SoaFloat4 r = {zero, zero, zero, zero};
return r;
}
static OZZ_INLINE SoaFloat4 one() {
const SimdFloat4 one = simd_float4::one();
const SoaFloat4 r = {one, one, one, one};
return r;
}
static OZZ_INLINE SoaFloat4 x_axis() {
const SimdFloat4 zero = simd_float4::zero();
const SoaFloat4 r = {simd_float4::one(), zero, zero, zero};
return r;
}
static OZZ_INLINE SoaFloat4 y_axis() {
const SimdFloat4 zero = simd_float4::zero();
const SoaFloat4 r = {zero, simd_float4::one(), zero, zero};
return r;
}
static OZZ_INLINE SoaFloat4 z_axis() {
const SimdFloat4 zero = simd_float4::zero();
const SoaFloat4 r = {zero, zero, simd_float4::one(), zero};
return r;
}
static OZZ_INLINE SoaFloat4 w_axis() {
const SimdFloat4 zero = simd_float4::zero();
const SoaFloat4 r = {zero, zero, zero, simd_float4::one()};
return r;
}
};
} // namespace math
} // namespace ozz
// Returns per element addition of _a and _b using operator +.
OZZ_INLINE ozz::math::SoaFloat4 operator+(const ozz::math::SoaFloat4& _a,
const ozz::math::SoaFloat4& _b) {
const ozz::math::SoaFloat4 r = {_a.x + _b.x, _a.y + _b.y, _a.z + _b.z,
_a.w + _b.w};
return r;
}
OZZ_INLINE ozz::math::SoaFloat3 operator+(const ozz::math::SoaFloat3& _a,
const ozz::math::SoaFloat3& _b) {
const ozz::math::SoaFloat3 r = {_a.x + _b.x, _a.y + _b.y, _a.z + _b.z};
return r;
}
OZZ_INLINE ozz::math::SoaFloat2 operator+(const ozz::math::SoaFloat2& _a,
const ozz::math::SoaFloat2& _b) {
const ozz::math::SoaFloat2 r = {_a.x + _b.x, _a.y + _b.y};
return r;
}
// Returns per element subtraction of _a and _b using operator -.
OZZ_INLINE ozz::math::SoaFloat4 operator-(const ozz::math::SoaFloat4& _a,
const ozz::math::SoaFloat4& _b) {
const ozz::math::SoaFloat4 r = {_a.x - _b.x, _a.y - _b.y, _a.z - _b.z,
_a.w - _b.w};
return r;
}
OZZ_INLINE ozz::math::SoaFloat3 operator-(const ozz::math::SoaFloat3& _a,
const ozz::math::SoaFloat3& _b) {
const ozz::math::SoaFloat3 r = {_a.x - _b.x, _a.y - _b.y, _a.z - _b.z};
return r;
}
OZZ_INLINE ozz::math::SoaFloat2 operator-(const ozz::math::SoaFloat2& _a,
const ozz::math::SoaFloat2& _b) {
const ozz::math::SoaFloat2 r = {_a.x - _b.x, _a.y - _b.y};
return r;
}
// Returns per element negative value of _v.
OZZ_INLINE ozz::math::SoaFloat4 operator-(const ozz::math::SoaFloat4& _v) {
const ozz::math::SoaFloat4 r = {-_v.x, -_v.y, -_v.z, -_v.w};
return r;
}
OZZ_INLINE ozz::math::SoaFloat3 operator-(const ozz::math::SoaFloat3& _v) {
const ozz::math::SoaFloat3 r = {-_v.x, -_v.y, -_v.z};
return r;
}
OZZ_INLINE ozz::math::SoaFloat2 operator-(const ozz::math::SoaFloat2& _v) {
const ozz::math::SoaFloat2 r = {-_v.x, -_v.y};
return r;
}
// Returns per element multiplication of _a and _b using operator *.
OZZ_INLINE ozz::math::SoaFloat4 operator*(const ozz::math::SoaFloat4& _a,
const ozz::math::SoaFloat4& _b) {
const ozz::math::SoaFloat4 r = {_a.x * _b.x, _a.y * _b.y, _a.z * _b.z,
_a.w * _b.w};
return r;
}
OZZ_INLINE ozz::math::SoaFloat3 operator*(const ozz::math::SoaFloat3& _a,
const ozz::math::SoaFloat3& _b) {
const ozz::math::SoaFloat3 r = {_a.x * _b.x, _a.y * _b.y, _a.z * _b.z};
return r;
}
OZZ_INLINE ozz::math::SoaFloat2 operator*(const ozz::math::SoaFloat2& _a,
const ozz::math::SoaFloat2& _b) {
const ozz::math::SoaFloat2 r = {_a.x * _b.x, _a.y * _b.y};
return r;
}
// Returns per element multiplication of _a and scalar value _f using
// operator *.
OZZ_INLINE ozz::math::SoaFloat4 operator*(const ozz::math::SoaFloat4& _a,
ozz::math::_SimdFloat4 _f) {
const ozz::math::SoaFloat4 r = {_a.x * _f, _a.y * _f, _a.z * _f, _a.w * _f};
return r;
}
OZZ_INLINE ozz::math::SoaFloat3 operator*(const ozz::math::SoaFloat3& _a,
ozz::math::_SimdFloat4 _f) {
const ozz::math::SoaFloat3 r = {_a.x * _f, _a.y * _f, _a.z * _f};
return r;
}
OZZ_INLINE ozz::math::SoaFloat2 operator*(const ozz::math::SoaFloat2& _a,
ozz::math::_SimdFloat4 _f) {
const ozz::math::SoaFloat2 r = {_a.x * _f, _a.y * _f};
return r;
}
// Multiplies _a and _b, then adds _addend.
// v = (_a * _b) + _addend
OZZ_INLINE ozz::math::SoaFloat2 MAdd(const ozz::math::SoaFloat2& _a,
const ozz::math::SoaFloat2& _b,
const ozz::math::SoaFloat2& _addend) {
const ozz::math::SoaFloat2 r = {ozz::math::MAdd(_a.x, _b.x, _addend.x),
ozz::math::MAdd(_a.y, _b.y, _addend.y)};
return r;
}
OZZ_INLINE ozz::math::SoaFloat3 MAdd(const ozz::math::SoaFloat3& _a,
const ozz::math::SoaFloat3& _b,
const ozz::math::SoaFloat3& _addend) {
const ozz::math::SoaFloat3 r = {ozz::math::MAdd(_a.x, _b.x, _addend.x),
ozz::math::MAdd(_a.y, _b.y, _addend.y),
ozz::math::MAdd(_a.z, _b.z, _addend.z)};
return r;
}
OZZ_INLINE ozz::math::SoaFloat4 MAdd(const ozz::math::SoaFloat4& _a,
const ozz::math::SoaFloat4& _b,
const ozz::math::SoaFloat4& _addend) {
const ozz::math::SoaFloat4 r = {ozz::math::MAdd(_a.x, _b.x, _addend.x),
ozz::math::MAdd(_a.y, _b.y, _addend.y),
ozz::math::MAdd(_a.z, _b.z, _addend.z),
ozz::math::MAdd(_a.w, _b.w, _addend.w)};
return r;
}
// Returns per element division of _a and _b using operator /.
OZZ_INLINE ozz::math::SoaFloat4 operator/(const ozz::math::SoaFloat4& _a,
const ozz::math::SoaFloat4& _b) {
const ozz::math::SoaFloat4 r = {_a.x / _b.x, _a.y / _b.y, _a.z / _b.z,
_a.w / _b.w};
return r;
}
OZZ_INLINE ozz::math::SoaFloat3 operator/(const ozz::math::SoaFloat3& _a,
const ozz::math::SoaFloat3& _b) {
const ozz::math::SoaFloat3 r = {_a.x / _b.x, _a.y / _b.y, _a.z / _b.z};
return r;
}
OZZ_INLINE ozz::math::SoaFloat2 operator/(const ozz::math::SoaFloat2& _a,
const ozz::math::SoaFloat2& _b) {
const ozz::math::SoaFloat2 r = {_a.x / _b.x, _a.y / _b.y};
return r;
}
// Returns per element division of _a and scalar value _f using operator/.
OZZ_INLINE ozz::math::SoaFloat4 operator/(const ozz::math::SoaFloat4& _a,
ozz::math::_SimdFloat4 _f) {
const ozz::math::SoaFloat4 r = {_a.x / _f, _a.y / _f, _a.z / _f, _a.w / _f};
return r;
}
OZZ_INLINE ozz::math::SoaFloat3 operator/(const ozz::math::SoaFloat3& _a,
ozz::math::_SimdFloat4 _f) {
const ozz::math::SoaFloat3 r = {_a.x / _f, _a.y / _f, _a.z / _f};
return r;
}
OZZ_INLINE ozz::math::SoaFloat2 operator/(const ozz::math::SoaFloat2& _a,
ozz::math::_SimdFloat4 _f) {
const ozz::math::SoaFloat2 r = {_a.x / _f, _a.y / _f};
return r;
}
// Returns true if each element of a is less than each element of _b.
OZZ_INLINE ozz::math::SimdInt4 operator<(const ozz::math::SoaFloat4& _a,
const ozz::math::SoaFloat4& _b) {
const ozz::math::SimdInt4 x = ozz::math::CmpLt(_a.x, _b.x);
const ozz::math::SimdInt4 y = ozz::math::CmpLt(_a.y, _b.y);
const ozz::math::SimdInt4 z = ozz::math::CmpLt(_a.z, _b.z);
const ozz::math::SimdInt4 w = ozz::math::CmpLt(_a.w, _b.w);
return ozz::math::And(ozz::math::And(ozz::math::And(x, y), z), w);
}
OZZ_INLINE ozz::math::SimdInt4 operator<(const ozz::math::SoaFloat3& _a,
const ozz::math::SoaFloat3& _b) {
const ozz::math::SimdInt4 x = ozz::math::CmpLt(_a.x, _b.x);
const ozz::math::SimdInt4 y = ozz::math::CmpLt(_a.y, _b.y);
const ozz::math::SimdInt4 z = ozz::math::CmpLt(_a.z, _b.z);
return ozz::math::And(ozz::math::And(x, y), z);
}
OZZ_INLINE ozz::math::SimdInt4 operator<(const ozz::math::SoaFloat2& _a,
const ozz::math::SoaFloat2& _b) {
const ozz::math::SimdInt4 x = ozz::math::CmpLt(_a.x, _b.x);
const ozz::math::SimdInt4 y = ozz::math::CmpLt(_a.y, _b.y);
return ozz::math::And(x, y);
}
// Returns true if each element of a is less or equal to each element of _b.
OZZ_INLINE ozz::math::SimdInt4 operator<=(const ozz::math::SoaFloat4& _a,
const ozz::math::SoaFloat4& _b) {
const ozz::math::SimdInt4 x = ozz::math::CmpLe(_a.x, _b.x);
const ozz::math::SimdInt4 y = ozz::math::CmpLe(_a.y, _b.y);
const ozz::math::SimdInt4 z = ozz::math::CmpLe(_a.z, _b.z);
const ozz::math::SimdInt4 w = ozz::math::CmpLe(_a.w, _b.w);
return ozz::math::And(ozz::math::And(ozz::math::And(x, y), z), w);
}
OZZ_INLINE ozz::math::SimdInt4 operator<=(const ozz::math::SoaFloat3& _a,
const ozz::math::SoaFloat3& _b) {
const ozz::math::SimdInt4 x = ozz::math::CmpLe(_a.x, _b.x);
const ozz::math::SimdInt4 y = ozz::math::CmpLe(_a.y, _b.y);
const ozz::math::SimdInt4 z = ozz::math::CmpLe(_a.z, _b.z);
return ozz::math::And(ozz::math::And(x, y), z);
}
OZZ_INLINE ozz::math::SimdInt4 operator<=(const ozz::math::SoaFloat2& _a,
const ozz::math::SoaFloat2& _b) {
const ozz::math::SimdInt4 x = ozz::math::CmpLe(_a.x, _b.x);
const ozz::math::SimdInt4 y = ozz::math::CmpLe(_a.y, _b.y);
return ozz::math::And(x, y);
}
// Returns true if each element of a is greater than each element of _b.
OZZ_INLINE ozz::math::SimdInt4 operator>(const ozz::math::SoaFloat4& _a,
const ozz::math::SoaFloat4& _b) {
const ozz::math::SimdInt4 x = ozz::math::CmpGt(_a.x, _b.x);
const ozz::math::SimdInt4 y = ozz::math::CmpGt(_a.y, _b.y);
const ozz::math::SimdInt4 z = ozz::math::CmpGt(_a.z, _b.z);
const ozz::math::SimdInt4 w = ozz::math::CmpGt(_a.w, _b.w);
return ozz::math::And(ozz::math::And(ozz::math::And(x, y), z), w);
}
OZZ_INLINE ozz::math::SimdInt4 operator>(const ozz::math::SoaFloat3& _a,
const ozz::math::SoaFloat3& _b) {
const ozz::math::SimdInt4 x = ozz::math::CmpGt(_a.x, _b.x);
const ozz::math::SimdInt4 y = ozz::math::CmpGt(_a.y, _b.y);
const ozz::math::SimdInt4 z = ozz::math::CmpGt(_a.z, _b.z);
return ozz::math::And(ozz::math::And(x, y), z);
}
OZZ_INLINE ozz::math::SimdInt4 operator>(const ozz::math::SoaFloat2& _a,
const ozz::math::SoaFloat2& _b) {
const ozz::math::SimdInt4 x = ozz::math::CmpGt(_a.x, _b.x);
const ozz::math::SimdInt4 y = ozz::math::CmpGt(_a.y, _b.y);
return ozz::math::And(x, y);
}
// Returns true if each element of a is greater or equal to each element of _b.
OZZ_INLINE ozz::math::SimdInt4 operator>=(const ozz::math::SoaFloat4& _a,
const ozz::math::SoaFloat4& _b) {
const ozz::math::SimdInt4 x = ozz::math::CmpGe(_a.x, _b.x);
const ozz::math::SimdInt4 y = ozz::math::CmpGe(_a.y, _b.y);
const ozz::math::SimdInt4 z = ozz::math::CmpGe(_a.z, _b.z);
const ozz::math::SimdInt4 w = ozz::math::CmpGe(_a.w, _b.w);
return ozz::math::And(ozz::math::And(ozz::math::And(x, y), z), w);
}
OZZ_INLINE ozz::math::SimdInt4 operator>=(const ozz::math::SoaFloat3& _a,
const ozz::math::SoaFloat3& _b) {
const ozz::math::SimdInt4 x = ozz::math::CmpGe(_a.x, _b.x);
const ozz::math::SimdInt4 y = ozz::math::CmpGe(_a.y, _b.y);
const ozz::math::SimdInt4 z = ozz::math::CmpGe(_a.z, _b.z);
return ozz::math::And(ozz::math::And(x, y), z);
}
OZZ_INLINE ozz::math::SimdInt4 operator>=(const ozz::math::SoaFloat2& _a,
const ozz::math::SoaFloat2& _b) {
const ozz::math::SimdInt4 x = ozz::math::CmpGe(_a.x, _b.x);
const ozz::math::SimdInt4 y = ozz::math::CmpGe(_a.y, _b.y);
return ozz::math::And(x, y);
}
// Returns true if each element of _a is equal to each element of _b.
// Uses a bitwise comparison of _a and _b, no tolerance is applied.
OZZ_INLINE ozz::math::SimdInt4 operator==(const ozz::math::SoaFloat4& _a,
const ozz::math::SoaFloat4& _b) {
const ozz::math::SimdInt4 x = ozz::math::CmpEq(_a.x, _b.x);
const ozz::math::SimdInt4 y = ozz::math::CmpEq(_a.y, _b.y);
const ozz::math::SimdInt4 z = ozz::math::CmpEq(_a.z, _b.z);
const ozz::math::SimdInt4 w = ozz::math::CmpEq(_a.w, _b.w);
return ozz::math::And(ozz::math::And(ozz::math::And(x, y), z), w);
}
OZZ_INLINE ozz::math::SimdInt4 operator==(const ozz::math::SoaFloat3& _a,
const ozz::math::SoaFloat3& _b) {
const ozz::math::SimdInt4 x = ozz::math::CmpEq(_a.x, _b.x);
const ozz::math::SimdInt4 y = ozz::math::CmpEq(_a.y, _b.y);
const ozz::math::SimdInt4 z = ozz::math::CmpEq(_a.z, _b.z);
return ozz::math::And(ozz::math::And(x, y), z);
}
OZZ_INLINE ozz::math::SimdInt4 operator==(const ozz::math::SoaFloat2& _a,
const ozz::math::SoaFloat2& _b) {
const ozz::math::SimdInt4 x = ozz::math::CmpEq(_a.x, _b.x);
const ozz::math::SimdInt4 y = ozz::math::CmpEq(_a.y, _b.y);
return ozz::math::And(x, y);
}
// Returns true if each element of a is different from each element of _b.
// Uses a bitwise comparison of _a and _b, no tolerance is applied.
OZZ_INLINE ozz::math::SimdInt4 operator!=(const ozz::math::SoaFloat4& _a,
const ozz::math::SoaFloat4& _b) {
const ozz::math::SimdInt4 x = ozz::math::CmpNe(_a.x, _b.x);
const ozz::math::SimdInt4 y = ozz::math::CmpNe(_a.y, _b.y);
const ozz::math::SimdInt4 z = ozz::math::CmpNe(_a.z, _b.z);
const ozz::math::SimdInt4 w = ozz::math::CmpNe(_a.w, _b.w);
return ozz::math::Or(ozz::math::Or(ozz::math::Or(x, y), z), w);
}
OZZ_INLINE ozz::math::SimdInt4 operator!=(const ozz::math::SoaFloat3& _a,
const ozz::math::SoaFloat3& _b) {
const ozz::math::SimdInt4 x = ozz::math::CmpNe(_a.x, _b.x);
const ozz::math::SimdInt4 y = ozz::math::CmpNe(_a.y, _b.y);
const ozz::math::SimdInt4 z = ozz::math::CmpNe(_a.z, _b.z);
return ozz::math::Or(ozz::math::Or(x, y), z);
}
OZZ_INLINE ozz::math::SimdInt4 operator!=(const ozz::math::SoaFloat2& _a,
const ozz::math::SoaFloat2& _b) {
const ozz::math::SimdInt4 x = ozz::math::CmpNe(_a.x, _b.x);
const ozz::math::SimdInt4 y = ozz::math::CmpNe(_a.y, _b.y);
return ozz::math::Or(x, y);
}
namespace ozz {
namespace math {
// Returns the (horizontal) addition of each element of _v.
OZZ_INLINE SimdFloat4 HAdd(const SoaFloat4& _v) {
return _v.x + _v.y + _v.z + _v.w;
}
OZZ_INLINE SimdFloat4 HAdd(const SoaFloat3& _v) { return _v.x + _v.y + _v.z; }
OZZ_INLINE SimdFloat4 HAdd(const SoaFloat2& _v) { return _v.x + _v.y; }
// Returns the dot product of _a and _b.
OZZ_INLINE SimdFloat4 Dot(const SoaFloat4& _a, const SoaFloat4& _b) {
return _a.x * _b.x + _a.y * _b.y + _a.z * _b.z + _a.w * _b.w;
}
OZZ_INLINE SimdFloat4 Dot(const SoaFloat3& _a, const SoaFloat3& _b) {
return _a.x * _b.x + _a.y * _b.y + _a.z * _b.z;
}
OZZ_INLINE SimdFloat4 Dot(const SoaFloat2& _a, const SoaFloat2& _b) {
return _a.x * _b.x + _a.y * _b.y;
}
// Returns the cross product of _a and _b.
OZZ_INLINE SoaFloat3 Cross(const SoaFloat3& _a, const SoaFloat3& _b) {
const SoaFloat3 r = {_a.y * _b.z - _b.y * _a.z, _a.z * _b.x - _b.z * _a.x,
_a.x * _b.y - _b.x * _a.y};
return r;
}
// Returns the length |_v| of _v.
OZZ_INLINE SimdFloat4 Length(const SoaFloat4& _v) {
const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z + _v.w * _v.w;
return Sqrt(len2);
}
OZZ_INLINE SimdFloat4 Length(const SoaFloat3& _v) {
const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z;
return Sqrt(len2);
}
OZZ_INLINE SimdFloat4 Length(const SoaFloat2& _v) {
const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y;
return Sqrt(len2);
}
// Returns the square length |_v|^2 of _v.
OZZ_INLINE SimdFloat4 LengthSqr(const SoaFloat4& _v) {
return _v.x * _v.x + _v.y * _v.y + _v.z * _v.z + _v.w * _v.w;
}
OZZ_INLINE SimdFloat4 LengthSqr(const SoaFloat3& _v) {
return _v.x * _v.x + _v.y * _v.y + _v.z * _v.z;
}
OZZ_INLINE SimdFloat4 LengthSqr(const SoaFloat2& _v) {
return _v.x * _v.x + _v.y * _v.y;
}
// Returns the normalized vector _v.
OZZ_INLINE SoaFloat4 Normalize(const SoaFloat4& _v) {
const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z + _v.w * _v.w;
assert(AreAllTrue(CmpNe(len2, simd_float4::zero())) &&
"_v is not normalizable");
const SimdFloat4 inv_len = math::simd_float4::one() / Sqrt(len2);
const SoaFloat4 r = {_v.x * inv_len, _v.y * inv_len, _v.z * inv_len,
_v.w * inv_len};
return r;
}
OZZ_INLINE SoaFloat3 Normalize(const SoaFloat3& _v) {
const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z;
assert(AreAllTrue(CmpNe(len2, simd_float4::zero())) &&
"_v is not normalizable");
const SimdFloat4 inv_len = math::simd_float4::one() / Sqrt(len2);
const SoaFloat3 r = {_v.x * inv_len, _v.y * inv_len, _v.z * inv_len};
return r;
}
OZZ_INLINE SoaFloat2 Normalize(const SoaFloat2& _v) {
const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y;
assert(AreAllTrue(CmpNe(len2, simd_float4::zero())) &&
"_v is not normalizable");
const SimdFloat4 inv_len = math::simd_float4::one() / Sqrt(len2);
const SoaFloat2 r = {_v.x * inv_len, _v.y * inv_len};
return r;
}
// Test if each vector _v is normalized.
OZZ_INLINE math::SimdInt4 IsNormalized(const SoaFloat4& _v) {
const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z + _v.w * _v.w;
return CmpLt(Abs(len2 - math::simd_float4::one()),
simd_float4::Load1(kNormalizationToleranceSq));
}
OZZ_INLINE math::SimdInt4 IsNormalized(const SoaFloat3& _v) {
const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z;
return CmpLt(Abs(len2 - math::simd_float4::one()),
simd_float4::Load1(kNormalizationToleranceSq));
}
OZZ_INLINE math::SimdInt4 IsNormalized(const SoaFloat2& _v) {
const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y;
return CmpLt(Abs(len2 - math::simd_float4::one()),
simd_float4::Load1(kNormalizationToleranceSq));
}
// Test if each vector _v is normalized using estimated tolerance.
OZZ_INLINE math::SimdInt4 IsNormalizedEst(const SoaFloat4& _v) {
const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z + _v.w * _v.w;
return CmpLt(Abs(len2 - math::simd_float4::one()),
simd_float4::Load1(kNormalizationToleranceEstSq));
}
OZZ_INLINE math::SimdInt4 IsNormalizedEst(const SoaFloat3& _v) {
const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z;
return CmpLt(Abs(len2 - math::simd_float4::one()),
simd_float4::Load1(kNormalizationToleranceEstSq));
}
OZZ_INLINE math::SimdInt4 IsNormalizedEst(const SoaFloat2& _v) {
const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y;
return CmpLt(Abs(len2 - math::simd_float4::one()),
simd_float4::Load1(kNormalizationToleranceEstSq));
}
// Returns the normalized vector _v if the norm of _v is not 0.
// Otherwise returns _safer.
OZZ_INLINE SoaFloat4 NormalizeSafe(const SoaFloat4& _v,
const SoaFloat4& _safer) {
assert(AreAllTrue(IsNormalizedEst(_safer)) && "_safer is not normalized");
const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z + _v.w * _v.w;
const math::SimdInt4 b = CmpNe(len2, math::simd_float4::zero());
const SimdFloat4 inv_len = math::simd_float4::one() / Sqrt(len2);
const SoaFloat4 r = {
Select(b, _v.x * inv_len, _safer.x), Select(b, _v.y * inv_len, _safer.y),
Select(b, _v.z * inv_len, _safer.z), Select(b, _v.w * inv_len, _safer.w)};
return r;
}
OZZ_INLINE SoaFloat3 NormalizeSafe(const SoaFloat3& _v,
const SoaFloat3& _safer) {
assert(AreAllTrue(IsNormalizedEst(_safer)) && "_safer is not normalized");
const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z;
const math::SimdInt4 b = CmpNe(len2, math::simd_float4::zero());
const SimdFloat4 inv_len = math::simd_float4::one() / Sqrt(len2);
const SoaFloat3 r = {Select(b, _v.x * inv_len, _safer.x),
Select(b, _v.y * inv_len, _safer.y),
Select(b, _v.z * inv_len, _safer.z)};
return r;
}
OZZ_INLINE SoaFloat2 NormalizeSafe(const SoaFloat2& _v,
const SoaFloat2& _safer) {
assert(AreAllTrue(IsNormalizedEst(_safer)) && "_safer is not normalized");
const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y;
const math::SimdInt4 b = CmpNe(len2, math::simd_float4::zero());
const SimdFloat4 inv_len = math::simd_float4::one() / Sqrt(len2);
const SoaFloat2 r = {Select(b, _v.x * inv_len, _safer.x),
Select(b, _v.y * inv_len, _safer.y)};
return r;
}
// Returns the linear interpolation of _a and _b with coefficient _f.
// _f is not limited to range [0,1].
OZZ_INLINE SoaFloat4 Lerp(const SoaFloat4& _a, const SoaFloat4& _b,
_SimdFloat4 _f) {
const SoaFloat4 r = {(_b.x - _a.x) * _f + _a.x, (_b.y - _a.y) * _f + _a.y,
(_b.z - _a.z) * _f + _a.z, (_b.w - _a.w) * _f + _a.w};
return r;
}
OZZ_INLINE SoaFloat3 Lerp(const SoaFloat3& _a, const SoaFloat3& _b,
_SimdFloat4 _f) {
const SoaFloat3 r = {(_b.x - _a.x) * _f + _a.x, (_b.y - _a.y) * _f + _a.y,
(_b.z - _a.z) * _f + _a.z};
return r;
}
OZZ_INLINE SoaFloat2 Lerp(const SoaFloat2& _a, const SoaFloat2& _b,
_SimdFloat4 _f) {
const SoaFloat2 r = {(_b.x - _a.x) * _f + _a.x, (_b.y - _a.y) * _f + _a.y};
return r;
}
// Returns the minimum of each element of _a and _b.
OZZ_INLINE SoaFloat4 Min(const SoaFloat4& _a, const SoaFloat4& _b) {
const SoaFloat4 r = {Min(_a.x, _b.x), Min(_a.y, _b.y), Min(_a.z, _b.z),
Min(_a.w, _b.w)};
return r;
}
OZZ_INLINE SoaFloat3 Min(const SoaFloat3& _a, const SoaFloat3& _b) {
const SoaFloat3 r = {Min(_a.x, _b.x), Min(_a.y, _b.y), Min(_a.z, _b.z)};
return r;
}
OZZ_INLINE SoaFloat2 Min(const SoaFloat2& _a, const SoaFloat2& _b) {
const SoaFloat2 r = {Min(_a.x, _b.x), Min(_a.y, _b.y)};
return r;
}
// Returns the maximum of each element of _a and _b.
OZZ_INLINE SoaFloat4 Max(const SoaFloat4& _a, const SoaFloat4& _b) {
const SoaFloat4 r = {Max(_a.x, _b.x), Max(_a.y, _b.y), Max(_a.z, _b.z),
Max(_a.w, _b.w)};
return r;
}
OZZ_INLINE SoaFloat3 Max(const SoaFloat3& _a, const SoaFloat3& _b) {
const SoaFloat3 r = {Max(_a.x, _b.x), Max(_a.y, _b.y), Max(_a.z, _b.z)};
return r;
}
OZZ_INLINE SoaFloat2 Max(const SoaFloat2& _a, const SoaFloat2& _b) {
const SoaFloat2 r = {Max(_a.x, _b.x), Max(_a.y, _b.y)};
return r;
}
// Clamps each element of _x between _a and _b.
// _a must be less or equal to b;
OZZ_INLINE SoaFloat4 Clamp(const SoaFloat4& _a, const SoaFloat4& _v,
const SoaFloat4& _b) {
return Max(_a, Min(_v, _b));
}
OZZ_INLINE SoaFloat3 Clamp(const SoaFloat3& _a, const SoaFloat3& _v,
const SoaFloat3& _b) {
return Max(_a, Min(_v, _b));
}
OZZ_INLINE SoaFloat2 Clamp(const SoaFloat2& _a, const SoaFloat2& _v,
const SoaFloat2& _b) {
return Max(_a, Min(_v, _b));
}
} // namespace math
} // namespace ozz
#endif // OZZ_OZZ_BASE_MATHS_SOA_FLOAT_H_
@@ -0,0 +1,276 @@
//----------------------------------------------------------------------------//
// //
// 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_BASE_MATHS_SOA_FLOAT4X4_H_
#define OZZ_OZZ_BASE_MATHS_SOA_FLOAT4X4_H_
#include <cassert>
#include "ozz/base/maths/soa_float.h"
#include "ozz/base/maths/soa_quaternion.h"
#include "ozz/base/platform.h"
namespace ozz {
namespace math {
// Declare the 4x4 soa matrix type. Uses the column major convention where the
// matrix-times-vector is written v'=Mv:
// [ m.cols[0].x m.cols[1].x m.cols[2].x m.cols[3].x ] {v.x}
// | m.cols[0].y m.cols[1].y m.cols[2].y m.cols[3].y | * {v.y}
// | m.cols[0].z m.cols[1].y m.cols[2].y m.cols[3].y | {v.z}
// [ m.cols[0].w m.cols[1].w m.cols[2].w m.cols[3].w ] {v.1}
struct SoaFloat4x4 {
// Soa matrix columns.
SoaFloat4 cols[4];
// Returns the identity matrix.
static OZZ_INLINE SoaFloat4x4 identity() {
const SimdFloat4 zero = simd_float4::zero();
const SimdFloat4 one = simd_float4::one();
SoaFloat4x4 ret = {{{one, zero, zero, zero},
{zero, one, zero, zero},
{zero, zero, one, zero},
{zero, zero, zero, one}}};
return ret;
}
// Returns a scaling matrix that scales along _v.
// _v.w is ignored.
static OZZ_INLINE SoaFloat4x4 Scaling(const SoaFloat4& _v) {
const SimdFloat4 zero = simd_float4::zero();
const SimdFloat4 one = simd_float4::one();
const SoaFloat4x4 ret = {{{_v.x, zero, zero, zero},
{zero, _v.y, zero, zero},
{zero, zero, _v.z, zero},
{zero, zero, zero, one}}};
return ret;
}
// Returns the rotation matrix built from quaternion defined by x, y, z and w
// components of _v.
static OZZ_INLINE SoaFloat4x4 FromQuaternion(const SoaQuaternion& _q) {
assert(AreAllTrue(IsNormalizedEst(_q)));
const SimdFloat4 zero = simd_float4::zero();
const SimdFloat4 one = simd_float4::one();
const SimdFloat4 two = one + one;
const SimdFloat4 xx = _q.x * _q.x;
const SimdFloat4 xy = _q.x * _q.y;
const SimdFloat4 xz = _q.x * _q.z;
const SimdFloat4 xw = _q.x * _q.w;
const SimdFloat4 yy = _q.y * _q.y;
const SimdFloat4 yz = _q.y * _q.z;
const SimdFloat4 yw = _q.y * _q.w;
const SimdFloat4 zz = _q.z * _q.z;
const SimdFloat4 zw = _q.z * _q.w;
const SoaFloat4x4 ret = {
{{one - two * (yy + zz), two * (xy + zw), two * (xz - yw), zero},
{two * (xy - zw), one - two * (xx + zz), two * (yz + xw), zero},
{two * (xz + yw), two * (yz - xw), one - two * (xx + yy), zero},
{zero, zero, zero, one}}};
return ret;
}
// Returns the affine transformation matrix built from split translation,
// rotation (quaternion) and scale.
static OZZ_INLINE SoaFloat4x4 FromAffine(const SoaFloat3& _translation,
const SoaQuaternion& _quaternion,
const SoaFloat3& _scale) {
assert(AreAllTrue(IsNormalizedEst(_quaternion)));
const SimdFloat4 zero = simd_float4::zero();
const SimdFloat4 one = simd_float4::one();
const SimdFloat4 two = one + one;
const SimdFloat4 xx = _quaternion.x * _quaternion.x;
const SimdFloat4 xy = _quaternion.x * _quaternion.y;
const SimdFloat4 xz = _quaternion.x * _quaternion.z;
const SimdFloat4 xw = _quaternion.x * _quaternion.w;
const SimdFloat4 yy = _quaternion.y * _quaternion.y;
const SimdFloat4 yz = _quaternion.y * _quaternion.z;
const SimdFloat4 yw = _quaternion.y * _quaternion.w;
const SimdFloat4 zz = _quaternion.z * _quaternion.z;
const SimdFloat4 zw = _quaternion.z * _quaternion.w;
const SoaFloat4x4 ret = {
{{_scale.x * (one - two * (yy + zz)), _scale.x * two * (xy + zw),
_scale.x * two * (xz - yw), zero},
{_scale.y * two * (xy - zw), _scale.y * (one - two * (xx + zz)),
_scale.y * two * (yz + xw), zero},
{_scale.z * two * (xz + yw), _scale.z * two * (yz - xw),
_scale.z * (one - two * (xx + yy)), zero},
{_translation.x, _translation.y, _translation.z, one}}};
return ret;
}
};
// Returns the transpose of matrix _m.
OZZ_INLINE SoaFloat4x4 Transpose(const SoaFloat4x4& _m) {
const SoaFloat4x4 ret = {
{{_m.cols[0].x, _m.cols[1].x, _m.cols[2].x, _m.cols[3].x},
{_m.cols[0].y, _m.cols[1].y, _m.cols[2].y, _m.cols[3].y},
{_m.cols[0].z, _m.cols[1].z, _m.cols[2].z, _m.cols[3].z},
{_m.cols[0].w, _m.cols[1].w, _m.cols[2].w, _m.cols[3].w}}};
return ret;
}
// Returns the inverse of matrix _m.
// If _invertible is not nullptr, each component will be set to true if its
// respective matrix is invertible. If _invertible is nullptr, then an assert is
// triggered in case any of the 4 matrices isn't invertible.
OZZ_INLINE SoaFloat4x4 Invert(const SoaFloat4x4& _m,
SimdInt4* _invertible = nullptr) {
const SoaFloat4* cols = _m.cols;
const SimdFloat4 a00 = cols[2].z * cols[3].w - cols[3].z * cols[2].w;
const SimdFloat4 a01 = cols[2].y * cols[3].w - cols[3].y * cols[2].w;
const SimdFloat4 a02 = cols[2].y * cols[3].z - cols[3].y * cols[2].z;
const SimdFloat4 a03 = cols[2].x * cols[3].w - cols[3].x * cols[2].w;
const SimdFloat4 a04 = cols[2].x * cols[3].z - cols[3].x * cols[2].z;
const SimdFloat4 a05 = cols[2].x * cols[3].y - cols[3].x * cols[2].y;
const SimdFloat4 a06 = cols[1].z * cols[3].w - cols[3].z * cols[1].w;
const SimdFloat4 a07 = cols[1].y * cols[3].w - cols[3].y * cols[1].w;
const SimdFloat4 a08 = cols[1].y * cols[3].z - cols[3].y * cols[1].z;
const SimdFloat4 a09 = cols[1].x * cols[3].w - cols[3].x * cols[1].w;
const SimdFloat4 a10 = cols[1].x * cols[3].z - cols[3].x * cols[1].z;
const SimdFloat4 a11 = cols[1].y * cols[3].w - cols[3].y * cols[1].w;
const SimdFloat4 a12 = cols[1].x * cols[3].y - cols[3].x * cols[1].y;
const SimdFloat4 a13 = cols[1].z * cols[2].w - cols[2].z * cols[1].w;
const SimdFloat4 a14 = cols[1].y * cols[2].w - cols[2].y * cols[1].w;
const SimdFloat4 a15 = cols[1].y * cols[2].z - cols[2].y * cols[1].z;
const SimdFloat4 a16 = cols[1].x * cols[2].w - cols[2].x * cols[1].w;
const SimdFloat4 a17 = cols[1].x * cols[2].z - cols[2].x * cols[1].z;
const SimdFloat4 a18 = cols[1].x * cols[2].y - cols[2].x * cols[1].y;
const SimdFloat4 b0x = cols[1].y * a00 - cols[1].z * a01 + cols[1].w * a02;
const SimdFloat4 b1x = -cols[1].x * a00 + cols[1].z * a03 - cols[1].w * a04;
const SimdFloat4 b2x = cols[1].x * a01 - cols[1].y * a03 + cols[1].w * a05;
const SimdFloat4 b3x = -cols[1].x * a02 + cols[1].y * a04 - cols[1].z * a05;
const SimdFloat4 b0y = -cols[0].y * a00 + cols[0].z * a01 - cols[0].w * a02;
const SimdFloat4 b1y = cols[0].x * a00 - cols[0].z * a03 + cols[0].w * a04;
const SimdFloat4 b2y = -cols[0].x * a01 + cols[0].y * a03 - cols[0].w * a05;
const SimdFloat4 b3y = cols[0].x * a02 - cols[0].y * a04 + cols[0].z * a05;
const SimdFloat4 b0z = cols[0].y * a06 - cols[0].z * a07 + cols[0].w * a08;
const SimdFloat4 b1z = -cols[0].x * a06 + cols[0].z * a09 - cols[0].w * a10;
const SimdFloat4 b2z = cols[0].x * a11 - cols[0].y * a09 + cols[0].w * a12;
const SimdFloat4 b3z = -cols[0].x * a08 + cols[0].y * a10 - cols[0].z * a12;
const SimdFloat4 b0w = -cols[0].y * a13 + cols[0].z * a14 - cols[0].w * a15;
const SimdFloat4 b1w = cols[0].x * a13 - cols[0].z * a16 + cols[0].w * a17;
const SimdFloat4 b2w = -cols[0].x * a14 + cols[0].y * a16 - cols[0].w * a18;
const SimdFloat4 b3w = cols[0].x * a15 - cols[0].y * a17 + cols[0].z * a18;
const SimdFloat4 det =
cols[0].x * b0x + cols[0].y * b1x + cols[0].z * b2x + cols[0].w * b3x;
const SimdInt4 invertible = CmpNe(det, simd_float4::zero());
assert((_invertible || AreAllTrue(invertible)) && "Matrix is not invertible");
if (_invertible != nullptr) {
*_invertible = invertible;
}
const SimdFloat4 inv_det =
Select(invertible, RcpEstNR(det), simd_float4::zero());
const SoaFloat4x4 ret = {
{{b0x * inv_det, b0y * inv_det, b0z * inv_det, b0w * inv_det},
{b1x * inv_det, b1y * inv_det, b1z * inv_det, b1w * inv_det},
{b2x * inv_det, b2y * inv_det, b2z * inv_det, b2w * inv_det},
{b3x * inv_det, b3y * inv_det, b3z * inv_det, b3w * inv_det}}};
return ret;
}
// Scales matrix _m along the axis defined by _v components.
// _v.w is ignored.
OZZ_INLINE SoaFloat4x4 Scale(const SoaFloat4x4& _m, const SoaFloat4& _v) {
const SoaFloat4x4 ret = {{{_m.cols[0].x * _v.x, _m.cols[0].y * _v.x,
_m.cols[0].z * _v.x, _m.cols[0].w * _v.x},
{_m.cols[1].x * _v.y, _m.cols[1].y * _v.y,
_m.cols[1].z * _v.y, _m.cols[1].w * _v.y},
{_m.cols[2].x * _v.z, _m.cols[2].y * _v.z,
_m.cols[2].z * _v.z, _m.cols[2].w * _v.z},
_m.cols[3]}};
return ret;
}
} // namespace math
} // namespace ozz
// Computes the multiplication of matrix Float4x4 and vector _v.
OZZ_INLINE ozz::math::SoaFloat4 operator*(const ozz::math::SoaFloat4x4& _m,
const ozz::math::SoaFloat4& _v) {
const ozz::math::SoaFloat4 ret = {
_m.cols[0].x * _v.x + _m.cols[1].x * _v.y + _m.cols[2].x * _v.z +
_m.cols[3].x * _v.w,
_m.cols[0].y * _v.x + _m.cols[1].y * _v.y + _m.cols[2].y * _v.z +
_m.cols[3].y * _v.w,
_m.cols[0].z * _v.x + _m.cols[1].z * _v.y + _m.cols[2].z * _v.z +
_m.cols[3].z * _v.w,
_m.cols[0].w * _v.x + _m.cols[1].w * _v.y + _m.cols[2].w * _v.z +
_m.cols[3].w * _v.w};
return ret;
}
// Computes the multiplication of two matrices _a and _b.
OZZ_INLINE ozz::math::SoaFloat4x4 operator*(const ozz::math::SoaFloat4x4& _a,
const ozz::math::SoaFloat4x4& _b) {
const ozz::math::SoaFloat4x4 ret = {
{_a * _b.cols[0], _a * _b.cols[1], _a * _b.cols[2], _a * _b.cols[3]}};
return ret;
}
// Computes the per element addition of two matrices _a and _b.
OZZ_INLINE ozz::math::SoaFloat4x4 operator+(const ozz::math::SoaFloat4x4& _a,
const ozz::math::SoaFloat4x4& _b) {
const ozz::math::SoaFloat4x4 ret = {
{{_a.cols[0].x + _b.cols[0].x, _a.cols[0].y + _b.cols[0].y,
_a.cols[0].z + _b.cols[0].z, _a.cols[0].w + _b.cols[0].w},
{_a.cols[1].x + _b.cols[1].x, _a.cols[1].y + _b.cols[1].y,
_a.cols[1].z + _b.cols[1].z, _a.cols[1].w + _b.cols[1].w},
{_a.cols[2].x + _b.cols[2].x, _a.cols[2].y + _b.cols[2].y,
_a.cols[2].z + _b.cols[2].z, _a.cols[2].w + _b.cols[2].w},
{_a.cols[3].x + _b.cols[3].x, _a.cols[3].y + _b.cols[3].y,
_a.cols[3].z + _b.cols[3].z, _a.cols[3].w + _b.cols[3].w}}};
return ret;
}
// Computes the per element subtraction of two matrices _a and _b.
OZZ_INLINE ozz::math::SoaFloat4x4 operator-(const ozz::math::SoaFloat4x4& _a,
const ozz::math::SoaFloat4x4& _b) {
const ozz::math::SoaFloat4x4 ret = {
{{_a.cols[0].x - _b.cols[0].x, _a.cols[0].y - _b.cols[0].y,
_a.cols[0].z - _b.cols[0].z, _a.cols[0].w - _b.cols[0].w},
{_a.cols[1].x - _b.cols[1].x, _a.cols[1].y - _b.cols[1].y,
_a.cols[1].z - _b.cols[1].z, _a.cols[1].w - _b.cols[1].w},
{_a.cols[2].x - _b.cols[2].x, _a.cols[2].y - _b.cols[2].y,
_a.cols[2].z - _b.cols[2].z, _a.cols[2].w - _b.cols[2].w},
{_a.cols[3].x - _b.cols[3].x, _a.cols[3].y - _b.cols[3].y,
_a.cols[3].z - _b.cols[3].z, _a.cols[3].w - _b.cols[3].w}}};
return ret;
}
#endif // OZZ_OZZ_BASE_MATHS_SOA_FLOAT4X4_H_
@@ -0,0 +1,99 @@
//----------------------------------------------------------------------------//
// //
// 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_BASE_MATHS_SOA_MATH_ARCHIVE_H_
#define OZZ_OZZ_BASE_MATHS_SOA_MATH_ARCHIVE_H_
#include "ozz/base/io/archive_traits.h"
#include "ozz/base/platform.h"
namespace ozz {
namespace math {
struct SoaFloat2;
struct SoaFloat3;
struct SoaFloat4;
struct SoaQuaternion;
struct SoaFloat4x4;
struct SoaTransform;
} // namespace math
namespace io {
OZZ_IO_TYPE_NOT_VERSIONABLE(math::SoaFloat2)
template <>
struct Extern<math::SoaFloat2> {
static void Save(OArchive& _archive, const math::SoaFloat2* _values,
size_t _count);
static void Load(IArchive& _archive, math::SoaFloat2* _values, size_t _count,
uint32_t _version);
};
OZZ_IO_TYPE_NOT_VERSIONABLE(math::SoaFloat3)
template <>
struct Extern<math::SoaFloat3> {
static void Save(OArchive& _archive, const math::SoaFloat3* _values,
size_t _count);
static void Load(IArchive& _archive, math::SoaFloat3* _values, size_t _count,
uint32_t _version);
};
OZZ_IO_TYPE_NOT_VERSIONABLE(math::SoaFloat4)
template <>
struct Extern<math::SoaFloat4> {
static void Save(OArchive& _archive, const math::SoaFloat4* _values,
size_t _count);
static void Load(IArchive& _archive, math::SoaFloat4* _values, size_t _count,
uint32_t _version);
};
OZZ_IO_TYPE_NOT_VERSIONABLE(math::SoaQuaternion)
template <>
struct Extern<math::SoaQuaternion> {
static void Save(OArchive& _archive, const math::SoaQuaternion* _values,
size_t _count);
static void Load(IArchive& _archive, math::SoaQuaternion* _values,
size_t _count, uint32_t _version);
};
OZZ_IO_TYPE_NOT_VERSIONABLE(math::SoaFloat4x4)
template <>
struct Extern<math::SoaFloat4x4> {
static void Save(OArchive& _archive, const math::SoaFloat4x4* _values,
size_t _count);
static void Load(IArchive& _archive, math::SoaFloat4x4* _values,
size_t _count, uint32_t _version);
};
OZZ_IO_TYPE_NOT_VERSIONABLE(math::SoaTransform)
template <>
struct Extern<math::SoaTransform> {
static void Save(OArchive& _archive, const math::SoaTransform* _values,
size_t _count);
static void Load(IArchive& _archive, math::SoaTransform* _values,
size_t _count, uint32_t _version);
};
} // namespace io
} // namespace ozz
#endif // OZZ_OZZ_BASE_MATHS_SOA_MATH_ARCHIVE_H_
@@ -0,0 +1,189 @@
//----------------------------------------------------------------------------//
// //
// 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_BASE_MATHS_SOA_QUATERNION_H_
#define OZZ_OZZ_BASE_MATHS_SOA_QUATERNION_H_
#include <cassert>
#include "ozz/base/maths/soa_float.h"
#include "ozz/base/platform.h"
namespace ozz {
namespace math {
struct SoaQuaternion {
SimdFloat4 x, y, z, w;
// Loads a quaternion from 4 SimdFloat4 values.
static OZZ_INLINE SoaQuaternion Load(_SimdFloat4 _x, _SimdFloat4 _y,
_SimdFloat4 _z, const SimdFloat4& _w) {
const SoaQuaternion r = {_x, _y, _z, _w};
return r;
}
// Returns the identity SoaQuaternion.
static OZZ_INLINE SoaQuaternion identity() {
const SimdFloat4 zero = simd_float4::zero();
const SoaQuaternion r = {zero, zero, zero, simd_float4::one()};
return r;
}
};
// Returns the conjugate of _q. This is the same as the inverse if _q is
// normalized. Otherwise the magnitude of the inverse is 1.f/|_q|.
OZZ_INLINE SoaQuaternion Conjugate(const SoaQuaternion& _q) {
const SoaQuaternion r = {-_q.x, -_q.y, -_q.z, _q.w};
return r;
}
// Returns the negate of _q. This represent the same rotation as q.
OZZ_INLINE SoaQuaternion operator-(const SoaQuaternion& _q) {
const SoaQuaternion r = {-_q.x, -_q.y, -_q.z, -_q.w};
return r;
}
// Returns the 4D dot product of quaternion _a and _b.
OZZ_INLINE SimdFloat4 Dot(const SoaQuaternion& _a, const SoaQuaternion& _b) {
return _a.x * _b.x + _a.y * _b.y + _a.z * _b.z + _a.w * _b.w;
}
// Returns the normalized SoaQuaternion _q.
OZZ_INLINE SoaQuaternion Normalize(const SoaQuaternion& _q) {
const SimdFloat4 len2 = _q.x * _q.x + _q.y * _q.y + _q.z * _q.z + _q.w * _q.w;
const SimdFloat4 inv_len = math::simd_float4::one() / Sqrt(len2);
const SoaQuaternion r = {_q.x * inv_len, _q.y * inv_len, _q.z * inv_len,
_q.w * inv_len};
return r;
}
// Returns the estimated normalized SoaQuaternion _q.
OZZ_INLINE SoaQuaternion NormalizeEst(const SoaQuaternion& _q) {
const SimdFloat4 len2 = _q.x * _q.x + _q.y * _q.y + _q.z * _q.z + _q.w * _q.w;
// Uses RSqrtEstNR (with one more Newton-Raphson step) as quaternions loose
// much precision due to normalization.
const SimdFloat4 inv_len = RSqrtEstNR(len2);
const SoaQuaternion r = {_q.x * inv_len, _q.y * inv_len, _q.z * inv_len,
_q.w * inv_len};
return r;
}
// Test if each quaternion of _q is normalized.
OZZ_INLINE SimdInt4 IsNormalized(const SoaQuaternion& _q) {
const SimdFloat4 len2 = _q.x * _q.x + _q.y * _q.y + _q.z * _q.z + _q.w * _q.w;
return CmpLt(Abs(len2 - math::simd_float4::one()),
simd_float4::Load1(kNormalizationToleranceSq));
}
// Test if each quaternion of _q is normalized. using estimated tolerance.
OZZ_INLINE SimdInt4 IsNormalizedEst(const SoaQuaternion& _q) {
const SimdFloat4 len2 = _q.x * _q.x + _q.y * _q.y + _q.z * _q.z + _q.w * _q.w;
return CmpLt(Abs(len2 - math::simd_float4::one()),
simd_float4::Load1(kNormalizationToleranceEstSq));
}
// Returns the linear interpolation of SoaQuaternion _a and _b with coefficient
// _f.
OZZ_INLINE SoaQuaternion Lerp(const SoaQuaternion& _a, const SoaQuaternion& _b,
_SimdFloat4 _f) {
const SoaQuaternion r = {(_b.x - _a.x) * _f + _a.x, (_b.y - _a.y) * _f + _a.y,
(_b.z - _a.z) * _f + _a.z,
(_b.w - _a.w) * _f + _a.w};
return r;
}
// Returns the linear interpolation of SoaQuaternion _a and _b with coefficient
// _f.
OZZ_INLINE SoaQuaternion NLerp(const SoaQuaternion& _a, const SoaQuaternion& _b,
_SimdFloat4 _f) {
const SoaFloat4 lerp = {(_b.x - _a.x) * _f + _a.x, (_b.y - _a.y) * _f + _a.y,
(_b.z - _a.z) * _f + _a.z, (_b.w - _a.w) * _f + _a.w};
const SimdFloat4 len2 =
lerp.x * lerp.x + lerp.y * lerp.y + lerp.z * lerp.z + lerp.w * lerp.w;
const SimdFloat4 inv_len = math::simd_float4::one() / Sqrt(len2);
const SoaQuaternion r = {lerp.x * inv_len, lerp.y * inv_len, lerp.z * inv_len,
lerp.w * inv_len};
return r;
}
// Returns the estimated linear interpolation of SoaQuaternion _a and _b with
// coefficient _f.
OZZ_INLINE SoaQuaternion NLerpEst(const SoaQuaternion& _a,
const SoaQuaternion& _b, _SimdFloat4 _f) {
const SoaFloat4 lerp = {(_b.x - _a.x) * _f + _a.x, (_b.y - _a.y) * _f + _a.y,
(_b.z - _a.z) * _f + _a.z, (_b.w - _a.w) * _f + _a.w};
const SimdFloat4 len2 =
lerp.x * lerp.x + lerp.y * lerp.y + lerp.z * lerp.z + lerp.w * lerp.w;
// Uses RSqrtEstNR (with one more Newton-Raphson step) as quaternions loose
// much precision due to normalization.
const SimdFloat4 inv_len = RSqrtEstNR(len2);
const SoaQuaternion r = {lerp.x * inv_len, lerp.y * inv_len, lerp.z * inv_len,
lerp.w * inv_len};
return r;
}
} // namespace math
} // namespace ozz
// Returns the addition of _a and _b.
OZZ_INLINE ozz::math::SoaQuaternion operator+(
const ozz::math::SoaQuaternion& _a, const ozz::math::SoaQuaternion& _b) {
const ozz::math::SoaQuaternion r = {_a.x + _b.x, _a.y + _b.y, _a.z + _b.z,
_a.w + _b.w};
return r;
}
// Returns the multiplication of _q and scalar value _f.
OZZ_INLINE ozz::math::SoaQuaternion operator*(
const ozz::math::SoaQuaternion& _q, const ozz::math::SimdFloat4& _f) {
const ozz::math::SoaQuaternion r = {_q.x * _f, _q.y * _f, _q.z * _f,
_q.w * _f};
return r;
}
// Returns the multiplication of _a and _b. If both _a and _b are normalized,
// then the result is normalized.
OZZ_INLINE ozz::math::SoaQuaternion operator*(
const ozz::math::SoaQuaternion& _a, const ozz::math::SoaQuaternion& _b) {
const ozz::math::SoaQuaternion r = {
_a.w * _b.x + _a.x * _b.w + _a.y * _b.z - _a.z * _b.y,
_a.w * _b.y + _a.y * _b.w + _a.z * _b.x - _a.x * _b.z,
_a.w * _b.z + _a.z * _b.w + _a.x * _b.y - _a.y * _b.x,
_a.w * _b.w - _a.x * _b.x - _a.y * _b.y - _a.z * _b.z};
return r;
}
// Returns true if each element of _a is equal to each element of _b.
// Uses a bitwise comparison of _a and _b, no tolerance is applied.
OZZ_INLINE ozz::math::SimdInt4 operator==(const ozz::math::SoaQuaternion& _a,
const ozz::math::SoaQuaternion& _b) {
const ozz::math::SimdInt4 x = ozz::math::CmpEq(_a.x, _b.x);
const ozz::math::SimdInt4 y = ozz::math::CmpEq(_a.y, _b.y);
const ozz::math::SimdInt4 z = ozz::math::CmpEq(_a.z, _b.z);
const ozz::math::SimdInt4 w = ozz::math::CmpEq(_a.w, _b.w);
return ozz::math::And(ozz::math::And(ozz::math::And(x, y), z), w);
}
#endif // OZZ_OZZ_BASE_MATHS_SOA_QUATERNION_H_
@@ -0,0 +1,53 @@
//----------------------------------------------------------------------------//
// //
// 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_BASE_MATHS_SOA_TRANSFORM_H_
#define OZZ_OZZ_BASE_MATHS_SOA_TRANSFORM_H_
#include "ozz/base/maths/soa_float.h"
#include "ozz/base/maths/soa_quaternion.h"
#include "ozz/base/platform.h"
namespace ozz {
namespace math {
// Stores an affine transformation with separate translation, rotation and scale
// attributes.
struct SoaTransform {
SoaFloat3 translation;
SoaQuaternion rotation;
SoaFloat3 scale;
static OZZ_INLINE SoaTransform identity() {
const SoaTransform ret = {SoaFloat3::zero(), SoaQuaternion::identity(),
SoaFloat3::one()};
return ret;
}
};
} // namespace math
} // namespace ozz
#endif // OZZ_OZZ_BASE_MATHS_SOA_TRANSFORM_H_
@@ -0,0 +1,59 @@
//----------------------------------------------------------------------------//
// //
// 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_BASE_MATHS_TRANSFORM_H_
#define OZZ_OZZ_BASE_MATHS_TRANSFORM_H_
#include "ozz/base/maths/quaternion.h"
#include "ozz/base/maths/vec_float.h"
#include "ozz/base/platform.h"
namespace ozz {
namespace math {
// Stores an affine transformation with separate translation, rotation and scale
// attributes.
struct Transform {
// Translation affine transformation component.
Float3 translation;
// Rotation affine transformation component.
Quaternion rotation;
// Scale affine transformation component.
Float3 scale;
// Builds an identity transform.
static OZZ_INLINE Transform identity() {
const Transform ret = {Float3::zero(), Quaternion::identity(),
Float3::one()};
return ret;
}
};
} // namespace math
} // namespace ozz
#endif // OZZ_OZZ_BASE_MATHS_TRANSFORM_H_
@@ -0,0 +1,467 @@
//----------------------------------------------------------------------------//
// //
// 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_BASE_MATHS_VEC_FLOAT_H_
#define OZZ_OZZ_BASE_MATHS_VEC_FLOAT_H_
#include <cassert>
#include <cmath>
#include "ozz/base/maths/math_constant.h"
#include "ozz/base/platform.h"
namespace ozz {
namespace math {
// Declares a 2d float vector.
struct Float2 {
float x, y;
// Constructs an uninitialized vector.
OZZ_INLINE Float2() {}
// Constructs a vector initialized with _f value.
explicit OZZ_INLINE Float2(float _f) : x(_f), y(_f) {}
// Constructs a vector initialized with _x and _y values.
OZZ_INLINE Float2(float _x, float _y) : x(_x), y(_y) {}
// Returns a vector with all components set to 0.
static OZZ_INLINE Float2 zero() { return Float2(0.f); }
// Returns a vector with all components set to 1.
static OZZ_INLINE Float2 one() { return Float2(1.f); }
// Returns a unitary vector x.
static OZZ_INLINE Float2 x_axis() { return Float2(1.f, 0.f); }
// Returns a unitary vector y.
static OZZ_INLINE Float2 y_axis() { return Float2(0.f, 1.f); }
};
// Declares a 3d float vector.
struct Float3 {
float x, y, z;
// Constructs an uninitialized vector.
OZZ_INLINE Float3() {}
// Constructs a vector initialized with _f value.
explicit OZZ_INLINE Float3(float _f) : x(_f), y(_f), z(_f) {}
// Constructs a vector initialized with _x, _y and _z values.
OZZ_INLINE Float3(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {}
// Returns a vector initialized with _v.x, _v.y and _z values.
OZZ_INLINE Float3(Float2 _v, float _z) : x(_v.x), y(_v.y), z(_z) {}
// Returns a vector with all components set to 0.
static OZZ_INLINE Float3 zero() { return Float3(0.f); }
// Returns a vector with all components set to 1.
static OZZ_INLINE Float3 one() { return Float3(1.f); }
// Returns a unitary vector x.
static OZZ_INLINE Float3 x_axis() { return Float3(1.f, 0.f, 0.f); }
// Returns a unitary vector y.
static OZZ_INLINE Float3 y_axis() { return Float3(0.f, 1.f, 0.f); }
// Returns a unitary vector z.
static OZZ_INLINE Float3 z_axis() { return Float3(0.f, 0.f, 1.f); }
};
// Declares a 4d float vector.
struct Float4 {
float x, y, z, w;
// Constructs an uninitialized vector.
OZZ_INLINE Float4() {}
// Constructs a vector initialized with _f value.
explicit OZZ_INLINE Float4(float _f) : x(_f), y(_f), z(_f), w(_f) {}
// Constructs a vector initialized with _x, _y, _z and _w values.
OZZ_INLINE Float4(float _x, float _y, float _z, float _w)
: x(_x), y(_y), z(_z), w(_w) {}
// Constructs a vector initialized with _v.x, _v.y, _v.z and _w values.
OZZ_INLINE Float4(Float3 _v, float _w) : x(_v.x), y(_v.y), z(_v.z), w(_w) {}
// Constructs a vector initialized with _v.x, _v.y, _z and _w values.
OZZ_INLINE Float4(Float2 _v, float _z, float _w)
: x(_v.x), y(_v.y), z(_z), w(_w) {}
// Returns a vector with all components set to 0.
static OZZ_INLINE Float4 zero() { return Float4(0.f); }
// Returns a vector with all components set to 1.
static OZZ_INLINE Float4 one() { return Float4(1.f); }
// Returns a unitary vector x.
static OZZ_INLINE Float4 x_axis() { return Float4(1.f, 0.f, 0.f, 0.f); }
// Returns a unitary vector y.
static OZZ_INLINE Float4 y_axis() { return Float4(0.f, 1.f, 0.f, 0.f); }
// Returns a unitary vector z.
static OZZ_INLINE Float4 z_axis() { return Float4(0.f, 0.f, 1.f, 0.f); }
// Returns a unitary vector w.
static OZZ_INLINE Float4 w_axis() { return Float4(0.f, 0.f, 0.f, 1.f); }
};
// Returns per element addition of _a and _b using operator +.
OZZ_INLINE Float4 operator+(const Float4& _a, const Float4& _b) {
return Float4(_a.x + _b.x, _a.y + _b.y, _a.z + _b.z, _a.w + _b.w);
}
OZZ_INLINE Float3 operator+(const Float3& _a, const Float3& _b) {
return Float3(_a.x + _b.x, _a.y + _b.y, _a.z + _b.z);
}
OZZ_INLINE Float2 operator+(const Float2& _a, const Float2& _b) {
return Float2(_a.x + _b.x, _a.y + _b.y);
}
// Returns per element subtraction of _a and _b using operator -.
OZZ_INLINE Float4 operator-(const Float4& _a, const Float4& _b) {
return Float4(_a.x - _b.x, _a.y - _b.y, _a.z - _b.z, _a.w - _b.w);
}
OZZ_INLINE Float3 operator-(const Float3& _a, const Float3& _b) {
return Float3(_a.x - _b.x, _a.y - _b.y, _a.z - _b.z);
}
OZZ_INLINE Float2 operator-(const Float2& _a, const Float2& _b) {
return Float2(_a.x - _b.x, _a.y - _b.y);
}
// Returns per element negative value of _v.
OZZ_INLINE Float4 operator-(const Float4& _v) {
return Float4(-_v.x, -_v.y, -_v.z, -_v.w);
}
OZZ_INLINE Float3 operator-(const Float3& _v) {
return Float3(-_v.x, -_v.y, -_v.z);
}
OZZ_INLINE Float2 operator-(const Float2& _v) { return Float2(-_v.x, -_v.y); }
// Returns per element multiplication of _a and _b using operator *.
OZZ_INLINE Float4 operator*(const Float4& _a, const Float4& _b) {
return Float4(_a.x * _b.x, _a.y * _b.y, _a.z * _b.z, _a.w * _b.w);
}
OZZ_INLINE Float3 operator*(const Float3& _a, const Float3& _b) {
return Float3(_a.x * _b.x, _a.y * _b.y, _a.z * _b.z);
}
OZZ_INLINE Float2 operator*(const Float2& _a, const Float2& _b) {
return Float2(_a.x * _b.x, _a.y * _b.y);
}
// Returns per element multiplication of _a and scalar value _f using
// operator *.
OZZ_INLINE Float4 operator*(const Float4& _a, float _f) {
return Float4(_a.x * _f, _a.y * _f, _a.z * _f, _a.w * _f);
}
OZZ_INLINE Float3 operator*(const Float3& _a, float _f) {
return Float3(_a.x * _f, _a.y * _f, _a.z * _f);
}
OZZ_INLINE Float2 operator*(const Float2& _a, float _f) {
return Float2(_a.x * _f, _a.y * _f);
}
// Returns per element division of _a and _b using operator /.
OZZ_INLINE Float4 operator/(const Float4& _a, const Float4& _b) {
return Float4(_a.x / _b.x, _a.y / _b.y, _a.z / _b.z, _a.w / _b.w);
}
OZZ_INLINE Float3 operator/(const Float3& _a, const Float3& _b) {
return Float3(_a.x / _b.x, _a.y / _b.y, _a.z / _b.z);
}
OZZ_INLINE Float2 operator/(const Float2& _a, const Float2& _b) {
return Float2(_a.x / _b.x, _a.y / _b.y);
}
// Returns per element division of _a and scalar value _f using operator/.
OZZ_INLINE Float4 operator/(const Float4& _a, float _f) {
return Float4(_a.x / _f, _a.y / _f, _a.z / _f, _a.w / _f);
}
OZZ_INLINE Float3 operator/(const Float3& _a, float _f) {
return Float3(_a.x / _f, _a.y / _f, _a.z / _f);
}
OZZ_INLINE Float2 operator/(const Float2& _a, float _f) {
return Float2(_a.x / _f, _a.y / _f);
}
// Returns the (horizontal) addition of each element of _v.
OZZ_INLINE float HAdd(const Float4& _v) { return _v.x + _v.y + _v.z + _v.w; }
OZZ_INLINE float HAdd(const Float3& _v) { return _v.x + _v.y + _v.z; }
OZZ_INLINE float HAdd(const Float2& _v) { return _v.x + _v.y; }
// Returns the dot product of _a and _b.
OZZ_INLINE float Dot(const Float4& _a, const Float4& _b) {
return _a.x * _b.x + _a.y * _b.y + _a.z * _b.z + _a.w * _b.w;
}
OZZ_INLINE float Dot(const Float3& _a, const Float3& _b) {
return _a.x * _b.x + _a.y * _b.y + _a.z * _b.z;
}
OZZ_INLINE float Dot(const Float2& _a, const Float2& _b) {
return _a.x * _b.x + _a.y * _b.y;
}
// Returns the cross product of _a and _b.
OZZ_INLINE Float3 Cross(const Float3& _a, const Float3& _b) {
return Float3(_a.y * _b.z - _b.y * _a.z, _a.z * _b.x - _b.z * _a.x,
_a.x * _b.y - _b.x * _a.y);
}
// Returns the length |_v| of _v.
OZZ_INLINE float Length(const Float4& _v) {
const float len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z + _v.w * _v.w;
return std::sqrt(len2);
}
OZZ_INLINE float Length(const Float3& _v) {
const float len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z;
return std::sqrt(len2);
}
OZZ_INLINE float Length(const Float2& _v) {
const float len2 = _v.x * _v.x + _v.y * _v.y;
return std::sqrt(len2);
}
// Returns the square length |_v|^2 of _v.
OZZ_INLINE float LengthSqr(const Float4& _v) {
return _v.x * _v.x + _v.y * _v.y + _v.z * _v.z + _v.w * _v.w;
}
OZZ_INLINE float LengthSqr(const Float3& _v) {
return _v.x * _v.x + _v.y * _v.y + _v.z * _v.z;
}
OZZ_INLINE float LengthSqr(const Float2& _v) {
return _v.x * _v.x + _v.y * _v.y;
}
// Returns the normalized vector _v.
OZZ_INLINE Float4 Normalize(const Float4& _v) {
const float len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z + _v.w * _v.w;
assert(len2 != 0.f && "_v is not normalizable");
const float len = std::sqrt(len2);
return Float4(_v.x / len, _v.y / len, _v.z / len, _v.w / len);
}
OZZ_INLINE Float3 Normalize(const Float3& _v) {
const float len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z;
assert(len2 != 0.f && "_v is not normalizable");
const float len = std::sqrt(len2);
return Float3(_v.x / len, _v.y / len, _v.z / len);
}
OZZ_INLINE Float2 Normalize(const Float2& _v) {
const float len2 = _v.x * _v.x + _v.y * _v.y;
assert(len2 != 0.f && "_v is not normalizable");
const float len = std::sqrt(len2);
return Float2(_v.x / len, _v.y / len);
}
// Returns true if _v is normalized.
OZZ_INLINE bool IsNormalized(const Float4& _v) {
const float len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z + _v.w * _v.w;
return std::abs(len2 - 1.f) < kNormalizationToleranceSq;
}
OZZ_INLINE bool IsNormalized(const Float3& _v) {
const float len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z;
return std::abs(len2 - 1.f) < kNormalizationToleranceSq;
}
OZZ_INLINE bool IsNormalized(const Float2& _v) {
const float len2 = _v.x * _v.x + _v.y * _v.y;
return std::abs(len2 - 1.f) < kNormalizationToleranceSq;
}
// Returns the normalized vector _v if the norm of _v is not 0.
// Otherwise returns _safer.
OZZ_INLINE Float4 NormalizeSafe(const Float4& _v, const Float4& _safer) {
assert(IsNormalized(_safer) && "_safer is not normalized");
const float len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z + _v.w * _v.w;
if (len2 <= 0.f) {
return _safer;
}
const float len = std::sqrt(len2);
return Float4(_v.x / len, _v.y / len, _v.z / len, _v.w / len);
}
OZZ_INLINE Float3 NormalizeSafe(const Float3& _v, const Float3& _safer) {
assert(IsNormalized(_safer) && "_safer is not normalized");
const float len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z;
if (len2 <= 0.f) {
return _safer;
}
const float len = std::sqrt(len2);
return Float3(_v.x / len, _v.y / len, _v.z / len);
}
OZZ_INLINE Float2 NormalizeSafe(const Float2& _v, const Float2& _safer) {
assert(IsNormalized(_safer) && "_safer is not normalized");
const float len2 = _v.x * _v.x + _v.y * _v.y;
if (len2 <= 0.f) {
return _safer;
}
const float len = std::sqrt(len2);
return Float2(_v.x / len, _v.y / len);
}
// Returns the linear interpolation of _a and _b with coefficient _f.
// _f is not limited to range [0,1].
OZZ_INLINE Float4 Lerp(const Float4& _a, const Float4& _b, float _f) {
return Float4((_b.x - _a.x) * _f + _a.x, (_b.y - _a.y) * _f + _a.y,
(_b.z - _a.z) * _f + _a.z, (_b.w - _a.w) * _f + _a.w);
}
OZZ_INLINE Float3 Lerp(const Float3& _a, const Float3& _b, float _f) {
return Float3((_b.x - _a.x) * _f + _a.x, (_b.y - _a.y) * _f + _a.y,
(_b.z - _a.z) * _f + _a.z);
}
OZZ_INLINE Float2 Lerp(const Float2& _a, const Float2& _b, float _f) {
return Float2((_b.x - _a.x) * _f + _a.x, (_b.y - _a.y) * _f + _a.y);
}
// Returns true if the distance between _a and _b is less than _tolerance.
OZZ_INLINE bool Compare(const Float4& _a, const Float4& _b, float _tolerance) {
const math::Float4 diff = _a - _b;
return Dot(diff, diff) <= _tolerance * _tolerance;
}
OZZ_INLINE bool Compare(const Float3& _a, const Float3& _b, float _tolerance) {
const math::Float3 diff = _a - _b;
return Dot(diff, diff) <= _tolerance * _tolerance;
}
OZZ_INLINE bool Compare(const Float2& _a, const Float2& _b, float _tolerance) {
const math::Float2 diff = _a - _b;
return Dot(diff, diff) <= _tolerance * _tolerance;
}
// Returns true if each element of a is less than each element of _b.
OZZ_INLINE bool operator<(const Float4& _a, const Float4& _b) {
return _a.x < _b.x && _a.y < _b.y && _a.z < _b.z && _a.w < _b.w;
}
OZZ_INLINE bool operator<(const Float3& _a, const Float3& _b) {
return _a.x < _b.x && _a.y < _b.y && _a.z < _b.z;
}
OZZ_INLINE bool operator<(const Float2& _a, const Float2& _b) {
return _a.x < _b.x && _a.y < _b.y;
}
// Returns true if each element of a is less or equal to each element of _b.
OZZ_INLINE bool operator<=(const Float4& _a, const Float4& _b) {
return _a.x <= _b.x && _a.y <= _b.y && _a.z <= _b.z && _a.w <= _b.w;
}
OZZ_INLINE bool operator<=(const Float3& _a, const Float3& _b) {
return _a.x <= _b.x && _a.y <= _b.y && _a.z <= _b.z;
}
OZZ_INLINE bool operator<=(const Float2& _a, const Float2& _b) {
return _a.x <= _b.x && _a.y <= _b.y;
}
// Returns true if each element of a is greater than each element of _b.
OZZ_INLINE bool operator>(const Float4& _a, const Float4& _b) {
return _a.x > _b.x && _a.y > _b.y && _a.z > _b.z && _a.w > _b.w;
}
OZZ_INLINE bool operator>(const Float3& _a, const Float3& _b) {
return _a.x > _b.x && _a.y > _b.y && _a.z > _b.z;
}
OZZ_INLINE bool operator>(const Float2& _a, const Float2& _b) {
return _a.x > _b.x && _a.y > _b.y;
}
// Returns true if each element of a is greater or equal to each element of _b.
OZZ_INLINE bool operator>=(const Float4& _a, const Float4& _b) {
return _a.x >= _b.x && _a.y >= _b.y && _a.z >= _b.z && _a.w >= _b.w;
}
OZZ_INLINE bool operator>=(const Float3& _a, const Float3& _b) {
return _a.x >= _b.x && _a.y >= _b.y && _a.z >= _b.z;
}
OZZ_INLINE bool operator>=(const Float2& _a, const Float2& _b) {
return _a.x >= _b.x && _a.y >= _b.y;
}
// Returns true if each element of a is equal to each element of _b.
// Uses a bitwise comparison of _a and _b, no tolerance is applied.
OZZ_INLINE bool operator==(const Float4& _a, const Float4& _b) {
return _a.x == _b.x && _a.y == _b.y && _a.z == _b.z && _a.w == _b.w;
}
OZZ_INLINE bool operator==(const Float3& _a, const Float3& _b) {
return _a.x == _b.x && _a.y == _b.y && _a.z == _b.z;
}
OZZ_INLINE bool operator==(const Float2& _a, const Float2& _b) {
return _a.x == _b.x && _a.y == _b.y;
}
// Returns true if each element of a is different from each element of _b.
// Uses a bitwise comparison of _a and _b, no tolerance is applied.
OZZ_INLINE bool operator!=(const Float4& _a, const Float4& _b) {
return _a.x != _b.x || _a.y != _b.y || _a.z != _b.z || _a.w != _b.w;
}
OZZ_INLINE bool operator!=(const Float3& _a, const Float3& _b) {
return _a.x != _b.x || _a.y != _b.y || _a.z != _b.z;
}
OZZ_INLINE bool operator!=(const Float2& _a, const Float2& _b) {
return _a.x != _b.x || _a.y != _b.y;
}
// Returns the minimum of each element of _a and _b.
OZZ_INLINE Float4 Min(const Float4& _a, const Float4& _b) {
return Float4(_a.x < _b.x ? _a.x : _b.x, _a.y < _b.y ? _a.y : _b.y,
_a.z < _b.z ? _a.z : _b.z, _a.w < _b.w ? _a.w : _b.w);
}
OZZ_INLINE Float3 Min(const Float3& _a, const Float3& _b) {
return Float3(_a.x < _b.x ? _a.x : _b.x, _a.y < _b.y ? _a.y : _b.y,
_a.z < _b.z ? _a.z : _b.z);
}
OZZ_INLINE Float2 Min(const Float2& _a, const Float2& _b) {
return Float2(_a.x < _b.x ? _a.x : _b.x, _a.y < _b.y ? _a.y : _b.y);
}
// Returns the maximum of each element of _a and _b.
OZZ_INLINE Float4 Max(const Float4& _a, const Float4& _b) {
return Float4(_a.x > _b.x ? _a.x : _b.x, _a.y > _b.y ? _a.y : _b.y,
_a.z > _b.z ? _a.z : _b.z, _a.w > _b.w ? _a.w : _b.w);
}
OZZ_INLINE Float3 Max(const Float3& _a, const Float3& _b) {
return Float3(_a.x > _b.x ? _a.x : _b.x, _a.y > _b.y ? _a.y : _b.y,
_a.z > _b.z ? _a.z : _b.z);
}
OZZ_INLINE Float2 Max(const Float2& _a, const Float2& _b) {
return Float2(_a.x > _b.x ? _a.x : _b.x, _a.y > _b.y ? _a.y : _b.y);
}
// Clamps each element of _x between _a and _b.
// _a must be less or equal to b;
OZZ_INLINE Float4 Clamp(const Float4& _a, const Float4& _v, const Float4& _b) {
const Float4 min(_v.x < _b.x ? _v.x : _b.x, _v.y < _b.y ? _v.y : _b.y,
_v.z < _b.z ? _v.z : _b.z, _v.w < _b.w ? _v.w : _b.w);
return Float4(_a.x > min.x ? _a.x : min.x, _a.y > min.y ? _a.y : min.y,
_a.z > min.z ? _a.z : min.z, _a.w > min.w ? _a.w : min.w);
}
OZZ_INLINE Float3 Clamp(const Float3& _a, const Float3& _v, const Float3& _b) {
const Float3 min(_v.x < _b.x ? _v.x : _b.x, _v.y < _b.y ? _v.y : _b.y,
_v.z < _b.z ? _v.z : _b.z);
return Float3(_a.x > min.x ? _a.x : min.x, _a.y > min.y ? _a.y : min.y,
_a.z > min.z ? _a.z : min.z);
}
OZZ_INLINE Float2 Clamp(const Float2& _a, const Float2& _v, const Float2& _b) {
const Float2 min(_v.x < _b.x ? _v.x : _b.x, _v.y < _b.y ? _v.y : _b.y);
return Float2(_a.x > min.x ? _a.x : min.x, _a.y > min.y ? _a.y : min.y);
}
} // namespace math
} // namespace ozz
#endif // OZZ_OZZ_BASE_MATHS_VEC_FLOAT_H_
@@ -0,0 +1,99 @@
//----------------------------------------------------------------------------//
// //
// 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_BASE_MEMORY_ALLOCATOR_H_
#define OZZ_OZZ_BASE_MEMORY_ALLOCATOR_H_
#include <cstddef>
#include <new>
#include <utility>
#include "ozz/base/platform.h"
namespace ozz {
namespace memory {
// Forwards declare Allocator class.
class Allocator;
// Defines the default allocator accessor.
Allocator* default_allocator();
// Set the default allocator, used for all dynamic allocation inside ozz.
// Returns current memory allocator, such that in can be restored if needed.
Allocator* SetDefaulAllocator(Allocator* _allocator);
// Defines an abstract allocator class.
// Implements helper methods to allocate/deallocate POD typed objects instead of
// raw memory.
// Implements New and Delete function to allocate C++ objects, as a replacement
// of new and delete operators.
class Allocator {
public:
// Default virtual destructor.
virtual ~Allocator() {}
// Next functions are the pure virtual functions that must be implemented by
// allocator concrete classes.
// Allocates _size bytes on the specified _alignment boundaries.
// Allocate function conforms with standard malloc function specifications.
virtual void* Allocate(size_t _size, size_t _alignment) = 0;
// Frees a block that was allocated with Allocate or Reallocate.
// Argument _block can be nullptr.
// Deallocate function conforms with standard free function specifications.
virtual void Deallocate(void* _block) = 0;
};
} // namespace memory
// ozz replacement for c++ operator new with, used to allocate with an
// ozz::memory::Allocator. Delete must be used to deallocate such object.
// It can be used for constructor with no argument:
// Type* object = New<Type>();
// or any number of argument:
// Type* object = New<Type>(1,2,3,4);
template <typename _Ty, typename... _Args>
_Ty* New(_Args&&... _args) {
void* alloc =
memory::default_allocator()->Allocate(sizeof(_Ty), alignof(_Ty));
return new (alloc) _Ty(std::forward<_Args>(_args)...);
}
template <typename _Ty>
void Delete(_Ty* _object) {
if (_object) {
// Prevents from false "unreferenced parameter" warning when _Ty has no
// explicit destructor.
(void)_object;
_object->~_Ty();
memory::default_allocator()->Deallocate(_object);
}
}
} // namespace ozz
#endif // OZZ_OZZ_BASE_MEMORY_ALLOCATOR_H_
@@ -0,0 +1,61 @@
//----------------------------------------------------------------------------//
// //
// 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_BASE_MEMORY_UNIQUE_PTR_H_
#define OZZ_OZZ_BASE_MEMORY_UNIQUE_PTR_H_
#include "ozz/base/memory/allocator.h"
#include <memory>
#include <utility>
namespace ozz {
// Defaut deleter for ozz unique_ptr, uses redirected memory allocator.
template <typename _Ty>
struct Deleter {
Deleter() {}
template <class _Up>
Deleter(const Deleter<_Up>&, _Ty* = nullptr) {}
void operator()(_Ty* _ptr) const {
ozz::Delete(_ptr);
}
};
// Defines ozz::unique_ptr to use ozz default deleter.
template <typename _Ty, typename _Deleter = ozz::Deleter<_Ty>>
using unique_ptr = std::unique_ptr<_Ty, _Deleter>;
// Implements make_unique to use ozz redirected memory allocator.
template <typename _Ty, typename... _Args>
unique_ptr<_Ty> make_unique(_Args&&... _args) {
return unique_ptr<_Ty>(New<_Ty>(std::forward<_Args>(_args)...));
}
} // namespace ozz
#endif // OZZ_OZZ_BASE_MEMORY_UNIQUE_PTR_H_
+114
View File
@@ -0,0 +1,114 @@
//----------------------------------------------------------------------------//
// //
// 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_BASE_PLATFORM_H_
#define OZZ_OZZ_BASE_PLATFORM_H_
// Ensures compiler supports c++11 language standards, to help user understand
// compilation error in case it's not supported.
// Unfortunately MSVC doesn't update __cplusplus, so test compiler version
// instead.
#if !((__cplusplus >= 201103L) || (_MSC_VER >= 1900))
#error "ozz-animation requires c++11 language standards."
#endif // __cplusplus
#include <stdint.h>
#include <cassert>
#include <cstddef>
namespace ozz {
// Finds the number of elements of a statically allocated array.
#define OZZ_ARRAY_SIZE(_array) (sizeof(_array) / sizeof(_array[0]))
// Instructs the compiler to try to inline a function, regardless cost/benefit
// compiler analysis.
// Syntax is: "OZZ_INLINE void function();"
#if defined(_MSC_VER)
#define OZZ_INLINE __forceinline
#else
#define OZZ_INLINE inline __attribute__((always_inline))
#endif
// Tells the compiler to never inline a function.
// Syntax is: "OZZ_NO_INLINE void function();"
#if defined(_MSC_VER)
#define OZZ_NOINLINE __declspec(noinline)
#else
#define OZZ_NOINLINE __attribute__((noinline))
#endif
// Tells the compiler that the memory addressed by the restrict -qualified
// pointer is not aliased, aka no other pointer will access that same memory.
// Syntax is: void function(int* OZZ_RESTRICT _p);"
#define OZZ_RESTRICT __restrict
// Defines macro to help with DEBUG/NDEBUG syntax.
#if defined(NDEBUG)
#define OZZ_IF_DEBUG(...)
#define OZZ_IF_NDEBUG(...) __VA_ARGS__
#else // NDEBUG
#define OZZ_IF_DEBUG(...) __VA_ARGS__
#define OZZ_IF_NDEBUG(...)
#endif // NDEBUG
// Case sensitive wildcard string matching:
// - a ? sign matches any character, except an empty string.
// - a * sign matches any string, including an empty string.
bool strmatch(const char* _str, const char* _pattern);
// Tests whether _block is aligned to _alignment boundary.
template <typename _Ty>
OZZ_INLINE bool IsAligned(_Ty _value, size_t _alignment) {
return (_value & (_alignment - 1)) == 0;
}
template <typename _Ty>
OZZ_INLINE bool IsAligned(_Ty* _address, size_t _alignment) {
return (reinterpret_cast<uintptr_t>(_address) & (_alignment - 1)) == 0;
}
// Aligns _block address to the first greater address that is aligned to
// _alignment boundaries.
template <typename _Ty>
OZZ_INLINE _Ty Align(_Ty _value, size_t _alignment) {
return static_cast<_Ty>(_value + (_alignment - 1)) & (0 - _alignment);
}
template <typename _Ty>
OZZ_INLINE _Ty* Align(_Ty* _address, size_t _alignment) {
return reinterpret_cast<_Ty*>(
(reinterpret_cast<uintptr_t>(_address) + (_alignment - 1)) &
(0 - _alignment));
}
// Offset a pointer from a given number of bytes.
template <typename _Ty>
_Ty* PointerStride(_Ty* _ty, size_t _stride) {
return reinterpret_cast<_Ty*>(reinterpret_cast<uintptr_t>(_ty) + _stride);
}
} // namespace ozz
#endif // OZZ_OZZ_BASE_PLATFORM_H_
+171
View File
@@ -0,0 +1,171 @@
//----------------------------------------------------------------------------//
// //
// 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_BASE_SPAN_H_
#define OZZ_OZZ_BASE_SPAN_H_
#include "ozz/base/platform.h"
namespace ozz {
// Defines a range [begin,end[ of objects ot type _Ty.
template <typename _Ty>
struct span {
// Constants and types
using element_type = _Ty;
using value_type = _Ty;
using index_type = size_t;
using difference_type = ptrdiff_t;
using pointer = _Ty*;
using const_pointer = const _Ty*;
using reference = _Ty&;
using const_reference = const _Ty&;
// Iterators
using iterator = pointer;
using const_iterator = const_pointer;
// Default constructor initializes range to empty.
span() : data_(nullptr), size_(0) {}
// Constructs a range from its extreme values.
span(_Ty* _begin, _Ty* _end) : data_(_begin), size_(static_cast<size_t>(_end - _begin)) {
assert(_begin <= _end && "Invalid range.");
}
// Construct a range from a pointer to a buffer and its size, ie its number of
// elements.
span(_Ty* _begin, size_t _size) : data_(_begin), size_(_size) {}
// Copy operator.
void operator=(const span& _other) {
data_ = _other.data_;
size_ = _other.size_;
}
// Construct a range from a single element.
explicit span(_Ty& _element) : data_(&_element), size_(1) {}
// Construct a range from an array, its size is automatically deduced.
// It isn't declared explicit as conversion is free and safe.
template <size_t _size>
span(_Ty (&_array)[_size]) : data_(_array), size_(_size) {}
// Reinitialized from an array, its size is automatically deduced.
template <size_t _size>
void operator=(_Ty (&_array)[_size]) {
data_ = _array;
size_ = _size;
}
// Implement cast operator to allow conversions to span<const _Ty>.
operator span<const _Ty>() const { return span<const _Ty>(data_, size_); }
// Returns a const reference to element _i of range [begin,end[.
_Ty& operator[](size_t _i) const {
assert(_i < size_ && "Index out of range.");
return data_[_i];
}
bool empty() const { return size_ == 0; }
// Complies with other contiguous containers.
_Ty* data() const { return data_; }
// Gets the number of elements of the range.
// This size isn't stored but computed from begin and end pointers.
size_t size() const { return size_; }
// Gets the size in byte of the range.
size_t size_bytes() const { return size_ * sizeof(element_type); }
// Iterator support
iterator begin() const { return data_; }
iterator end() const { return data_ + size_; }
private:
// span begin pointer.
_Ty* data_;
// span end pointer, should never be dereferenced.
size_t size_;
};
// Returns a span from an array.
template <typename _Ty, size_t _Size>
inline span<_Ty> make_span(_Ty (&_arr)[_Size]) {
return {_arr};
}
// Returns a mutable span from a container.
template <typename _Container>
inline span<typename _Container::value_type> make_span(_Container& _container) {
return {_container.data(), _container.size()};
}
// Returns a non mutable span from a container.
template <typename _Container>
inline span<const typename _Container::value_type> make_span(
const _Container& _container) {
return {_container.data(), _container.size()};
}
// As bytes
template <typename _Ty>
inline span<const char> as_bytes(const span<_Ty>& _span) {
return {reinterpret_cast<const char*>(_span.data()), _span.size_bytes()};
}
template <typename _Ty>
inline span<char> as_writable_bytes(const span<_Ty>& _span) {
// Compilation will fail here if _Ty is const. This prevents from writing to
// const data.
return {reinterpret_cast<char*>(_span.data()), _span.size_bytes()};
}
template <>
inline span<const char> as_bytes(const span<char>& _span) {
return _span;
}
template <>
inline span<char> as_writable_bytes(const span<char>& _span) {
return _span;
}
// Fills a typed span from a byte source span. Source byte span is modified to
// reflect remain size.
template <typename _Ty>
inline span<_Ty> fill_span(span<char>& _src, size_t _count) {
assert(ozz::IsAligned(_src.data(), alignof(_Ty)) && "Invalid alignment.");
const span<_Ty> ret = {reinterpret_cast<_Ty*>(_src.data()), _count};
// Validity assertion is done by span constructor.
_src = {reinterpret_cast<char*>(ret.end()), _src.end()};
return ret;
}
} // namespace ozz
#endif // OZZ_OZZ_BASE_SPAN_H_
@@ -0,0 +1,184 @@
//----------------------------------------------------------------------------//
// //
// 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_GEOMETRY_RUNTIME_SKINNING_JOB_H_
#define OZZ_OZZ_GEOMETRY_RUNTIME_SKINNING_JOB_H_
#include "ozz/base/platform.h"
#include "ozz/base/span.h"
namespace ozz {
namespace math {
struct Float4x4;
}
namespace geometry {
// Provides per-vertex matrix palette skinning job implementation.
// Skinning is the process of creating the association of skeleton joints with
// some vertices of a mesh. Portions of the mesh's skin can normally be
// associated with multiple joints, each one having a weight. The sum of the
// weights for a vertex is equal to 1. To calculate the final position of the
// vertex, each joint transformation is applied to the vertex position, scaled
// by its corresponding weight. This algorithm is called matrix palette skinning
// because of the set of joint transformations (stored as transform matrices)
// form a palette for the skin vertex to choose from.
//
// This job iterates and transforms vertices (points and vectors) provided as
// input using the matrix palette skinning algorithm. The implementation
// supports any number of joints influences per vertex, and can transform one
// point (vertex position) and two vectors (vertex normal and tangent) per loop
// (aka vertex). It assumes bi-normals aren't needed as they can be rebuilt
// from the normal and tangent with a lower cost than skinning (a single cross
// product).
// Input and output buffers must be provided with a stride value (aka the
// number of bytes from a vertex to the next). This allows the job to support
// vertices packed as array-of-structs (array of vertices with positions,
// normals...) or struct-of-arrays (buffers of points, buffer of normals...).
// The skinning job optimizes every code path at maximum. The loop is indeed not
// the same depending on the number of joints influencing a vertex (or if there
// are normals to transform). To maximize performances, application should
// partition its vertices based on their number of joints influences, and call
// a different job for every vertices set.
// Joint matrices are accessed using the per-vertex joints indices provided as
// input. These matrices must be pre-multiplied with the inverse of the skeleton
// bind-pose matrices. This allows to transform vertices to joints local space.
// In case of non-uniform-scale matrices, the job proposes to transform vectors
// using an optional set of matrices, whose are usually inverse transpose of
// joints matrices (see http://www.glprogramming.com/red/appendixf.html). This
// code path is less efficient than the one without this matrices set, and
// should only be used when input matrices have non uniform scaling or shearing.
// The job does not owned the buffers (in/output) and will thus not delete them
// during job's destruction.
struct SkinningJob {
// Default constructor, initializes default values.
SkinningJob();
// Validates job parameters.
// Returns true for a valid job, false otherwise:
// - if any range is invalid. See each range description.
// - if normals are provided but positions aren't.
// - if tangents are provided but normals aren't.
// - if no output is provided while an input is. For example, if input normals
// are provided, then output normals must also.
bool Validate() const;
// Runs job's skinning task.
// The job is validated before any operation is performed, see Validate() for
// more details.
// Returns false if *this job is not valid.
bool Run() const;
// Number of vertices to transform. All input and output arrays must store at
// least this number of vertices.
int vertex_count;
// Maximum number of joints influencing each vertex. Must be greater than 0.
// The number of influences drives how joint_indices and joint_weights are
// sampled:
// - influences_count joint indices are red from joint_indices for each
// vertex.
// - influences_count - 1 joint weights are red from joint_weightrs for each
// vertex. The weight of the last joint is restored (weights are normalized).
int influences_count;
// Array of matrices for each joint. Joint are indexed through indices array.
span<const math::Float4x4> joint_matrices;
// Optional array of inverse transposed matrices for each joint. If provided,
// this array is used to transform vectors (normals and tangents), otherwise
// joint_matrices array is used.
// As explained here (http://www.glprogramming.com/red/appendixf.html) in the,
// red book, transforming normals requires a special attention when the
// transformation matrix has scaling or shearing. In this case the right
// transformation is done by the inverse transpose of the transformation that
// transforms points. Any rotation matrix is good though.
// These matrices are optional as they might by costly to compute, and also
// fall into a more costly code path in the skinning algorithm.
span<const math::Float4x4> joint_inverse_transpose_matrices;
// Array of joints indices. This array is used to indexes matrices in joints
// array.
// Each vertex has influences_max number of indices, meaning that the size of
// this array must be at least influences_max * vertex_count.
span<const uint16_t> joint_indices;
size_t joint_indices_stride;
// Array of joints weights. This array is used to associate a weight to every
// joint that influences a vertex. The number of weights required per vertex
// is "influences_max - 1". The weight for the last joint (for each vertex) is
// restored at runtime thanks to the fact that the sum of the weights for each
// vertex is 1.
// Each vertex has (influences_max - 1) number of weights, meaning that the
// size of this array must be at least (influences_max - 1)* vertex_count.
span<const float> joint_weights;
size_t joint_weights_stride;
// Input vertex positions array (3 float values per vertex) and stride (number
// of bytes between each position).
// Array length must be at least vertex_count * in_positions_stride.
span<const float> in_positions;
size_t in_positions_stride;
// Input vertex normals (3 float values per vertex) array and stride (number
// of bytes between each normal).
// Array length must be at least vertex_count * in_normals_stride.
span<const float> in_normals;
size_t in_normals_stride;
// Input vertex tangents (3 float values per vertex) array and stride (number
// of bytes between each tangent).
// Array length must be at least vertex_count * in_tangents_stride.
span<const float> in_tangents;
size_t in_tangents_stride;
// Output vertex positions (3 float values per vertex) array and stride
// (number of bytes between each position).
// Array length must be at least vertex_count * out_positions_stride.
span<float> out_positions;
size_t out_positions_stride;
// Output vertex normals (3 float values per vertex) array and stride (number
// of bytes between each normal).
// Note that output normals are not normalized by the skinning job. This task
// should be handled by the application, who knows if transform matrices have
// uniform scale, and if normals are re-normalized later in the rendering
// pipeline (shader vertex transformation stage).
// Array length must be at least vertex_count * out_normals_stride.
span<float> out_normals;
size_t out_normals_stride;
// Output vertex positions (3 float values per vertex) array and stride
// (number of bytes between each tangent).
// Like normals, Note that output tangents are not normalized by the skinning
// job.
// Array length must be at least vertex_count * out_tangents_stride.
span<float> out_tangents;
size_t out_tangents_stride;
};
} // namespace geometry
} // namespace ozz
#endif // OZZ_OZZ_GEOMETRY_RUNTIME_SKINNING_JOB_H_
+408
View File
@@ -0,0 +1,408 @@
//----------------------------------------------------------------------------//
// //
// 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_OPTIONS_OPTIONS_H_
#define OZZ_OZZ_OPTIONS_OPTIONS_H_
// Implements a command line option processing utility. It helps with command
// line parsing by converting arguments to c++ objects of type bool, int, float
// or const char* c string.
// Unlike getogt(), program options can be scattered in the source files (a la
// google-gflags). Options are collected by a parser which then automatically
// generate the help/usage screen based on registered options.
//
// This library is made of two c++ file (.h/.cc) with no other dependency.
//
// To set an option from the command line, use the form --option=value for
// non-boolean options, and --option/--nooption for booleans.
// For example, "--var=46" will set "var" variable to 46. If "var" type is not
// compatible with the specified argument (in this case an integer, a float or a
// string), then the parser displays the help message and requires application
// to exit.
//
// Boolean options can be set using different syntax:
// - to set a boolean option to true: "--var", "--var=true", "--var=t",
// "--var=yes", "--var=y", "--var=1".
// - to set a boolean option to false: "--novar", "--var=false", "--var=f",
// "--var=no", "--var=n", "--var=0".
// Consistently using single-form --option/--nooption is recommended though.
//
// Specifying an option (in the command line) that has not been registered is
// an error, it will require the application to exit.
//
// As in getopt() and gflags, -- by itself terminates flags processing. So in:
// "foo -f1=1 -- -f2=2", f1 is considered but -f2 is not.
//
// Parsing is invoked through ozz::options::ParseCommandLine function, providing
// argc and argv arguments of the main function. This function also takes as
// argument two strings to specify the version and usage message.
//
// To declare/register a new option, use OZZ_OPTIONS_DECLARE_* like macros.
// Supported options types are bool, int, float and string (c string).
// OZZ_OPTIONS_DECLARE_* macros arguments allow to give the option a:
// - name, used in the code to read option value.
// - description, used by the help screen.
// - default value.
// - required flag, that specifies if the option is optional.
// So for example, in order to define a boolean "verbose" option, that is false
// by default and optional (ie: not required):
// OZZ_OPTIONS_DECLARE_BOOL(verbose, "Display verbose output", false, false);
// This option can then be referenced from the code using OPTIONS_verbose c++
// global variable, that implement an automatic cast operator to the option's
// type (bool in this case).
//
// The parser also integrates built-in options:
// --help displays the help screen, that is automatically generated based on the
// registered options.
// --version displays executable's version.
#include <cstddef>
#include <string>
namespace ozz {
namespace options {
// Eumerates options parsing results.
enum ParseResult {
// Command line was parsed successfully.
kSuccess,
// Command line was parsed successfully, but an argument (like --help) was
// specified and requires application to exit.
kExitSuccess,
// Command line parsing failed because of an invalid option or syntax. See
// std::cout output for more details.
kExitFailure,
};
// Parses all registered options using the command line specified with (_argc,
// _argv) arguments. Options are registered using OZZ_OPTIONS_DECLARE_* macros.
// Valid command line syntax is explained on top of this options.h file and
// displayed by the help/usage screen.
// ParseCommandLine expects that _argc >= 1 and _argv[0] is the executable path.
// _version and _usage are used to respectively set the executable version and
// usage string in case that the help/usage screen is displayed (--help).
// _version and _usage are not copied, ParseCommandLine caller is in charge of
// maintaining their allocation during application lifetime.
// See ParseResult for more details about returned values.
ParseResult ParseCommandLine(int _argc, const char* const* _argv,
const char* _version, const char* _usage);
// Get the executable path that was extracted from the last call to
// ParseCommandLine.
// If ParseCommandLine has never been called, then ParsedExecutablePath
// returns a default empty string.
std::string ParsedExecutablePath();
// Get the executable name that was extracted from the last call to
// ParseCommandLine.
// If ParseCommandLine has never been called, then ParsedExecutableName
// returns a default empty string.
const char* ParsedExecutableName();
// Get the executable usage that was extracted from the last call to
// ParseCommandLine.
// If ParseCommandLine has never been called, then ParsedExecutableUsage
// returns a default empty string.
const char* ParsedExecutableUsage();
#define OZZ_OPTIONS_DECLARE_BOOL(_name, _help, _default, _required) \
OZZ_OPTIONS_DECLARE_VARIABLE(ozz::options::BoolOption, _name, _help, \
_default, _required)
#define OZZ_OPTIONS_DECLARE_BOOL_FN(_name, _help, _default, _required, _fn) \
OZZ_OPTIONS_DECLARE_VARIABLE_FN(ozz::options::BoolOption, _name, _help, \
_default, _required, _fn)
#define OZZ_OPTIONS_DECLARE_INT(_name, _help, _default, _required) \
OZZ_OPTIONS_DECLARE_VARIABLE(ozz::options::IntOption, _name, _help, \
_default, _required)
#define OZZ_OPTIONS_DECLARE_INT_FN(_name, _help, _default, _required, _fn) \
OZZ_OPTIONS_DECLARE_VARIABLE_FN(ozz::options::IntOption, _name, _help, \
_default, _required, _fn)
#define OZZ_OPTIONS_DECLARE_FLOAT(_name, _help, _default, _required) \
OZZ_OPTIONS_DECLARE_VARIABLE(ozz::options::FloatOption, _name, _help, \
_default, _required)
#define OZZ_OPTIONS_DECLARE_FLOAT_FN(_name, _help, _default, _required, _fn) \
OZZ_OPTIONS_DECLARE_VARIABLE_FN(ozz::options::FloatOption, _name, _help, \
_default, _required, _fn)
#define OZZ_OPTIONS_DECLARE_STRING(_name, _help, _default, _required) \
OZZ_OPTIONS_DECLARE_VARIABLE(ozz::options::StringOption, _name, _help, \
_default, _required)
#define OZZ_OPTIONS_DECLARE_STRING_FN(_name, _help, _default, _required, _fn) \
OZZ_OPTIONS_DECLARE_VARIABLE_FN(ozz::options::StringOption, _name, _help, \
_default, _required, _fn)
#define OZZ_OPTIONS_DECLARE_VARIABLE(_type, _name, _help, _default, _required) \
/* Instantiates a registrer for an option of type _type with name _name */ \
static ozz::options::internal::Registrer<_type> OPTIONS_##_name( \
#_name, _help, _default, _required);
#define OZZ_OPTIONS_DECLARE_VARIABLE_FN(_type, _name, _help, _default, \
_required, _fn) \
/* Instantiates a registrer for an option of type _type with name _name */ \
static ozz::options::internal::Registrer<_type> OPTIONS_##_name( \
#_name, _help, _default, _required, _fn);
// Defines option interface.
class Option {
public:
// Returns option's name.
const char* name() const { return name_; }
// Returns help string.
const char* help() const { return help_; }
// A required option is satisfied if it was successfully parsed from the
// command line. Non required option are always satisfied.
bool statisfied() const { return parsed_ || !required_; }
// Returns true if the option is required.
bool required() const { return required_; }
// Calls validation function if one is set.
// Returns true if no function is set, or the function returns true.
bool Validate(int _argc);
// Parse the command line and set the option's value.
// Returns true if argument parsing succeeds, false if argument doesn't match
// or was already parsed (in case of an argument specified more than once).
bool Parse(const char* _argv);
// Restores default value.
void RestoreDefault();
// Outputs default value as a string.
virtual std::string FormatDefault() const = 0;
// Outputs type of value as a c string.
virtual const char* FormatType() const = 0;
// Implements the sorting operator.
bool operator<(const Option& _option) const { return name_ < _option.name_; }
protected:
// Declares validation function prototype.
// _option is the option to validate.
// _argc the number of argument processed.
// *_exit can be set to true to require application to exit. This flag is
// relevant only if the function does not return false. Application will
// exit anyway if false is returned.
typedef bool (*ValidateFn)(const Option& _option, int _argc);
// Construct an option.
// _name and _help are set to an empty c string if nullptr.
Option(const char* _name, const char* _help, bool _required,
ValidateFn _validate = nullptr);
// Destructor.
virtual ~Option();
// Parse the command line and set the option value.
virtual bool ParseImpl(const char* _argv) = 0;
// Restores default value typed implementation.
virtual void RestoreDefaultImpl() = 0;
private:
// Option's name.
const char* name_;
// Option's help message.
const char* help_;
// Is this option required?
bool required_;
// Was this option successfully parsed from the command line.
bool parsed_;
// Validate function. nullptr if no function is set.
ValidateFn validate_;
};
// Defines a strongly typed option class
template <typename _Type>
class TypedOption : public Option {
public:
// Lets the type be known.
typedef _Type Type;
// Defines an option.
TypedOption(const char* _name, const char* _help, _Type _default,
bool _required, Option::ValidateFn _validate = nullptr)
: Option(_name, _help, _required, _validate),
default_(_default),
value_(_default) {}
virtual ~TypedOption() {}
// Implicit conversion to the option type.
operator _Type() const { return value_; }
// Explicit getter.
const _Type& value() const { return value_; }
// Get the default value.
const _Type& default_value() const { return default_; }
private:
// Parse the command line and set the option value.
virtual bool ParseImpl(const char* _argv);
// Restores default value implementation.
virtual void RestoreDefaultImpl() { value_ = default_; }
// Outputs default value as a string.
virtual std::string FormatDefault() const;
// Outputs type of value as a string.
virtual const char* FormatType() const;
// Default option's value.
_Type default_;
// Current option's value.
_Type value_;
};
// Declares all available option types.
typedef TypedOption<bool> BoolOption;
typedef TypedOption<int> IntOption;
typedef TypedOption<float> FloatOption;
typedef TypedOption<const char*> StringOption;
// Declares the option parser class.
// Option are registered by the parser and updated when command line arguments
// are parsed.
class Parser {
public:
// Construct a parser with only built-in options.
Parser();
// Destroys the parser. Options does not need to be unregistered.
~Parser();
// Parses the command line against all registered options.
// _argv arguments are parser until the end to the first "--" argument found.
// Note that _argv arguments memory allocations must remains valid for the
// life of parser, as some arguments like string options or executable path
// and name will be pointed by the parser (ie: not copied).
// See ParseResult for more details about returned values.
ParseResult Parse(int _argc, const char* const* _argv);
// Displays the help screen that is automatically built from all registered
// options. Executable name is only available if ::Parse() was called with a
// valid argv[0].
void Help();
// Registers a new option in this parser.
// Registered options are updated when Parse() is called.
// Returns true on success or false if:
// - _option is not a valid option (ex: bad name...), or if an
// option with the same name already exists.
// - _option si nullptr.
// - more than kMaxOptions were registered.
bool RegisterOption(Option* _option);
// Unregisters an option that was successfully registered using
// ::RegisterOption().
// Returns true if no more option is registered.
bool UnregisterOption(Option* _option);
// Get the maximum number of options that can be registered.
// This excludes built-in options.
int max_options() const;
// Set executable usage string.
// Note that _usage string will not be copied but rather pointed. This means
// that _usage allocation must remain valid for all the parser's life.
void set_usage(const char* _usage);
// Get executable usage string.
const char* usage() const;
// Set executable version string.
// Note that _usage string will not be copied but rather pointed. This means
// that _usage allocation must remain valid for all the parser's life.
void set_version(const char* _version);
// Get executable version string.
const char* version() const;
// Returns the path of the executable that was extracted from argument 0.
std::string executable_path() const;
// Returns the name of the executable that was extracted from argument 0.
const char* executable_name() const;
private:
// Get end of registered options array.
Option** options_end() { return options_ + options_count_; }
// Collection of registered options.
Option* options_[32];
// Number of registered options, including built-in options.
int options_count_;
// Number of built-in options.
int builtin_options_count_;
// The path of the executable, extracted from the first argument.
const char* executable_path_begin_;
const char* executable_path_end_;
// The name of the executable, extracted from the first argument.
const char* executable_name_;
// Executable version set with ::set_version().
const char* version_;
// Executable usage set with ::set_usage().
const char* usage_;
// Built-in version option.
BoolOption builtin_version_;
// Built-in help option.
BoolOption builtin_help_;
};
namespace internal {
// Automatically registers itself to the global parser.
template <typename _Option>
class Registrer : public _Option {
public:
Registrer(const char* _name, const char* _help,
typename _Option::Type _default, bool _required,
typename _Option::ValidateFn _fn = nullptr);
virtual ~Registrer();
};
} // namespace internal
} // namespace options
} // namespace ozz
#endif // OZZ_OZZ_OPTIONS_OPTIONS_H_