Index: trunk/nv/gfx/animation.hh
===================================================================
--- trunk/nv/gfx/animation.hh	(revision 285)
+++ trunk/nv/gfx/animation.hh	(revision 286)
@@ -12,5 +12,7 @@
 #include <nv/interface/stream.hh>
 #include <nv/math.hh>
-#include <nv/interface/vertex.hh>
+#include <nv/interface/animation_key.hh>
+#include <nv/interface/interpolation_raw.hh>
+#include <nv/interface/interpolation_template.hh>
 #include <nv/transform.hh>
 #include <glm/gtc/matrix_transform.hpp>
Index: trunk/nv/interface/animation_key.hh
===================================================================
--- trunk/nv/interface/animation_key.hh	(revision 286)
+++ trunk/nv/interface/animation_key.hh	(revision 286)
@@ -0,0 +1,243 @@
+// Copyright (C) 2014 ChaosForge / Kornel Kisielewicz
+// http://chaosforge.org/
+//
+// This file is part of NV Libraries.
+// For conditions of distribution and use, see copyright notice in nv.hh
+
+// WARNING: this file is explicitly designed to fuck with your brain
+
+#ifndef NV_ANIMATION_KEY_HH
+#define NV_ANIMATION_KEY_HH
+
+#include <nv/common.hh>
+#include <nv/transform.hh>
+#include <nv/math.hh>
+
+namespace nv
+{
+
+	enum class animation_slot : uint8
+	{
+		TIME     = 0,
+		POSITION = 1,
+		ROTATION = 2,
+		SCALE    = 3,
+		TFORM    = 4,
+
+		SLOT_MAX       = 4,
+		SLOT_MAX_STORE = 8,
+	};
+
+	namespace detail
+	{
+		template < typename KEY, animation_slot SLOT >
+		struct key_has_slot_impl
+		{
+			static bool const value = false;
+		};
+
+		template < typename KEY >
+		struct key_has_slot_impl< KEY, animation_slot::TIME >
+		{
+		private:
+			struct fallback { int time; };
+			struct derived : KEY, fallback { };
+			template<typename C, C> struct cht; 
+			template<typename C> static char (&test(cht<int fallback::*, &C::time>*))[1]; 
+			template<typename C> static char (&test(...))[2]; 
+		public:
+			static bool const value = sizeof(test<derived>(0)) == 2;;
+		};
+
+		template < typename KEY >
+		struct key_has_slot_impl< KEY, animation_slot::POSITION >
+		{
+		private:
+			struct fallback { int position; };
+			struct derived : KEY, fallback { };
+			template<typename C, C> struct cht; 
+			template<typename C> static char (&test(cht<int fallback::*, &C::position>*))[1]; 
+			template<typename C> static char (&test(...))[2]; 
+		public:
+			static bool const value = sizeof(test<derived>(0)) == 2;;
+		};
+
+		template < typename KEY >
+		struct key_has_slot_impl< KEY, animation_slot::ROTATION >
+		{
+		private:
+			struct fallback { int rotation; };
+			struct derived : KEY, fallback { };
+			template<typename C, C> struct cht; 
+			template<typename C> static char (&test(cht<int fallback::*, &C::rotation>*))[1]; 
+			template<typename C> static char (&test(...))[2]; 
+		public:
+			static bool const value = sizeof(test<derived>(0)) == 2;;
+		};
+
+		template < typename KEY >
+		struct key_has_slot_impl< KEY, animation_slot::SCALE >
+		{
+		private:
+			struct fallback { int scale; };
+			struct derived : KEY, fallback { };
+			template<typename C, C> struct cht; 
+			template<typename C> static char (&test(cht<int fallback::*, &C::scale>*))[1]; 
+			template<typename C> static char (&test(...))[2]; 
+		public:
+			static bool const value = sizeof(test<derived>(0)) == 2;;
+		};
+
+		template < typename KEY >
+		struct key_has_slot_impl< KEY, animation_slot::TFORM >
+		{
+		private:
+			struct fallback { int tform; };
+			struct derived : KEY, fallback { };
+			template<typename C, C> struct cht; 
+			template<typename C> static char (&test(cht<int fallback::*, &C::tform>*))[1]; 
+			template<typename C> static char (&test(...))[2]; 
+		public:
+			static bool const value = sizeof(test<derived>(0)) == 2;;
+		};
+
+		template < typename KEY, animation_slot SLOT, bool HAS_SLOT >
+		struct key_slot_info_impl
+		{
+		};
+
+		template < typename KEY, animation_slot SLOT >
+		struct key_slot_info_impl < KEY, SLOT, false >
+		{
+			typedef empty_type value_type;
+			static const datatype etype  = datatype::NONE;
+			static const int      offset = 0;
+		};
+
+		template < typename KEY >
+		struct key_slot_info_impl< KEY, animation_slot::TIME, true >
+		{
+			typedef decltype( KEY::time ) value_type;
+			static const datatype etype  = type_to_enum< decltype( KEY::time ) >::type;
+			static const int      offset = offsetof( KEY, time );
+		};
+
+		template < typename KEY >
+		struct key_slot_info_impl< KEY, animation_slot::POSITION, true >
+		{
+			typedef decltype( KEY::position ) value_type;
+			static const datatype etype  = type_to_enum< decltype( KEY::position ) >::type;
+			static const int      offset = offsetof( KEY, position );
+			static void interpolate( KEY& key, const KEY& k1, const KEY& k2, float factor )
+			{
+				key.position = nv::interpolate( k1.position, k2.position, factor );
+			}
+		};
+
+		template < typename KEY >
+		struct key_slot_info_impl< KEY, animation_slot::ROTATION, true >
+		{
+			typedef decltype( KEY::rotation ) value_type;
+			static const datatype etype  = type_to_enum< decltype( KEY::rotation ) >::type;
+			static const int      offset = offsetof( KEY, rotation );
+			static void interpolate( KEY& key, const KEY& k1, const KEY& k2, float factor )
+			{
+				key.rotation = nv::interpolate( k1.rotation, k2.rotation, factor );
+			}
+		};
+
+		template < typename KEY >
+		struct key_slot_info_impl< KEY, animation_slot::SCALE, true >
+		{
+			typedef decltype( KEY::scale ) value_type;
+			static const datatype etype  = type_to_enum< decltype( KEY::scale ) >::type;
+			static const int      offset = offsetof( KEY, scale );
+			static void interpolate( KEY& key, const KEY& k1, const KEY& k2, float factor )
+			{
+				key.scale = nv::interpolate( k1.scale, k2.scale, factor );
+			}
+		};
+
+		template < typename KEY >
+		struct key_slot_info_impl< KEY, animation_slot::TFORM, true >
+		{
+			typedef decltype( KEY::tform ) value_type;
+			static const datatype etype  = type_to_enum< decltype( KEY::tform ) >::type;
+			static const int      offset = offsetof( KEY, tform );
+			static void interpolate( KEY& key, const KEY& k1, const KEY& k2, float factor )
+			{
+				key.tform = nv::interpolate( k1.tform, k2.tform, factor );
+			}
+		};
+	}
+
+	template < typename KEY, animation_slot SLOT >
+	struct key_has_slot : public detail::key_has_slot_impl< KEY, SLOT >
+	{
+	};
+
+
+	template < typename KEY, animation_slot SLOT >
+	struct key_slot_info : public detail::key_slot_info_impl< KEY, SLOT, detail::key_has_slot_impl< KEY, SLOT >::value >
+	{
+	};
+
+	struct key_descriptor_slot
+	{
+		datatype       etype;
+		uint32         offset;
+		animation_slot vslot;
+		key_descriptor_slot() : etype(NONE), offset(0), vslot(animation_slot::TIME) {}
+	};
+
+	struct key_descriptor
+	{
+		key_descriptor_slot slots[ animation_slot::SLOT_MAX_STORE ];
+		uint32              count;
+		uint32              size;
+
+		key_descriptor() : count(0), size(0) {}
+
+		template < typename KEY >
+		void initialize()
+		{
+			count = 0;
+			initialize_slot< KEY, animation_slot::TIME >();
+			initialize_slot< KEY, animation_slot::POSITION >();
+			initialize_slot< KEY, animation_slot::ROTATION >();
+			initialize_slot< KEY, animation_slot::SCALE >();
+			initialize_slot< KEY, animation_slot::TFORM >();
+			size = sizeof( KEY );
+		}
+
+		bool operator==( const key_descriptor& rhs ) const
+		{
+			if ( size  != rhs.size )  return false;
+			if ( count != rhs.count ) return false;
+			for ( uint32 i = 0; i < count; ++i )
+			{
+				if ( slots[i].etype  != rhs.slots[i].etype )  return false;
+				if ( slots[i].offset != rhs.slots[i].offset ) return false;
+				if ( slots[i].vslot  != rhs.slots[i].vslot )  return false;
+			}
+			return true;
+		}
+
+	private:
+		template < typename KEY, animation_slot SLOT >
+		void initialize_slot()
+		{
+			typedef key_slot_info< KEY, SLOT > slot_info;
+			slots[ count ].etype  = slot_info::etype;
+			if ( slots[ count ].etype != datatype::NONE )
+			{
+				slots[ count ].vslot  = SLOT;
+				slots[ count ].offset = slot_info::offset;
+				count++;
+			}
+		}
+	};
+
+}
+
+#endif // NV_ANIMATION_KEY_HH
Index: trunk/nv/interface/interpolation_raw.hh
===================================================================
--- trunk/nv/interface/interpolation_raw.hh	(revision 286)
+++ trunk/nv/interface/interpolation_raw.hh	(revision 286)
@@ -0,0 +1,142 @@
+// Copyright (C) 2014 ChaosForge / Kornel Kisielewicz
+// http://chaosforge.org/
+//
+// This file is part of NV Libraries.
+// For conditions of distribution and use, see copyright notice in nv.hh
+
+// WARNING: this file is explicitly designed to fuck with your brain
+
+#ifndef NV_INTERPOLATION_RAW_HH
+#define NV_INTERPOLATION_RAW_HH
+
+#include <nv/common.hh>
+#include <nv/transform.hh>
+#include <nv/math.hh>
+#include <nv/interface/animation_key.hh>
+
+namespace nv
+{
+
+	inline uint32 interpolate_raw_linear( uint32 count, float factor, const float* k1, const float* k2, float* result )
+	{
+		for ( uint32 i = 0; i < count; ++i )
+		{
+			result[i] = k1[i] + factor * (k2[i] - k1[i]); 
+		}
+		return count;
+	}
+
+	inline uint32 interpolate_raw_quat( float factor, const float* k1, const float* k2, float* result )
+	{
+		*((quat*)(result)) = interpolate( *((quat*)(k1)), *((quat*)(k2)), factor );
+		return 4;
+	}
+
+	inline uint32 interpolate_raw( const key_descriptor_slot& slot, float factor, const float* k1, const float* k2, float* result )
+	{
+		uint32 count = get_datatype_info( slot.etype ).elements;
+		switch ( slot.vslot )
+		{
+		case animation_slot::TIME:     return 0;
+		case animation_slot::POSITION: return interpolate_raw_linear( count, factor, k1, k2, result );
+		case animation_slot::ROTATION: return interpolate_raw_quat( factor, k1, k2, result );
+		case animation_slot::SCALE:    return interpolate_raw_linear( count, factor, k1, k2, result );
+		case animation_slot::TFORM:    return 
+										   interpolate_raw_linear( 3, factor, k1, k2, result ) + 
+										   interpolate_raw_quat( factor, k1 + 3, k2 + 3, result + 3 );
+		default:
+			return 0;
+		};
+	}
+
+	inline quat make_quat_fixed( const float* data )
+	{
+		quat result;
+		memcpy((float*)(&result), data, sizeof(quat));
+		return result;
+	}
+
+	inline mat4 extract_matrix_raw( const key_descriptor& desc, const float* data )
+	{
+		if ( desc.count == 1 )
+		{
+			switch ( desc.slots[0].vslot )
+			{
+			case animation_slot::TIME:     return mat4();
+			case animation_slot::POSITION: return glm::translate( mat4(),glm::make_vec3( data ) );
+			case animation_slot::ROTATION: return glm::mat4_cast( make_quat_fixed( data ) );
+			case animation_slot::SCALE:    return glm::scale( mat4(),glm::make_vec3( data ) );
+			case animation_slot::TFORM:    return transform( glm::make_vec3( data ), make_quat_fixed( data + 3 ) ).extract();
+			default:
+				return mat4();
+			};
+		}
+		else
+		{
+			mat4 position;
+			mat4 rotation;
+			mat4 scale;
+			for ( uint32 i = 0; i < desc.count; ++i )
+			{
+				uint32 offset = desc.slots[i].offset / 4;
+				switch ( desc.slots[i].vslot )
+				{
+				case animation_slot::TIME:     break;
+				case animation_slot::POSITION: 
+					position = glm::translate( position,glm::make_vec3( data + offset ) ); break;
+				case animation_slot::ROTATION: 
+					rotation = glm::mat4_cast( make_quat_fixed( data + offset ) ); break;
+				case animation_slot::SCALE:    
+					scale    = glm::scale( mat4(),glm::make_vec3( data + offset ) ); break;
+				case animation_slot::TFORM:    return transform( glm::make_vec3( data + offset ), make_quat_fixed( data + offset + 3 ) ).extract();
+				default:
+					break;
+				}
+			}
+			return position * rotation * scale;
+		}
+	}
+
+	inline transform extract_transform_raw( const key_descriptor& desc, const float* data )
+	{
+		if ( desc.count == 1 )
+		{
+			switch ( desc.slots[0].vslot )
+			{
+			case animation_slot::TIME:     return transform();
+			case animation_slot::POSITION: return transform( glm::make_vec3( data ) );
+			case animation_slot::ROTATION: return transform( make_quat_fixed( data ) );
+			case animation_slot::SCALE:    return transform();
+			case animation_slot::TFORM:    return transform( glm::make_vec3( data ), make_quat_fixed( data + 3 ) );
+			default:
+				return transform();
+			};
+		}
+		else
+		{
+			vec3 position;
+			quat rotation;
+			for ( uint32 i = 0; i < desc.count; ++i )
+			{
+				uint32 offset = desc.slots[i].offset / 4;
+				switch ( desc.slots[i].vslot )
+				{
+				case animation_slot::TIME:     break;
+				case animation_slot::POSITION: 
+					position = glm::make_vec3( data + offset ); break;
+				case animation_slot::ROTATION: 
+					rotation = make_quat_fixed( data + offset ); break;
+				case animation_slot::SCALE:	   break;
+				case animation_slot::TFORM:    return transform( glm::make_vec3( data + offset ), make_quat_fixed( data + 3 ) );
+				default:
+					break;
+				}
+			}
+			return transform( position, rotation );
+		}
+	}
+
+
+}
+
+#endif // NV_INTERPOLATION_RAW_HH
Index: trunk/nv/interface/interpolation_template.hh
===================================================================
--- trunk/nv/interface/interpolation_template.hh	(revision 286)
+++ trunk/nv/interface/interpolation_template.hh	(revision 286)
@@ -0,0 +1,179 @@
+// Copyright (C) 2014 ChaosForge / Kornel Kisielewicz
+// http://chaosforge.org/
+//
+// This file is part of NV Libraries.
+// For conditions of distribution and use, see copyright notice in nv.hh
+
+// WARNING: this file is explicitly designed to fuck with your brain
+
+#ifndef NV_INTERPOLATION_TEMPLATE_HH
+#define NV_INTERPOLATION_TEMPLATE_HH
+
+#include <nv/common.hh>
+#include <nv/transform.hh>
+#include <nv/math.hh>
+#include <nv/interface/animation_key.hh>
+
+namespace nv
+{
+
+	template < typename KEY, animation_slot SLOT > 
+	void interpolate_slot( KEY& key, const KEY& k1, const KEY& k2, float factor, const std::true_type& )
+	{
+		key_slot_info< KEY, SLOT >::interpolate( key, k1, k2, factor );
+	}
+
+	template < typename KEY, animation_slot SLOT > 
+	void interpolate_slot( KEY&, const KEY&, const KEY&, float, const std::false_type& )
+	{
+	}
+
+	template < typename KEY >
+	void interpolate_key( KEY& key, const KEY& k1, const KEY& k2, float factor )
+	{
+		interpolate_slot< KEY, animation_slot::POSITION >( key, k1, k2, factor, std::integral_constant< bool, key_has_slot< KEY, animation_slot::POSITION >::value >() );
+		interpolate_slot< KEY, animation_slot::ROTATION >( key, k1, k2, factor, std::integral_constant< bool, key_has_slot< KEY, animation_slot::ROTATION >::value >() );
+		interpolate_slot< KEY, animation_slot::SCALE >( key, k1, k2, factor, std::integral_constant< bool, key_has_slot< KEY, animation_slot::SCALE >::value >() );
+		interpolate_slot< KEY, animation_slot::TFORM >( key, k1, k2, factor, std::integral_constant< bool, key_has_slot< KEY, animation_slot::TFORM >::value >() );
+	}
+
+	namespace detail
+	{
+		template < typename T >
+		mat4 extract_matrix_slot( const T& ) { static_assert( false, "extract_matrix_slot" ); }
+		template <> inline mat4 extract_matrix_slot( const mat4& m ) { return m; }
+		template <> inline mat4 extract_matrix_slot( const transform& m ) { return m.extract(); }
+
+		template < typename T >
+		transform extract_transfrom_slot( const T& ) { static_assert( false, "extract_matrix_slot" ); }
+		template <> inline transform extract_transfrom_slot( const mat4& m ) { return transform(m); }
+		template <> inline transform extract_transfrom_slot( const transform& m ) { return m; }
+
+		template < typename KEY >
+		mat4 extract_matrix_p_impl( const KEY& k ) { return glm::translate(mat4(),k.position); }
+		template < typename KEY >
+		mat4 extract_matrix_r_impl( const KEY& k ) { return glm::mat4_cast( k.rotation ); }
+		template < typename KEY >
+		mat4 extract_matrix_s_impl( const KEY& k ) { return glm::scale(mat4(),k.scale); }
+		template < typename KEY >
+		mat4 extract_matrix_pr_impl( const KEY& k )
+		{
+			// TODO: this is obviously unoptimized
+			mat4 result = glm::mat4_cast( k.rotation );
+			result[3] = vec4( k.position, 1.0f );
+			return result;
+		}
+		template < typename KEY >
+		mat4 extract_matrix_rs_impl( const KEY& k )
+		{
+			// TODO: this is obviously unoptimized
+			mat4 result = glm::mat4_cast( k.rotation );
+			return glm::scale(result,k.scale);
+		}
+		template < typename KEY >
+		mat4 extract_matrix_ps_impl( const KEY& k )
+		{
+			// TODO: this is obviously unoptimized
+			return glm::scale(glm::translate(mat4(),k.position),k.scale);
+		}
+		template < typename KEY >
+		mat4 extract_matrix_prs_impl( const KEY& k )
+		{
+			// TODO: this is obviously unoptimized
+			return glm::translate(mat4(),k.position) * glm::mat4_cast( k.rotation ) * glm::scale(mat4(),k.scale);
+		}
+
+		template < typename KEY >
+		mat4 extract_matrix_prs( const KEY& k, const std::false_type&, const std::false_type&, const std::false_type& )
+		{ return mat4(); }
+		template < typename KEY >
+		mat4 extract_matrix_prs( const KEY& k, const std::true_type&, const std::false_type&, const std::false_type& )
+		{ return extract_matrix_p_impl(k); }
+		template < typename KEY >
+		mat4 extract_matrix_prs( const KEY& k, const std::false_type&, const std::true_type&, const std::false_type& )
+		{ return extract_matrix_r_impl(k); }
+		template < typename KEY >
+		mat4 extract_matrix_prs( const KEY& k, const std::false_type&, const std::false_type&, const std::true_type& )
+		{ return extract_matrix_s_impl(k); }
+		template < typename KEY >
+		mat4 extract_matrix_prs( const KEY& k, const std::true_type&, const std::true_type&, const std::false_type& )
+		{ return extract_matrix_pr_impl(k); }
+		template < typename KEY >
+		mat4 extract_matrix_prs( const KEY& k, const std::false_type&, const std::true_type&, const std::true_type& )
+		{ return extract_matrix_rs_impl(k); }
+		template < typename KEY >
+		mat4 extract_matrix_prs( const KEY& k, const std::true_type&, const std::false_type&, const std::true_type& )
+		{ return extract_matrix_ps_impl(k); }
+		template < typename KEY >
+		mat4 extract_matrix_prs( const KEY& k, const std::true_type&, const std::true_type&, const std::true_type& )
+		{ return extract_matrix_prs_impl(k); }
+
+
+		template < typename KEY >
+		transform extract_transform_pr_impl( const KEY& k, const std::false_type&, const std::false_type& ) { return transform(); }
+		template < typename KEY >
+		transform extract_transform_pr_impl( const KEY& k, const std::true_type&, const std::true_type& ) { return transform( k.position, k.rotation ); }
+		template < typename KEY >
+		transform extract_transform_pr_impl( const KEY& k, const std::true_type&, const std::false_type& ) { return transform( k.position ); }
+		template < typename KEY >
+		transform extract_transform_pr_impl( const KEY& k, const std::false_type&, const std::true_type& ) { return transform( k.rotation ); }
+
+
+
+		template < typename KEY >
+		mat4 extract_matrix_impl( const KEY& k, const std::true_type& )
+		{
+			static_assert( key_has_slot< KEY, animation_slot::POSITION >::value == false, "key!");
+			static_assert( key_has_slot< KEY, animation_slot::ROTATION >::value == false, "key!");
+			static_assert( key_has_slot< KEY, animation_slot::SCALE >::value == false, "key!");
+			return extract_matrix_slot( k.tform );
+		}
+
+		template < typename KEY >
+		mat4 extract_matrix_impl( const KEY& k, const std::false_type& )
+		{
+			static_assert( key_has_slot< KEY, animation_slot::TFORM >::value == false, "key!");
+			return extract_matrix_prs( k,
+				std::integral_constant< bool, key_has_slot< KEY, animation_slot::POSITION >::value >(),
+				std::integral_constant< bool, key_has_slot< KEY, animation_slot::ROTATION >::value >(),
+				std::integral_constant< bool, key_has_slot< KEY, animation_slot::SCALE >::value >()
+				);
+		}
+
+		template < typename KEY >
+		transform extract_transform_impl( const KEY& k, const std::true_type& )
+		{
+			static_assert( key_has_slot< KEY, animation_slot::POSITION >::value == false, "key!");
+			static_assert( key_has_slot< KEY, animation_slot::ROTATION >::value == false, "key!");
+			static_assert( key_has_slot< KEY, animation_slot::SCALE >::value == false, "key!");
+			return extract_transfrom_slot( k.tform );
+		}
+
+		template < typename KEY >
+		transform extract_transform_impl( const KEY& k, const std::false_type& )
+		{
+			static_assert( key_has_slot< KEY, animation_slot::TFORM >::value == false, "key!");
+			static_assert( key_has_slot< KEY, animation_slot::SCALE >::value == false, "key!");
+			return extract_transform_pr_impl( k, 
+				std::integral_constant< bool, key_has_slot< KEY, animation_slot::POSITION >::value >(),
+				std::integral_constant< bool, key_has_slot< KEY, animation_slot::ROTATION >::value >() 
+				);
+		}
+	}
+
+	template < typename KEY >
+	mat4 extract_matrix( const KEY& k )
+	{
+		return detail::extract_matrix_impl( k, std::integral_constant< bool, key_has_slot< KEY, animation_slot::TFORM >::value >() );
+	}
+
+	template < typename KEY >
+	transform extract_transform( const KEY& k )
+	{
+		return detail::extract_transform_impl( k, std::integral_constant< bool, key_has_slot< KEY, animation_slot::TFORM >::value >() );
+	}
+
+
+}
+
+#endif // NV_INTERPOLATION_TEMPLATE_HH
Index: trunk/nv/interface/vertex.hh
===================================================================
--- trunk/nv/interface/vertex.hh	(revision 285)
+++ trunk/nv/interface/vertex.hh	(revision 286)
@@ -32,16 +32,4 @@
 	};
 
