/* -----------------------------------------------------------------------------
	GSFramework
	Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */


#ifndef	__NQUATERNIONCHANNEL__
#define	__NQUATERNIONCHANNEL__


		#include "geometry/curve.h"
		#include "math/quaternion.h"
		#include "container/narray.h"


namespace GS {

	static const float DefaultChannelOptimizationThresholdQuaternion = 0.01f;

/// Quaternion key.
struct	QuaternionKey
{
		Time		t;
		Quaternion	q;

		QuaternionKey(const Time &_t, const Quaternion &_q) : t(_t), q(_q) {}
		QuaternionKey() { q.Set(); }
};

/*!
	@short	Quaternion channel.

	This class hold a set of quaternion keys and can interpolate inside the set
	to determine a particular quaternion at a given time.

	@author Emmanuel Julien (ejulien@gsworks.fr)
*/
class	QuaternionChannel
{
private:

		ArrayList <QuaternionKey *> keys;

		uint			PerformChannelOptimize(uint count, QuaternionKey *src, QuaternionKey *dst, float threshold);

public:

		const ArrayList <QuaternionKey *> &GetKeys() const { return keys; }

		TimeRange		GetTimeRange() const;
		Time			GetDuration() const { return GetTimeRange().valueRange(); }

		/// Insert a key, sort by time.
		bool			Insert(const QuaternionKey &key);
		/// Evaluate channel.
		void			Evaluate(Time t, Quaternion &q, Curve::LoopMode loop = Curve::Constant, Time loop_start = Time::Inf, Time loop_end = Time::Inf) const;

		/// Optimize channel.
		uint			Optimize(float threshold = DefaultChannelOptimizationThresholdQuaternion);
		/// Delete all keys in channel.
		void			Clear();

		/// Return the memory usage for the channel.
		size_t			MemoryFootPrint() const { return size_t(keys.GetCount()) * sizeof(QuaternionKey) + sizeof(QuaternionChannel); }

		bool			FromMetaTag(NML::Tag &);
		NML::Tag		*AsMetaTag();

		QuaternionChannel();
		~QuaternionChannel();
};

} // GS


#endif	// __NQUATERNIONCHANNEL__
