Index: trunk/nv/formats/md3_loader.hh
===================================================================
--- trunk/nv/formats/md3_loader.hh	(revision 410)
+++ trunk/nv/formats/md3_loader.hh	(revision 411)
@@ -41,5 +41,5 @@
 	private:
 		void release_mesh_frame( mesh_data* data, sint32 frame, sint32 surface );
-		key_raw_channel* load_tags( const string_view& tag );
+		raw_data_channel* load_tags( const string_view& tag );
 		bool m_merge_all;
 		void* m_md3;
Index: trunk/nv/gfx/animation.hh
===================================================================
--- trunk/nv/gfx/animation.hh	(revision 410)
+++ trunk/nv/gfx/animation.hh	(revision 411)
@@ -20,177 +20,146 @@
 {
 
-	struct key_raw_channel
-	{
-		data_descriptor desc;
-		uint8*          data;
-		uint32          count;
-
-		key_raw_channel() : data( nullptr ), count( 0 ) {}
-		~key_raw_channel() 
-		{
-			if ( data != nullptr ) delete[] data;
-		}
-
-		uint32 size() const { return count * desc.element_size(); }
-
-		template < typename KEY >
-		static key_raw_channel* create( uint32 count = 0 )
-		{
-			key_raw_channel* result = new key_raw_channel();
-			result->desc.initialize<KEY>();
-			result->count = count;
-			result->data  = (count > 0 ? ( new uint8[ result->size() ] ) : nullptr );
-			return result;
-		}
-
-		static key_raw_channel* create( const data_descriptor& keydesc, uint32 count = 0 )
-		{
-			key_raw_channel* result = new key_raw_channel();
-			result->desc  = keydesc;
-			result->count = count;
-			result->data  = (count > 0 ? ( new uint8[ result->size() ] ) : nullptr );
-			return result;
-		}
-
-		uint32 get_raw( uint32 index, float* result ) const 
-		{
-			if ( count == 0 ) return 0;
-			uint32 keyfsize   = desc.element_size() / 4;
-			const float* fdata = reinterpret_cast<const float*>( data ) + keyfsize * index;
-			uint32 mod        = 0;
-			if ( desc[0].vslot == slot::TIME ) mod = 1;
+	class key_data
+	{
+	public:
+		key_data() {}
+
+		void add_channel( raw_data_channel* channel ) 
+		{
+			NV_ASSERT( channel, "nullptr passed to add_channel!" );
+			m_channels.push_back( channel );
+			for ( const auto& cslot : channel->descriptor() )
+				if ( cslot.vslot != slot::TIME )
+					m_final_key.push_slot( cslot.etype, cslot.vslot );
+		}
+
+		mat4 get_raw_matrix( uint32 index ) const 
+		{
+			float key[ 16 ];
+			float* pkey = key;
+			for ( uint16 i = 0; i < m_channels.size(); ++i )
+			{
+				pkey += get_raw( m_channels[i], index, pkey );
+			}
+			return extract_matrix_raw( m_final_key, key );
+		}
+
+		transform get_raw_transform( uint32 index ) const 
+		{
+			float key[ 16 ];
+			float* pkey = key;
+			for ( uint16 i = 0; i < m_channels.size(); ++i )
+			{
+				pkey += get_raw( m_channels[i], index, pkey );
+			}
+			return extract_transform_raw( m_final_key, key );
+		}
+
+		mat4 get_matrix( float time ) const
+		{
+			float key[ 16 ];
+			float* pkey = key;
+			for ( uint16 i = 0; i < m_channels.size(); ++i )
+			{
+				pkey += interpolate_raw( m_channels[i], time, pkey );
+			}
+			return extract_matrix_raw( m_final_key, key );
+		}
+
+		transform get_transform( float time ) const
+		{
+			float key[ 16 ];
+			float* pkey = key;
+			for ( uint16 i = 0; i < m_channels.size(); ++i )
+			{
+				pkey += interpolate_raw( m_channels[i], time, pkey );
+			}
+			return extract_transform_raw( m_final_key, key );
+		}
+
+		size_t get_channel_count() const { return m_channels.size(); }
+		const raw_data_channel* get_channel( size_t index ) const { return m_channels[ index ]; }
+		const data_descriptor& get_final_key() const { return m_final_key; }
+
+		virtual ~key_data()
+		{
+			for ( auto channel : m_channels ) delete channel;
+		}
+
+		static uint32 get_raw( const raw_data_channel* channel, uint32 index, float* result )
+		{
+			if ( channel->element_count() == 0 ) return 0;
+			uint32 keyfsize = channel->element_size() / 4;
+			const float* fdata = reinterpret_cast<const float*>( channel->data ) + keyfsize * index;
+			uint32 mod = 0;
+			if ( channel->descriptor()[0].vslot == slot::TIME ) mod = 1;
 			raw_copy_n( fdata + mod, keyfsize - mod, result );
 			return keyfsize - mod;
 		}
 
-		uint32 interpolate_raw( float time, float* result ) const 
-		{
-			if ( count == 0 ) return 0;
-			uint32 keyfsize   = desc.element_size() / 4;
+
+		static uint32 interpolate_raw( const raw_data_channel* channel, float time, float* result )
+		{
+			if ( channel->element_count() == 0 ) return 0;
+			uint32 keyfsize = channel->element_size() / 4;
 			uint32 keyfresult = keyfsize;
-			const float* fdata = reinterpret_cast<const float*>( data );
+			const float* fdata = reinterpret_cast<const float*>( channel->data );
 
 			uint32 slot = 0;
-			int index0  = -1;
-			int index1  = -1;
+			int index0 = -1;
+			int index1 = -1;
 			float factor = 1.0f;
-			if ( desc[0].vslot == slot::TIME )
-			{
-				NV_ASSERT( desc[0].offset == 0, "time offset not zero!" );
+			if ( channel->descriptor()[0].vslot == slot::TIME )
+			{
+				NV_ASSERT( channel->descriptor()[0].offset == 0, "time offset not zero!" );
 				slot++;
 				keyfresult--;
-				if ( count == 1 ) 
+				if ( channel->element_count() == 1 )
 				{
 					raw_copy_n( fdata + 1, keyfresult, result );
 					return keyfresult;
 				}
-				for ( unsigned i = 1 ; i < count ; i++ )
+				for ( unsigned i = 1; i < channel->element_count(); i++ )
 				{
-					if ( time < fdata[ i * keyfsize ] ) 
+					if ( time < fdata[i * keyfsize] )
 					{
-						index0 = static_cast<int>(i) - 1; 
+						index0 = static_cast<int>( i ) - 1;
 						break;
 					}
 				}
-				NV_ASSERT( index0 >= 0, "animation time fail!");
+				NV_ASSERT( index0 >= 0, "animation time fail!" );
 				index1 = index0 + 1;
-				float time0  = fdata[ index0 * static_cast<int>( keyfsize ) ];
-				float time1  = fdata[ index1 * static_cast<int>( keyfsize ) ];
-				float delta  = time1 - time0;
-				factor = glm::clamp( (time - time0) / delta, 0.0f, 1.0f );
+				float time0 = fdata[index0 * static_cast<int>( keyfsize )];
+				float time1 = fdata[index1 * static_cast<int>( keyfsize )];
+				float delta = time1 - time0;
+				factor = glm::clamp( ( time - time0 ) / delta, 0.0f, 1.0f );
 			}
 			else
 			{
-				if ( count == 1 ) 
+				if ( channel->element_count() == 1 )
 				{
 					raw_copy_n( fdata, keyfresult, result );
 					return keyfresult;
 				}
-				index0 = glm::clamp<int>( int( time ), 0, int( count ) - 2 );
+				index0 = glm::clamp<int>( int( time ), 0, int( channel->element_count() ) - 2 );
 				index1 = index0 + 1;
-				factor = glm::clamp<float> ( time - index0, 0.0f, 1.0f );
+				factor = glm::clamp<float>( time - index0, 0.0f, 1.0f );
 			}
 			uint32 ret = 0;
-			for ( ; slot < desc.slot_count(); ++slot )
-			{
-				ret += nv::interpolate_raw( 
-					desc[slot], factor, 
-					fdata + index0 * static_cast<int>( keyfsize ) + desc[slot].offset / 4,
-					fdata + index1 * static_cast<int>( keyfsize ) + desc[slot].offset / 4,
+			for ( ; slot < channel->descriptor().slot_count(); ++slot )
+			{
+				ret += nv::interpolate_raw(
+					channel->descriptor()[slot], factor,
+					fdata + index0 * static_cast<int>( keyfsize ) + channel->descriptor()[slot].offset / 4,
+					fdata + index1 * static_cast<int>( keyfsize ) + channel->descriptor()[slot].offset / 4,
 					result + ret );
 			}
 			return ret;
 		}
-	};
-
-	class key_data
-	{
-	public:
-		key_data() {}
-
-		void add_channel( key_raw_channel* channel ) 
-		{
-			NV_ASSERT( channel, "nullptr passed to add_channel!" );
-			m_channels.push_back( channel );
-			for ( const auto& cslot : channel->desc )
-				if ( cslot.vslot != slot::TIME )
-					m_final_key.push_slot( cslot.etype, cslot.vslot );
-		}
-
-		mat4 get_raw_matrix( uint32 index ) const 
-		{
-			float key[ 16 ];
-			float* pkey = key;
-			for ( uint16 i = 0; i < m_channels.size(); ++i )
-			{
-				pkey += m_channels[i]->get_raw( index, pkey );
-			}
-			return extract_matrix_raw( m_final_key, key );
-		}
-
-		transform get_raw_transform( uint32 index ) const 
-		{
-			float key[ 16 ];
-			float* pkey = key;
-			for ( uint16 i = 0; i < m_channels.size(); ++i )
-			{
-				pkey += m_channels[i]->get_raw( index, pkey );
-			}
-			return extract_transform_raw( m_final_key, key );
-		}
-
-		mat4 get_matrix( float time ) const
-		{
-			float key[ 16 ];
-			float* pkey = key;
-			for ( uint16 i = 0; i < m_channels.size(); ++i )
-			{
-				pkey += m_channels[i]->interpolate_raw( time, pkey );
-			}
-			return extract_matrix_raw( m_final_key, key );
-		}
-
-		transform get_transform( float time ) const
-		{
-			float key[ 16 ];
-			float* pkey = key;
-			for ( uint16 i = 0; i < m_channels.size(); ++i )
-			{
-				pkey += m_channels[i]->interpolate_raw( time, pkey );
-			}
-			return extract_transform_raw( m_final_key, key );
-		}
-
-		size_t get_channel_count() const { return m_channels.size(); }
-		const key_raw_channel* get_channel( size_t index ) const { return m_channels[ index ]; }
-		const data_descriptor& get_final_key() const { return m_final_key; }
-
-		virtual ~key_data()
-		{
-			for ( auto channel : m_channels ) delete channel;
-		}
+
 	private:
+
 		data_descriptor m_final_key;
-		vector< key_raw_channel* > m_channels;
+		vector< raw_data_channel* > m_channels;
 	};
 
@@ -204,7 +173,7 @@
 	public:
 		key_channel_interpolator() : m_data( nullptr ) {}
-		key_channel_interpolator( const key_raw_channel* data ) : m_data( nullptr ) { set_data( data ); }
-		key_channel_interpolator( const key_raw_channel* data, bool ) : m_data( data ) {}
-		void set_data( const key_raw_channel* data )
+		key_channel_interpolator( const raw_data_channel* data ) : m_data( nullptr ) { set_data( data ); }
+		key_channel_interpolator( const raw_data_channel* data, bool ) : m_data( data ) {}
+		void set_data( const raw_data_channel* data )
 		{
 			m_data = data;
@@ -229,5 +198,5 @@
 
 	private:
-		const key_raw_channel* m_data;
+		const raw_data_channel* m_data;
 	};
  
@@ -237,6 +206,6 @@
 	public:
 		key_channel_interpolator() : m_data( nullptr ) {}
-		key_channel_interpolator( const key_raw_channel* data ) : m_data( nullptr ) { set_data( data ); }
-		void set_data( const key_raw_channel* data )
+		key_channel_interpolator( const raw_data_channel* data ) : m_data( nullptr ) { set_data( data ); }
+		void set_data( const raw_data_channel* data )
 		{
 			m_data = data;
@@ -268,5 +237,5 @@
 
 	private:
-		const key_raw_channel* m_data;
+		const raw_data_channel* m_data;
 	};
  
@@ -295,5 +264,5 @@
 		struct key_s { float time; vec3 scale; };
 	public:
-		explicit key_vectors_prs( const key_raw_channel* p, const key_raw_channel* r, const key_raw_channel* s )
+		explicit key_vectors_prs( const raw_data_channel* p, const raw_data_channel* r, const raw_data_channel* s )
 		{
 			m_pchannel = p;
@@ -305,5 +274,5 @@
 		}
 		size_t size() const { return 0; } // TODO: remove?
-		bool empty() const { return m_pchannel->count == 0 && m_rchannel->count == 0 && m_schannel->count == 0; }
+		bool empty() const { return m_pchannel->element_count() == 0 && m_rchannel->count == 0 && m_schannel->count == 0; }
 		virtual mat4 get_matrix( float time ) const
 		{
@@ -331,7 +300,7 @@
 		{
 			return 3 * sizeof( size_t ) 
-				+ m_pchannel->count * sizeof( key_p )
-				+ m_rchannel->count * sizeof( key_r )
-				+ m_schannel->count * sizeof( key_s );
+				+ m_pchannel->element_count() * sizeof( key_p )
+				+ m_rchannel->element_count() * sizeof( key_r )
+				+ m_schannel->element_count() * sizeof( key_s );
 		}
 		~key_vectors_prs()
@@ -339,7 +308,7 @@
 		}
 	protected:
-		const key_raw_channel* m_pchannel;
-		const key_raw_channel* m_rchannel;
-		const key_raw_channel* m_schannel;
+		const raw_data_channel* m_pchannel;
+		const raw_data_channel* m_rchannel;
+		const raw_data_channel* m_schannel;
 		key_channel_interpolator< key_p, true > m_pinter;
 		key_channel_interpolator< key_r, true > m_rinter;
@@ -354,5 +323,5 @@
 		};
 	public:
-		explicit transform_vector( const key_raw_channel* channel ) 
+		explicit transform_vector( const raw_data_channel* channel )
 		{
 			data_descriptor kd;
@@ -367,6 +336,6 @@
 			delete m_channel;
 		}
-		bool empty() const { return m_channel->count == 0; }
-		size_t size() const { return m_channel->count; }
+		bool empty() const { return m_channel->element_count() == 0; }
+		size_t size() const { return m_channel->element_count(); }
 		const transform& get( size_t index ) const { return reinterpret_cast<key*>(m_channel->data)[ index ].tform; }
 		const transform* data() const { return reinterpret_cast<const transform*>( m_channel->data ); }
@@ -374,5 +343,5 @@
 		virtual uint32 raw_size() const 
 		{
-			return sizeof( size_t ) + m_channel->count * sizeof( key );
+			return sizeof( size_t ) + m_channel->element_count() * sizeof( key );
 		}
 
@@ -389,5 +358,5 @@
 	protected:
 		key_channel_interpolator< key, false > m_interpolator;
-		const key_raw_channel* m_channel;
+		const raw_data_channel* m_channel;
 	};
 
Index: trunk/nv/gfx/keyframed_mesh.hh
===================================================================
--- trunk/nv/gfx/keyframed_mesh.hh	(revision 410)
+++ trunk/nv/gfx/keyframed_mesh.hh	(revision 411)
@@ -52,5 +52,5 @@
 		const mesh_data*        m_mesh_data;
 		const mesh_nodes_data*  m_tag_map;
-		const mesh_raw_channel* m_vchannel;
+		const raw_data_channel* m_vchannel;
 
 		buffer       m_pbuffer;
Index: trunk/nv/gfx/mesh_creator.hh
===================================================================
--- trunk/nv/gfx/mesh_creator.hh	(revision 410)
+++ trunk/nv/gfx/mesh_creator.hh	(revision 411)
@@ -27,6 +27,6 @@
 		void merge( mesh_data* other );
 	private:
-		mesh_raw_channel* merge_channels( mesh_raw_channel* a, mesh_raw_channel* b );
-		mesh_raw_channel* append_channels( mesh_raw_channel* a, mesh_raw_channel* b, uint32 frame_count = 1 );
+		raw_data_channel* merge_channels( raw_data_channel* a, raw_data_channel* b );
+		raw_data_channel* append_channels( raw_data_channel* a, raw_data_channel* b, uint32 frame_count = 1 );
 
 		mesh_data* m_data;
Index: trunk/nv/interface/context.hh
===================================================================
--- trunk/nv/interface/context.hh	(revision 410)
+++ trunk/nv/interface/context.hh	(revision 411)
@@ -155,5 +155,5 @@
 		}
 
-		void add_vertex_buffers( vertex_array va, buffer buf, const mesh_raw_channel* channel )
+		void add_vertex_buffers( vertex_array va, buffer buf, const raw_data_channel* channel )
 		{
 			for ( const auto& cslot : channel->desc )
@@ -300,8 +300,8 @@
 		{
 			vertex_array  va = create_vertex_array();
-			array_view< mesh_raw_channel* > channels = data->get_raw_channels();
+			array_view< raw_data_channel* > channels = data->get_raw_channels();
 			for ( uint32 ch = 0; ch < channels.size(); ++ch )
 			{
-				const mesh_raw_channel* channel = channels[ch];
+				const raw_data_channel* channel = channels[ch];
 				if ( channel->count > 0 )
 				{
Index: trunk/nv/interface/data_descriptor.hh
===================================================================
--- trunk/nv/interface/data_descriptor.hh	(revision 410)
+++ trunk/nv/interface/data_descriptor.hh	(revision 411)
@@ -14,4 +14,10 @@
 namespace nv
 {
+	// TODO: move somewhere else, or change to generic buffer_type
+	enum buffer_type
+	{
+		VERTEX_BUFFER,
+		INDEX_BUFFER,
+	};
 
 	enum class slot : uint8
@@ -232,23 +238,4 @@
 			}
 			return true;
-		}
-
-		template < typename IndexType >
-		void initialize_index()
-		{
-			count = 1;
-			size = sizeof( IndexType );
-			slots[0].etype = type_to_enum< IndexType >::type;
-			slots[0].vslot = slot::INDEX;
-			slots[0].offset = 0;
-		}
-
-		void initialize_index( datatype itype )
-		{
-			count = 1;
-			size  = get_datatype_info( itype ).size;
-			slots[0].etype  = itype;
-			slots[0].vslot  = slot::INDEX;
-			slots[0].offset = 0;
 		}
 
@@ -320,4 +307,73 @@
 	};
 
+	struct raw_data_channel
+	{
+		raw_data_channel() : data( nullptr ), count( 0 ) {}
+		~raw_data_channel()
+		{
+			if ( data != nullptr ) delete[] data;
+		}
+
+		// TODO: this could have more options if stored!
+		buffer_type get_buffer_type() const
+		{
+			if ( count > 0 && desc[0].vslot == slot::INDEX )
+			{
+				return INDEX_BUFFER;
+			}
+			return VERTEX_BUFFER;
+		}
+
+		const data_descriptor& descriptor() const { return desc;  }
+		uint32 element_size() const { return desc.element_size(); }
+		uint32 element_count() const { return count; }
+		uint32 size() const { return count * desc.element_size(); }
+
+		template < typename VTX >
+		static raw_data_channel* create( uint32 count = 0 )
+		{
+			raw_data_channel* result = new raw_data_channel();
+			result->desc.initialize<VTX>();
+			result->count = count;
+			result->data = ( count > 0 ? ( new uint8[result->size()] ) : nullptr );
+			return result;
+		}
+		static raw_data_channel* create( const data_descriptor& vtxdesc, uint32 count = 0 )
+		{
+			raw_data_channel* result = new raw_data_channel();
+			result->desc = vtxdesc;
+			result->count = count;
+			result->data = ( count > 0 ? ( new uint8[result->size()] ) : nullptr );
+			return result;
+		}
+
+		template < typename IndexType >
+		static raw_data_channel* create_index( uint32 count = 0 )
+		{
+			raw_data_channel* result = new raw_data_channel();
+			result->desc.push_slot( type_to_enum< IndexType >::type, slot::INDEX );
+			result->count = count;
+			result->data = ( count > 0 ? ( new uint8[result->size()] ) : nullptr );
+			return result;
+		}
+
+		// TODO: remove this
+		static raw_data_channel* create_index( datatype etype, uint32 count = 0, slot s = slot::INDEX )
+		{
+			raw_data_channel* result = new raw_data_channel();
+			result->desc.push_slot( etype, s );
+			result->count = count;
+			result->data = ( count > 0 ? ( new uint8[result->size()] ) : nullptr );
+			return result;
+		}
+
+		friend class mesh_creator;
+
+		data_descriptor desc;
+		uint8*          data;
+		uint32          count;
+
+	};
+
 }
 
Index: trunk/nv/interface/mesh_data.hh
===================================================================
--- trunk/nv/interface/mesh_data.hh	(revision 410)
+++ trunk/nv/interface/mesh_data.hh	(revision 411)
@@ -17,80 +17,6 @@
 {
 
-	enum buffer_type
-	{
-		VERTEX_BUFFER,
-		INDEX_BUFFER,
-	};
-
-
 	// TODO: friend mesh_data_creator class?
 	// TODO: private const etc
-
-
-	struct mesh_raw_channel
-	{
-		friend class mesh_creator;
-
-		data_descriptor desc;
-		uint8*          data;
-		uint32          count;
-
-		mesh_raw_channel() : data( nullptr ), count( 0 ) {}
-		~mesh_raw_channel() 
-		{
-			if ( data != nullptr ) delete[] data;
-		}
-
-		// TODO: this could have more options if stored!
-		buffer_type get_buffer_type() const
-		{
-			if ( count > 0 && desc[0].vslot == slot::INDEX )
-			{
-				return INDEX_BUFFER;
-			}
-			return VERTEX_BUFFER;
-		}
-
-		uint32 size() const { return count * desc.element_size(); }
-
-		template < typename VTX >
-		static mesh_raw_channel* create( uint32 count = 0 )
-		{
-			mesh_raw_channel* result = new mesh_raw_channel();
-			result->desc.initialize<VTX>();
-			result->count = count;
-			result->data  = (count > 0 ? ( new uint8[ result->size() ] ) : nullptr );
-			return result;
-		}
-		static mesh_raw_channel* create( const data_descriptor& vtxdesc, uint32 count = 0 )
-		{
-			mesh_raw_channel* result = new mesh_raw_channel();
-			result->desc  = vtxdesc;
-			result->count = count;
-			result->data  = (count > 0 ? ( new uint8[ result->size() ] ) : nullptr );
-			return result;
-		}
-
-		template < typename ITYPE >
-		static mesh_raw_channel* create_index( uint32 count = 0 )
-		{
-			mesh_raw_channel* result = new mesh_raw_channel();
-			result->desc.initialize_index<ITYPE>();
-			result->count = count;
-			result->data  = (count > 0 ? ( new uint8[ result->size() ] ) : nullptr );
-			return result;
-		}
-
-		// TODO: remove this
-		static mesh_raw_channel* create_index( datatype etype, uint32 count = 0 )
-		{
-			mesh_raw_channel* result = new mesh_raw_channel();
-			result->desc.initialize_index( etype );
-			result->count = count;
-			result->data  = (count > 0 ? ( new uint8[ result->size() ] ) : nullptr );
-			return result;
-		}
-
-	};
 
 	class mesh_data
@@ -102,5 +28,5 @@
 		explicit mesh_data( const std::string& name ) : m_name(name), m_index_channel( nullptr ) {}
 
-		void add_channel( mesh_raw_channel* channel ) 
+		void add_channel( raw_data_channel* channel )
 		{
 			NV_ASSERT( channel, "nullptr passed to add_channel!" );
@@ -113,8 +39,8 @@
 		}
 
-		array_view< mesh_raw_channel* > get_raw_channels()  const { return m_channels; }
-		const mesh_raw_channel*         get_index_channel() const { return m_index_channel; }
+		array_view< raw_data_channel* > get_raw_channels()  const { return m_channels; }
+		const raw_data_channel*         get_index_channel() const { return m_index_channel; }
 		size_t get_channel_count() const { return m_channels.size(); }
-		const mesh_raw_channel* get_channel( size_t index ) const 
+		const raw_data_channel* get_channel( size_t index ) const
 		{ 
 			if ( m_channels.size() > index ) return m_channels[index];
@@ -122,5 +48,5 @@
 		}
 
-		const mesh_raw_channel* get_channel( slot s ) const 
+		const raw_data_channel* get_channel( slot s ) const
 		{ 
 			for ( auto ch : m_channels )
@@ -159,5 +85,5 @@
 
 		template < typename VTX >
-		const mesh_raw_channel* get_channel() const
+		const raw_data_channel* get_channel() const
 		{
 			data_descriptor compare;
@@ -216,6 +142,6 @@
 	private:
 		std::string                 m_name;
-		vector< mesh_raw_channel* > m_channels;
-		mesh_raw_channel*           m_index_channel;
+		vector< raw_data_channel* > m_channels;
+		raw_data_channel*           m_index_channel;
 	};
 
Index: trunk/src/formats/assimp_loader.cc
===================================================================
--- trunk/src/formats/assimp_loader.cc	(revision 410)
+++ trunk/src/formats/assimp_loader.cc	(revision 411)
@@ -118,9 +118,9 @@
 
 	bool skinned = mesh->mNumBones > 0;
-	mesh_raw_channel* channel = nullptr;
+	raw_data_channel* channel = nullptr;
 	if ( skinned )
-		channel = mesh_raw_channel::create< assimp_skinned_vtx >( mesh->mNumVertices );
+		channel = raw_data_channel::create< assimp_skinned_vtx >( mesh->mNumVertices );
 	else
-		channel = mesh_raw_channel::create< assimp_plain_vtx >( mesh->mNumVertices );
+		channel = raw_data_channel::create< assimp_plain_vtx >( mesh->mNumVertices );
 
 	data->add_channel( channel );
@@ -169,5 +169,5 @@
 	}
 
-	mesh_raw_channel* ichannel = mesh_raw_channel::create_index( USHORT, mesh->mNumFaces * 3 );
+	raw_data_channel* ichannel = raw_data_channel::create_index( USHORT, mesh->mNumFaces * 3 );
 	data->add_channel( ichannel );
 	uint16* indices = reinterpret_cast<uint16*>( ichannel->data );
@@ -315,5 +315,5 @@
 			if ( m > 0 && bones.size() > 0 )
 			{
-				mesh_raw_channel* channel = meshes[m].get_raw_channels()[0];
+				raw_data_channel* channel = meshes[m].get_raw_channels()[0];
 				assimp_skinned_vtx* va = reinterpret_cast< assimp_skinned_vtx* >( channel->data );
 				for ( unsigned v = 0; v < channel->count; ++v )
@@ -418,7 +418,7 @@
 
 	data->data = new key_data;
-	key_raw_channel* raw_pchannel = key_raw_channel::create<assimp_key_p>( node->mNumPositionKeys );
-	key_raw_channel* raw_rchannel = key_raw_channel::create<assimp_key_r>( node->mNumRotationKeys );
-	//key_raw_channel* raw_schannel = key_raw_channel::create<assimp_key_s>( node->mNumScalingKeys );
+	raw_data_channel* raw_pchannel = raw_data_channel::create<assimp_key_p>( node->mNumPositionKeys );
+	raw_data_channel* raw_rchannel = raw_data_channel::create<assimp_key_r>( node->mNumRotationKeys );
+	//raw_data_channel* raw_schannel = raw_data_channel::create<assimp_key_s>( node->mNumScalingKeys );
 	data->data->add_channel( raw_pchannel );
 	data->data->add_channel( raw_rchannel );
Index: trunk/src/formats/md2_loader.cc
===================================================================
--- trunk/src/formats/md2_loader.cc	(revision 410)
+++ trunk/src/formats/md2_loader.cc	(revision 411)
@@ -324,5 +324,5 @@
 	size_t frame_count   = ( frame == -1 ? num_frames : 1 );
 
-	mesh_raw_channel* mc_pn = mesh_raw_channel::create< vtx_md2_pn >( num_verts * frame_count );
+	raw_data_channel* mc_pn = raw_data_channel::create< vtx_md2_pn >( num_verts * frame_count );
 	vtx_md2_pn* vtx_pn = reinterpret_cast< vtx_md2_pn* >( mc_pn->data );
 
@@ -347,5 +347,5 @@
 	}
 
-	mesh_raw_channel* mc_t = mesh_raw_channel::create< vtx_md2_t >( num_verts );
+	raw_data_channel* mc_t = raw_data_channel::create< vtx_md2_t >( num_verts );
 	vtx_md2_t* vtx_t = reinterpret_cast< vtx_md2_t* >( mc_t->data );
 
@@ -357,5 +357,5 @@
 	}
 
-	mesh_raw_channel* ic = mesh_raw_channel::create_index< uint16 >( m_new_indexes.size() );
+	raw_data_channel* ic = raw_data_channel::create_index< uint16 >( m_new_indexes.size() );
 	if ( m_new_indexes.size() > 0 )
 	{
Index: trunk/src/formats/md3_loader.cc
===================================================================
--- trunk/src/formats/md3_loader.cc	(revision 410)
+++ trunk/src/formats/md3_loader.cc	(revision 411)
@@ -286,8 +286,8 @@
 }
 
-nv::key_raw_channel* nv::md3_loader::load_tags( const string_view& tag )
+nv::raw_data_channel* nv::md3_loader::load_tags( const string_view& tag )
 {
 	md3_t* md3 = reinterpret_cast< md3_t* >( m_md3 );
-	key_raw_channel* result = key_raw_channel::create<md3_key>( uint32( md3->header.num_frames ) );
+	raw_data_channel* result = raw_data_channel::create<md3_key>( uint32( md3->header.num_frames ) );
 	// TODO: is this brain damaged in efficiency (loop nest order) or what?
 	for ( sint32 f = 0; f < md3->header.num_frames; ++f )
@@ -352,7 +352,7 @@
 		}
 
-	mesh_raw_channel* mc_pn = mesh_raw_channel::create< vtx_md3_pn >( uint32( num_verts * frame_count ) );
-	mesh_raw_channel* mc_t  = mesh_raw_channel::create< vtx_md3_t >( uint32( num_verts ) );
-	mesh_raw_channel* ic = mesh_raw_channel::create_index< uint16 >( uint32( index_count ) );
+	raw_data_channel* mc_pn = raw_data_channel::create< vtx_md3_pn >( uint32( num_verts * frame_count ) );
+	raw_data_channel* mc_t  = raw_data_channel::create< vtx_md3_t >( uint32( num_verts ) );
+	raw_data_channel* ic = raw_data_channel::create_index< uint16 >( uint32( index_count ) );
 	vtx_md3_pn* vtx_pn = reinterpret_cast< vtx_md3_pn* >( mc_pn->data );
 	vtx_md3_t*  vtx_t  = reinterpret_cast< vtx_md3_t* >( mc_t->data );
@@ -435,5 +435,5 @@
 		nodes[i].data      = new key_data;
 	
-		key_raw_channel* keys = load_tags( name );
+		raw_data_channel* keys = load_tags( name );
 		nodes[i].data->add_channel( keys );
 	}
Index: trunk/src/formats/md5_loader.cc
===================================================================
--- trunk/src/formats/md5_loader.cc	(revision 410)
+++ trunk/src/formats/md5_loader.cc	(revision 411)
@@ -159,7 +159,7 @@
 					md5_vtx_t* tdata = nullptr;
 					{
-						mesh_raw_channel* ch_pnt = mesh_raw_channel::create<md5_vtx_pnt>( num_verts );
-						mesh_raw_channel* ch_t   = mesh_raw_channel::create<md5_vtx_t>( num_verts );
-						mesh_raw_channel* ch_pntiw = mesh_raw_channel::create<md5_vtx_pntiw>( num_verts );
+						raw_data_channel* ch_pnt = raw_data_channel::create<md5_vtx_pnt>( num_verts );
+						raw_data_channel* ch_t   = raw_data_channel::create<md5_vtx_t>( num_verts );
+						raw_data_channel* ch_pntiw = raw_data_channel::create<md5_vtx_pntiw>( num_verts );
 						tdata = reinterpret_cast< md5_vtx_t* >( ch_t->data );
 						mesh->add_channel( ch_pnt );
@@ -190,5 +190,5 @@
 					sstream >> num_tris;
 
-					mesh_raw_channel* ch_i = mesh_raw_channel::create_index<uint32>( num_tris * 3 );
+					raw_data_channel* ch_i = raw_data_channel::create_index<uint32>( num_tris * 3 );
 					uint32* vtx_i                = reinterpret_cast< uint32* >( ch_i->data );
 					uint32 idx = 0;
@@ -256,5 +256,5 @@
 				nodes[i].target_id = -1;
 				nodes[i].data      = new key_data;
-				nodes[i].data->add_channel( key_raw_channel::create< md5_key_t >( num_frames ) );
+				nodes[i].data->add_channel( raw_data_channel::create< md5_key_t >( num_frames ) );
 				next_line( sstream ); 
 			}
Index: trunk/src/formats/nmd_loader.cc
===================================================================
--- trunk/src/formats/nmd_loader.cc	(revision 410)
+++ trunk/src/formats/nmd_loader.cc	(revision 411)
@@ -43,5 +43,5 @@
 		nmd_stream_header stream_header;
 		source.read( &stream_header, sizeof( stream_header ), 1 );
-		mesh_raw_channel* channel = mesh_raw_channel::create( stream_header.format, stream_header.count );
+		raw_data_channel* channel = raw_data_channel::create( stream_header.format, stream_header.count );
 		source.read( channel->data, stream_header.format.element_size(), stream_header.count );
 		mesh->add_channel( channel );
@@ -128,5 +128,5 @@
 				nv::nmd_stream_header cheader;
 				source.read( &cheader, sizeof( cheader ), 1 );
-				key_raw_channel* channel = key_raw_channel::create( cheader.format, cheader.count );
+				raw_data_channel* channel = raw_data_channel::create( cheader.format, cheader.count );
 				source.read( channel->data, channel->desc.element_size(), channel->count );
 				kdata->add_channel( channel );
@@ -162,5 +162,5 @@
 static void nmd_dump_mesh( const mesh_data* mesh, stream& stream_out )
 {
-	array_view< mesh_raw_channel* > data  = mesh->get_raw_channels();
+	array_view< raw_data_channel* > data  = mesh->get_raw_channels();
 
 	uint32 size = sizeof( nmd_element_header );
@@ -248,5 +248,5 @@
 		for ( uint32 c = 0; c < chan_count; ++c )
 		{
-			const key_raw_channel* channel = node->data->get_channel(c);
+			const raw_data_channel* channel = node->data->get_channel(c);
 
 			eheader.type     = nmd_type::KEY_CHANNEL;
Index: trunk/src/formats/obj_loader.cc
===================================================================
--- trunk/src/formats/obj_loader.cc	(revision 410)
+++ trunk/src/formats/obj_loader.cc	(revision 411)
@@ -324,5 +324,5 @@
 		}
 	
-		mesh_raw_channel* channel = new mesh_raw_channel();
+		raw_data_channel* channel = new raw_data_channel();
 		nv::uint8* data = nullptr;
 
Index: trunk/src/gfx/mesh_creator.cc
===================================================================
--- trunk/src/gfx/mesh_creator.cc	(revision 410)
+++ trunk/src/gfx/mesh_creator.cc	(revision 411)
@@ -19,6 +19,6 @@
 		key_data* keys   = m_data->m_nodes[i].data;
 		key_data* pkeys  = ( parent_id != -1 ? m_data->m_nodes[parent_id].data : nullptr );
-		size_t count     = ( keys ? keys->get_channel(0)->count : 0 );
-		size_t pcount    = ( pkeys ? pkeys->get_channel(0)->count : 0 );
+		size_t count     = ( keys ? keys->get_channel(0)->element_count() : 0 );
+		size_t pcount    = ( pkeys ? pkeys->get_channel(0)->element_count() : 0 );
 		max_frames = nv::max<uint32>( count, max_frames );
 		if ( pkeys && pkeys->get_channel_count() > 0 && keys && keys->get_channel_count() > 0 )
@@ -66,5 +66,5 @@
 			}
 
-			key_raw_channel* raw_channel = key_raw_channel::create<nv_key_transform>( max_keys );
+			raw_data_channel* raw_channel = raw_data_channel::create<nv_key_transform>( max_keys );
 			key_data* new_keys = new key_data;
 			new_keys->add_channel( raw_channel );
@@ -80,5 +80,5 @@
 				{
 					size_t idx = nv::min( old_keys->get_channel(c)->count - 1, n );
-					pkey += old_keys->get_channel(c)->get_raw( idx, pkey );
+					pkey += old_keys->get_raw( old_keys->get_channel(c), idx, pkey );
 				}
 				channel[n].tform = extract_transform_raw( final_key, key );
@@ -106,5 +106,5 @@
 			for ( size_t c = 0; c < kdata->get_channel_count(); ++c )
 			{
-				const key_raw_channel* channel = kdata->get_channel(c);
+				const raw_data_channel* channel = kdata->get_channel(c);
 				size_t key_size = channel->desc.element_size();
 				for ( size_t n = 0; n < channel->count; ++n )
@@ -125,5 +125,5 @@
 	for ( uint32 c = 0; c < m_data->get_channel_count(); ++c )
 	{
-		const mesh_raw_channel* channel = m_data->get_channel(c);
+		const raw_data_channel* channel = m_data->get_channel(c);
 		const data_descriptor&  desc    = channel->desc;
 		uint8* raw_data = channel->data;
@@ -173,5 +173,5 @@
 	size_t n_offset = 0;
 	if ( ch_n == -1 ) return;
-	mesh_raw_channel* channel = m_data->m_channels[ unsigned( ch_n ) ];
+	raw_data_channel* channel = m_data->m_channels[ unsigned( ch_n ) ];
 	for ( const auto& cslot : channel->desc )
 		if ( cslot.vslot == slot::NORMAL )
@@ -196,12 +196,12 @@
 	uint32 n_channel_index = 0;
 
-	const mesh_raw_channel* p_channel = nullptr;
-	      mesh_raw_channel* n_channel = nullptr;
-	const mesh_raw_channel* t_channel = nullptr;
-	const mesh_raw_channel* i_channel = nullptr;
+	const raw_data_channel* p_channel = nullptr;
+	      raw_data_channel* n_channel = nullptr;
+	const raw_data_channel* t_channel = nullptr;
+	const raw_data_channel* i_channel = nullptr;
 
 	for ( uint32 c = 0; c < m_data->get_channel_count(); ++c )
 	{
-		const mesh_raw_channel* channel = m_data->get_channel(c);
+		const raw_data_channel* channel = m_data->get_channel(c);
 
 		for ( const auto& cslot : channel->desc )
@@ -247,5 +247,5 @@
 	}
 
-	mesh_raw_channel* g_channel = mesh_raw_channel::create<vertex_g>( p_channel->count );
+	raw_data_channel* g_channel = raw_data_channel::create<vertex_g>( p_channel->count );
 	vec4* tangents              = reinterpret_cast<vec4*>( g_channel->data );
 	vec3* tangents2             = new vec3[ p_channel->count ];
@@ -334,5 +334,5 @@
 }
 
-nv::mesh_raw_channel* nv::mesh_data_creator::merge_channels( mesh_raw_channel* a, mesh_raw_channel* b )
+nv::raw_data_channel* nv::mesh_data_creator::merge_channels( raw_data_channel* a, raw_data_channel* b )
 {
 	NV_ASSERT( a->count == b->count, "merge_channel - bad channels!" );
@@ -352,5 +352,5 @@
 		raw_copy_n( b->data + i * bdesc.element_size(), bdesc.element_size(), data + i*desc.element_size() + adesc.element_size() );
 	}
-	mesh_raw_channel* result = new mesh_raw_channel;
+	raw_data_channel* result = new raw_data_channel;
 	result->count = count;
 	result->desc  = desc;
@@ -359,5 +359,5 @@
 }
 
-nv::mesh_raw_channel* nv::mesh_data_creator::append_channels( mesh_raw_channel* a, mesh_raw_channel* b, uint32 frame_count )
+nv::raw_data_channel* nv::mesh_data_creator::append_channels( raw_data_channel* a, raw_data_channel* b, uint32 frame_count )
 {
 	if ( a->desc != b->desc ) return nullptr;
@@ -391,7 +391,7 @@
 	}
 
-	mesh_raw_channel* result = new mesh_raw_channel;
-	result->count = a->count + b->count;
-	result->desc  = a->desc;
+	raw_data_channel* result = new raw_data_channel;
+	result->count = a->element_count() + b->element_count();
+	result->desc  = a->descriptor();
 	result->data  = data;
 	return result;
@@ -405,5 +405,5 @@
 	for ( uint32 c = 0; c < m_data->get_channel_count(); ++c )
 	{
-		if ( m_data->get_channel(c)->desc != other->get_channel(c)->desc )
+		if ( m_data->get_channel(c)->descriptor() != other->get_channel(c)->descriptor() )
 			return false;
 	}
@@ -419,8 +419,8 @@
 	int och_ti = other->get_channel_index( slot::TEXCOORD );
 	if ( ch_pi == -1 || ch_ti == -1 ) return;
-	size_t size   = m_data->m_channels[ unsigned(ch_ti) ]->count;
-	size_t osize  =  other->m_channels[ unsigned(och_ti) ]->count;
-	size_t count  = m_data->m_channels[ unsigned(ch_pi) ]->count;
-	size_t ocount =  other->m_channels[ unsigned(och_pi) ]->count;
+	size_t size   = m_data->m_channels[ unsigned(ch_ti) ]->element_count();
+	size_t osize  =  other->m_channels[ unsigned(och_ti) ]->element_count();
+	size_t count  = m_data->m_channels[ unsigned(ch_pi) ]->element_count();
+	size_t ocount =  other->m_channels[ unsigned(och_pi) ]->element_count();
 	if ( count % size != 0 || ocount % osize != 0 ) return;
 	if ( count / size != ocount / osize ) return;
@@ -428,6 +428,6 @@
 	for ( uint32 c = 0; c < m_data->get_channel_count(); ++c )
 	{
-		mesh_raw_channel* old = m_data->m_channels[c];
-		size_t frame_count = ( old->get_buffer_type() == INDEX_BUFFER ? 1 : old->count / size );
+		raw_data_channel* old = m_data->m_channels[c];
+		size_t frame_count = ( old->get_buffer_type() == INDEX_BUFFER ? 1 : old->element_count() / size );
 		m_data->m_channels[c] = append_channels( old, other->m_channels[c], frame_count );
 		NV_ASSERT( m_data->m_channels[c], "Merge problem!" );
@@ -440,5 +440,5 @@
 					NV_ASSERT( size + osize < uint16(-1), "Index out of range!" );
 					uint16* indexes = reinterpret_cast<uint16*>( m_data->m_channels[c]->data );
-					for ( uint16 i = uint16( old->count ); i < m_data->m_channels[c]->count; ++i )
+					for ( uint16 i = uint16( old->element_count() ); i < m_data->m_channels[c]->element_count(); ++i )
 						indexes[i] += uint16( size );
 
@@ -448,5 +448,5 @@
 				{
 					uint32* indexes = reinterpret_cast<uint32*>( m_data->m_channels[c]->data );
-					for ( uint32 i = old->count; i < m_data->m_channels[c]->count; ++i )
+					for ( uint32 i = old->element_count(); i < m_data->m_channels[c]->element_count(); ++i )
 						indexes[i] += size;
 				}
Index: trunk/src/gfx/skeletal_mesh.cc
===================================================================
--- trunk/src/gfx/skeletal_mesh.cc	(revision 410)
+++ trunk/src/gfx/skeletal_mesh.cc	(revision 411)
@@ -15,5 +15,5 @@
 	, m_data( a_mesh_data )
 {
-	const mesh_raw_channel* pnt_chan = a_mesh_data->get_channel<md5_vtx_pnt>();
+	const raw_data_channel* pnt_chan = a_mesh_data->get_channel<md5_vtx_pnt>();
 	m_pntdata.assign( reinterpret_cast<const md5_vtx_pnt*>( pnt_chan->data ), pnt_chan->count );
 	m_bone_offset.resize( bones->get_count() );
