mirror of https://github.com/mosra/magnum.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
758 lines
37 KiB
758 lines
37 KiB
#ifndef Magnum_Animation_Track_h |
|
#define Magnum_Animation_Track_h |
|
/* |
|
This file is part of Magnum. |
|
|
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 |
|
Vladimír Vondruš <mosra@centrum.cz> |
|
|
|
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. |
|
*/ |
|
|
|
/** @file |
|
* @brief Class @ref Magnum::Animation::Track, @ref Magnum::Animation::TrackViewStorage, @ref Magnum::Animation::TrackView |
|
*/ |
|
|
|
#include <Corrade/Containers/Array.h> |
|
|
|
#include "Magnum/Animation/Animation.h" |
|
#include "Magnum/Animation/Interpolation.h" |
|
#include "Magnum/Math/Range.h" |
|
|
|
namespace Magnum { namespace Animation { |
|
|
|
/** |
|
@brief Animation track |
|
@tparam K Key type |
|
@tparam V Value type |
|
@tparam R Result type |
|
|
|
Immutable storage of keyframe + value pairs. Usually used in combination with |
|
the @ref Player class, but it's possible to use it separately as well. |
|
|
|
@section Animation-Track-usage Basic usage |
|
|
|
Animation track is defined by a list of keyframes (time+value pairs), |
|
interpolator function and extrapolation behavior. |
|
|
|
@snippet MagnumAnimation.cpp Track-usage |
|
|
|
@section Animation-Track-interpolators Types and interpolators |
|
|
|
The track supports arbitrary types for keys, values and interpolators. These |
|
are common combinations: |
|
|
|
@m_class{m-fullwidth} |
|
|
|
Interpolation type | Value type | Result type | Interpolator |
|
------------------- | ----------------- | ------------- | ------------ |
|
Constant | any `V` | `V` | @ref Math::select() |
|
Linear | @cpp bool @ce <b></b> | @cpp bool @ce <b></b> | @ref Math::select() |
|
Linear | @ref Math::BoolVector | @ref Math::BoolVector | @ref Math::select() |
|
Linear | any scalar `V` | `V` | @ref Math::lerp() |
|
Linear | any vector `V` | `V` | @ref Math::lerp() |
|
Linear | @ref Math::Quaternion | @ref Math::Quaternion | @ref Math::lerp(const Quaternion<T>&, const Quaternion<T>&, T) "Math::lerp()" |
|
Spherical linear | @ref Math::Quaternion | @ref Math::Quaternion | @ref Math::slerp(const Quaternion<T>&, const Quaternion<T>&, T) "Math::slerp()" |
|
Screw linear | @ref Math::DualQuaternion | @ref Math::DualQuaternion | @ref Math::sclerp(const DualQuaternion<T>&, const DualQuaternion<T>&, T) "Math::sclerp()" |
|
|
|
It's also possible to supply a generic interpolation behavior by passing the |
|
@ref Interpolation enum to the constructor. In case the interpolator function |
|
is not passed in as well, it's autodetected using @ref interpolatorFor(). See |
|
its documentation for more information. The @ref Interpolation enum is then |
|
stored in @ref interpolation() and acts as a hint for desired interpolation |
|
behavior for users who might want to use their own interpolator. |
|
|
|
@section Animation-Track-performance Performance tuning |
|
|
|
The snippet shown above is convenience-oriented at a cost of sacrificing some |
|
performance. You have the following options: |
|
|
|
@subsection Animation-Track-performance-hint Keyframe hinting |
|
|
|
The @ref Track and @ref TrackView classes are fully stateless and the |
|
@ref at(K) const function performs a linear search for matching keyframe from |
|
the beginning every time. You can use @ref at(K, std::size_t&) const to |
|
remember last used keyframe index and pass it in the next iteration as a hint: |
|
|
|
@snippet MagnumAnimation.cpp Track-performance-hint |
|
|
|
@subsection Animation-Track-performance-strict Strict interpolation |
|
|
|
While it's possible to have different @ref Extrapolation modes for frames |
|
outside of the track range with graceful handling of single- or zero-frame |
|
animations, the additional checks have some impact. The @ref atStrict() has |
|
implicit @ref Extrapolation::Extrapolated behavior and assumes there are always |
|
at least two keyframes, resulting in more compact interpolation code. If your |
|
animation data satisfy the prerequisites, simply use it in place of @ref at(): |
|
|
|
@snippet MagnumAnimation.cpp Track-performance-strict |
|
|
|
@subsection Animation-Track-performance-cache Cache-efficient data layout |
|
|
|
Usually multiple tracks (translation, rotation, scaling) are combined together |
|
to form a single animation. In order to achieve better data layout, consider |
|
interleaving the data and passing them using |
|
@ref Corrade::Containers::StridedArrayView to multiple @ref TrackView |
|
instead of having data duplicated scattered across disjoint allocations of |
|
@ref Track instances: |
|
|
|
@snippet MagnumAnimation.cpp Track-performance-cache |
|
|
|
@subsection Animation-Track-performance-interpolator Interpolator function choice |
|
|
|
The interpolator function has a direct effect on animation performance. You can |
|
choose a less complex interpolator (constant instead of linear or linear |
|
instead of spheric linear, for example) either during construction or passing |
|
it directly to @ref at() / @ref atStrict(). The @ref interpolator() can act as |
|
a hint on what kind of function should be chosen. Depending on how the track |
|
was constructed, passing the interpolator directly to @ref at() / @ref atStrict() |
|
usually also results in it being inlined by the compiler and thus faster than |
|
an indirect function call. |
|
|
|
Note that when constructing the track by just passing @ref Interpolator to the |
|
constructor, the function is chosen by @ref interpolatorFor(), which favors |
|
correctness over performance. See its documentation for more information. |
|
@experimental |
|
*/ |
|
template<class K, class V, class R |
|
#ifdef DOXYGEN_GENERATING_OUTPUT |
|
= ResultOf<V> |
|
#endif |
|
> class Track { |
|
public: |
|
/** @brief Key type */ |
|
typedef K KeyType; |
|
|
|
/** @brief Value type */ |
|
typedef V ValueType; |
|
|
|
/** @brief Animation result type */ |
|
typedef R ResultType; |
|
|
|
/** @brief Interpolation function */ |
|
typedef ResultType(*Interpolator)(const ValueType&, const ValueType&, Float); |
|
|
|
/** |
|
* @brief Construct an empty track |
|
* |
|
* The @ref data(), @ref keys(), @ref values() and @ref interpolator() |
|
* functions return @cpp nullptr @ce, @ref at() always returns a |
|
* default-constructed value. |
|
*/ |
|
explicit Track() noexcept: _data{}, _interpolator{}, _before{}, _after{} {} |
|
|
|
/** |
|
* @brief Construct with custom interpolator |
|
* @param data Keyframe data |
|
* @param interpolator Interpolator function |
|
* @param before Extrapolation behavior |
|
* @param after Extrapolation behavior after |
|
* |
|
* The keyframe data are assumed to be stored in sorted order. It's not |
|
* an error to have two successive keyframes with the same frame value. |
|
* The @ref interpolation() field is set to @ref Interpolation::Custom. |
|
* See @ref Track(Containers::Array<std::pair<K, V>>&&, Interpolation, Interpolator, Extrapolation, Extrapolation) or |
|
* @ref Track(Containers::Array<std::pair<K, V>>&&, Interpolation, Extrapolation, Extrapolation) |
|
* for an alternative. |
|
*/ |
|
explicit Track(Containers::Array<std::pair<K, V>>&& data, Interpolator interpolator, Extrapolation before, Extrapolation after) noexcept: _data{std::move(data)}, _interpolator{interpolator}, _interpolation{Interpolation::Custom}, _before{before}, _after{after} {} |
|
|
|
/** @overload */ |
|
explicit Track(std::initializer_list<std::pair<K, V>> data, Interpolator interpolator, Extrapolation before, Extrapolation after): Track<K, V, R>{Containers::Array<std::pair<K, V>>{Containers::InPlaceInit, data}, interpolator, before, after} {} |
|
|
|
/** @overload |
|
* Equivalent to calling @ref Track(Containers::Array<std::pair<K, V>>&&, Interpolator, Extrapolation, Extrapolation) |
|
* with both @p before and @p after set to @p extrapolation. |
|
*/ |
|
explicit Track(Containers::Array<std::pair<K, V>>&& data, Interpolator interpolator, Extrapolation extrapolation = Extrapolation::Constant) noexcept: Track<K, V, R>{std::move(data), interpolator, extrapolation, extrapolation} {} |
|
|
|
/** @overload */ |
|
explicit Track(std::initializer_list<std::pair<K, V>> data, Interpolator interpolator, Extrapolation extrapolation = Extrapolation::Constant): Track<K, V, R>{Containers::Array<std::pair<K, V>>{Containers::InPlaceInit, data}, interpolator, extrapolation, extrapolation} {} |
|
|
|
/** |
|
* @brief Construct with both generic and custom interpolator |
|
* @param data Keyframe data |
|
* @param interpolation Interpolation behavior |
|
* @param interpolator Interpolator function |
|
* @param before Extrapolation behavior |
|
* @param after Extrapolation behavior after |
|
* |
|
* The keyframe data are assumed to be stored in sorted order. It's not |
|
* an error to have two successive keyframes with the same frame value. |
|
* @p interpolation acts as a behavior hint to users that might want to |
|
* supply their own interpolator function to @ref at() or |
|
* @ref atStrict(). |
|
*/ |
|
explicit Track(Containers::Array<std::pair<K, V>>&& data, Interpolation interpolation, Interpolator interpolator, Extrapolation before, Extrapolation after) noexcept: _data{std::move(data)}, _interpolator{interpolator}, _interpolation{interpolation}, _before{before}, _after{after} {} |
|
|
|
/** @overload */ |
|
explicit Track(std::initializer_list<std::pair<K, V>> data, Interpolation interpolation, Interpolator interpolator, Extrapolation before, Extrapolation after): Track<K, V, R>{Containers::Array<std::pair<K, V>>{Containers::InPlaceInit, data}, interpolation, interpolator, before, after} {} |
|
|
|
/** @overload |
|
* Equivalent to calling @ref Track(Containers::Array<std::pair<K, V>>&&, Interpolation, Interpolator, Extrapolation, Extrapolation) |
|
* with both @p before and @p after set to @p extrapolation. |
|
*/ |
|
explicit Track(Containers::Array<std::pair<K, V>>&& data, Interpolation interpolation, Interpolator interpolator, Extrapolation extrapolation = Extrapolation::Constant) noexcept: Track<K, V, R>{std::move(data), interpolation, interpolator, extrapolation, extrapolation} {} |
|
|
|
/** @overload */ |
|
explicit Track(std::initializer_list<std::pair<K, V>> data, Interpolation interpolation, Interpolator interpolator, Extrapolation extrapolation = Extrapolation::Constant): Track<K, V, R>{Containers::Array<std::pair<K, V>>{Containers::InPlaceInit, data}, interpolation, interpolator, extrapolation} {} |
|
|
|
/** |
|
* @brief Construct with generic interpolation behavior |
|
* @param data Keyframe data |
|
* @param interpolation Interpolation behavior |
|
* @param before Extrapolation behavior |
|
* @param after Extrapolation behavior after |
|
* |
|
* The keyframe data are assumed to be stored in sorted order. It's not |
|
* an error to have two successive keyframes with the same frame value. |
|
* The @ref interpolator() function is autodetected from |
|
* @p interpolation using @ref interpolatorFor(). See its documentation |
|
* for more information. |
|
*/ |
|
explicit Track(Containers::Array<std::pair<K, V>>&& data, Interpolation interpolation, Extrapolation before, Extrapolation after) noexcept: _data{std::move(data)}, _interpolator{interpolatorFor<V, R>(interpolation)}, _interpolation{interpolation}, _before{before}, _after{after} {} |
|
|
|
/** @overload */ |
|
explicit Track(std::initializer_list<std::pair<K, V>> data, Interpolation interpolation, Extrapolation before, Extrapolation after): Track<K, V, R>{Containers::Array<std::pair<K, V>>{Containers::InPlaceInit, data}, interpolation, before, after} {} |
|
|
|
/** @overload |
|
* Equivalent to calling @ref Track(Containers::Array<std::pair<K, V>>&&, Interpolation, Extrapolation, Extrapolation) |
|
* with both @p before and @p after set to @p extrapolation. |
|
*/ |
|
explicit Track(Containers::Array<std::pair<K, V>>&& data, Interpolation interpolation, Extrapolation extrapolation = Extrapolation::Constant) noexcept: Track<K, V, R>{std::move(data), interpolation, extrapolation, extrapolation} {} |
|
|
|
/** @overload */ |
|
explicit Track(std::initializer_list<std::pair<K, V>> data, Interpolation interpolation, Extrapolation extrapolation = Extrapolation::Constant): Track<K, V, R>{Containers::Array<std::pair<K, V>>{Containers::InPlaceInit, data}, interpolation, extrapolation, extrapolation} {} |
|
|
|
/** @brief Copying is not allowed */ |
|
Track(const Track<K, V, R>&) = delete; |
|
|
|
/** @brief Move constructor */ |
|
Track(Track<K, V, R>&&) = default; |
|
|
|
/** @brief Copying is not allowed */ |
|
Track<K, V, R>& operator=(const Track<K, V, R>&) = delete; |
|
|
|
/** @brief Move constructor */ |
|
Track<K, V, R>& operator=(Track<K, V, R>&&) = default; |
|
|
|
/** @brief Conversion to a view */ |
|
operator TrackView<K, V, R>() const noexcept { |
|
return TrackView<K, V, R>{_data, _interpolation, _interpolator, _before, _after}; |
|
} |
|
|
|
/** |
|
* @brief Interpolation behavior |
|
* |
|
* Acts as a behavior hint to users that might want to supply their own |
|
* interpolator function to @ref at() or @ref atStrict(). |
|
* @see @ref interpolator() |
|
*/ |
|
Interpolation interpolation() const { return _interpolation; } |
|
|
|
/** |
|
* @brief Interpolation function |
|
* |
|
* @see @ref interpolation() |
|
*/ |
|
Interpolator interpolator() const { return _interpolator; } |
|
|
|
/** |
|
* @brief Extrapolation behavior before first keyframe |
|
* |
|
* @see @ref after(), @ref at() |
|
*/ |
|
Extrapolation before() const { return _before; } |
|
|
|
/** |
|
* @brief Extrapolation behavior after last keyframe |
|
* |
|
* @see @ref before(), @ref at() |
|
*/ |
|
Extrapolation after() const { return _after; } |
|
|
|
/** |
|
* @brief Duration of the track |
|
* |
|
* Calculated from first and last keyframe. If there are no keyframes, |
|
* a default-constructed value is returned. Use @ref Math::join() to |
|
* calculate combined duration for a set of tracks. |
|
*/ |
|
Math::Range1D<K> duration() const { |
|
return _data.empty() ? Math::Range1D<K>{} : Math::Range1D<K>{_data.front().first, _data.back().first}; |
|
} |
|
|
|
/** @brief Keyframe count */ |
|
std::size_t size() const { return _data.size(); } |
|
|
|
/** |
|
* @brief Keyframe data |
|
* |
|
* @see @ref keys(), @ref values(), @ref operator[]() |
|
*/ |
|
Containers::ArrayView<const std::pair<K, V>> data() const { return _data; } |
|
|
|
/** |
|
* @brief Key data |
|
* |
|
* @see @ref data(), @ref values(), @ref operator[]() |
|
*/ |
|
Containers::StridedArrayView<const K> keys() const { |
|
return _data ? Containers::StridedArrayView<const K>{&_data[0].first, _data.size(), sizeof(std::pair<K, V>)} : nullptr; |
|
} |
|
|
|
/** |
|
* @brief Value data |
|
* |
|
* @see @ref data(), @ref keys(), @ref operator[]() |
|
*/ |
|
Containers::StridedArrayView<const V> values() const { |
|
return _data ? Containers::StridedArrayView<const V>{&_data[0].second, _data.size(), sizeof(std::pair<K, V>)} : nullptr; |
|
} |
|
|
|
/** |
|
* @brief Keyframe access |
|
* |
|
* @see @ref size() |
|
*/ |
|
const std::pair<K, V>& operator[](std::size_t i) const { return _data[i]; } |
|
|
|
/** |
|
* @brief Animated value at a given time |
|
* |
|
* Calls @ref interpolate(), see its documentation for more |
|
* information. Note that this function performs a linear search every |
|
* time, use @ref at(K, std::size_t&) const to supply a search hint. |
|
* @see @ref atStrict(K, std::size_t&) const, |
|
* @ref at(Interpolator, K) const |
|
*/ |
|
R at(K frame) const { |
|
std::size_t hint{}; |
|
return at(_interpolator, frame, hint); |
|
} |
|
|
|
/** |
|
* @brief Animated value at a given time |
|
* |
|
* Calls @ref interpolate(), see its documentation for more |
|
* information. |
|
* @see @ref at(K) const, @ref atStrict(K, std::size_t&) const, |
|
* @ref at(Interpolator, K, std::size_t&) const |
|
*/ |
|
R at(K frame, std::size_t& hint) const { |
|
return at(_interpolator, frame, hint); |
|
} |
|
|
|
/** |
|
* @brief Animated value at a given time |
|
* |
|
* Unlike @ref at(K) const calls @ref interpolate() with |
|
* @p interpolator, overriding the interpolator function set in |
|
* constructor. See its documentation for more information. |
|
* @see @ref at(K, std::size_t&) const, |
|
* @ref atStrict(Interpolator, K, std::size_t&) const |
|
*/ |
|
R at(Interpolator interpolator, K frame) const { |
|
std::size_t hint{}; |
|
return at(interpolator, frame, hint); |
|
} |
|
|
|
/** |
|
* @brief Animated value at a given time |
|
* |
|
* Unlike @ref at(K, std::size_t&) const calls @ref interpolate() with |
|
* @p interpolator, overriding the interpolator function set in |
|
* constructor. See its documentation for more information. |
|
* @see @ref atStrict(Interpolator, K, std::size_t&) const |
|
*/ |
|
R at(Interpolator interpolator, K frame, std::size_t& hint) const { |
|
return interpolate(keys(), values(), _before, _after, interpolator, frame, hint); |
|
} |
|
|
|
/** |
|
* @brief Animated value at a given time |
|
* |
|
* A faster version of @ref at(K, std::size_t&) const with some |
|
* restrictions. Calls @ref interpolateStrict(), see its documentation |
|
* for more information. |
|
* @see @ref atStrict(Interpolator, K, std::size_t&) const |
|
*/ |
|
R atStrict(K frame, std::size_t& hint) const { |
|
return atStrict(_interpolator, frame, hint); |
|
} |
|
|
|
/** |
|
* @brief Animated value at a given time |
|
* |
|
* Unlike @ref atStrict(K, std::size_t&) const calls @ref interpolate() |
|
* with @p interpolator, overriding the interpolator function set in |
|
* constructor. See its documentation for more information. |
|
* @see @ref at(K, std::size_t&) const |
|
*/ |
|
R atStrict(Interpolator interpolator, K frame, std::size_t& hint) const { |
|
return interpolateStrict(keys(), values(), interpolator, frame, hint); |
|
} |
|
|
|
private: |
|
Containers::Array<std::pair<K, V>> _data; |
|
Interpolator _interpolator; |
|
Interpolation _interpolation; |
|
Extrapolation _before, _after; |
|
}; |
|
|
|
/** |
|
@brief Type-erased track view storage |
|
|
|
Cast to @ref TrackView of correct type to get access to all members. |
|
@experimental |
|
*/ |
|
template<class K> class TrackViewStorage { |
|
public: |
|
/** @brief Key type */ |
|
typedef K KeyType; |
|
|
|
constexpr /*implicit*/ TrackViewStorage() noexcept: _keys{}, _values{}, _interpolator{}, _interpolation{}, _before{}, _after{} {} |
|
|
|
/** |
|
* @brief Interpolation behavior |
|
* |
|
* Acts as a behavior hint to users that might want to supply their own |
|
* interpolator function to @ref TrackView::at() or |
|
* @ref TrackView::atStrict(). |
|
* @see @ref TrackView::interpolator() |
|
*/ |
|
Interpolation interpolation() const { return _interpolation; } |
|
|
|
/** |
|
* @brief Extrapolation behavior before first keyframe |
|
* |
|
* @see @ref TrackView::after(), @ref TrackView::at(), |
|
* @ref TrackView::atStrict() |
|
*/ |
|
Extrapolation before() const { return _before; } |
|
|
|
/** |
|
* @brief Extrapolation behavior after last keyframe |
|
* |
|
* @see @ref TrackView::before(), @ref TrackView::at(), |
|
* @ref TrackView::atStrict() |
|
*/ |
|
Extrapolation after() const { return _after; } |
|
|
|
/** |
|
* @brief Duration of the track |
|
* |
|
* Calculated from first and last keyframe. If there are no keyframes, |
|
* a default-constructed value is returned. Use @ref Math::join() to |
|
* calculate combined duration for a set of tracks. |
|
*/ |
|
Math::Range1D<K> duration() const { |
|
return _keys.empty() ? Math::Range1D<K>{} : Math::Range1D<K>{_keys.front(), _keys.back()}; |
|
} |
|
|
|
/** @brief Keyframe count */ |
|
std::size_t size() const { |
|
return _keys.size(); |
|
} |
|
|
|
/** |
|
* @brief Key data |
|
* |
|
* @see @ref TrackView::values(), @ref TrackView::operator[]() |
|
*/ |
|
Containers::StridedArrayView<const K> keys() const { |
|
return _keys; |
|
} |
|
|
|
private: |
|
template<class, class, class> friend class TrackView; |
|
|
|
template<class V, class R> explicit TrackViewStorage(const Containers::StridedArrayView<const K>& keys, const Containers::StridedArrayView<const V>& values, Interpolation interpolation, R(*interpolator)(const V&, const V&, Float), Extrapolation before, Extrapolation after) noexcept: _keys{keys}, _values{reinterpret_cast<const Containers::StridedArrayView<const char>&>(values)}, _interpolator{reinterpret_cast<void(*)()>(interpolator)}, _interpolation{interpolation}, _before{before}, _after{after} {} |
|
|
|
Containers::StridedArrayView<const K> _keys; |
|
Containers::StridedArrayView<const char> _values; |
|
void(*_interpolator)(void); |
|
Interpolation _interpolation; |
|
Extrapolation _before, _after; |
|
}; |
|
|
|
/** |
|
@brief Animation track view |
|
@tparam K Key type |
|
@tparam V Value type |
|
@tparam R Result type |
|
|
|
Unlike @ref Track this is a non-owning view onto keyframe + value pairs. See |
|
its documentation for more information. |
|
@experimental |
|
*/ |
|
template<class K, class V, class R |
|
#ifdef DOXYGEN_GENERATING_OUTPUT |
|
= ResultOf<V> |
|
#endif |
|
> class TrackView: public TrackViewStorage<K> { |
|
public: |
|
/** @brief Value type */ |
|
typedef V ValueType; |
|
|
|
/** @brief Animation result type */ |
|
typedef R ResultType; |
|
|
|
/** @brief Interpolation function */ |
|
typedef ResultType(*Interpolator)(const ValueType&, const ValueType&, Float); |
|
|
|
/** |
|
* @brief Construct an empty track |
|
* |
|
* The @ref keys(), @ref values() and @ref interpolator() functions |
|
* return @cpp nullptr @ce, @ref at() always returns a |
|
* default-constructed value. |
|
*/ |
|
/*implicit*/ TrackView() noexcept {} |
|
|
|
/** |
|
* @brief Construct with custom interpolator |
|
* @param keys Frame keys |
|
* @param values Frame values |
|
* @param interpolator Interpolation function |
|
* @param before Extrapolation behavior before |
|
* @param after Extrapolation behavior after |
|
* |
|
* The keyframe data are assumed to be stored in sorted order. It's not |
|
* an error to have two successive keyframes with the same frame value. |
|
* The @ref interpolation() field is set to @ref Interpolation::Custom. |
|
* See @ref TrackView(const Containers::StridedArrayView<const K>&, const Containers::StridedArrayView<const V>&, Interpolation, Interpolator, Extrapolation, Extrapolation) or |
|
* @ref TrackView(const Containers::StridedArrayView<const K>&, const Containers::StridedArrayView<const V>&, Interpolation, Extrapolation, Extrapolation) |
|
* for an alternative. |
|
*/ |
|
/*implicit*/ TrackView(const Containers::StridedArrayView<const K>& keys, const Containers::StridedArrayView<const V>& values, Interpolator interpolator, Extrapolation before, Extrapolation after) noexcept: TrackViewStorage<K>{keys, values, Interpolation::Custom, interpolator, before, after} {} |
|
|
|
/** @overload |
|
* Equivalent to calling @ref TrackView(const Containers::StridedArrayView<const K>&, const Containers::StridedArrayView<const V>&, Interpolator, Extrapolation, Extrapolation) |
|
* with both @p before and @p after set to @p extrapolation. |
|
*/ |
|
/*implicit*/ TrackView(const Containers::StridedArrayView<const K>& keys, const Containers::StridedArrayView<const V>& values, Interpolator interpolator, Extrapolation extrapolation = Extrapolation::Extrapolated) noexcept: TrackView<K, V, R>{keys, values, interpolator, extrapolation, extrapolation} {} |
|
|
|
/** |
|
* @brief Construct with custom interpolator from an interleaved array |
|
* @param data Keyframe data |
|
* @param interpolator Interpolation function |
|
* @param before Extrapolation behavior before |
|
* @param after Extrapolation behavior after |
|
* |
|
* Converts @p data to a pair of strided array views and calls |
|
* @ref TrackView(const Containers::StridedArrayView<const K>&, const Containers::StridedArrayView<const V>&, Interpolator, Extrapolation, Extrapolation). |
|
*/ |
|
/*implicit*/ TrackView(Containers::ArrayView<const std::pair<K, V>> data, Interpolator interpolator, Extrapolation before, Extrapolation after) noexcept: TrackView<K, V, R>{Containers::StridedArrayView<const K>{data ? &data[0].first : nullptr, data.size(), sizeof(std::pair<K, V>)}, Containers::StridedArrayView<const V>{data ? &data[0].second : nullptr, data.size(), sizeof(std::pair<K, V>)}, interpolator, before, after} {} |
|
|
|
/** @overload |
|
* Equivalent to calling @ref TrackView(Containers::ArrayView<const std::pair<K, V>>, Interpolator, Extrapolation, Extrapolation) |
|
* with both @p before and @p after set to @p extrapolation. |
|
*/ |
|
explicit TrackView(Containers::ArrayView<const std::pair<K, V>> data, Interpolator interpolator, Extrapolation extrapolation = Extrapolation::Extrapolated) noexcept: TrackView<K, V, R>{data, interpolator, extrapolation, extrapolation} {} |
|
|
|
/** |
|
* @brief Construct with both generic and custom interpolator |
|
* @param keys Frame keys |
|
* @param values Frame values |
|
* @param interpolation Interpolation behavior |
|
* @param interpolator Interpolator function |
|
* @param before Extrapolation behavior before |
|
* @param after Extrapolation behavior after |
|
* |
|
* The keyframe data are assumed to be stored in sorted order. It's not |
|
* an error to have two successive keyframes with the same frame value. |
|
* @p interpolation acts as a behavior hint to users that might want to |
|
* supply their own interpolator function to @ref at() or |
|
* @ref atStrict(). |
|
*/ |
|
/*implicit*/ TrackView(const Containers::StridedArrayView<const K>& keys, const Containers::StridedArrayView<const V>& values, Interpolation interpolation, Interpolator interpolator, Extrapolation before, Extrapolation after) noexcept: TrackViewStorage<K>{keys, values, interpolation, interpolator, before, after} {} |
|
|
|
/** @overload |
|
* Equivalent to calling @ref TrackView(const Containers::StridedArrayView<const K>&, const Containers::StridedArrayView<const V>&, Interpolation, Interpolator, Extrapolation, Extrapolation) |
|
* with both @p before and @p after set to @p extrapolation. |
|
*/ |
|
/*implicit*/ TrackView(const Containers::StridedArrayView<const K>& keys, const Containers::StridedArrayView<const V>& values, Interpolation interpolation, Interpolator interpolator, Extrapolation extrapolation = Extrapolation::Extrapolated) noexcept: TrackView<K, V, R>{keys, values, interpolation, interpolator, extrapolation, extrapolation} {} |
|
|
|
/** |
|
* @brief Construct with both generic and custom interpolator from an interleaved array |
|
* @param data Keyframe data |
|
* @param interpolation Interpolation behavior |
|
* @param interpolator Interpolator function |
|
* @param before Extrapolation behavior before |
|
* @param after Extrapolation behavior after |
|
* |
|
* Converts @p data to a pair of strided array views and calls |
|
* @ref TrackView(const Containers::StridedArrayView<const K>&, const Containers::StridedArrayView<const V>&, Interpolator, Extrapolation, Extrapolation). |
|
*/ |
|
/*implicit*/ TrackView(Containers::ArrayView<const std::pair<K, V>> data, Interpolation interpolation, Interpolator interpolator, Extrapolation before, Extrapolation after) noexcept: TrackViewStorage<K>{Containers::StridedArrayView<const K>{data ? &data[0].first : nullptr, data.size(), sizeof(std::pair<K, V>)}, Containers::StridedArrayView<const V>{data ? &data[0].second : nullptr, data.size(), sizeof(std::pair<K, V>)}, interpolation, interpolator, before, after} {} |
|
|
|
/** @overload |
|
* Equivalent to calling @ref TrackView(Containers::ArrayView<const std::pair<K, V>>, Interpolation, Interpolator, Extrapolation, Extrapolation) |
|
* with both @p before and @p after set to @p extrapolation. |
|
*/ |
|
/*implicit*/ TrackView(Containers::ArrayView<const std::pair<K, V>> data, Interpolation interpolation, Interpolator interpolator, Extrapolation extrapolation = Extrapolation::Extrapolated) noexcept: TrackView<K, V, R>{data, interpolation, interpolator, extrapolation, extrapolation} {} |
|
|
|
/** |
|
* @brief Construct with generic interpolation behavior |
|
* @param keys Frame keys |
|
* @param values Frame values |
|
* @param interpolation Interpolation behavior |
|
* @param before Extrapolation behavior before |
|
* @param after Extrapolation behavior after |
|
* |
|
* The keyframe data are assumed to be stored in sorted order. It's not |
|
* an error to have two successive keyframes with the same frame value. |
|
* The @ref interpolator() function is autodetected from |
|
* @p interpolation using @ref interpolatorFor(). See its documentation |
|
* for more information. |
|
*/ |
|
/*implicit*/ TrackView(const Containers::StridedArrayView<const K>& keys, const Containers::StridedArrayView<const V>& values, Interpolation interpolation, Extrapolation before, Extrapolation after) noexcept: TrackViewStorage<K>{keys, values, interpolation, interpolatorFor<V, R>(interpolation), before, after} {} |
|
|
|
/** @overload |
|
* Equivalent to calling @ref TrackView(const Containers::StridedArrayView<const K>&, const Containers::StridedArrayView<const V>&, Interpolation, Extrapolation, Extrapolation) |
|
* with both @p before and @p after set to @p extrapolation. |
|
*/ |
|
/*implicit*/ TrackView(const Containers::StridedArrayView<const K>& keys, const Containers::StridedArrayView<const V>& values, Interpolation interpolation, Extrapolation extrapolation = Extrapolation::Extrapolated) noexcept: TrackView<K, V, R>{keys, values, interpolation, extrapolation, extrapolation} {} |
|
|
|
/** |
|
* @brief Construct with generic interpolation behavior from an interleaved array |
|
* @param data Keyframe data |
|
* @param interpolation Interpolation behavior |
|
* @param before Extrapolation behavior before |
|
* @param after Extrapolation behavior after |
|
* |
|
* Converts @p data to a pair of strided array views and calls |
|
* @ref TrackView(const Containers::StridedArrayView<const K>&, const Containers::StridedArrayView<const V>&, Interpolator, Extrapolation, Extrapolation). |
|
*/ |
|
/*implicit*/ TrackView(Containers::ArrayView<const std::pair<K, V>> data, Interpolation interpolation, Extrapolation before, Extrapolation after) noexcept: TrackView<K, V, R>{Containers::StridedArrayView<const K>{data ? &data[0].first : nullptr, data.size(), sizeof(std::pair<K, V>)}, Containers::StridedArrayView<const V>{data ? &data[0].second : nullptr, data.size(), sizeof(std::pair<K, V>)}, interpolation, before, after} {} |
|
|
|
/** @overload |
|
* Equivalent to calling @ref TrackView(Containers::ArrayView<const std::pair<K, V>>, Interpolation, Extrapolation, Extrapolation) |
|
* with both @p before and @p after set to @p extrapolation. |
|
*/ |
|
/*implicit*/ TrackView(Containers::ArrayView<const std::pair<K, V>> data, Interpolation interpolation, Extrapolation extrapolation = Extrapolation::Extrapolated) noexcept: TrackView<K, V, R>{data, interpolation, extrapolation, extrapolation} {} |
|
|
|
/** |
|
* @brief Interpolation function |
|
* |
|
* @see @ref interpolation() |
|
*/ |
|
Interpolator interpolator() const { |
|
return reinterpret_cast<Interpolator>(TrackViewStorage<K>::_interpolator); |
|
} |
|
|
|
/** |
|
* @brief Value data |
|
* |
|
* @see @ref keys(), @ref operator[]() |
|
*/ |
|
Containers::StridedArrayView<const V> values() const { |
|
return reinterpret_cast<const Containers::StridedArrayView<const V>&>(TrackViewStorage<K>::_values); |
|
} |
|
|
|
/** |
|
* @brief Keyframe access |
|
* |
|
* @see @ref size() |
|
*/ |
|
std::pair<K, V> operator[](std::size_t i) const { |
|
return {TrackViewStorage<K>::_keys[i], values()[i]}; |
|
} |
|
|
|
/** |
|
* @brief Animated value at a given time |
|
* |
|
* Calls @ref interpolate(), see its documentation for more |
|
* information. Note that this function performs a linear search every |
|
* time, use @ref at(K, std::size_t&) const to supply a search hint. |
|
* @see @ref atStrict(K, std::size_t&) const, |
|
* @ref at(Interpolator, K) const |
|
*/ |
|
R at(K frame) const { |
|
std::size_t hint{}; |
|
return at(interpolator(), frame, hint); |
|
} |
|
|
|
/** |
|
* @brief Animated value at a given time |
|
* |
|
* Calls @ref interpolate(), see its documentation for more |
|
* information. |
|
* @see @ref at(K) const, @ref atStrict(K, std::size_t&) const, |
|
* @ref at(Interpolator, K, std::size_t&) const |
|
*/ |
|
R at(K frame, std::size_t& hint) const { |
|
return at(interpolator(), frame, hint); |
|
} |
|
|
|
/** |
|
* @brief Animated value at a given time |
|
* |
|
* Unlike @ref at(K) const calls @ref interpolate() with |
|
* @p interpolator, overriding the interpolator function set in |
|
* constructor. See its documentation for more information. |
|
* @see @ref at(K, std::size_t&) const, |
|
* @ref atStrict(Interpolator, K, std::size_t&) const |
|
*/ |
|
R at(Interpolator interpolator, K frame) const { |
|
std::size_t hint{}; |
|
return at(interpolator, frame, hint); |
|
} |
|
|
|
/** |
|
* @brief Animated value at a given time |
|
* |
|
* Unlike @ref at(K, std::size_t&) const calls @ref interpolate() with |
|
* @p interpolator, overriding the interpolator function set in |
|
* constructor. See its documentation for more information. |
|
* @see @ref atStrict(Interpolator, K, std::size_t&) const |
|
*/ |
|
R at(Interpolator interpolator, K frame, std::size_t& hint) const { |
|
return interpolate(TrackViewStorage<K>::_keys, values(), TrackViewStorage<K>::_before, TrackViewStorage<K>::_after, interpolator, frame, hint); |
|
} |
|
|
|
/** |
|
* @brief Animated value at a given time |
|
* |
|
* A faster version of @ref at(K, std::size_t&) const with some |
|
* restrictions. Calls @ref interpolateStrict(), see its documentation |
|
* for more information. |
|
* @see @ref atStrict(Interpolator, K, std::size_t&) const |
|
*/ |
|
R atStrict(K frame, std::size_t& hint) const { |
|
return atStrict(interpolator(), frame, hint); |
|
} |
|
|
|
/** |
|
* @brief Animated value at a given time |
|
* |
|
* Unlike @ref atStrict(K, std::size_t&) const calls @ref interpolate() |
|
* with @p interpolator, overriding the interpolator function set in |
|
* constructor. See its documentation for more information. |
|
* @see @ref at(K, std::size_t&) const |
|
*/ |
|
R atStrict(Interpolator interpolator, K frame, std::size_t& hint) const { |
|
return interpolateStrict(TrackViewStorage<K>::_keys, values(), interpolator, frame, hint); |
|
} |
|
}; |
|
|
|
}} |
|
|
|
#endif
|
|
|