AnimationCurve.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. //
  2. // AnimationCurve.h
  3. // cocos2d_libs
  4. //
  5. // Created by 徐俊杰 on 2020/5/15.
  6. //
  7. #ifndef AnimationCurve_h
  8. #define AnimationCurve_h
  9. #include "rparticle/Macros/RParticleMacros.h"
  10. #include "rparticle/Utilities/dynamic_array.h"
  11. //#include "SerializeUtility.h"
  12. #include "rparticle/Math/FloatConversion.h"
  13. //#include "Runtime/Math/Vector3.h"
  14. //#include "Runtime/Math/Quaternion.h"
  15. //#include "Runtime/Modules/ExportModules.h"
  16. //#include "rparticle/Serialize/TransferFunctions/SerializeTransfer.h"
  17. #include "rparticle/Serialize/SerializeUtility.h"
  18. NS_RRP_BEGIN
  19. enum { kDefaultWrapMode = 0, kClamp = 1 << 0, kRepeat = 1 << 1, kPingPong = 1 << 2, kClampForever = 1 << 3 };
  20. #define kCurveTimeEpsilon 0.00001F
  21. /*
  22. AnimationCurves in Maya are represented as time/value keys with 2D tangents which are always of normalized length.
  23. From the tangents a slope is calculated (tangent.y / tangent.x) -> (thus length of the tangent doesn't matter)
  24. When the slope is multiplied by the time range of the curve (rhs.time - lhs.time) it can be evaluated using
  25. a standard hermite interpolator.
  26. In the Unity AnimationCurve the slopes are directly stored in the keyframe instead of the 2D tangent vectors.
  27. */
  28. ///@TODO: Curve templates suck.
  29. /// Lets make some implementation where they share the same data structure and only Evaluate is specialized.
  30. template<class T>
  31. struct KeyframeTpl
  32. {
  33. // DECLARE_SERIALIZE_OPTIMIZE_TRANSFER (Keyframe)
  34. inline static const char* GetTypeString () { return "Keyframe"; }
  35. inline static bool IsAnimationChannel () { return false; }
  36. inline static bool MightContainPPtr () { return false; }
  37. // Disable transfer optimization in Editor because tangentMode optimized serialization when reading AssetBundles will corrupt data
  38. inline static bool AllowTransferOptimization ()
  39. {
  40. #if UNITY_EDITOR
  41. return false;
  42. #else
  43. return true;
  44. #endif
  45. }
  46. template<class TransferFunction>
  47. void Transfer (TransferFunction& transfer);
  48. float time;
  49. T value;
  50. T inSlope;
  51. T outSlope;
  52. //#if UNITY_EDITOR
  53. int tangentMode = 0;
  54. //#endif
  55. #if UNITY_EDITOR
  56. KeyframeTpl ()
  57. {
  58. tangentMode = 0;
  59. }
  60. #else
  61. KeyframeTpl () {}
  62. #endif
  63. KeyframeTpl (float t, const T& v);
  64. friend bool operator < (const KeyframeTpl& lhs, const KeyframeTpl& rhs) { return lhs.time < rhs.time; }
  65. };
  66. enum AnimationCurveType {
  67. kFloatCurve = 0,
  68. kVector3Curve = 1,
  69. kQuaternionCurve = 2
  70. };
  71. template<class T>
  72. class AnimationCurveTpl
  73. {
  74. public:
  75. //TODO: Serialize
  76. // DECLARE_SERIALIZE_NO_PPTR (AnimationCurve)
  77. template<class TransferFunction>
  78. void Transfer (TransferFunction& transfer);
  79. /// Stores the curve as a pure cubic function with 4 coefficients
  80. struct Cache
  81. {
  82. int index;
  83. float time;
  84. float timeEnd;
  85. T coeff[4];
  86. Cache () { time = std::numeric_limits<float>::infinity (); index=0; timeEnd = 0.0f; memset(&coeff, 0, sizeof(coeff)); }
  87. void Invalidate () { time = std::numeric_limits<float>::infinity (); index=0; }
  88. };
  89. typedef KeyframeTpl<T> Keyframe;
  90. typedef dynamic_array<Keyframe> KeyframeContainer;
  91. typedef typename KeyframeContainer::iterator iterator;
  92. typedef typename KeyframeContainer::const_iterator const_iterator;
  93. public:
  94. AnimationCurveTpl ()
  95. {
  96. m_PreInfinity = m_PostInfinity = kInternalClamp;
  97. }
  98. /// Evaluates the AnimationCurve caching the segment.
  99. T Evaluate (float curveT) const;
  100. T EvaluateClamp (float curveT) const;
  101. bool IsValid () const { return m_Curve.size () >= 2; }
  102. int AddKey (const Keyframe& key);
  103. /// Performs no error checking. And doesn't invalidate the cache!
  104. void AddKeyBackFast (const Keyframe& key) { m_Curve.push_back (key); }
  105. const Keyframe& GetKey (int index) const { AssertMsg(index >= 0 && index < m_Curve.size(), "Index (%d) is out of range [0, %i)", index, (int)m_Curve.size()); return m_Curve[index]; }
  106. /// When changing the keyframe using GetKey you are not allowed to change the time!
  107. /// After modifying a key you have to call InvalidateCache
  108. Keyframe& GetKey (int index) { AssertMsg(index >= 0 && index < m_Curve.size(), "Index (%d) is out of range [0, %i)", index, (int)m_Curve.size()); return const_cast<Keyframe&> (m_Curve[index]); }
  109. iterator begin () { return m_Curve.begin (); }
  110. iterator end () { return m_Curve.end (); }
  111. const_iterator begin () const { return m_Curve.begin (); }
  112. const_iterator end () const { return m_Curve.end (); }
  113. void InvalidateCache ();
  114. int GetKeyCount () const { return m_Curve.size (); }
  115. void RemoveKeys (iterator begin, iterator end);
  116. /// Returns the first and last keyframe time
  117. std::pair<float, float> GetRange () const;
  118. enum { kInternalPingPong = 0, kInternalRepeat = 1, kInternalClamp = 2 };
  119. // How does the curve before the first keyframe
  120. void SetPreInfinity (int pre);
  121. int GetPreInfinity () const;
  122. // How does the curve behave after the last keyframe
  123. void SetPostInfinity (int post);
  124. int GetPostInfinity () const;
  125. // How does the curve before the first keyframe
  126. void SetPreInfinityInternal (int pre) { m_PreInfinity = pre; InvalidateCache (); }
  127. int GetPreInfinityInternal () const { return m_PreInfinity; }
  128. // How does the curve behave after the last keyframe
  129. void SetPostInfinityInternal (int post) { m_PostInfinity = post; InvalidateCache (); }
  130. int GetPostInfinityInternal () const { return m_PostInfinity; }
  131. void Assign (const Keyframe* begin, const Keyframe* end) { m_Curve.assign (begin, end); InvalidateCache(); }
  132. void Swap (KeyframeContainer& newArray) { m_Curve.swap(newArray); InvalidateCache(); }
  133. void Sort () { std::sort(m_Curve.begin(), m_Curve.end()); InvalidateCache(); }
  134. void ResizeUninitialized (int size) { m_Curve.resize_uninitialized(size); }
  135. ///@TODO: Cleanup old code to completely get rid of this
  136. int FindIndex (const Cache& cache, float curveT) const;
  137. ///@TODO: Cleanup old code to completely get rid of this
  138. /// Returns the closest keyframe index that is less than time.
  139. /// Returns -1 if time is outside the range of the curve
  140. int FindIndex (float time) const;
  141. void CalculateCacheData (Cache& cache, int lhs, int rhs, float timeOffset) const;
  142. private:
  143. void FindIndexForSampling (const Cache& cache, float curveT, int& lhs, int& rhs) const;
  144. /// Evaluates the AnimationCurve directly.
  145. void EvaluateWithoutCache (float curveT, T& output)const;
  146. float WrapTime (float curveT) const;
  147. mutable Cache m_Cache;
  148. mutable Cache m_ClampCache;
  149. KeyframeContainer m_Curve;
  150. int m_PreInfinity;
  151. int m_PostInfinity;
  152. };
  153. typedef AnimationCurveTpl<float> AnimationCurveBase;
  154. typedef AnimationCurveTpl<float> AnimationCurve;
  155. typedef AnimationCurveTpl<Quaternionf> AnimationCurveQuat;
  156. typedef AnimationCurveTpl<Vector3f> AnimationCurveVec3;
  157. template<class T>
  158. template<class TransferFunction>
  159. inline void KeyframeTpl<T>::Transfer (TransferFunction& transfer)
  160. {
  161. TRANSFER (time);
  162. TRANSFER (value);
  163. TRANSFER (inSlope);
  164. TRANSFER (outSlope);
  165. #if UNITY_EDITOR
  166. if (!transfer.IsSerializingForGameRelease())
  167. TRANSFER (tangentMode);
  168. #endif
  169. }
  170. template<class T>
  171. template<class TransferFunction>
  172. inline void AnimationCurveTpl<T>::Transfer (TransferFunction& transfer)
  173. {
  174. transfer.SetVersion(2);
  175. //TODO: Transfer dynamic_array
  176. transfer.Transfer (m_Curve, "m_Curve");//, kHideInEditorMask);
  177. transfer.Transfer (m_PreInfinity, "m_PreInfinity");//, kHideInEditorMask);
  178. transfer.Transfer (m_PostInfinity, "m_PostInfinity");//, kHideInEditorMask);
  179. if (transfer.IsReading ())
  180. InvalidateCache ();
  181. }
  182. inline int TimeToFrame (float time, float sampleRate)
  183. {
  184. return RoundfToInt(time * sampleRate);
  185. }
  186. inline float FrameToTime (int frame, float sampleRate)
  187. {
  188. return (float)frame / sampleRate;
  189. }
  190. inline float FloatFrameToTime (float frame, float sampleRate)
  191. {
  192. return frame / sampleRate;
  193. }
  194. void HandleSteppedCurve (const KeyframeTpl<float>& lhs, const KeyframeTpl<float>& rhs, float& value);
  195. void HandleSteppedTangent (const KeyframeTpl<float>& lhs, const KeyframeTpl<float>& rhs, float& value);
  196. void HandleSteppedCurve (const KeyframeTpl<Vector3f>& lhs, const KeyframeTpl<Vector3f>& rhs, Vector3f& value);
  197. void HandleSteppedTangent (const KeyframeTpl<Vector3f>& lhs, const KeyframeTpl<Vector3f>& rhs, Vector3f& tangent);
  198. void HandleSteppedCurve (const KeyframeTpl<Quaternionf>& lhs, const KeyframeTpl<Quaternionf>& rhs, Quaternionf& tangent);
  199. void HandleSteppedTangent (const KeyframeTpl<Quaternionf>& lhs, const KeyframeTpl<Quaternionf>& rhs, Quaternionf& tangent);
  200. inline float PingPong (float t, float length)
  201. {
  202. t = Repeat (t, length * 2.0F);
  203. t = length - Abs (t - length);
  204. return t;
  205. }
  206. inline float Repeat (float t, float begin, float end)
  207. {
  208. return Repeat (t - begin, end - begin) + begin;
  209. }
  210. inline double RepeatD (double t, double begin, double end)
  211. {
  212. return RepeatD (t - begin, end - begin) + begin;
  213. }
  214. inline float PingPong (float t, float begin, float end)
  215. {
  216. return PingPong (t - begin, end - begin) + begin;
  217. }
  218. #if (defined(__GNUC__) && (__GNUC__ >= 4 && __GNUC_MINOR__ >= 3)) || defined(__clang__)
  219. // in GCC 4.3 and above the explicit template specialization cannot have a storage class
  220. #define SPEC_STORAGE_CLASS inline
  221. #else
  222. #define SPEC_STORAGE_CLASS static
  223. #endif
  224. #define kMaxTan 5729577.9485111479F
  225. template<class T>
  226. static T MaxTan () { return kMaxTan; }
  227. template<>
  228. SPEC_STORAGE_CLASS Quaternionf MaxTan<Quaternionf> () { return Quaternionf(kMaxTan, kMaxTan, kMaxTan, kMaxTan); }
  229. template<>
  230. SPEC_STORAGE_CLASS Vector3f MaxTan<Vector3f> () { return Vector3f(kMaxTan, kMaxTan, kMaxTan); }
  231. #undef kMaxTan
  232. template<class T>
  233. static T Zero () { return T (); }
  234. template<>
  235. SPEC_STORAGE_CLASS Quaternionf Zero<Quaternionf> () { return Quaternionf(0.0F, 0.0F, 0.0F, 0.0F); }
  236. template<>
  237. SPEC_STORAGE_CLASS Vector3f Zero<Vector3f> () { return Vector3f(0.0F, 0.0F, 0.0F); }
  238. #undef SPEC_STORAGE_CLASS
  239. void ScaleCurveValue (AnimationCurve& curve, float scale);
  240. void OffsetCurveValue (AnimationCurve& curve, float offset);
  241. void ScaleCurveTime (AnimationCurve& curve, float scale);
  242. void OffsetCurveTime (AnimationCurve& curve, float offset);
  243. template<class T>
  244. inline T HermiteInterpolate (float t, T p0, T m0, T m1, T p1)
  245. {
  246. float t2 = t * t;
  247. float t3 = t2 * t;
  248. float a = 2.0F * t3 - 3.0F * t2 + 1.0F;
  249. float b = t3 - 2.0F * t2 + t;
  250. float c = t3 - t2;
  251. float d = -2.0F * t3 + 3.0F * t2;
  252. return a * p0 + b * m0 + c * m1 + d * p1;
  253. }
  254. struct KeyframeCompare
  255. {
  256. template<class T>
  257. bool operator ()(KeyframeTpl<T> const& k, float t) { return k.time < t; }
  258. // These are necessary for debug STL (validation of predicates)
  259. template<class T>
  260. bool operator ()(KeyframeTpl<T> const& k1, KeyframeTpl<T> const& k2) { return k1.time < k2.time; }
  261. template<class T>
  262. bool operator ()(float t, KeyframeTpl<T> const& k) { return !operator() (k, t); }
  263. };
  264. NS_RRP_END
  265. #endif /* AnimationCurve_h */