Page 1 of 1

[Share] Animation System

Posted: Fri Apr 04, 2014 10:04 am
by salival
Hello everyone, I'm doing a game that needed multiple animation blending, so I created a simple system for this. Maybe someone else has use for it. Oh, and feel free to come with ideas or improvements :)

Have a good day.

Usage:

Code: Select all

//animation id's
enum AnimationID
{
	ANIM_IDLE,
	ANIM_RUN
};

//pseudo code
class MyEntity : public Animations
{
	public:
		/**
		 * Get entity reference
		 * @return				Entity reference.
		 */
		Ogre::Entity& getEntity() const {
			return *mEntity;
		}

	private:
		
		Ogre::Entity* mEntity;
};

void test()
{
	MyEntity entity;

	entity.registerAnimation(entity.getEntity(), 1.0f, 7.5, 4.5, true, ANIM_IDLE, "Idle");
	entity.registerAnimation(entity.getEntity(), 1.0f, 7.5, 4.5, true, ANIM_RUN, "Run");

	//set idle as default
	entity.setAnimation( ANIM_IDLE, Animations::eInstant );

	//switch using blending
	entity.setAnimation( ANIM_RUN );

	//update each frame
	entity.updateAnimations( timestep );
}
src:

Code: Select all

#include <animations.h>
#include <ogre/OgreEntity.h>
#include <ogre/OgreAnimationState.h>

//constructor
Animations::Animations() :	mActiveStatePtr( nullptr )
{
}

//registerAnimation
void Animations::registerAnimation(Ogre::Entity& entity, float speed, float blend_in, float blend_out, bool looping, AnimationID animationId, std::string const& name)
{
	if( entity.hasAnimationState(name) )
	{
		auto* statePtr = entity.getAnimationState(name);
		if( statePtr )
		{
			statePtr->setLoop(looping);
			statePtr->setEnabled(0);
			statePtr->setWeight(0);
			statePtr->setTimePosition(0);
			mAnimationSet[animationId] = AnimationData(statePtr, speed, blend_in, blend_out);
		}
	}
}

//setAnimation
void Animations::setAnimation(AnimationID animationId, SwitchStates state)
{
	auto it = mAnimationSet.find(animationId);
	if( it != std::end(mAnimationSet) ) {
		setAnimation(it->second, state);
	}
}

//setAnimation
void Animations::setAnimation(AnimationData& animation, SwitchStates state)
{
	switch( state )
	{
		case eInstant:
		{
			if( mActiveStatePtr ) {
				mActiveStatePtr->mStatePtr->setWeight(0);
				mActiveStatePtr->mStatePtr->setEnabled(0);
			}
			mActiveStatePtr = &animation;
			mActiveStatePtr->mStatePtr->setEnabled(1);
			mActiveStatePtr->mStatePtr->setTimePosition(0);
			mActiveStatePtr->mStatePtr->setWeight(1);
			break;
		}
		case eBlending:
		{
			//blending.
			if( mActiveStatePtr && mActiveStatePtr != &animation ) {
				mDeadList.push_back( mActiveStatePtr );
			}

			//activate new animation state.
			mActiveStatePtr = &animation;
			mActiveStatePtr->mStatePtr->setEnabled(1);
			break;
		}
	}
}

// Update the animation states.
void Animations::updateAnimations(float timestep)
{
	//blend in the new active animation.
	if( mActiveStatePtr )
	{
		Ogre::Real weight = mActiveStatePtr->mStatePtr->getWeight();
		if( weight < 1 ) {
			weight = std::min<float>( weight + (timestep * mActiveStatePtr->mBlendIn), 1.0f );
			mActiveStatePtr->mStatePtr->setWeight(weight);
		}
		mActiveStatePtr->mStatePtr->addTime(timestep * mActiveStatePtr->mSpeed);
	}

	//blend out / remove the "dead" animations.
	std::for_each( std::begin(mDeadList), std::end(mDeadList), [&]( AnimationData* dataPtr ) {
		dataPtr->mStatePtr->setWeight( std::max<float>( dataPtr->mStatePtr->getWeight() - (timestep * dataPtr->mBlendOut), 0.0f ) );
	});
	mDeadList.remove_if( [&]( AnimationData* dataPtr ) { return (dataPtr->mStatePtr->getWeight() == 0.0f || dataPtr == mActiveStatePtr); } );
}

//setAnimationSpeed
void Animations::setAnimationSpeed(AnimationID animationId, float speed)
{
	auto it = mAnimationSet.find( animationId );
	if( it != std::end(mAnimationSet) ) {
		it->second.mSpeed = speed;
	}
}

