Initial commit
This commit is contained in:
+76
@@ -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, ¤t, _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, ¤t, _fct);
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// Applies a specified functor to each joint in a depth-first order.
|
||||
// _Fct is of type void(const Joint& _current, const Joint* _parent) where the
|
||||
// first argument is the child of the second argument. _parent is null if the
|
||||
// _current joint is the root.
|
||||
template <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_
|
||||
+51
@@ -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_
|
||||
@@ -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_
|
||||
@@ -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_
|
||||
@@ -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
@@ -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
@@ -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_
|
||||
@@ -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_
|
||||
@@ -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_
|
||||
@@ -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
@@ -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
@@ -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_
|
||||
@@ -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_
|
||||
Reference in New Issue
Block a user