123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282 |
- //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
- // Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
- // Copyright (C) 2015 Faust Logic, Inc.
- //
- // 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.
- //
- //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
- #include "afx/arcaneFX.h"
- #include "afx/util/afxAnimCurve.h"
- afxAnimCurve::afxAnimCurve() : usable( false ), final_value( 0.0f ), start_value( 0.0f )
- {
- evaluator = new afxHermiteEval();
- final_time = 0.0f;
- start_time = 0.0f;
- }
- afxAnimCurve::~afxAnimCurve()
- {
- delete evaluator;
- }
- void afxAnimCurve::addKey( Point2F &v )
- {
- Key k;
- k.time = v.x;
- k.value = v.y;
-
- keys.push_back( k );
- usable = false;
- }
- void afxAnimCurve::addKey( F32 time, F32 value )
- {
- Key k;
- k.time = time;
- k.value = value;
-
- keys.push_back( k );
- usable = false;
- }
- void afxAnimCurve::setKeyTime( int index, F32 t )
- {
- if( ( index < 0 ) || ( index >= keys.size() ) )
- return;
- Key &k = keys[index];
- k.time = t;
- usable = false;
- }
- void afxAnimCurve::setKeyValue( int index, F32 v )
- {
- if( ( index < 0 ) || ( index >= keys.size() ) )
- return;
- Key &k = keys[index];
- k.value = v;
- if( index == 0 )
- start_value = v;
- else if( index == keys.size()-1 )
- final_value = v;
- }
- //bool afxAnimCurve::compare_Key( const afxAnimCurve::Key &a, const afxAnimCurve::Key &b )
- //{
- // return a.time < b.time;
- //}
- S32 QSORT_CALLBACK afxAnimCurve::compare_Key( const void* a, const void* b )
- {
- const Key *key_a = (Key *)a;
- const Key *key_b = (Key *)b;
- //Con::printf( "*** %f %f", key_a->time, key_b->time );
- //return key_a->time < key_b->time;
-
- if (key_a->time > key_b->time)
- return 1;
- else if (key_a->time < key_b->time)
- return -1;
- else
- return 0;
- }
- void afxAnimCurve::sort( )
- {
- if( keys.size() == 0 )
- return;
- //std::sort( keys.begin(), keys.end(), afxAnimCurve::compare_Key );
- dQsort( keys.address(), keys.size(), sizeof(Key), afxAnimCurve::compare_Key );
-
- start_value = keys[0].value;
- final_value = keys[keys.size()-1].value;
- start_time = keys[0].time;
- final_time = keys[keys.size()-1].time;
- usable = true;
- }
- int afxAnimCurve::numKeys()
- {
- return keys.size();
- }
- F32 afxAnimCurve::getKeyTime( int index )
- {
- if( ( index < 0 ) || ( index >= keys.size() ) )
- return 0.0f;
- Key &k = keys[index];
- return k.time;
- }
- F32 afxAnimCurve::getKeyValue( int index )
- {
- if( ( index < 0 ) || ( index >= keys.size() ) )
- return 0.0f;
- Key &k = keys[index];
- return k.value;
- }
- Point2F afxAnimCurve::getSegment( F32 time )
- {
- Point2F segment( 0, 0 );
- if( keys.size() == 0 )
- return segment;
- int start_index = 0;
- for( ; start_index < keys.size()-1; start_index++ )
- {
- if( time < keys[start_index+1].time )
- break;
- }
- int end_index = start_index+1;
- segment.x = (F32)start_index;
- segment.y = (F32)end_index;
- return segment;
- }
- F32 afxAnimCurve::evaluate( F32 time )
- {
- if( !usable )
- return 0.0f;
-
- if( time <= start_time )
- return start_value;
-
- if( time >= final_time )
- return final_value;
- if( keys.size() == 1 )
- return start_value;
- int start_index = 0;
- for( ; start_index < keys.size()-1; start_index++ )
- {
- if( time < keys[start_index+1].time )
- break;
- }
- int end_index = start_index+1;
- Key k0 = keys[start_index];
- Key k1 = keys[end_index];
- Point2F v0( (F32) k0.time, k0.value );
- Point2F v1( (F32) k1.time, k1.value );
- // Compute tangents
- Point2F tan0 = computeTangentK0( v0, v1, start_index );
- Point2F tan1 = computeTangentK1( v0, v1, end_index );
- F32 time_perc = (F32)( time - k0.time ) / (F32)( k1.time - k0.time );
- Point2F vnew = evaluator->evaluateCurve( v0,
- v1,
- tan0,
- tan1,
- time_perc );
- return vnew.y;
- }
- Point2F afxAnimCurve::computeTangentK0( Point2F &k0, Point2F &k1, int start_index )
- {
- Point2F tan0;
-
- Point2F k_prev;
- Point2F k_next;
- // tangent for k0
- if( start_index == 0 )
- {
- k_prev = k0; // Setting previous point to k0, creating a hidden point in
- // the same spot
- k_next = k1;
- }
- else
- {
- Key &k = keys[start_index-1];
- k_prev.set( k.time, k.value );
- k_next = k1;
- }
- tan0 = k_next-k_prev; //k_next.subtract( k_prev );
- tan0 *= .5f;
- return tan0;
- }
- Point2F afxAnimCurve::computeTangentK1( Point2F &k0, Point2F &k1, int end_index )
- {
- Point2F tan1;
-
- Point2F k_prev;
- Point2F k_next;
- // tangent for k1
- if( end_index == keys.size()-1 )
- {
- k_prev = k0;
- k_next = k1; // Setting next point to k1, creating a hidden point in
- // the same spot
- }
- else
- {
- k_prev = k0;
- Key &k = keys[end_index+1];
- k_next.set( k.time, k.value );
- }
- tan1 = k_next-k_prev; //k_next.subtract( k_prev );
- tan1 *= .5f;
- return tan1;
- }
- void afxAnimCurve::print()
- {
- Con::printf( "afxAnimCurve -------------------------" );
- for( int i = 0; i < keys.size(); i++ )
- {
- Key &k = keys[i];
- Con::printf( "%f: %f", k.time, k.value );
- }
- Con::printf( "-----------------------------------" );
- }
- void afxAnimCurve::printKey( int index )
- {
- Key &k = keys[index];
- Con::printf( "%f: %f", k.time, k.value );
- }
|