-	enum class animation_slot : uint8
-	{
- 		TIME     = 0,
- 		POSITION = 1,
- 		ROTATION = 2,
- 		SCALE    = 3,
- 		TFORM    = 4,
-
- 		SLOT_MAX       = 4,
- 		SLOT_MAX_STORE = 8,
-	};
-
 	namespace detail
 	{
@@ -213,144 +201,6 @@
 		};
 
-		template < typename KEY, animation_slot SLOT >
-		struct key_has_slot_impl
-		{
-			static bool const value = false;
-		};
-
-		template < typename KEY >
-		struct key_has_slot_impl< KEY, animation_slot::TIME >
-		{
-		private:
-			struct fallback { int time; };
-			struct derived : KEY, fallback { };
-			template<typename C, C> struct cht; 
-			template<typename C> static char (&test(cht<int fallback::*, &C::time>*))[1]; 
-			template<typename C> static char (&test(...))[2]; 
-		public:
-			static bool const value = sizeof(test<derived>(0)) == 2;;
-		};
-
-		template < typename KEY >
-		struct key_has_slot_impl< KEY, animation_slot::POSITION >
-		{
-		private:
-			struct fallback { int position; };
-			struct derived : KEY, fallback { };
-			template<typename C, C> struct cht; 
-			template<typename C> static char (&test(cht<int fallback::*, &C::position>*))[1]; 
-			template<typename C> static char (&test(...))[2]; 
-		public:
-			static bool const value = sizeof(test<derived>(0)) == 2;;
-		};
-
-		template < typename KEY >
-		struct key_has_slot_impl< KEY, animation_slot::ROTATION >
-		{
-		private:
-			struct fallback { int rotation; };
-			struct derived : KEY, fallback { };
-			template<typename C, C> struct cht; 
-			template<typename C> static char (&test(cht<int fallback::*, &C::rotation>*))[1]; 
-			template<typename C> static char (&test(...))[2]; 
-		public:
-			static bool const value = sizeof(test<derived>(0)) == 2;;
-		};
-
-		template < typename KEY >
-		struct key_has_slot_impl< KEY, animation_slot::SCALE >
-		{
-		private:
-			struct fallback { int scale; };
-			struct derived : KEY, fallback { };
-			template<typename C, C> struct cht; 
-			template<typename C> static char (&test(cht<int fallback::*, &C::scale>*))[1]; 
-			template<typename C> static char (&test(...))[2]; 
-		public:
-			static bool const value = sizeof(test<derived>(0)) == 2;;
-		};
-
-		template < typename KEY >
-		struct key_has_slot_impl< KEY, animation_slot::TFORM >
-		{
-		private:
-			struct fallback { int tform; };
-			struct derived : KEY, fallback { };
-			template<typename C, C> struct cht; 
-			template<typename C> static char (&test(cht<int fallback::*, &C::tform>*))[1]; 
-			template<typename C> static char (&test(...))[2]; 
-		public:
-			static bool const value = sizeof(test<derived>(0)) == 2;;
-		};
-
-		template < typename KEY, animation_slot SLOT, bool HAS_SLOT >
-		struct key_slot_info_impl
-		{
-		};
-
-		template < typename KEY, animation_slot SLOT >
-		struct key_slot_info_impl < KEY, SLOT, false >
-		{
-			typedef empty_type value_type;
-			static const datatype etype  = datatype::NONE;
-			static const int      offset = 0;
-		};
-
-		template < typename KEY >
-		struct key_slot_info_impl< KEY, animation_slot::TIME, true >
-		{
-			typedef decltype( KEY::time ) value_type;
-			static const datatype etype  = type_to_enum< decltype( KEY::time ) >::type;
-			static const int      offset = offsetof( KEY, time );
-		};
-
-		template < typename KEY >
-		struct key_slot_info_impl< KEY, animation_slot::POSITION, true >
-		{
-			typedef decltype( KEY::position ) value_type;
-			static const datatype etype  = type_to_enum< decltype( KEY::position ) >::type;
-			static const int      offset = offsetof( KEY, position );
-			static void interpolate( KEY& key, const KEY& k1, const KEY& k2, float factor )
-			{
-				key.position = nv::interpolate( k1.position, k2.position, factor );
-			}
-		};
-
-		template < typename KEY >
-		struct key_slot_info_impl< KEY, animation_slot::ROTATION, true >
-		{
-			typedef decltype( KEY::rotation ) value_type;
-			static const datatype etype  = type_to_enum< decltype( KEY::rotation ) >::type;
-			static const int      offset = offsetof( KEY, rotation );
-			static void interpolate( KEY& key, const KEY& k1, const KEY& k2, float factor )
-			{
-				key.rotation = nv::interpolate( k1.rotation, k2.rotation, factor );
-			}
-		};
-
-		template < typename KEY >
-		struct key_slot_info_impl< KEY, animation_slot::SCALE, true >
-		{
-			typedef decltype( KEY::scale ) value_type;
-			static const datatype etype  = type_to_enum< decltype( KEY::scale ) >::type;
-			static const int      offset = offsetof( KEY, scale );
-			static void interpolate( KEY& key, const KEY& k1, const KEY& k2, float factor )
-			{
-				key.scale = nv::interpolate( k1.scale, k2.scale, factor );
-			}
-		};
-
-		template < typename KEY >
-		struct key_slot_info_impl< KEY, animation_slot::TFORM, true >
-		{
-			typedef decltype( KEY::tform ) value_type;
-			static const datatype etype  = type_to_enum< decltype( KEY::tform ) >::type;
-			static const int      offset = offsetof( KEY, tform );
-			static void interpolate( KEY& key, const KEY& k1, const KEY& k2, float factor )
-			{
-				key.tform = nv::interpolate( k1.tform, k2.tform, factor );
-			}
-		};
 	}