//clearAnimations
void Animations::clearAnimations()
{
	mAnimationSet.clear();
	mActiveStatePtr = nullptr;
}
header:

Code: Select all

#include <list>
#include <map>

//forward declaration.
namespace Ogre {
	class Entity;
	class AnimationState;
}

class Animations
{
	public:

		/**
		 * Constructor
		 */
		Animations();

		//typedefs
		typedef std::list<AnimationData*> DeadList;
		typedef std::map<AnimationID, AnimationData> MAnimationSet;

		//animation switch states
		enum SwitchStates
		{
			eBlending,
			eInstant
		};

		/**
		* Register new animation state.
		* @param	entity				Entity reference.
		* @param	speed				Animation speed.
		* @param	blend_in			Animation blend in speed.
		* @param	blend_out			Animation blend in speed.
		* @param	looping				Animation loop state.
		* @param	animationId			Animation id.
		* @param	name				Skeleton animation name.
		*/
		void registerAnimation(Ogre::Entity& entity, float speed, float blend_in, float blend_out, bool looping, AnimationID animationId, std::string const& name);

		/**
		* Set new animation state.
		* @param			Animation id.
		* @param			Current animation state.
		*/
		void setAnimation(AnimationID animationId, SwitchStates state = eBlending);

		/**
		 * Set new animation state.
		 * @param			AnimationData reference.
		 * @param			Current animation state.
		 */
		void setAnimation(AnimationData& animation, SwitchStates state = eBlending);

		/**
		 * Set new animation speed.
		 * @param	animationId			Animation id.
		 * @param	speed				New animation speed.
		 */
		void setAnimationSpeed(AnimationID animationId, float speed);

		/**
		 * Update the animation states.
		 * @param	timestep			Current timestep.
		 */
		void updateAnimations(float timestep);

		/**
		* clear animations.
		*/
		void clearAnimations();

		/**
		 * Get current active animation.
		 * @return				Current active animation state.
		 */
		inline AnimationData* getActiveState() {
			return mActiveStatePtr;
		}

	private:

		// animation states.
		MAnimationSet mAnimationSet;

		// storage of dead states.
		DeadList mDeadList;

		// current active animation state.
		AnimationData* mActiveStatePtr;
};

Re: [Share] Animation System

Posted: Sun Apr 13, 2014 11:22 pm
by nickG
subscribed for integration in my code
thanks

Re: [Share] Animation System

Posted: Sun May 04, 2014 8:24 pm
by RigoCL
Thanks for sharing.

I started to implement my own Animation Manager some months ago, considering that most of the Ogre examples use one, and only one, global variable for keep tracking and updating only one animation at any time, the problem is that in most cases you need to deal with several animations at any time, some meshes already come with a skeleton file, some others don't but you still need to animate them.

This blending algorithm is very handy to improve my own animation manager.

Re: [Share] Animation System

Posted: Wed May 07, 2014 5:40 pm
by Thyrion
just to be sure you don't missed this thread
http://www.ogre3d.org/forums/viewtopic.php?f=11&t=45260

Re: [Share] Animation System

Posted: Tue May 13, 2014 1:23 pm
by RigoCL
I did, old post btw, hope it still woks, thanks anyway.

Re: [Share] Animation System

Posted: Tue May 13, 2014 1:25 pm
by Zonder

Re: [Share] Animation System

Posted: Tue May 13, 2014 5:49 pm
by Thyrion
but no sourcecode? and
I decided to try to make a more
"professional" one (maintained, with regular releases,...etc)
could hold this for a year? XD

Re: [Share] Animation System

Posted: Wed May 14, 2014 9:03 am
by Zonder
Thyrion wrote:but no sourcecode? and
I decided to try to make a more
"professional" one (maintained, with regular releases,...etc)
could hold this for a year? XD
I wasn't endorsing it but just pointing out there was also another project eithen though it's commercial.

Re: [Share] Animation System

Posted: Thu May 22, 2014 6:59 am
by frostbyte
Dont waste your time...
AFAICSee the commercial project is dead ...havn't been been updated since 2009 and the link to the free-tryout is broken...
NEVER the less - payment option still seems to be availble - with an outrageous price range( can buy unity pro for that price...but i would'nt :roll: )
TechnoFreak's project still works, looks preety, nice , FREE...and OpenSource!!!
best thing is to write your own blending - so this code snipplet can become quite handy - thanks for sharing... 8)

Re: [Share] Animation System

Posted: Thu May 22, 2014 1:57 pm
by RigoCL
I do agree that TechnoFreak's project is the one and only option, but writing your own code would be a waste of time either, unless you have plenty of spare time.