Initial commit

This commit is contained in:
Martin Felis
2021-11-11 21:22:24 +01:00
commit b78045ffe7
812 changed files with 421882 additions and 0 deletions
@@ -0,0 +1,137 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#ifndef OZZ_OZZ_ANIMATION_RUNTIME_ANIMATION_H_
#define OZZ_OZZ_ANIMATION_RUNTIME_ANIMATION_H_
#include "ozz/base/io/archive_traits.h"
#include "ozz/base/platform.h"
#include "ozz/base/span.h"
namespace ozz {
namespace io {
class IArchive;
class OArchive;
} // namespace io
namespace animation {
// Forward declares the AnimationBuilder, used to instantiate an Animation.
namespace offline {
class AnimationBuilder;
}
// Forward declaration of key frame's type.
struct Float3Key;
struct QuaternionKey;
// Defines a runtime skeletal animation clip.
// The runtime animation data structure stores animation keyframes, for all the
// joints of a skeleton. This structure is usually filled by the
// AnimationBuilder and deserialized/loaded at runtime.
// For each transformation type (translation, rotation and scale), Animation
// structure stores a single array of keyframes that contains all the tracks
// required to animate all the joints of a skeleton, matching breadth-first
// joints order of the runtime skeleton structure. In order to optimize cache
// coherency when sampling the animation, Keyframes in this array are sorted by
// time, then by track number.
class Animation {
public:
// Builds a default animation.
Animation();
// Declares the public non-virtual destructor.
~Animation();
// Gets the animation clip duration.
float duration() const { return duration_; }
// Gets the number of animated tracks.
int num_tracks() const { return num_tracks_; }
// Returns the number of SoA elements matching the number of tracks of *this
// animation. This value is useful to allocate SoA runtime data structures.
int num_soa_tracks() const { return (num_tracks_ + 3) / 4; }
// Gets animation name.
const char* name() const { return name_ ? name_ : ""; }
// Gets the buffer of translations keys.
span<const Float3Key> translations() const {
return translations_;
}
// Gets the buffer of rotation keys.
span<const QuaternionKey> rotations() const { return rotations_; }
// Gets the buffer of scale keys.
span<const Float3Key> scales() const { return scales_; }
// Get the estimated animation's size in bytes.
size_t size() const;
// Serialization functions.
// Should not be called directly but through io::Archive << and >> operators.
void Save(ozz::io::OArchive& _archive) const;
void Load(ozz::io::IArchive& _archive, uint32_t _version);
protected:
private:
// Disables copy and assignation.
Animation(Animation const&);
void operator=(Animation const&);
// AnimationBuilder class is allowed to instantiate an Animation.
friend class offline::AnimationBuilder;
// Internal destruction function.
void Allocate(size_t _name_len, size_t _translation_count,
size_t _rotation_count, size_t _scale_count);
void Deallocate();
// Duration of the animation clip.
float duration_;
// The number of joint tracks. Can differ from the data stored in translation/
// rotation/scale buffers because of SoA requirements.
int num_tracks_;
// Animation name.
char* name_;
// Stores all translation/rotation/scale keys begin and end of buffers.
span<Float3Key> translations_;
span<QuaternionKey> rotations_;
span<Float3Key> scales_;
};
} // namespace animation
namespace io {
OZZ_IO_TYPE_VERSION(6, animation::Animation)
OZZ_IO_TYPE_TAG("ozz-animation", animation::Animation)
} // namespace io
} // namespace ozz
#endif // OZZ_OZZ_ANIMATION_RUNTIME_ANIMATION_H_
@@ -0,0 +1,43 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#ifndef OZZ_OZZ_ANIMATION_RUNTIME_ANIMATION_UTILS_H_
#define OZZ_OZZ_ANIMATION_RUNTIME_ANIMATION_UTILS_H_
#include "ozz/animation/runtime/animation.h"
namespace ozz {
namespace animation {
// Count translation, rotation or scale keyframes for a given track number. Use
// a negative _track value to count all tracks.
int CountTranslationKeyframes(const Animation& _animation, int _track = -1);
int CountRotationKeyframes(const Animation& _animation, int _track = -1);
int CountScaleKeyframes(const Animation& _animation, int _track = -1);
} // namespace animation
} // namespace ozz
#endif // OZZ_OZZ_ANIMATION_RUNTIME_ANIMATION_UTILS_H_
@@ -0,0 +1,138 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#ifndef OZZ_OZZ_ANIMATION_RUNTIME_BLENDING_JOB_H_
#define OZZ_OZZ_ANIMATION_RUNTIME_BLENDING_JOB_H_
#include "ozz/base/maths/simd_math.h"
#include "ozz/base/span.h"
namespace ozz {
// Forward declaration of math structures.
namespace math {
struct SoaTransform;
}
namespace animation {
// ozz::animation::BlendingJob is in charge of blending (mixing) multiple poses
// (the result of a sampled animation) according to their respective weight,
// into one output pose.
// The number of transforms/joints blended by the job is defined by the number
// of transforms of the bind pose (note that this is a SoA format). This means
// that all buffers must be at least as big as the bind pose buffer.
// Partial animation blending is supported through optional joint weights that
// can be specified with layers joint_weights buffer. Unspecified joint weights
// are considered as a unit weight of 1.f, allowing to mix full and partial
// blend operations in a single pass.
// The job does not owned any buffers (input/output) and will thus not delete
// them during job's destruction.
struct BlendingJob {
// Default constructor, initializes default values.
BlendingJob();
// Validates job parameters.
// Returns true for a valid job, false otherwise:
// -if layer range is not valid (can be empty though).
// -if additive layer range is not valid (can be empty though).
// -if any layer is not valid.
// -if output range is not valid.
// -if any buffer (including layers' content : transform, joint weights...) is
// smaller than the bind pose buffer.
// -if the threshold value is less than or equal to 0.f.
bool Validate() const;
// Runs job's blending task.
// The job is validated before any operation is performed, see Validate() for
// more details.
// Returns false if *this job is not valid.
bool Run() const;
// Defines a layer of blending input data (local space transforms) and
// parameters (weights).
struct Layer {
// Default constructor, initializes default values.
Layer();
// Blending weight of this layer. Negative values are considered as 0.
// Normalization is performed during the blending stage so weight can be in
// any range, even though range [0:1] is optimal.
float weight;
// The range [begin,end[ of input layer posture. This buffer expect to store
// local space transforms, that are usually outputted from a sampling job.
// This range must be at least as big as the bind pose buffer, even though
// only the number of transforms defined by the bind pose buffer will be
// processed.
span<const math::SoaTransform> transform;
// Optional range [begin,end[ of blending weight for each joint in this
// layer.
// If both pointers are nullptr (default case) then per joint weight
// blending is disabled. A valid range is defined as being at least as big
// as the bind pose buffer, even though only the number of transforms
// defined by the bind pose buffer will be processed. When a layer doesn't
// specifies per joint weights, then it is implicitly considered as
// being 1.f. This default value is a reference value for the normalization
// process, which implies that the range of values for joint weights should
// be [0,1]. Negative weight values are considered as 0, but positive ones
// aren't clamped because they could exceed 1.f if all layers contains valid
// joint weights.
span<const math::SimdFloat4> joint_weights;
};
// The job blends the bind pose to the output when the accumulated weight of
// all layers is less than this threshold value.
// Must be greater than 0.f.
float threshold;
// Job input layers, can be empty or nullptr.
// The range of layers that must be blended.
span<const Layer> layers;
// Job input additive layers, can be empty or nullptr.
// The range of layers that must be added to the output.
span<const Layer> additive_layers;
// The skeleton bind pose. The size of this buffer defines the number of
// transforms to blend. This is the reference because this buffer is defined
// by the skeleton that all the animations belongs to.
// It is used when the accumulated weight for a bone on all layers is
// less than the threshold value, in order to fall back on valid transforms.
span<const ozz::math::SoaTransform> bind_pose;
// Job output.
// The range of output transforms to be filled with blended layer
// transforms during job execution.
// Must be at least as big as the bind pose buffer, but only the number of
// transforms defined by the bind pose buffer size will be processed.
span<ozz::math::SoaTransform> output;
};
} // namespace animation
} // namespace ozz
#endif // OZZ_OZZ_ANIMATION_RUNTIME_BLENDING_JOB_H_
@@ -0,0 +1,114 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#ifndef OZZ_OZZ_ANIMATION_RUNTIME_IK_AIM_JOB_H_
#define OZZ_OZZ_ANIMATION_RUNTIME_IK_AIM_JOB_H_
#include "ozz/base/platform.h"
#include "ozz/base/maths/simd_math.h"
namespace ozz {
// Forward declaration of math structures.
namespace math {
struct SimdQuaternion;
}
namespace animation {
// ozz::animation::IKAimJob rotates a joint so it aims at a target. Joint aim
// direction and up vectors can be different from joint axis. The job computes
// the transformation (rotation) that needs to be applied to the joints such
// that a provided forward vector (in joint local-space) aims at the target
// position (in skeleton model-space). Up vector (in joint local-space) is also
// used to keep the joint oriented in the same direction as the pole vector.
// The job also exposes an offset (in joint local-space) from where the forward
// vector should aim the target.
// Result is unstable if joint-to-target direction is parallel to pole vector,
// or if target is too close to joint position.
struct IKAimJob {
// Default constructor, initializes default values.
IKAimJob();
// Validates job parameters. Returns true for a valid job, or false otherwise:
// -if output quaternion pointer is nullptr
bool Validate() const;
// Runs job's execution task.
// The job is validated before any operation is performed, see Validate() for
// more details.
// Returns false if *this job is not valid.
bool Run() const;
// Job input.
// Target position to aim at, in model-space
math::SimdFloat4 target;
// Joint forward axis, in joint local-space, to be aimed at target position.
// This vector shall be normalized, otherwise validation will fail.
// Default is x axis.
math::SimdFloat4 forward;
// Offset position from the joint in local-space, that will aim at target.
math::SimdFloat4 offset;
// Joint up axis, in joint local-space, used to keep the joint oriented in the
// same direction as the pole vector. Default is y axis.
math::SimdFloat4 up;
// Pole vector, in model-space. The pole vector defines the direction
// the up should point to. Note that IK chain orientation will flip when
// target vector and the pole vector are aligned/crossing each other. It's
// caller responsibility to ensure that this doesn't happen.
math::SimdFloat4 pole_vector;
// Twist_angle rotates joint around the target vector.
// Default is 0.
float twist_angle;
// Weight given to the IK correction clamped in range [0,1]. This allows to
// blend / interpolate from no IK applied (0 weight) to full IK (1).
float weight;
// Joint model-space matrix.
const math::Float4x4* joint;
// Job output.
// Output local-space joint correction quaternion. It needs to be multiplied
// with joint local-space quaternion.
math::SimdQuaternion* joint_correction;
// Optional boolean output value, set to true if target can be reached with IK
// computations. Target is considered not reachable when target is between
// joint and offset position.
bool* reached;
};
} // namespace animation
} // namespace ozz
#endif // OZZ_OZZ_ANIMATION_RUNTIME_IK_AIM_JOB_H_
@@ -0,0 +1,128 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#ifndef OZZ_OZZ_ANIMATION_RUNTIME_IK_TWO_BONE_JOB_H_
#define OZZ_OZZ_ANIMATION_RUNTIME_IK_TWO_BONE_JOB_H_
#include "ozz/base/platform.h"
#include "ozz/base/maths/simd_math.h"
namespace ozz {
// Forward declaration of math structures.
namespace math {
struct SimdQuaternion;
}
namespace animation {
// ozz::animation::IKTwoBoneJob performs inverse kinematic on a three joints
// chain (two bones).
// The job computes the transformations (rotations) that needs to be applied to
// the first two joints of the chain (named start and middle joints) such that
// the third joint (named end) reaches the provided target position (if
// possible). The job outputs start and middle joint rotation corrections as
// quaternions.
// The three joints must be ancestors, but don't need to be direct
// ancestors (joints in-between will simply remain fixed).
// Implementation is inspired by Autodesk Maya 2 bone IK, improved stability
// wise and extended with Soften IK.
struct IKTwoBoneJob {
// Constructor, initializes default values.
IKTwoBoneJob();
// Validates job parameters. Returns true for a valid job, or false otherwise:
// -if any input pointer is nullptr
// -if mid_axis isn't normalized.
bool Validate() const;
// Runs job's execution task.
// The job is validated before any operation is performed, see Validate() for
// more details.
// Returns false if *this job is not valid.
bool Run() const;
// Job input.
// Target IK position, in model-space. This is the position the end of the
// joint chain will try to reach.
math::SimdFloat4 target;
// Normalized middle joint rotation axis, in middle joint local-space. Default
// value is z axis. This axis is usually fixed for a given skeleton (as it's
// in middle joint space). Its direction is defined like this: a positive
// rotation around this axis will open the angle between the two bones. This
// in turn also to define which side the two joints must bend. Job validation
// will fail if mid_axis isn't normalized.
math::SimdFloat4 mid_axis;
// Pole vector, in model-space. The pole vector defines the direction the
// middle joint should point to, allowing to control IK chain orientation.
// Note that IK chain orientation will flip when target vector and the pole
// vector are aligned/crossing each other. It's caller responsibility to
// ensure that this doesn't happen.
math::SimdFloat4 pole_vector;
// Twist_angle rotates IK chain around the vector define by start-to-target
// vector. Default is 0.
float twist_angle;
// Soften ratio allows the chain to gradually fall behind the target
// position. This prevents the joint chain from snapping into the final
// position, softening the final degrees before the joint chain becomes flat.
// This ratio represents the distance to the end, from which softening is
// starting.
float soften;
// Weight given to the IK correction clamped in range [0,1]. This allows to
// blend / interpolate from no IK applied (0 weight) to full IK (1).
float weight;
// Model-space matrices of the start, middle and end joints of the chain.
// The 3 joints should be ancestors. They don't need to be direct
// ancestors though.
const math::Float4x4* start_joint;
const math::Float4x4* mid_joint;
const math::Float4x4* end_joint;
// Job output.
// Local-space corrections to apply to start and middle joints in order for
// end joint to reach target position.
// These quaternions must be multiplied to the local-space quaternion of their
// respective joints.
math::SimdQuaternion* start_joint_correction;
math::SimdQuaternion* mid_joint_correction;
// Optional boolean output value, set to true if target can be reached with IK
// computations. Reachability is driven by bone chain length, soften ratio and
// target distance. Target is considered unreached if weight is less than 1.
bool* reached;
};
} // namespace animation
} // namespace ozz
#endif // OZZ_OZZ_ANIMATION_RUNTIME_IK_TWO_BONE_JOB_H_
@@ -0,0 +1,120 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#ifndef OZZ_OZZ_ANIMATION_RUNTIME_LOCAL_TO_MODEL_JOB_H_
#define OZZ_OZZ_ANIMATION_RUNTIME_LOCAL_TO_MODEL_JOB_H_
#include "ozz/base/platform.h"
#include "ozz/base/span.h"
namespace ozz {
// Forward declaration math structures.
namespace math {
struct SoaTransform;
}
namespace math {
struct Float4x4;
}
namespace animation {
// Forward declares the Skeleton object used to describe joint hierarchy.
class Skeleton;
// Computes model-space joint matrices from local-space SoaTransform.
// This job uses the skeleton to define joints parent-child hierarchy. The job
// iterates through all joints to compute their transform relatively to the
// skeleton root.
// Job inputs is an array of SoaTransform objects (in local-space), ordered like
// skeleton's joints. Job output is an array of matrices (in model-space),
// ordered like skeleton's joints. Output are matrices, because the combination
// of affine transformations can contain shearing or complex transformation
// that cannot be represented as Transform object.
struct LocalToModelJob {
// Default constructor, initializes default values.
LocalToModelJob();
// Validates job parameters. Returns true for a valid job, or false otherwise:
// -if any input pointer, including ranges, is nullptr.
// -if the size of the input is smaller than the skeleton's number of joints.
// Note that this input has a SoA format.
// -if the size of of the output is smaller than the skeleton's number of
// joints.
bool Validate() const;
// Runs job's local-to-model task.
// The job is validated before any operation is performed, see Validate() for
// more details.
// Returns false if job is not valid. See Validate() function.
bool Run() const;
// Job input.
// The Skeleton object describing the joint hierarchy used for local to
// model space conversion.
const Skeleton* skeleton;
// The root matrix will multiply to every model space matrices, default nullptr
// means an identity matrix. This can be used to directly compute world-space
// transforms for example.
const ozz::math::Float4x4* root;
// Defines "from" which joint the local-to-model conversion should start.
// Default value is ozz::Skeleton::kNoParent, meaning the whole hierarchy is
// updated. This parameter can be used to optimize update by limiting
// conversion to part of the joint hierarchy. Note that "from" parent should
// be a valid matrix, as it is going to be used as part of "from" joint
// hierarchy update.
int from;
// Defines "to" which joint the local-to-model conversion should go, "to"
// included. Update will end before "to" joint is reached if "to" is not part
// of the hierarchy starting from "from". Default value is
// ozz::animation::Skeleton::kMaxJoints, meaning the hierarchy (starting from
// "from") is updated to the last joint.
int to;
// If true, "from" joint is not updated during job execution. Update starts
// with all children of "from". This can be used to update a model-space
// transform independently from the local-space one. To do so: set "from"
// joint model-space transform matrix, and run this Job with "from_excluded"
// to update all "from" children.
// Default value is false.
bool from_excluded;
// The input range that store local transforms.
span<const ozz::math::SoaTransform> input;
// Job output.
// The output range to be filled with model-space matrices.
span<ozz::math::Float4x4> output;
};
} // namespace animation
} // namespace ozz
#endif // OZZ_OZZ_ANIMATION_RUNTIME_LOCAL_TO_MODEL_JOB_H_
@@ -0,0 +1,181 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#ifndef OZZ_OZZ_ANIMATION_RUNTIME_SAMPLING_JOB_H_
#define OZZ_OZZ_ANIMATION_RUNTIME_SAMPLING_JOB_H_
#include "ozz/base/platform.h"
#include "ozz/base/span.h"
namespace ozz {
// Forward declaration of math structures.
namespace math {
struct SoaTransform;
}
namespace animation {
// Forward declares the animation type to sample.
class Animation;
// Forward declares the cache object used by the SamplingJob.
class SamplingCache;
// Samples an animation at a given time ratio in the unit interval [0,1] (where
// 0 is the beginning of the animation, 1 is the end), to output the
// corresponding posture in local-space.
// SamplingJob uses a cache (aka SamplingCache) to store intermediate values
// (decompressed animation keyframes...) while sampling. This cache also stores
// pre-computed values that allows drastic optimization while playing/sampling
// the animation forward. Backward sampling works, but isn't optimized through
// the cache. The job does not owned the buffers (in/output) and will thus not
// delete them during job's destruction.
struct SamplingJob {
// Default constructor, initializes default values.
SamplingJob();
// Validates job parameters. Returns true for a valid job, or false otherwise:
// -if any input pointer is nullptr
// -if output range is invalid.
bool Validate() const;
// Runs job's sampling task.
// The job is validated before any operation is performed, see Validate() for
// more details.
// Returns false if *this job is not valid.
bool Run() const;
// Time ratio in the unit interval [0,1] used to sample animation (where 0 is
// the beginning of the animation, 1 is the end). It should be computed as the
// current time in the animation , divided by animation duration.
// This ratio is clamped before job execution in order to resolves any
// approximation issue on range bounds.
float ratio;
// The animation to sample.
const Animation* animation;
// A cache object that must be big enough to sample *this animation.
SamplingCache* cache;
// Job output.
// The output range to be filled with sampled joints during job execution.
// If there are less joints in the animation compared to the output range,
// then remaining SoaTransform are left unchanged.
// If there are more joints in the animation, then the last joints are not
// sampled.
span<ozz::math::SoaTransform> output;
};
namespace internal {
// Soa hot data to interpolate.
struct InterpSoaFloat3;
struct InterpSoaQuaternion;
} // namespace internal
// Declares the cache object used by the workload to take advantage of the
// frame coherency of animation sampling.
class SamplingCache {
public:
// Constructs an empty cache. The cache needs to be resized with the
// appropriate number of tracks before it can be used with a SamplingJob.
SamplingCache();
// Constructs a cache that can be used to sample any animation with at most
// _max_tracks tracks. _num_tracks is internally aligned to a multiple of
// soa size, which means max_tracks() can return a different (but bigger)
// value than _max_tracks.
explicit SamplingCache(int _max_tracks);
// Deallocates cache.
~SamplingCache();
// Resize the number of joints that the cache can support.
// This also implicitly invalidate the cache.
void Resize(int _max_tracks);
// Invalidate the cache.
// The SamplingJob automatically invalidates a cache when required
// during sampling. This automatic mechanism is based on the animation
// address and sampling time ratio. The weak point is that it can result in a
// crash if ever the address of an animation is used again with another
// animation (could be the result of successive call to delete / new).
// Therefore it is recommended to manually invalidate a cache when it is
// known that this cache will not be used for with an animation again.
void Invalidate();
// The maximum number of tracks that the cache can handle.
int max_tracks() const { return max_soa_tracks_ * 4; }
int max_soa_tracks() const { return max_soa_tracks_; }
private:
// Disables copy and assignation.
SamplingCache(SamplingCache const&);
void operator=(SamplingCache const&);
friend struct SamplingJob;
// Steps the cache in order to use it for a potentially new animation and
// ratio. If the _animation is different from the animation currently cached,
// or if the _ratio shows that the animation is played backward, then the
// cache is invalidated and reseted for the new _animation and _ratio.
void Step(const Animation& _animation, float _ratio);
// The animation this cache refers to. nullptr means that the cache is invalid.
const Animation* animation_;
// The current time ratio in the animation.
float ratio_;
// The number of soa tracks that can store this cache.
int max_soa_tracks_;
// Soa hot data to interpolate.
internal::InterpSoaFloat3* soa_translations_;
internal::InterpSoaQuaternion* soa_rotations_;
internal::InterpSoaFloat3* soa_scales_;
// Points to the keys in the animation that are valid for the current time
// ratio.
int* translation_keys_;
int* rotation_keys_;
int* scale_keys_;
// Current cursors in the animation. 0 means that the cache is invalid.
int translation_cursor_;
int rotation_cursor_;
int scale_cursor_;
// Outdated soa entries. One bit per soa entry (32 joints per byte).
uint8_t* outdated_translations_;
uint8_t* outdated_rotations_;
uint8_t* outdated_scales_;
};
} // namespace animation
} // namespace ozz
#endif // OZZ_OZZ_ANIMATION_RUNTIME_SAMPLING_JOB_H_
@@ -0,0 +1,144 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#ifndef OZZ_OZZ_ANIMATION_RUNTIME_SKELETON_H_
#define OZZ_OZZ_ANIMATION_RUNTIME_SKELETON_H_
#include "ozz/base/io/archive_traits.h"
#include "ozz/base/platform.h"
#include "ozz/base/span.h"
namespace ozz {
namespace io {
class IArchive;
class OArchive;
} // namespace io
namespace math {
struct SoaTransform;
}
namespace animation {
// Forward declaration of SkeletonBuilder, used to instantiate a skeleton.
namespace offline {
class SkeletonBuilder;
}
// This runtime skeleton data structure provides a const-only access to joint
// hierarchy, joint names and bind-pose. This structure is filled by the
// SkeletonBuilder and can be serialize/deserialized.
// Joint names, bind-poses and hierarchy information are all stored in separate
// arrays of data (as opposed to joint structures for the RawSkeleton), in order
// to closely match with the way runtime algorithms use them. Joint hierarchy is
// packed as an array of parent jont indices (16 bits), stored in depth-first
// order. This is enough to traverse the whole joint hierarchy. See
// IterateJointsDF() from skeleton_utils.h that implements a depth-first
// traversal utility.
class Skeleton {
public:
// Defines Skeleton constant values.
enum Constants {
// Defines the maximum number of joints.
// This is limited in order to control the number of bits required to store
// a joint index. Limiting the number of joints also helps handling worst
// size cases, like when it is required to allocate an array of joints on
// the stack.
kMaxJoints = 1024,
// Defines the maximum number of SoA elements required to store the maximum
// number of joints.
kMaxSoAJoints = (kMaxJoints + 3) / 4,
// Defines the index of the parent of the root joint (which has no parent in
// fact).
kNoParent = -1,
};
// Builds a default skeleton.
Skeleton();
// Declares the public non-virtual destructor.
~Skeleton();
// Returns the number of joints of *this skeleton.
int num_joints() const { return static_cast<int>(joint_parents_.size()); }
// Returns the number of soa elements matching the number of joints of *this
// skeleton. This value is useful to allocate SoA runtime data structures.
int num_soa_joints() const { return (num_joints() + 3) / 4; }
// Returns joint's bind poses. Bind poses are stored in soa format.
span<const math::SoaTransform> joint_bind_poses() const {
return joint_bind_poses_;
}
// Returns joint's parent indices range.
span<const int16_t> joint_parents() const { return joint_parents_; }
// Returns joint's name collection.
span<const char* const> joint_names() const {
return span<const char* const>(joint_names_.begin(), joint_names_.end());
}
// Serialization functions.
// Should not be called directly but through io::Archive << and >> operators.
void Save(ozz::io::OArchive& _archive) const;
void Load(ozz::io::IArchive& _archive, uint32_t _version);
private:
// Disables copy and assignation.
Skeleton(Skeleton const&);
void operator=(Skeleton const&);
// Internal allocation/deallocation function.
// Allocate returns the beginning of the contiguous buffer of names.
char* Allocate(size_t _char_count, size_t _num_joints);
void Deallocate();
// SkeletonBuilder class is allowed to instantiate an Skeleton.
friend class offline::SkeletonBuilder;
// Buffers below store joint informations in joing depth first order. Their
// size is equal to the number of joints of the skeleton.
// Bind pose of every joint in local space.
span<math::SoaTransform> joint_bind_poses_;
// Array of joint parent indexes.
span<int16_t> joint_parents_;
// Stores the name of every joint in an array of c-strings.
span<char*> joint_names_;
};
} // namespace animation
namespace io {
OZZ_IO_TYPE_VERSION(2, animation::Skeleton)
OZZ_IO_TYPE_TAG("ozz-skeleton", animation::Skeleton)
} // namespace io
} // namespace ozz
#endif // OZZ_OZZ_ANIMATION_RUNTIME_SKELETON_H_
@@ -0,0 +1,90 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#ifndef OZZ_OZZ_ANIMATION_RUNTIME_SKELETON_UTILS_H_
#define OZZ_OZZ_ANIMATION_RUNTIME_SKELETON_UTILS_H_
#include "ozz/animation/runtime/skeleton.h"
#include "ozz/base/maths/transform.h"
#include <cassert>
namespace ozz {
namespace animation {
// Get bind-pose of a skeleton joint.
ozz::math::Transform GetJointLocalBindPose(const Skeleton& _skeleton,
int _joint);
// Test if a joint is a leaf. _joint number must be in range [0, num joints].
// "_joint" is a leaf if it's the last joint, or next joint's parent isn't
// "_joint".
inline bool IsLeaf(const Skeleton& _skeleton, int _joint) {
const int num_joints = _skeleton.num_joints();
assert(_joint >= 0 && _joint < num_joints && "_joint index out of range");
const span<const int16_t>& parents = _skeleton.joint_parents();
const int next = _joint + 1;
return next == num_joints || parents[next] != _joint;
}
// Applies a specified functor to each joint in a depth-first order.
// _Fct is of type void(int _current, int _parent) where the first argument is
// the child of the second argument. _parent is kNoParent if the
// _current joint is a root. _from indicates the joint from which the joint
// hierarchy traversal begins. Use Skeleton::kNoParent to traverse the
// whole hierarchy, in case there are multiple roots.
template <typename _Fct>
inline _Fct IterateJointsDF(const Skeleton& _skeleton, _Fct _fct,
int _from = Skeleton::kNoParent) {
const span<const int16_t>& parents = _skeleton.joint_parents();
const int num_joints = _skeleton.num_joints();
//
// parents[i] >= _from is true as long as "i" is a child of "_from".
static_assert(Skeleton::kNoParent < 0,
"Algorithm relies on kNoParent being negative");
for (int i = _from < 0 ? 0 : _from, process = i < num_joints; process;
++i, process = i < num_joints && parents[i] >= _from) {
_fct(i, parents[i]);
}
return _fct;
}
// Applies a specified functor to each joint in a reverse (from leaves to root)
// depth-first order. _Fct is of type void(int _current, int _parent) where the
// first argument is the child of the second argument. _parent is kNoParent if
// the _current joint is a root.
template <typename _Fct>
inline _Fct IterateJointsDFReverse(const Skeleton& _skeleton, _Fct _fct) {
const span<const int16_t>& parents = _skeleton.joint_parents();
for (int i = _skeleton.num_joints() - 1; i >= 0; --i) {
_fct(i, parents[i]);
}
return _fct;
}
} // namespace animation
} // namespace ozz
#endif // OZZ_OZZ_ANIMATION_RUNTIME_SKELETON_UTILS_H_
@@ -0,0 +1,169 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#ifndef OZZ_OZZ_ANIMATION_RUNTIME_TRACK_H_
#define OZZ_OZZ_ANIMATION_RUNTIME_TRACK_H_
#include "ozz/base/io/archive_traits.h"
#include "ozz/base/platform.h"
#include "ozz/base/span.h"
#include "ozz/base/maths/quaternion.h"
#include "ozz/base/maths/vec_float.h"
namespace ozz {
namespace animation {
// Forward declares the TrackBuilder, used to instantiate a Track.
namespace offline {
class TrackBuilder;
}
namespace internal {
// Runtime user-channel track internal implementation.
// The runtime track data structure exists for 1 to 4 float types (FloatTrack,
// ..., Float4Track) and quaternions (QuaternionTrack). See RawTrack for more
// details on track content. The runtime track data structure is optimized for
// the processing of ozz::animation::TrackSamplingJob and
// ozz::animation::TrackTriggeringJob. Keyframe ratios, values and interpolation
// mode are all store as separate buffers in order to access the cache
// coherently. Ratios are usually accessed/read alone from the jobs that all
// start by looking up the keyframes to interpolate indeed.
template <typename _ValueType>
class Track {
public:
typedef _ValueType ValueType;
Track();
~Track();
// Keyframe accessors.
span<const float> ratios() const { return ratios_; }
span<const _ValueType> values() const { return values_; }
span<const uint8_t> steps() const { return steps_; }
// Get the estimated track's size in bytes.
size_t size() const;
// Get track name.
const char* name() const { return name_ ? name_ : ""; }
// Serialization functions.
// Should not be called directly but through io::Archive << and >> operators.
void Save(ozz::io::OArchive& _archive) const;
void Load(ozz::io::IArchive& _archive, uint32_t _version);
private:
// Disables copy and assignation.
Track(Track const&);
void operator=(Track const&);
// TrackBuilder class is allowed to allocate a Track.
friend class offline::TrackBuilder;
// Internal destruction function.
void Allocate(size_t _keys_count, size_t _name_len);
void Deallocate();
// Keyframe ratios (0 is the beginning of the track, 1 is the end).
span<float> ratios_;
// Keyframe values.
span<_ValueType> values_;
// Keyframe modes (1 bit per key): 1 for step, 0 for linear.
span<uint8_t> steps_;
// Track name.
char* name_;
};
// Definition of operations policies per track value type.
template <typename _ValueType>
struct TrackPolicy {
inline static _ValueType Lerp(const _ValueType& _a, const _ValueType& _b,
float _alpha) {
return math::Lerp(_a, _b, _alpha);
}
inline static float Distance(const _ValueType& _a, const _ValueType& _b) {
return math::Length(_a - _b);
}
inline static _ValueType identity() { return _ValueType(0.f); }
};
// Specialization for float policy.
template <>
inline float TrackPolicy<float>::Distance(const float& _a, const float& _b) {
return std::abs(_a - _b);
}
// Specialization for quaternions policy.
template <>
inline math::Quaternion TrackPolicy<math::Quaternion>::Lerp(
const math::Quaternion& _a, const math::Quaternion& _b, float _alpha) {
// Uses NLerp to favor speed. This same function is used when optimizing the
// curve (key frame reduction), so "constant speed" interpolation can still be
// approximated with a lower tolerance value if it matters.
return math::NLerp(_a, _b, _alpha);
}
template <>
inline float TrackPolicy<math::Quaternion>::Distance(
const math::Quaternion& _a, const math::Quaternion& _b) {
const float cos_half_angle =
_a.x * _b.x + _a.y * _b.y + _a.z * _b.z + _a.w * _b.w;
// Return value is 1 - half cosine, so the closer the quaternions, the closer
// to 0.
return 1.f - math::Min(1.f, std::abs(cos_half_angle));
}
template <>
inline math::Quaternion TrackPolicy<math::Quaternion>::identity() {
return math::Quaternion::identity();
}
} // namespace internal
// Runtime track data structure instantiation.
class FloatTrack : public internal::Track<float> {};
class Float2Track : public internal::Track<math::Float2> {};
class Float3Track : public internal::Track<math::Float3> {};
class Float4Track : public internal::Track<math::Float4> {};
class QuaternionTrack : public internal::Track<math::Quaternion> {};
} // namespace animation
namespace io {
OZZ_IO_TYPE_VERSION(1, animation::FloatTrack)
OZZ_IO_TYPE_TAG("ozz-float_track", animation::FloatTrack)
OZZ_IO_TYPE_VERSION(1, animation::Float2Track)
OZZ_IO_TYPE_TAG("ozz-float2_track", animation::Float2Track)
OZZ_IO_TYPE_VERSION(1, animation::Float3Track)
OZZ_IO_TYPE_TAG("ozz-float3_track", animation::Float3Track)
OZZ_IO_TYPE_VERSION(1, animation::Float4Track)
OZZ_IO_TYPE_TAG("ozz-float4_track", animation::Float4Track)
OZZ_IO_TYPE_VERSION(1, animation::QuaternionTrack)
OZZ_IO_TYPE_TAG("ozz-quat_track", animation::QuaternionTrack)
} // namespace io
} // namespace ozz
#endif // OZZ_OZZ_ANIMATION_RUNTIME_TRACK_H_
@@ -0,0 +1,80 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#ifndef OZZ_OZZ_ANIMATION_RUNTIME_TRACK_SAMPLING_JOB_H_
#define OZZ_OZZ_ANIMATION_RUNTIME_TRACK_SAMPLING_JOB_H_
#include "ozz/animation/runtime/track.h"
namespace ozz {
namespace animation {
namespace internal {
// TrackSamplingJob internal implementation. See *TrackSamplingJob for more
// details.
template <typename _Track>
struct TrackSamplingJob {
typedef typename _Track::ValueType ValueType;
TrackSamplingJob();
// Validates all parameters.
bool Validate() const;
// Validates and executes sampling.
bool Run() const;
// Ratio used to sample track, clamped in range [0,1] before job execution. 0
// is the beginning of the track, 1 is the end. This is a ratio rather than a
// ratio because tracks have no duration.
float ratio;
// Track to sample.
const _Track* track;
// Job output.
typename _Track::ValueType* result;
};
} // namespace internal
// Track sampling job implementation. Track sampling allows to query a track
// value for a specified ratio. This is a ratio rather than a time because
// tracks have no duration.
struct FloatTrackSamplingJob : public internal::TrackSamplingJob<FloatTrack> {};
struct Float2TrackSamplingJob : public internal::TrackSamplingJob<Float2Track> {
};
struct Float3TrackSamplingJob : public internal::TrackSamplingJob<Float3Track> {
};
struct Float4TrackSamplingJob : public internal::TrackSamplingJob<Float4Track> {
};
struct QuaternionTrackSamplingJob
: public internal::TrackSamplingJob<QuaternionTrack> {};
} // namespace animation
} // namespace ozz
#endif // OZZ_OZZ_ANIMATION_RUNTIME_TRACK_SAMPLING_JOB_H_
@@ -0,0 +1,161 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#ifndef OZZ_OZZ_ANIMATION_RUNTIME_TRACK_TRIGGERING_JOB_H_
#define OZZ_OZZ_ANIMATION_RUNTIME_TRACK_TRIGGERING_JOB_H_
#include "ozz/base/platform.h"
namespace ozz {
namespace animation {
class FloatTrack;
// Track edge triggering job implementation. Edge triggering wording refers to
// signal processing, where a signal edge is a transition from low to high or
// from high to low. It is called an "edge" because of the square wave which
// represents a signal has edges at those points. A rising edge is the
// transition from low to high, a falling edge is from high to low.
// TrackTriggeringJob detects when track curve crosses a threshold value,
// triggering dated events that can be processed as state changes.
// Only FloatTrack is supported, because comparing to a threshold for other
// track types isn't possible.
// The job execution actually performs a lazy evaluation of edges. It builds an
// iterator that will process the next edge on each call to ++ operator.
struct TrackTriggeringJob {
TrackTriggeringJob();
// Validates job parameters.
bool Validate() const;
// Validates and executes job. Execution is lazy. Iterator operator ++ is
// actually doing the processing work.
bool Run() const;
// Input range. 0 is the beginning of the track, 1 is the end.
// from and to can be of any sign, any order, and any range. The job will
// perform accordingly:
// - if difference between from and to is greater than 1, the iterator will
// loop multiple times on the track.
// - if from is greater than to, then the track is processed backward (rising
// edges in forward become falling ones).
float from;
float to;
// Edge detection threshold value.
// A rising edge is detected as soon as the track value becomes greater than
// the threshold.
// A falling edge is detected as soon as the track value becomes smaller or
// equal than the threshold.
float threshold;
// Track to sample.
const FloatTrack* track;
// Job output iterator.
class Iterator;
Iterator* iterator;
// Returns an iterator referring to the past-the-end element. It should only
// be used to test if iterator loop reached the end (using operator !=), and
// shall not be dereferenced.
Iterator end() const;
// Structure of an edge as detected by the job.
struct Edge {
float ratio; // Ratio at which track value crossed threshold.
bool rising; // true is edge is rising (getting higher than threshold).
};
};
// Iterator implementation. Calls to ++ operator will compute the next edge. It
// should be compared (using operator !=) to job's end iterator to test if the
// last edge has been reached.
class TrackTriggeringJob::Iterator {
public:
Iterator() : job_(nullptr), outer_(0.f), inner_(0) {}
// Evaluate next edge.
// Calling this function on an end iterator results in an assertion in debug,
// an undefined behavior otherwise.
const Iterator& operator++();
Iterator operator++(int) {
Iterator prev = *this;
++*this;
return prev;
}
// Compare with other iterators.
bool operator!=(const Iterator& _it) const {
return inner_ != _it.inner_ || outer_ != _it.outer_ || job_ != _it.job_;
}
bool operator==(const Iterator& _it) const {
return job_ == _it.job_ && outer_ == _it.outer_ && inner_ == _it.inner_;
}
// Dereferencing operators.
const Edge& operator*() const {
assert(*this != job_->end() && "Can't dereference end iterator.");
return edge_;
}
const Edge* operator->() const {
assert(*this != job_->end() && "Can't dereference end iterator.");
return &edge_;
}
private:
friend struct TrackTriggeringJob;
// Constructors used by the job.
explicit Iterator(const TrackTriggeringJob* _job);
struct End {};
Iterator(const TrackTriggeringJob* _job, End)
: job_(_job),
outer_(0.f),
inner_(-2) { // Can never be reached while looping.
}
// Job this iterator works on.
const TrackTriggeringJob* job_;
// Current value of the outer loop, aka a ratio cursor between from and to.
float outer_;
// Current value of the inner loop, aka a key frame index.
ptrdiff_t inner_;
// Latest evaluated edge.
Edge edge_;
};
// end() job function inline implementation.
inline TrackTriggeringJob::Iterator TrackTriggeringJob::end() const {
return Iterator(this, Iterator::End());
}
} // namespace animation
} // namespace ozz
#endif // OZZ_OZZ_ANIMATION_RUNTIME_TRACK_TRIGGERING_JOB_H_
@@ -0,0 +1,51 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#ifndef OZZ_OZZ_ANIMATION_RUNTIME_TRACK_TRIGGERING_JOB_TRAIT_H_
#define OZZ_OZZ_ANIMATION_RUNTIME_TRACK_TRIGGERING_JOB_TRAIT_H_
// Defines iterator traits required to use TrackTriggeringJob::Iterator
// with stl algorithms.
// This is a separate file from "track_triggering_job.h" to prevent everyone
// from including stl file <iterator>.
#include "ozz/animation/runtime/track_triggering_job.h"
#include <iterator>
// Specializes std::iterator_traits.
namespace std {
template <>
struct iterator_traits<ozz::animation::TrackTriggeringJob::Iterator> {
typedef ptrdiff_t difference_type;
typedef ozz::animation::TrackTriggeringJob::Edge value_type;
typedef const ozz::animation::TrackTriggeringJob::Edge* pointer;
typedef const ozz::animation::TrackTriggeringJob::Edge& reference;
typedef forward_iterator_tag iterator_category;
};
} // namespace std
#endif // OZZ_OZZ_ANIMATION_RUNTIME_TRACK_TRIGGERING_JOB_TRAIT_H_