Created
August 13, 2012 20:06
-
-
Save finlaybob/3343751 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #pragma once | |
| #ifndef SHIFTERS_H | |
| #define SHIFTERS_H | |
| /** | |
| * This work is licensed under a Creative Commons, | |
| * Attribution-NonCommercial-ShareAlike 3.0 Unported License. | |
| * http://creativecommons.org/licenses/by-nc-sa/3.0/ | |
| * | |
| * You may copy, tweak, and build upon this work non-commercially | |
| * as long as 1. The author is credited and 2. You license the modified | |
| * creations under identical terms. | |
| * | |
| * | |
| * This library allows you to obtain a variety of different movements or | |
| * "tween". I hate that word with the fire of a thousand suns. So I've | |
| * called them Shifters instead. | |
| * | |
| * There are: | |
| * Linear, Quadratic, Cubic, Sinusoidal and Circular. These ease in and | |
| * out. | |
| * | |
| * ElasticOut only eases out for now. | |
| * | |
| * To get one: | |
| * Shifters::Linear<glm::vec3> position; | |
| **/ | |
| #ifndef PI | |
| #define PI 3.14159265359 | |
| #endif | |
| #include "glm/glm.hpp" | |
| namespace Shifter | |
| { | |
| template <class T> | |
| class Linear{ | |
| public: | |
| T current; | |
| T target; | |
| float duration; | |
| T out; | |
| float t; | |
| bool finished; | |
| Linear(T cur,T tgt, float dur): current(cur), target(tgt), duration(dur) | |
| { | |
| t = 0; | |
| finished = false; | |
| } | |
| T getVal(){ | |
| if (t<duration && !finished) | |
| { | |
| out = ((target-current)*(t/duration))+(current); | |
| } | |
| else | |
| { | |
| out = target; | |
| finished = true; | |
| } | |
| t++; | |
| return out; | |
| } | |
| void reset(T cur,T tgt, float dur){ | |
| current = cur; | |
| target = tgt; | |
| duration = dur; | |
| finished = false; | |
| t=0; | |
| } | |
| }; | |
| template <class T> | |
| class Quadratic{ | |
| public: | |
| T current; | |
| T target; | |
| float duration; | |
| T out; | |
| float t; | |
| bool finished; | |
| Quadratic(T cur,T tgt, float dur): current(cur), target(tgt), duration(dur) | |
| { | |
| t = 0; | |
| finished = false; | |
| } | |
| T getVal() | |
| { | |
| T c = (target-current); | |
| T b = current; | |
| if(t<duration && !finished){ | |
| float _t = t/(duration/2); | |
| if (_t < 1) | |
| { | |
| out = (c*0.5f)*_t*_t + b; | |
| }else{ | |
| _t--; | |
| out = (-c*0.5f) * (_t*(_t-2) - 1) + b; | |
| } | |
| t++; | |
| }else{ | |
| out = target; | |
| finished = true; | |
| } | |
| return out; | |
| } | |
| void reset(T cur,T tgt, float dur){ | |
| current = cur; | |
| target = tgt; | |
| duration = dur; | |
| finished = false; | |
| t=0; | |
| } | |
| }; | |
| template <class T> | |
| class Cubic{ | |
| public: | |
| T current; | |
| T target; | |
| float duration; | |
| T out; | |
| float t; | |
| bool finished; | |
| Cubic(T cur,T tgt, float dur): current(cur), target(tgt), duration(dur) | |
| { | |
| t = 0; | |
| finished = false; | |
| } | |
| T getVal() | |
| { | |
| T c = (target-current); | |
| T b = current; | |
| if(t<duration && !finished){ | |
| float _t = t/(duration/2); | |
| if (_t < 1) | |
| { | |
| out = (c*0.5f)*_t*_t*_t + b; | |
| }else{ | |
| _t-=2; | |
| out = (c*0.5f) * (_t*_t*_t + 2) + b; | |
| } | |
| t++; | |
| }else{ | |
| out = target; | |
| finished = true; | |
| } | |
| return out; | |
| } | |
| void reset(T cur,T tgt, float dur){ | |
| current = cur; | |
| target = tgt; | |
| duration = dur; | |
| finished = false; | |
| t=0; | |
| } | |
| }; | |
| template<class T> | |
| class Sinusoidal{ | |
| public: | |
| T current; | |
| T target; | |
| float duration; | |
| T out; | |
| float t; | |
| bool finished; | |
| Sinusoidal(T cur,T tgt, float dur): current(cur), target(tgt), duration(dur) | |
| { | |
| t = 0; | |
| finished = false; | |
| } | |
| T getVal(){ | |
| T c = (target - current); | |
| T b = current; | |
| if(t<duration && !finished){ | |
| out = -c/2.0f * float(cos(PI*(t/duration)) - 1) + b; | |
| t++; | |
| }else{ | |
| finished = true; | |
| out = target; | |
| } | |
| return out; | |
| } | |
| void reset(T cur,T tgt, float dur){ | |
| current = cur; | |
| target = tgt; | |
| duration = dur; | |
| finished = false; | |
| t=0; | |
| } | |
| }; | |
| template <class T> | |
| class Circular{ | |
| public: | |
| T current; | |
| T target; | |
| float duration; | |
| T out; | |
| float t; | |
| bool finished; | |
| Circular(T cur,T tgt, float dur): current(cur), target(tgt), duration(dur) | |
| { | |
| t = 0; | |
| finished = false; | |
| } | |
| T getVal() | |
| { | |
| T c = (target-current); | |
| T b = current; | |
| if(t<duration && !finished){ | |
| float _t = t/(duration/2); | |
| if (_t < 1) | |
| { | |
| out = -c/2.0f * (sqrt(1 - _t*_t) - 1) + b; | |
| }else{ | |
| _t-=2; | |
| out = c/2.0f * (sqrt(1 - _t*_t) + 1) + b; | |
| } | |
| t++; | |
| }else{ | |
| out = target; | |
| finished = true; | |
| } | |
| return out; | |
| } | |
| void reset(T cur,T tgt, float dur){ | |
| current = cur; | |
| target = tgt; | |
| duration = dur; | |
| finished = false; | |
| t=0; | |
| } | |
| }; | |
| template <class T> | |
| /* | |
| * For the love of god, do not try and use a glm::vec3 in here... | |
| */ | |
| class ElasticOut{ | |
| public: | |
| T current; | |
| T target; | |
| float duration,amplitude,period; | |
| T out; | |
| float t; | |
| bool finished; | |
| ElasticOut(T cur,T tgt, float dur, float amp = 0.0f): | |
| current(cur), target(tgt), duration(dur), amplitude(amp) | |
| { | |
| assert(typeid(T) != typeid(glm::vec3)); | |
| t = 0; | |
| finished = false; | |
| } | |
| T getVal(){ | |
| float _t = t; | |
| T c = (target-current); | |
| T b = current; | |
| float s = 0; | |
| float a = amplitude; | |
| float p = duration*0.3f; | |
| if(fabs(a) < c){ | |
| a = c; | |
| } | |
| if(t<duration && !finished) | |
| { | |
| if (_t==0){ | |
| out = b; | |
| }else{ | |
| if ((_t/=duration)==1) { | |
| out = b+c; | |
| }else{ | |
| s = T(p/(2.0f*PI) * asin(c/a)); | |
| out = T(a*pow(2,-10*_t) * sin( (_t*duration-s)*(2*PI)/p ) + c + b); | |
| } | |
| } | |
| t++; | |
| }else{ | |
| finished = true; | |
| out = target; | |
| } | |
| return out; | |
| } | |
| void reset(T cur,T tgt, float dur, float amp = 0.0f) | |
| { | |
| current = cur; | |
| target = tgt; | |
| duration = dur; | |
| amplitude = amp; | |
| finished = false; | |
| t = 0; | |
| } | |
| }; | |
| class ElasticOutVec3{ | |
| public: | |
| Shifter::ElasticOut<float> *ex; | |
| Shifter::ElasticOut<float> *ey; | |
| Shifter::ElasticOut<float> *ez; | |
| glm::vec3 current; | |
| glm::vec3 target; | |
| float duration; | |
| float amplitude; | |
| bool finished; | |
| ElasticOutVec3(glm::vec3 Vcur,glm::vec3 Vtgt, float dur, float amp = 0.0f): | |
| current(Vcur), target(Vtgt), duration(dur), amplitude(amp) | |
| { | |
| finished = false; | |
| ex = new Shifter::ElasticOut<float>(current.x,target.x,duration,amplitude); | |
| ey = new Shifter::ElasticOut<float>(current.y,target.y,duration,amplitude); | |
| ez = new Shifter::ElasticOut<float>(current.z,target.z,duration,amplitude); | |
| } | |
| glm::vec3 getVal(){ | |
| finished = (ex->finished && ey->finished && ez->finished); | |
| return glm::vec3(ex->getVal(),ey->getVal(),ez->getVal()); | |
| } | |
| void reset(glm::vec3 Vcur,glm::vec3 Vtgt, float dur, float amp = 0.0f) | |
| { | |
| current = Vcur; | |
| target = Vtgt; | |
| duration = dur; | |
| amplitude = amp; | |
| finished = false; | |
| ex->reset(current.x,target.x,duration,amplitude); | |
| ey->reset(current.y,target.y,duration,amplitude); | |
| ez->reset(current.z,target.z,duration,amplitude); | |
| } | |
| ~ElasticOutVec3(){ | |
| delete ex; | |
| delete ey; | |
| delete ez; | |
| } | |
| }; | |
| }; | |
| #endif // SHIFTERS |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment