afxAnimCurve.cpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
  2. // Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
  3. // Copyright (C) 2015 Faust Logic, Inc.
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to
  7. // deal in the Software without restriction, including without limitation the
  8. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9. // sell copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  21. // IN THE SOFTWARE.
  22. //
  23. //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
  24. #include "afx/arcaneFX.h"
  25. #include "afx/util/afxAnimCurve.h"
  26. afxAnimCurve::afxAnimCurve() : usable( false ), final_value( 0.0f ), start_value( 0.0f )
  27. {
  28. evaluator = new afxHermiteEval();
  29. final_time = 0.0f;
  30. start_time = 0.0f;
  31. }
  32. afxAnimCurve::~afxAnimCurve()
  33. {
  34. delete evaluator;
  35. }
  36. void afxAnimCurve::addKey( Point2F &v )
  37. {
  38. Key k;
  39. k.time = v.x;
  40. k.value = v.y;
  41. keys.push_back( k );
  42. usable = false;
  43. }
  44. void afxAnimCurve::addKey( F32 time, F32 value )
  45. {
  46. Key k;
  47. k.time = time;
  48. k.value = value;
  49. keys.push_back( k );
  50. usable = false;
  51. }
  52. void afxAnimCurve::setKeyTime( int index, F32 t )
  53. {
  54. if( ( index < 0 ) || ( index >= keys.size() ) )
  55. return;
  56. Key &k = keys[index];
  57. k.time = t;
  58. usable = false;
  59. }
  60. void afxAnimCurve::setKeyValue( int index, F32 v )
  61. {
  62. if( ( index < 0 ) || ( index >= keys.size() ) )
  63. return;
  64. Key &k = keys[index];
  65. k.value = v;
  66. if( index == 0 )
  67. start_value = v;
  68. else if( index == keys.size()-1 )
  69. final_value = v;
  70. }
  71. //bool afxAnimCurve::compare_Key( const afxAnimCurve::Key &a, const afxAnimCurve::Key &b )
  72. //{
  73. // return a.time < b.time;
  74. //}
  75. S32 QSORT_CALLBACK afxAnimCurve::compare_Key( const void* a, const void* b )
  76. {
  77. const Key *key_a = (Key *)a;
  78. const Key *key_b = (Key *)b;
  79. //Con::printf( "*** %f %f", key_a->time, key_b->time );
  80. //return key_a->time < key_b->time;
  81. if (key_a->time > key_b->time)
  82. return 1;
  83. else if (key_a->time < key_b->time)
  84. return -1;
  85. else
  86. return 0;
  87. }
  88. void afxAnimCurve::sort( )
  89. {
  90. if( keys.size() == 0 )
  91. return;
  92. //std::sort( keys.begin(), keys.end(), afxAnimCurve::compare_Key );
  93. dQsort( keys.address(), keys.size(), sizeof(Key), afxAnimCurve::compare_Key );
  94. start_value = keys[0].value;
  95. final_value = keys[keys.size()-1].value;
  96. start_time = keys[0].time;
  97. final_time = keys[keys.size()-1].time;
  98. usable = true;
  99. }
  100. int afxAnimCurve::numKeys()
  101. {
  102. return keys.size();
  103. }
  104. F32 afxAnimCurve::getKeyTime( int index )
  105. {
  106. if( ( index < 0 ) || ( index >= keys.size() ) )
  107. return 0.0f;
  108. Key &k = keys[index];
  109. return k.time;
  110. }
  111. F32 afxAnimCurve::getKeyValue( int index )
  112. {
  113. if( ( index < 0 ) || ( index >= keys.size() ) )
  114. return 0.0f;
  115. Key &k = keys[index];
  116. return k.value;
  117. }
  118. Point2F afxAnimCurve::getSegment( F32 time )
  119. {
  120. Point2F segment( 0, 0 );
  121. if( keys.size() == 0 )
  122. return segment;
  123. int start_index = 0;
  124. for( ; start_index < keys.size()-1; start_index++ )
  125. {
  126. if( time < keys[start_index+1].time )
  127. break;
  128. }
  129. int end_index = start_index+1;
  130. segment.x = (F32)start_index;
  131. segment.y = (F32)end_index;
  132. return segment;
  133. }
  134. F32 afxAnimCurve::evaluate( F32 time )
  135. {
  136. if( !usable )
  137. return 0.0f;
  138. if( time <= start_time )
  139. return start_value;
  140. if( time >= final_time )
  141. return final_value;
  142. if( keys.size() == 1 )
  143. return start_value;
  144. int start_index = 0;
  145. for( ; start_index < keys.size()-1; start_index++ )
  146. {
  147. if( time < keys[start_index+1].time )
  148. break;
  149. }
  150. int end_index = start_index+1;
  151. Key k0 = keys[start_index];
  152. Key k1 = keys[end_index];
  153. Point2F v0( (F32) k0.time, k0.value );
  154. Point2F v1( (F32) k1.time, k1.value );
  155. // Compute tangents
  156. Point2F tan0 = computeTangentK0( v0, v1, start_index );
  157. Point2F tan1 = computeTangentK1( v0, v1, end_index );
  158. F32 time_perc = (F32)( time - k0.time ) / (F32)( k1.time - k0.time );
  159. Point2F vnew = evaluator->evaluateCurve( v0,
  160. v1,
  161. tan0,
  162. tan1,
  163. time_perc );
  164. return vnew.y;
  165. }
  166. Point2F afxAnimCurve::computeTangentK0( Point2F &k0, Point2F &k1, int start_index )
  167. {
  168. Point2F tan0;
  169. Point2F k_prev;
  170. Point2F k_next;
  171. // tangent for k0
  172. if( start_index == 0 )
  173. {
  174. k_prev = k0; // Setting previous point to k0, creating a hidden point in
  175. // the same spot
  176. k_next = k1;
  177. }
  178. else
  179. {
  180. Key &k = keys[start_index-1];
  181. k_prev.set( k.time, k.value );
  182. k_next = k1;
  183. }
  184. tan0 = k_next-k_prev; //k_next.subtract( k_prev );
  185. tan0 *= .5f;
  186. return tan0;
  187. }
  188. Point2F afxAnimCurve::computeTangentK1( Point2F &k0, Point2F &k1, int end_index )
  189. {
  190. Point2F tan1;
  191. Point2F k_prev;
  192. Point2F k_next;
  193. // tangent for k1
  194. if( end_index == keys.size()-1 )
  195. {
  196. k_prev = k0;
  197. k_next = k1; // Setting next point to k1, creating a hidden point in
  198. // the same spot
  199. }
  200. else
  201. {
  202. k_prev = k0;
  203. Key &k = keys[end_index+1];
  204. k_next.set( k.time, k.value );
  205. }
  206. tan1 = k_next-k_prev; //k_next.subtract( k_prev );
  207. tan1 *= .5f;
  208. return tan1;
  209. }
  210. void afxAnimCurve::print()
  211. {
  212. Con::printf( "afxAnimCurve -------------------------" );
  213. for( int i = 0; i < keys.size(); i++ )
  214. {
  215. Key &k = keys[i];
  216. Con::printf( "%f: %f", k.time, k.value );
  217. }
  218. Con::printf( "-----------------------------------" );
  219. }
  220. void afxAnimCurve::printKey( int index )
  221. {
  222. Key &k = keys[index];
  223. Con::printf( "%f: %f", k.time, k.value );
  224. }