+
 
 	template < typename VT, slot SLOT >
@@ -365,15 +215,4 @@
 	};
 
-	template < typename KEY, animation_slot SLOT >
-	struct key_has_slot : public detail::key_has_slot_impl< KEY, SLOT >
-	{
-	};
-
-
-	template < typename KEY, animation_slot SLOT >
-	struct key_slot_info : public detail::key_slot_info_impl< KEY, SLOT, detail::key_has_slot_impl< KEY, SLOT >::value >
-	{
-	};
-	
 	struct vertex_descriptor_slot
 	{
@@ -451,335 +290,4 @@
 	};
 
-	struct key_descriptor_slot
-	{
-		datatype       etype;
-		uint32         offset;
-		animation_slot vslot;
-		key_descriptor_slot() : etype(NONE), offset(0), vslot(animation_slot::TIME) {}
-	};
-
-	struct key_descriptor
-	{
-		key_descriptor_slot slots[ animation_slot::SLOT_MAX_STORE ];
-		uint32              count;
-		uint32              size;
-
-		key_descriptor() : count(0), size(0) {}
-
-		template < typename KEY >
-		void initialize()
-		{
-			count = 0;
-			initialize_slot< KEY, animation_slot::TIME >();
-			initialize_slot< KEY, animation_slot::POSITION >();
-			initialize_slot< KEY, animation_slot::ROTATION >();
-			initialize_slot< KEY, animation_slot::SCALE >();
-			initialize_slot< KEY, animation_slot::TFORM >();
-			size = sizeof( KEY );
-		}
-
-		bool operator==( const key_descriptor& rhs ) const
-		{
-			if ( size  != rhs.size )  return false;
-			if ( count != rhs.count ) return false;
-			for ( uint32 i = 0; i < count; ++i )
-			{
-				if ( slots[i].etype  != rhs.slots[i].etype )  return false;
-				if ( slots[i].offset != rhs.slots[i].offset ) return false;
-				if ( slots[i].vslot  != rhs.slots[i].vslot )  return false;
-			}
-			return true;
-		}
-
-	private:
-		template < typename KEY, animation_slot SLOT >
-		void initialize_slot()
-		{
-			typedef key_slot_info< KEY, SLOT > slot_info;
-			slots[ count ].etype  = slot_info::etype;
-			if ( slots[ count ].etype != datatype::NONE )
-			{
-				slots[ count ].vslot  = SLOT;
-				slots[ count ].offset = slot_info::offset;
-				count++;
-			}
-		}
-	};
-
-	template < typename KEY, animation_slot SLOT > 
-	void interpolate_slot( KEY& key, const KEY& k1, const KEY& k2, float factor, const std::true_type& )
-	{
-		key_slot_info< KEY, SLOT >::interpolate( key, k1, k2, factor );
-	}
-
-	template < typename KEY, animation_slot SLOT > 
-	void interpolate_slot( KEY&, const KEY&, const KEY&, float, const std::false_type& )
-	{
-	}
-
-	template < typename KEY >
-	void interpolate_key( KEY& key, const KEY& k1, const KEY& k2, float factor )
-	{
-		interpolate_slot< KEY, animation_slot::POSITION >( key, k1, k2, factor, std::integral_constant< bool, key_has_slot< KEY, animation_slot::POSITION >::value >() );
-		interpolate_slot< KEY, animation_slot::ROTATION >( key, k1, k2, factor, std::integral_constant< bool, key_has_slot< KEY, animation_slot::ROTATION >::value >() );
-		interpolate_slot< KEY, animation_slot::SCALE >( key, k1, k2, factor, std::integral_constant< bool, key_has_slot< KEY, animation_slot::SCALE >::value >() );
-		interpolate_slot< KEY, animation_slot::TFORM >( key, k1, k2, factor, std::integral_constant< bool, key_has_slot< KEY, animation_slot::TFORM >::value >() );
-	}
-
-	namespace detail
-	{
-		template < typename T >
-		mat4 extract_matrix_slot( const T& ) { static_assert( false, "extract_matrix_slot" ); }
-		template <> inline mat4 extract_matrix_slot( const mat4& m ) { return m; }
-		template <> inline mat4 extract_matrix_slot( const transform& m ) { return m.extract(); }
-
-		template < typename T >
-		transform extract_transfrom_slot( const T& ) { static_assert( false, "extract_matrix_slot" ); }
-		template <> inline transform extract_transfrom_slot( const mat4& m ) { return transform(m); }
-		template <> inline transform extract_transfrom_slot( const transform& m ) { return m; }
-
-		template < typename KEY >
-		mat4 extract_matrix_p_impl( const KEY& k ) { return glm::translate(mat4(),k.position); }
-		template < typename KEY >
-		mat4 extract_matrix_r_impl( const KEY& k ) { return glm::mat4_cast( k.rotation ); }
-		template < typename KEY >
-		mat4 extract_matrix_s_impl( const KEY& k ) { return glm::scale(mat4(),k.scale); }
-		template < typename KEY >
-		mat4 extract_matrix_pr_impl( const KEY& k )
-		{
-			// TODO: this is obviously unoptimized
-			mat4 result = glm::mat4_cast( k.rotation );
-			result[3] = vec4( k.position, 1.0f );
-			return result;
-		}
-		template < typename KEY >
-		mat4 extract_matrix_rs_impl( const KEY& k )
-		{
-			// TODO: this is obviously unoptimized
-			mat4 result = glm::mat4_cast( k.rotation );
-			return glm::scale(result,k.scale);
-		}
-		template < typename KEY >
-		mat4 extract_matrix_ps_impl( const KEY& k )
-		{
-			// TODO: this is obviously unoptimized
-			return glm::scale(glm::translate(mat4(),k.position),k.scale);
-		}
-		template < typename KEY >
-		mat4 extract_matrix_prs_impl( const KEY& k )
-		{
-			// TODO: this is obviously unoptimized
-			return glm::translate(mat4(),k.position) * glm::mat4_cast( k.rotation ) * glm::scale(mat4(),k.scale);
-		}
-
-		template < typename KEY >
-		mat4 extract_matrix_prs( const KEY& k, const std::false_type&, const std::false_type&, const std::false_type& )
-		{ return mat4(); }
-		template < typename KEY >
-		mat4 extract_matrix_prs( const KEY& k, const std::true_type&, const std::false_type&, const std::false_type& )
-		{ return extract_matrix_p_impl(k); }
-		template < typename KEY >
-		mat4 extract_matrix_prs( const KEY& k, const std::false_type&, const std::true_type&, const std::false_type& )
-		{ return extract_matrix_r_impl(k); }
-		template < typename KEY >
-		mat4 extract_matrix_prs( const KEY& k, const std::false_type&, const std::false_type&, const std::true_type& )
-		{ return extract_matrix_s_impl(k); }
-		template < typename KEY >
-		mat4 extract_matrix_prs( const KEY& k, const std::true_type&, const std::true_type&, const std::false_type& )
-		{ return extract_matrix_pr_impl(k); }
-		template < typename KEY >
-		mat4 extract_matrix_prs( const KEY& k, const std::false_type&, const std::true_type&, const std::true_type& )
-		{ return extract_matrix_rs_impl(k); }
-		template < typename KEY >
-		mat4 extract_matrix_prs( const KEY& k, const std::true_type&, const std::false_type&, const std::true_type& )
-		{ return extract_matrix_ps_impl(k); }
-		template < typename KEY >
-		mat4 extract_matrix_prs( const KEY& k, const std::true_type&, const std::true_type&, const std::true_type& )
-		{ return extract_matrix_prs_impl(k); }
-
-
-		template < typename KEY >
-		transform extract_transform_pr_impl( const KEY& k, const std::false_type&, const std::false_type& ) { return transform(); }
-		template < typename KEY >
-		transform extract_transform_pr_impl( const KEY& k, const std::true_type&, const std::true_type& ) { return transform( k.position, k.rotation ); }
-		template < typename KEY >
-		transform extract_transform_pr_impl( const KEY& k, const std::true_type&, const std::false_type& ) { return transform( k.position ); }
-		template < typename KEY >
-		transform extract_transform_pr_impl( const KEY& k, const std::false_type&, const std::true_type& ) { return transform( k.rotation ); }
-
-
-
-		template < typename KEY >
-		mat4 extract_matrix_impl( const KEY& k, const std::true_type& )
-		{
-			static_assert( key_has_slot< KEY, animation_slot::POSITION >::value == false, "key!");
-			static_assert( key_has_slot< KEY, animation_slot::ROTATION >::value == false, "key!");
-			static_assert( key_has_slot< KEY, animation_slot::SCALE >::value == false, "key!");
-			return extract_matrix_slot( k.tform );
-		}
-
-		template < typename KEY >
-		mat4 extract_matrix_impl( const KEY& k, const std::false_type& )
-		{
-			static_assert( key_has_slot< KEY, animation_slot::TFORM >::value == false, "key!");
-			return extract_matrix_prs( k,
-				std::integral_constant< bool, key_has_slot< KEY, animation_slot::POSITION >::value >(),
-				std::integral_constant< bool, key_has_slot< KEY, animation_slot::ROTATION >::value >(),
-				std::integral_constant< bool, key_has_slot< KEY, animation_slot::SCALE >::value >()
-				);
-		}
-
-		template < typename KEY >
-		transform extract_transform_impl( const KEY& k, const std::true_type& )
-		{
-			static_assert( key_has_slot< KEY, animation_slot::POSITION >::value == false, "key!");
-			static_assert( key_has_slot< KEY, animation_slot::ROTATION >::value == false, "key!");
-			static_assert( key_has_slot< KEY, animation_slot::SCALE >::value == false, "key!");
-			return extract_transfrom_slot( k.tform );
-		}
-
-		template < typename KEY >
-		transform extract_transform_impl( const KEY& k, const std::false_type& )
-		{
-			static_assert( key_has_slot< KEY, animation_slot::TFORM >::value == false, "key!");
-			static_assert( key_has_slot< KEY, animation_slot::SCALE >::value == false, "key!");
-			return extract_transform_pr_impl( k, 
-				std::integral_constant< bool, key_has_slot< KEY, animation_slot::POSITION >::value >(),
-				std::integral_constant< bool, key_has_slot< KEY, animation_slot::ROTATION >::value >() 
-			);
-		}
-	}
-
-	template < typename KEY >
-	mat4 extract_matrix( const KEY& k )
-	{
-		return detail::extract_matrix_impl( k, std::integral_constant< bool, key_has_slot< KEY, animation_slot::TFORM >::value >() );
-	}
-
-	template < typename KEY >
-	transform extract_transform( const KEY& k )
-	{
-		return detail::extract_transform_impl( k, std::integral_constant< bool, key_has_slot< KEY, animation_slot::TFORM >::value >() );
-	}
-
-	inline uint32 interpolate_raw_linear( uint32 count, float factor, const float* k1, const float* k2, float* result )
-	{
-		for ( uint32 i = 0; i < count; ++i )
-		{
-			result[i] = k1[i] + factor * (k2[i] - k1[i]); 
-		}
-		return count;
-	}
-
-	inline uint32 interpolate_raw_quat( float factor, const float* k1, const float* k2, float* result )
-	{
-		*((quat*)(result)) = interpolate( *((quat*)(k1)), *((quat*)(k2)), factor );
-		return 4;
-	}
-
-	inline uint32 interpolate_raw( const key_descriptor_slot& slot, float factor, const float* k1, const float* k2, float* result )
-	{
-		uint32 count = get_datatype_info( slot.etype ).elements;
-		switch ( slot.vslot )
-		{
-		case animation_slot::TIME:     return 0;
-		case animation_slot::POSITION: return interpolate_raw_linear( count, factor, k1, k2, result );
-		case animation_slot::ROTATION: return interpolate_raw_quat( factor, k1, k2, result );
-		case animation_slot::SCALE:    return interpolate_raw_linear( count, factor, k1, k2, result );
-		case animation_slot::TFORM:    return 
-										   interpolate_raw_linear( 3, factor, k1, k2, result ) + 
-										   interpolate_raw_quat( factor, k1 + 3, k2 + 3, result + 3 );
-		default:
-			return 0;
-		};
-	}
-
-	inline quat make_quat_fixed( const float* data )
-	{
-		quat result;
-		memcpy((float*)(&result), data, sizeof(quat));
-		return result;
-	}
-
-	inline mat4 extract_matrix_raw( const key_descriptor& desc, const float* data )
-	{
-		if ( desc.count == 1 )
-		{
-			switch ( desc.slots[0].vslot )
-			{
-			case animation_slot::TIME:     return mat4();
-			case animation_slot::POSITION: return glm::translate( mat4(),glm::make_vec3( data ) );
-			case animation_slot::ROTATION: return glm::mat4_cast( make_quat_fixed( data ) );
-			case animation_slot::SCALE:    return glm::scale( mat4(),glm::make_vec3( data ) );
-			case animation_slot::TFORM:    return transform( glm::make_vec3( data ), make_quat_fixed( data + 3 ) ).extract();
-			default:
-				return mat4();
-			};
-		}
-		else
-		{
-			mat4 position;
-			mat4 rotation;
-			mat4 scale;
-			for ( uint32 i = 0; i < desc.count; ++i )
-			{
-				uint32 offset = desc.slots[i].offset / 4;
-				switch ( desc.slots[i].vslot )
-				{
-				case animation_slot::TIME:     break;
-				case animation_slot::POSITION: 
-					position = glm::translate( position,glm::make_vec3( data + offset ) ); break;
-				case animation_slot::ROTATION: 
-					rotation = glm::mat4_cast( make_quat_fixed( data + offset ) ); break;
-				case animation_slot::SCALE:    
-					scale    = glm::scale( mat4(),glm::make_vec3( data + offset ) ); break;
-				case animation_slot::TFORM:    return transform( glm::make_vec3( data + offset ), make_quat_fixed( data + offset + 3 ) ).extract();
-				default:
-					break;
-				}
-			}
-			return position * rotation * scale;
-		}
-	}
-
-	inline transform extract_transform_raw( const key_descriptor& desc, const float* data )
-	{
-		if ( desc.count == 1 )
-		{
-			switch ( desc.slots[0].vslot )
-			{
-			case animation_slot::TIME:     return transform();
-			case animation_slot::POSITION: return transform( glm::make_vec3( data ) );
-			case animation_slot::ROTATION: return transform( make_quat_fixed( data ) );
-			case animation_slot::SCALE:    return transform();
-			case animation_slot::TFORM:    return transform( glm::make_vec3( data ), make_quat_fixed( data + 3 ) );
-			default:
-				return transform();
-			};
-		}
-		else
-		{
-			vec3 position;
-			quat rotation;
-			for ( uint32 i = 0; i < desc.count; ++i )
-			{
-				uint32 offset = desc.slots[i].offset / 4;
-				switch ( desc.slots[i].vslot )
-				{
-				case animation_slot::TIME:     break;
-				case animation_slot::POSITION: 
-					position = glm::make_vec3( data + offset ); break;
-				case animation_slot::ROTATION: 
-					rotation = make_quat_fixed( data + offset ); break;
-				case animation_slot::SCALE:	   break;
-				case animation_slot::TFORM:    return transform( glm::make_vec3( data + offset ), make_quat_fixed( data + 3 ) );
-				default:
-					break;
-				}
-			}
-			return transform( position, rotation );
-		}
-	}
-
 }
 
