Torque3D Documentation / _generateds / afxAnimCurve.cpp

afxAnimCurve.cpp

Engine/source/afx/util/afxAnimCurve.cpp

More...

Detailed Description

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