Commit 8d2ab73d authored by Janis Born's avatar Janis Born
parents b9b47af8 71870e59
////////////////////////////////////////////////////////////////////////////////
// Ole Untzelmann <ole.untzelmann@rwth-aachen.de> //
// Animation classes //
////////////////////////////////////////////////////////////////////////////////
#ifndef ANIMATION_HH
#define ANIMATION_HH
#include <math.h>
#include <vector>
#include <queue>
#include "Interpolator.hh"
#include "EaseFunctions.hh"
#include <ACGL/Utils/Log.hh>
#include <tr1/memory>
#include <ACGL/Base/Macros.hh>
#include <ACGL/Types.hh>
#include <ACGL/Base/Interfaces.hh>
using namespace ACGL::Base;
namespace ACGL{
namespace Animations{
// Animation *************************************************************************************
class Animation
{
public:
Animation() : mInited(false) {};
virtual ~Animation() {};
/**
Excecute an animation
@param msec The time in millicesonds to move on
@return Time left after the update
*/
virtual long update(uint_t msec) = 0;
virtual void init() = 0;
/**
Returns if an animation has finished.
@return True if animation is finished
*/
virtual bool finished() = 0;
protected:
bool mInited;
private:
};
ACGL_SHARED_TYPEDEF(Animation)
typedef std::vector<SharedAnimation> AnimationList;
typedef std::queue<SharedAnimation> AnimationQueue;
class AnimationManager
{
public:
static void push(const SharedAnimation& _animation);
static void update(uint_t _msec);
static void cleanUp();
protected:
private:
static AnimationList mAnimations;
};
// AnimationEvent *************************************************************************************
class AnimationEvent : public Animation
{
public:
AnimationEvent(const uint_t _id, const SharedINotifiable& _event);
virtual long update(uint_t _msec);
virtual bool finished();
private:
SharedINotifiable mEvent;
uint_t mId;
};
ACGL_SHARED_TYPEDEF(AnimationEvent)
// AnimationWait *************************************************************************************
class AnimationWait : public Animation
{
public:
AnimationWait(const uint_t _duration);
virtual void init();
virtual long update(uint_t _msec);
virtual bool finished();
private:
long mTimeLeft;
long mDuration;
};
ACGL_SHARED_TYPEDEF(AnimationWait)
// AnimationSequential *************************************************************************************
class AnimationSequential : public Animation
{
public:
AnimationSequential(const uint_t _loops = 0);
virtual ~AnimationSequential();
virtual void init();
virtual long update(uint_t _msec);
virtual bool finished();
void push_animation(const SharedAnimation& _animation);
private:
uint_t mLoops;
bool mFrontInited;
uint_t mCurrentPosition;
AnimationList mAnimations;
//AnimationQueue mFinishedAnimations;
};
ACGL_SHARED_TYPEDEF(AnimationSequential)
// AnimationParallel *************************************************************************************
class AnimationParallel : public Animation
{
public:
AnimationParallel(const uint_t _loops = 0);
virtual ~AnimationParallel();
virtual void init();
virtual long update(uint_t _msec);
virtual bool finished();
void push_animation(const SharedAnimation& animation);
private:
uint_t mLoops;
std::queue<uint_t> mAnimationsToInit;
AnimationList mAnimations;
AnimationList mFinishedAnimations;
};
ACGL_SHARED_TYPEDEF(AnimationParallel)
// AnimationVariable *************************************************************************************
template <class T, class Interpolator>
class AnimationVariable : public Animation
{
public:
AnimationVariable(T& _data, uint_t _duration, const SharedEaseFunction& _ease_function, const Interpolator& _interpolator = Interpolator()) :
mpEaseFunction(_ease_function),
mInterpolator(_interpolator),
mDuration(_duration),
mCurrentTime(0),
mpData(_data) { }
virtual ~AnimationVariable()
{
mBlendInterpolators.clear();
}
virtual void init()
{
mCurrentTime = 0;
mInterpolator.init(mpData);
}
virtual long update(uint_t _msec)
{
long time_span;
if(mDuration-mCurrentTime >= _msec) time_span = _msec;
else time_span = mDuration-mCurrentTime;
mCurrentTime += time_span;
float progress = (float)mCurrentTime/(float)mDuration;
mpData = mInterpolator.interpolate( mpEaseFunction->value(progress) );
float sub_progress;
for(unsigned int i = 0;i < mBlendInterpolators.size();i++)
{
sub_progress = (progress - mBlendInterpolators[i].start)/(mBlendInterpolators[i].end - mBlendInterpolators[i].start);
if(0.0f <= sub_progress && sub_progress <= 1.0f)
{
mBlendInterpolators[i].mpInterpolator->blend(&mpData, mBlendInterpolators[i].mpEaseFunction->value(sub_progress) );
}
}
return _msec-time_span;
}
virtual bool finished()
{
if(mCurrentTime >= mDuration)
mpData = mInterpolator.finish();
return mCurrentTime >= mDuration;
}
void add_blend_interpolator(const SharedBlendInterpolator& _interpolator, const SharedEaseFunction& _ease_function, float _start = 0.0f, float _end = 1.0f)
{
mBlendInterpolators.push_back((blend_interpolator_t){_interpolator, _ease_function, _start, _end, false});
}
inline const SharedEaseFunction& get_ease_function(){ return mpEaseFunction;}
inline void set_ease_function(const SharedEaseFunction& _ease_function){ mpEaseFunction.reset(); mpEaseFunction = _ease_function;}
inline Interpolator& get_interpolator(){ return mInterpolator; }
//void set_interpolator(Interpolator* interpolator){ this->interpolator = interpolator; }
protected:
private:
SharedEaseFunction mpEaseFunction;
Interpolator mInterpolator;
uint_t mCurrentTime;
uint_t mDuration;
T& mpData;
struct blend_interpolator_t{
SharedBlendInterpolator mpInterpolator;
SharedEaseFunction mpEaseFunction;
float start, end;
bool active;
};
typedef std::vector<blend_interpolator_t> BlendInterpolators;
BlendInterpolators mBlendInterpolators;
};
typedef AnimationVariable<float, LinearInterpolatorFloat > AnimationFloatLinear;
ACGL_SHARED_TYPEDEF(AnimationFloatLinear)
typedef AnimationVariable<glm::vec3, LinearInterpolatorVec3 > AnimationVec3Linear;
ACGL_SHARED_TYPEDEF(AnimationVec3Linear)
}
}
#endif // ANIMATION_HH
////////////////////////////////////////////////////////////////////////////////
// Ole Untzelmann <ole.untzelmann@rwth-aachen.de> //
// Interpolation Example //
////////////////////////////////////////////////////////////////////////////////
#ifndef EASEFUNCTIONS_HH
#define EASEFUNCTIONS_HH
#include <math.h>
#include <tr1/memory>
#include <ACGL/Base/Macros.hh>
namespace ACGL
{
namespace Animations
{
class EaseFunction
{
public:
virtual ~EaseFunction(){}
virtual float value(const float _progress) = 0;
};
ACGL_SHARED_TYPEDEF(EaseFunction)
/*
float Linear(float progress, ease_function_parameter& parameter);
float InQuad(float progress, ease_function_parameter& parameter);
float OutQuad(float progress, ease_function_parameter& parameter);
float InOutQuad(float progress, ease_function_parameter& parameter);
float BlendLinear(float progress, ease_function_parameter& parameter);
float BlendSin(float progress, ease_function_parameter& parameter);
float BlendCos(float progress, ease_function_parameter& parameter);
float BlendSinDamped(float progress, ease_function_parameter& parameter);
float BlendCosDamped(float progress, ease_function_parameter& parameter);
*/
namespace EaseFunctions{
class Linear : public EaseFunction
{
public:
Linear(){ }
virtual ~Linear(){}
virtual float value(const float _progress)
{
return _progress;
}
};
class InQuad : public EaseFunction
{
public:
InQuad(){ }
virtual ~InQuad(){}
virtual float value(const float _progress)
{
return _progress*_progress;
}
};
class OutQuad : public EaseFunction
{
public:
OutQuad(){ }
virtual ~OutQuad(){}
virtual float value(const float _progress)
{
return 1.0f-_progress*_progress;
}
};
class InOutQuad : public EaseFunction
{
public:
InOutQuad(){ }
virtual ~InOutQuad(){}
virtual float value(const float _progress)
{
if(_progress < 0.5)
return 2.0f*_progress*_progress;
else
return 1.0f-2.0f*pow(_progress-1.0f,2.0);
}
};
class BlendLinear : public EaseFunction
{
public:
BlendLinear(){ }
virtual ~BlendLinear(){}
virtual float value(const float _progress)
{
return 2*fmin(_progress, 1-_progress);
}
};
class BlendSin : public EaseFunction
{
public:
BlendSin(){ }
virtual ~BlendSin(){}
virtual float value(const float _progress)
{
return sin(20*M_PI*_progress);
}
};
class BlendCos : public EaseFunction
{
public:
BlendCos(){ }
virtual ~BlendCos(){}
virtual float value(const float _progress)
{
return cos(6*M_PI*_progress)-1.0f;
}
};
class BlendSinDamped : public EaseFunction
{
public:
BlendSinDamped(){ }
virtual ~BlendSinDamped(){}
virtual float value(const float _progress)
{
return 2*fmin(_progress, 1-_progress)*sin(10*M_PI*_progress);
}
};
class BlendCosDamped : public EaseFunction
{
public:
BlendCosDamped(){ }
virtual ~BlendCosDamped(){}
virtual float value(const float _progress)
{
return 2*fmin(_progress, 1.0f-_progress)*cos(10.0f*M_PI*_progress);
}
};
}
}
}
#endif // EASEFUNCTIONS_HH
////////////////////////////////////////////////////////////////////////////////
// Ole Untzelmann <ole.untzelmann@rwth-aachen.de> //
// Interpolation Example //
////////////////////////////////////////////////////////////////////////////////
#ifndef INTERPOLATOR_HH
#define INTERPOLATOR_HH
#include "EaseFunctions.hh"
#include <ACGL/Utils/Log.hh>
#include <ACGL/Scene/NURBSCurve.hh>
#include <vector>
#include <ACGL/Types.hh>
#include <tr1/memory>
#include <ACGL/Base/Macros.hh>
namespace ACGL
{
namespace Animations
{
class BlendInterpolator
{
public:
virtual void blend(const void* value, const float progress) = 0;
};
ACGL_SHARED_TYPEDEF(BlendInterpolator)
struct interpolator_blend_t
{
EaseFunction* ease_function;
BlendInterpolator* interpolator;
float start, end;
};
typedef std::vector<interpolator_blend_t> BlendVector;
// Interpolator *************************************************************************************
template <class T>
class LinearInterpolator : public BlendInterpolator
{
public:
LinearInterpolator() :
mStartValue(),
mEndValue(),
mDiffValue(),
mSetStartPoint(true)
{
}
LinearInterpolator(const T& _end_value) :
mStartValue(),
mEndValue(_end_value),
mDiffValue(),
mSetStartPoint(true)
{
}
LinearInterpolator(const T& _start_value, const T& _end_value) :
mStartValue(_start_value),
mEndValue(_end_value),
mDiffValue(_end_value - _start_value),
mSetStartPoint(false)
{
}
inline void init(const T& _initValue)
{
if(mSetStartPoint)
{
mStartValue = _initValue;
mDiffValue = mEndValue-mStartValue;
}
}
inline const T interpolate(const float _progress)
{
//std::cout << "[LinearInterpolator] progress: "<<_progress<<std::endl;
return mStartValue + _progress*mDiffValue;
}
inline const T& finish()
{
return mEndValue;
}
virtual void blend(const void* _value, const float _progress)
{
*((T*)_value) += mEndValue*_progress;
}
protected:
private:
T mStartValue;
T mEndValue;
T mDiffValue;
bool mSetStartPoint;
};
typedef LinearInterpolator<float> LinearInterpolatorFloat;
ACGL_SHARED_TYPEDEF(LinearInterpolatorFloat)
typedef LinearInterpolator<glm::vec3> LinearInterpolatorVec3;
ACGL_SHARED_TYPEDEF(LinearInterpolatorVec3)
template <class T>
class LinearPathInterpolator
{
public:
LinearPathInterpolator()
{
}
inline void init(const T& init_value)
{
}
inline const T interpolate(float _progress)
{
unsigned int i = 0;
for(i = 0 ;i < mKeypoints.size();i++)
{
if(mKeypoints[i].time >= _progress)
break;
}
if(i == 0)
{
return mKeypoints[0].data;
}else if(i < mKeypoints.size())
{
float val = (_progress-mKeypoints[i-1].time)
/(mKeypoints[i].time-mKeypoints[i-1].time);
return mKeypoints[i-1].data*(1.0f-val)+mKeypoints[i].data*val;
}
}
inline const T& finish()
{
return mKeypoints[mKeypoints.size()-1].data;
}
void insertControlPoint(const T& _data, const float _time)
{
unsigned int i = 0;
while(i < mKeypoints.size() && mKeypoints[i].time < _time) i++;
mKeypoints.insert(mKeypoints.begin()+i,(key_point_t){_data, _time});
}
protected:
private:
struct key_point_t{T data;float time;};
std::vector<key_point_t> mKeypoints;
};
typedef LinearPathInterpolator<float> LinearPathInterpolatorFloat;
ACGL_SHARED_TYPEDEF(LinearPathInterpolatorFloat)
typedef LinearPathInterpolator<glm::vec3> LinearPathInterpolatorVec3;
ACGL_SHARED_TYPEDEF(LinearPathInterpolatorVec3)
template<class T, ACGL::uint_t DATA_DIMENSION>
class NURBSPathInterpolator
{
public:
NURBSPathInterpolator(ACGL::Scene::NURBSCurve<DATA_DIMENSION> curve) :
curve(curve)
{
}
void init(T& init_value)
{
// insert_control_point(data, 0.0f);
}
const T interpolate(float progress)
{
curve.insertKnot(progress);
// TODO: Interpolation code is missing
return T();
}
const T& finish()
{
return T();
}
inline ACGL::Scene::NURBSCurve<DATA_DIMENSION>& get_curve()
{
return curve;
}
protected:
private:
ACGL::Scene::NURBSCurve<DATA_DIMENSION> curve;
};
}
}
#endif // INTERPOLATOR_HH
////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2011, Computer Graphics Group RWTH Aachen University //
// All rights reserved. //
////////////////////////////////////////////////////////////////////////////////
#ifndef ACGL_INTERFACES_HH
#define ACGL_INTERFACES_HH
#include <ACGL/Types.hh>
#include <ACGL/Base/Macros.hh>
namespace ACGL{
namespace Base{
class INotifiable
{
public:
virtual void notify(uint_t _id) = 0;
};
ACGL_SHARED_TYPEDEF(INotifiable)
}
}
#endif // ACGL_INTERFACES_HH
#include <ACGL/Animations/Animation.hh>
namespace ACGL
{
namespace Animations
{
AnimationList AnimationManager::mAnimations;
void AnimationManager::push(const SharedAnimation& _animation)
{
mAnimations.push_back(_animation);
_animation->init();
}
void AnimationManager::update(uint_t _msec)
{
uint_t id = 0;
while(id < mAnimations.size())
{
mAnimations[id]->update(_msec);
if(mAnimations[id]->finished())
{
mAnimations.erase(mAnimations.begin()+id);
/*mAnimations[id].reset();
mAnimations[id] = mAnimations[mAnimations.size()-1];
mAnimations.erase(mAnimations.end()-1);*/
} else id++;
}
}
void AnimationManager::cleanUp()
{
mAnimations.clear();
}
AnimationEvent::AnimationEvent(const uint_t _id, const SharedINotifiable& _event) :
Animation(),
mEvent(_event),
mId(_id)
{
}
long AnimationEvent::update(uint_t _msec)
{
return _msec;
}
bool AnimationEvent::finished()
{
if(mEvent)
mEvent->notify(mId);
return true;
}