Index: /trunk/nv/formats/assimp_loader.hh
===================================================================
--- /trunk/nv/formats/assimp_loader.hh	(revision 415)
+++ /trunk/nv/formats/assimp_loader.hh	(revision 416)
@@ -22,5 +22,5 @@
 		explicit assimp_loader( const std::string& a_ext, uint32 a_assimp_flags = 0 );
 		virtual bool load( stream& source );
-		virtual mesh_data* release_mesh_data( size_t index = 0 );
+		virtual data_channel_set* release_mesh_data( size_t index = 0 );
 		virtual size_t get_mesh_count() const { return m_mesh_count; }
 		virtual ~assimp_loader();
@@ -30,7 +30,7 @@
 		void scene_report() const;
 	private:
-		mesh_nodes_data* release_merged_bones( mesh_data* meshes );
+		mesh_nodes_data* release_merged_bones( data_channel_set* meshes );
 		bool load_bones( size_t index, array_ref< mesh_node_data > bones );
-		void load_mesh_data( mesh_data* data, size_t index );
+		void load_mesh_data( data_channel_set* data, size_t index );
 		sint16 load_node( uint32 anim_id, mesh_node_data* nodes, const void* vnode, sint16 this_id, sint16 parent_id );
 		uint32 count_nodes( const void* node ) const;
Index: /trunk/nv/formats/md2_loader.hh
===================================================================
--- /trunk/nv/formats/md2_loader.hh	(revision 415)
+++ /trunk/nv/formats/md2_loader.hh	(revision 416)
@@ -27,9 +27,9 @@
 		virtual ~md2_loader();
 		virtual bool load( stream& source );
-		virtual mesh_data* release_mesh_data( size_t index = 0 );
+		virtual data_channel_set* release_mesh_data( size_t index = 0 );
 		virtual mesh_data_pack* release_mesh_data_pack();
 		virtual size_t get_mesh_count() const { return 1; }
 	private:
-		void release_mesh_frame( mesh_data* data, sint32 frame );
+		void release_mesh_frame( data_channel_set* data, sint32 frame );
 		size_t get_max_frames() const;
 		void reindex();
Index: /trunk/nv/formats/md3_loader.hh
===================================================================
--- /trunk/nv/formats/md3_loader.hh	(revision 415)
+++ /trunk/nv/formats/md3_loader.hh	(revision 416)
@@ -33,5 +33,5 @@
 		virtual ~md3_loader();
 		virtual bool load( stream& source );
-		virtual mesh_data* release_mesh_data( size_t index = 0 );
+		virtual data_channel_set* release_mesh_data( size_t index = 0 );
 		virtual mesh_data_pack* release_mesh_data_pack();
 		virtual size_t get_mesh_count() const { return 1; }
@@ -40,5 +40,5 @@
 		virtual mesh_nodes_data* release_mesh_nodes_data( size_t = 0 );
 	private:
-		void release_mesh_frame( mesh_data* data, sint32 frame, sint32 surface );
+		void release_mesh_frame( data_channel_set* data, sint32 frame, sint32 surface );
 		raw_data_channel* load_tags( const string_view& tag );
 		bool m_merge_all;
Index: /trunk/nv/formats/md5_loader.hh
===================================================================
--- /trunk/nv/formats/md5_loader.hh	(revision 415)
+++ /trunk/nv/formats/md5_loader.hh	(revision 416)
@@ -55,5 +55,5 @@
 		virtual ~md5_loader();
 		virtual bool load( stream& source );
-		virtual mesh_data* release_mesh_data( size_t index = 0 );
+		virtual data_channel_set* release_mesh_data( size_t index = 0 );
 		virtual size_t get_nodes_data_count() const { return 1; }
 		virtual mesh_nodes_data* release_mesh_nodes_data( size_t = 0 );
@@ -84,10 +84,10 @@
 		void reset();
 		void build_frame_skeleton( mesh_node_data* nodes, uint32 index, const array_view<md5_joint_info>& joint_info, const array_view<transform>& base_frames, const array_view<float>& frame_data );
-		bool prepare_mesh( mesh_node_data* nodes, uint32 vtx_count, mesh_data* mdata, md5_weight* weights, md5_weight_info* weight_info );
+		bool prepare_mesh( mesh_node_data* nodes, uint32 vtx_count, data_channel_set* mdata, md5_weight* weights, md5_weight_info* weight_info );
 	protected:
 		file_type m_type;
 		uint32 m_md5_version;
 		mesh_nodes_data* m_nodes;
-		dynamic_array<mesh_data*> m_meshes;
+		dynamic_array<data_channel_set*> m_meshes;
 	};
 
Index: /trunk/nv/formats/nmd_loader.hh
===================================================================
--- /trunk/nv/formats/nmd_loader.hh	(revision 415)
+++ /trunk/nv/formats/nmd_loader.hh	(revision 416)
@@ -66,5 +66,5 @@
 		nmd_loader() : m_node_data( nullptr ), m_node_array( nullptr ), m_strings( nullptr ) {}
 		virtual bool load( stream& source );
-		virtual mesh_data* release_mesh_data( size_t index = 0 );
+		virtual data_channel_set* release_mesh_data( size_t index = 0 );
 		virtual size_t get_nodes_data_count() const { return 1; }
 		virtual mesh_nodes_data* release_mesh_nodes_data( size_t = 0 );
@@ -78,10 +78,10 @@
 		bool load_animation( stream& source, const nmd_element_header& e );
 
-		mesh_nodes_data*          m_node_data;
-		mesh_node_data*           m_node_array;
-		string_table*             m_strings;
-		vector< uint16 >          m_mesh_names;
-		vector< uint16 >          m_node_names;
-		vector< mesh_data* >      m_meshes;
+		mesh_nodes_data*            m_node_data;
+		mesh_node_data*             m_node_array;
+		string_table*               m_strings;
+		vector< uint16 >            m_mesh_names;
+		vector< uint16 >            m_node_names;
+		vector< data_channel_set* > m_meshes;
 	};
 
Index: /trunk/nv/formats/obj_loader.hh
===================================================================
--- /trunk/nv/formats/obj_loader.hh	(revision 415)
+++ /trunk/nv/formats/obj_loader.hh	(revision 416)
@@ -27,13 +27,13 @@
 		obj_loader( bool normals = true, bool tangents = false );
 		virtual bool load( stream& source );
-		virtual mesh_data* release_mesh_data( size_t index = 0 );
+		virtual data_channel_set* release_mesh_data( size_t index = 0 );
 		virtual mesh_data_pack* release_mesh_data_pack();
 		virtual size_t get_mesh_count() const { return m_meshes.size(); }
 		~obj_loader();
 	private:
-		data_descriptor      m_descriptor;
-		bool                 m_normals;
-		bool                 m_tangents;
-		vector< mesh_data* > m_meshes;
+		data_descriptor             m_descriptor;
+		bool                        m_normals;
+		bool                        m_tangents;
+		vector< data_channel_set* > m_meshes;
 	};
 
Index: /trunk/nv/gfx/animation.hh
===================================================================
--- /trunk/nv/gfx/animation.hh	(revision 415)
+++ /trunk/nv/gfx/animation.hh	(revision 416)
@@ -12,5 +12,5 @@
 #include <nv/interface/stream.hh>
 #include <nv/stl/math.hh>
-#include <nv/interface/data_descriptor.hh>
+#include <nv/interface/data_channel.hh>
 #include <nv/interface/interpolation_raw.hh>
 #include <nv/interface/interpolation_template.hh>
@@ -20,17 +20,16 @@
 {
 
-	class key_data
+	class key_data : public data_channel_set
 	{
 	public:
 		key_data() {}
 
-		void add_channel( raw_data_channel* channel ) 
+		void add_key_channel( raw_data_channel* channel ) 
 		{
 			NV_ASSERT( channel, "nullptr passed to add_channel!" );
-			m_channels.push_back( channel );
+			add_channel( channel );
 			for ( const auto& cslot : channel->descriptor() )
 				if ( cslot.vslot != slot::TIME )
 					m_final_key.push_slot( cslot.etype, cslot.vslot );
-			//m_final_key.append( channel->descriptor() );
 		}
 
@@ -39,5 +38,5 @@
 			float key[ 16 ];
 			float* pkey = key;
-			for ( uint16 i = 0; i < m_channels.size(); ++i )
+			for ( uint16 i = 0; i < size(); ++i )
 			{
 				pkey += get_raw( m_channels[i], index, pkey );
@@ -50,5 +49,5 @@
 			float key[ 16 ];
 			float* pkey = key;
-			for ( uint16 i = 0; i < m_channels.size(); ++i )
+			for ( uint16 i = 0; i < size(); ++i )
 			{
 				pkey += get_raw( m_channels[i], index, pkey );
@@ -61,5 +60,5 @@
 			float key[ 16 ];
 			float* pkey = key;
-			for ( uint16 i = 0; i < m_channels.size(); ++i )
+			for ( uint16 i = 0; i < size(); ++i )
 			{
 				pkey += interpolate_raw( m_channels[i], time, pkey );
@@ -72,5 +71,5 @@
 			float key[ 16 ];
 			float* pkey = key;
-			for ( uint16 i = 0; i < m_channels.size(); ++i )
+			for ( uint16 i = 0; i < size(); ++i )
 			{
 				pkey += interpolate_raw( m_channels[i], time, pkey );
@@ -79,12 +78,5 @@
 		}
 
-		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 )
@@ -98,5 +90,4 @@
 			return keyfsize - mod;
 		}
-
 
 		static uint32 interpolate_raw( const raw_data_channel* channel, float time, float* result )
@@ -160,7 +151,5 @@
 
 	private:
-
 		data_descriptor m_final_key;
-		vector< raw_data_channel* > m_channels;
 	};
 
Index: /trunk/nv/gfx/mesh_creator.hh
===================================================================
--- /trunk/nv/gfx/mesh_creator.hh	(revision 415)
+++ /trunk/nv/gfx/mesh_creator.hh	(revision 416)
@@ -27,6 +27,6 @@
 		void merge( mesh_data* other );
 	private:
-		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 );
+		raw_data_channel* merge_channels( const raw_data_channel* a, const raw_data_channel* b );
+		raw_data_channel* append_channels( const raw_data_channel* a, const raw_data_channel* b, uint32 frame_count = 1 );
 
 		mesh_data* m_data;
@@ -50,13 +50,5 @@
 	public:
 		mesh_creator( mesh_data_pack* pack ) : m_pack( pack ) {}
-		void delete_mesh( uint32 index )
-		{
-			if ( index < m_pack->get_count() )
-			{
-				m_pack->m_meshes[ index ].destroy();
-				m_pack->m_meshes[ m_pack->m_count-1 ].move_to( m_pack->m_meshes[ index ] );
-				m_pack->m_count--;
-			}
-		}
+		void delete_mesh( uint32 index );
 		// assumes that keys are equally spaced
 		void pre_transform_keys() 
Index: /trunk/nv/interface/context.hh
===================================================================
--- /trunk/nv/interface/context.hh	(revision 415)
+++ /trunk/nv/interface/context.hh	(revision 416)
@@ -300,8 +300,9 @@
 		{
 			vertex_array  va = create_vertex_array();
-			array_view< raw_data_channel* > channels = data->get_raw_channels();
-			for ( uint32 ch = 0; ch < channels.size(); ++ch )
-			{
-				const raw_data_channel* channel = channels[ch];
+			//array_view< raw_data_channel* > channels = data->get_raw_channels();
+			//for ( uint32 ch = 0; ch < channels.size(); ++ch )
+			for ( auto channel : *data )
+			{
+//				const raw_data_channel* channel = channels[ch];
 				if ( channel->size() > 0 )
 				{
Index: /trunk/nv/interface/data_descriptor.hh
===================================================================
--- /trunk/nv/interface/data_descriptor.hh	(revision 415)
+++ /trunk/nv/interface/data_descriptor.hh	(revision 416)
@@ -17,28 +17,28 @@
 	enum class slot : uint8
 	{
-		POSITION    = 0,
-		TEXCOORD    = 1,
-		NORMAL      = 2,
-		TANGENT     = 3,
-		BONEINDEX   = 4,
-		BONEWEIGHT  = 5,
-		COLOR       = 6,
-
-		INDEX       = 7,
-
-		TIME        = 8,
+		POSITION = 0,
+		TEXCOORD = 1,
+		NORMAL = 2,
+		TANGENT = 3,
+		BONEINDEX = 4,
+		BONEWEIGHT = 5,
+		COLOR = 6,
+
+		INDEX = 7,
+
+		TIME = 8,
 		TRANSLATION = 9,
-		ROTATION    = 10,
-		SCALE       = 11,
-		TFORM       = 12,
-
-		MAX_STORE   = 8,
+		ROTATION = 10,
+		SCALE = 11,
+		TFORM = 12,
+
+		MAX_STORE = 8,
 	};
 
 	struct data_descriptor_slot
 	{
-		datatype etype  = NONE;
+		datatype etype = NONE;
 		uint32   offset = 0;
-		slot     vslot  = slot::POSITION;
+		slot     vslot = slot::POSITION;
 	};
 
@@ -46,7 +46,7 @@
 	struct has_slot : false_type {};
 
- 	template < typename Struct >
- 	struct has_slot< Struct, slot::POSITION, void_t< NV_VOID_DECLTYPE( Struct::position ) > > : true_type {};
-	
+	template < typename Struct >
+	struct has_slot< Struct, slot::POSITION, void_t< NV_VOID_DECLTYPE( Struct::position ) > > : true_type{};
+
 	template < typename Struct >
 	struct has_slot < Struct, slot::TEXCOORD, void_t< NV_VOID_DECLTYPE( Struct::texcoord ) > > : true_type{};
@@ -97,5 +97,5 @@
 		{
 			typedef empty_type value_type;
-			static const datatype etype  = datatype::NONE;
+			static const datatype etype = datatype::NONE;
 			static const int      offset = 0;
 		};
@@ -105,5 +105,5 @@
 		{
 			typedef decltype( Struct::position ) value_type;
-			static const datatype etype  = type_to_enum< decltype( Struct::position ) >::type;
+			static const datatype etype = type_to_enum< decltype( Struct::position ) >::type;
 			static const int      offset = NV_OFFSET_OF( Struct, position );
 		};
@@ -113,5 +113,5 @@
 		{
 			typedef decltype( Struct::texcoord ) value_type;
-			static const datatype etype  = type_to_enum< decltype( Struct::texcoord ) >::type;
+			static const datatype etype = type_to_enum< decltype( Struct::texcoord ) >::type;
 			static const int      offset = NV_OFFSET_OF( Struct, texcoord );
 		};
@@ -121,5 +121,5 @@
 		{
 			typedef decltype( Struct::normal ) value_type;
-			static const datatype etype  = type_to_enum< decltype( Struct::normal ) >::type;
+			static const datatype etype = type_to_enum< decltype( Struct::normal ) >::type;
 			static const int      offset = NV_OFFSET_OF( Struct, normal );
 		};
@@ -129,5 +129,5 @@
 		{
 			typedef decltype( Struct::tangent ) value_type;
-			static const datatype etype  = type_to_enum< decltype( Struct::tangent ) >::type;
+			static const datatype etype = type_to_enum< decltype( Struct::tangent ) >::type;
 			static const int      offset = NV_OFFSET_OF( Struct, tangent );
 		};
@@ -137,5 +137,5 @@
 		{
 			typedef decltype( Struct::boneindex ) value_type;
-			static const datatype etype  = type_to_enum< decltype( Struct::boneindex ) >::type;
+			static const datatype etype = type_to_enum< decltype( Struct::boneindex ) >::type;
 			static const int      offset = NV_OFFSET_OF( Struct, boneindex );
 		};
@@ -145,5 +145,5 @@
 		{
 			typedef decltype( Struct::boneweight ) value_type;
-			static const datatype etype  = type_to_enum< decltype( Struct::boneweight ) >::type;
+			static const datatype etype = type_to_enum< decltype( Struct::boneweight ) >::type;
 			static const int      offset = NV_OFFSET_OF( Struct, boneweight );
 		};
@@ -153,5 +153,5 @@
 		{
 			typedef decltype( Struct::color ) value_type;
-			static const datatype etype  = type_to_enum< decltype( Struct::color ) >::type;
+			static const datatype etype = type_to_enum< decltype( Struct::color ) >::type;
 			static const int      offset = NV_OFFSET_OF( Struct, color );
 		};
@@ -161,5 +161,5 @@
 		{
 			typedef decltype( Struct::index ) value_type;
-			static const datatype etype  = type_to_enum< decltype( Struct::index ) >::type;
+			static const datatype etype = type_to_enum< decltype( Struct::index ) >::type;
 			static const int      offset = NV_OFFSET_OF( Struct, index );
 		};
@@ -226,7 +226,7 @@
 			for ( uint32 i = 0; i < m_size; ++i )
 			{
-				if ( m_slots[i].etype  != rhs.m_slots[i].etype )  return false;
+				if ( m_slots[i].etype != rhs.m_slots[i].etype )  return false;
 				if ( m_slots[i].offset != rhs.m_slots[i].offset ) return false;
-				if ( m_slots[i].vslot  != rhs.m_slots[i].vslot )  return false;
+				if ( m_slots[i].vslot != rhs.m_slots[i].vslot )  return false;
 			}
 			return true;
@@ -274,7 +274,7 @@
 		void push_slot( datatype etype, slot vslot )
 		{
-			m_slots[m_size].etype  = etype;
+			m_slots[m_size].etype = etype;
 			m_slots[m_size].offset = m_element_size;
-			m_slots[m_size].vslot  = vslot;
+			m_slots[m_size].vslot = vslot;
 			m_element_size += get_datatype_info( etype ).size;
 			m_size++;
@@ -285,7 +285,7 @@
 			for ( const auto& dslot : desc )
 			{
-				m_slots[m_size].etype  = dslot.etype;
+				m_slots[m_size].etype = dslot.etype;
 				m_slots[m_size].offset = m_element_size;
-				m_slots[m_size].vslot  = dslot.vslot;
+				m_slots[m_size].vslot = dslot.vslot;
 				m_element_size += get_datatype_info( dslot.etype ).size;
 				m_size++;
@@ -314,5 +314,5 @@
 			if ( m_slots[m_size].etype != datatype::NONE )
 			{
-				m_slots[m_size].vslot  = Slot;
+				m_slots[m_size].vslot = Slot;
 				m_slots[m_size].offset = sinfo::offset;
 				m_size++;
@@ -321,106 +321,4 @@
 	};
 
-	struct raw_data_channel
-	{
-		raw_data_channel() : m_data( nullptr ), m_size( 0 ) {}
-		~raw_data_channel()
-		{
-			if ( m_data != nullptr ) delete[] m_data;
-		}
-
-		const data_descriptor& descriptor() const { return m_desc;  }
-		uint32 element_size() const { return m_desc.element_size(); }
-		uint32 size() const { return m_size; }
-		uint32 raw_size() const { return m_size * m_desc.element_size(); }
-		const uint8* raw_data() const { return m_data; }
-
-		// TODO: constexpr compile-time cast check?
-		template < typename Struct >
-		const Struct* data_cast() const 
-		{ 
-			return reinterpret_cast<const Struct*>( m_data );
-		}
-
-		bool has_slot( slot vslot ) const { return m_desc.has_slot( vslot ); }
-
-		template < typename Struct >
-		friend class data_channel_creator;
-		friend class raw_data_channel_creator;
-
-	protected:
-		uint8*          m_data;
-		data_descriptor m_desc;
-		uint32          m_size;
-
-	};
-
-	class raw_data_channel_creator
-	{
-	public:
-		raw_data_channel_creator( const data_descriptor& desc, uint32 size )
-		{
-			m_channel = new raw_data_channel();
-			m_channel->m_desc = desc;
-			m_channel->m_size = size;
-			m_channel->m_data = ( size > 0 ? ( new uint8[m_channel->raw_size()] ) : nullptr );
-			m_owned   = true;
-		}
-		explicit raw_data_channel_creator( raw_data_channel* channel )
-		{
-			m_channel = channel;
-			m_owned   = false;
-		}
-
-		uint32 element_size() const { return m_channel->element_size(); }
-		uint32 size() const { return m_channel->size(); }
-		uint32 raw_size() const { return m_channel->size() * m_channel->element_size(); }
-		uint8* raw_data() { return m_channel->m_data; }
-		const uint8* raw_data() const { return m_channel->m_data; }
-		raw_data_channel* channel() { return m_channel; }
-
-		data_descriptor& descriptor() { return m_channel->m_desc; }
-		const data_descriptor& descriptor() const { return m_channel->m_desc; }
-
-		raw_data_channel* release()
-		{
-			raw_data_channel* result = m_channel;
-			m_channel = nullptr;
-			return result;
-		}
-
-		~raw_data_channel_creator()
-		{
-			if ( m_owned && m_channel ) delete m_channel;
-		}
-	protected:
-		raw_data_channel* m_channel;
-		bool              m_owned;
-	};
-
-	template < typename Struct >
-	class data_channel_creator : public raw_data_channel_creator
-	{
-	public:
-		explicit data_channel_creator( uint32 size ) 
-			: raw_data_channel_creator( data_descriptor::create< Struct >(), size ) {}
-		// TODO - descriptor check
-		explicit data_channel_creator( raw_data_channel* channel )
-			: raw_data_channel_creator( channel ) {}
-		
-		Struct* data() { return reinterpret_cast< Struct* >( m_channel->m_data ); }
-		const Struct* data() const { return reinterpret_cast< const Struct* >( m_channel->m_data ); }
-
-		const Struct& operator []( uint32 i ) const
-		{
-			NV_ASSERT( i < m_channel->m_size, "data_channel_creator indexing failure!" );
-			return reinterpret_cast< const Struct* >( m_channel->m_data )[i];
-		}
-
-		Struct& operator []( uint32 i ) 
-		{
-			NV_ASSERT( i < m_channel->m_size, "data_channel_creator indexing failure!" );
-			return reinterpret_cast<Struct*>( m_channel->m_data )[i];
-		}
-	};
 }
 
Index: /trunk/nv/interface/mesh_data.hh
===================================================================
--- /trunk/nv/interface/mesh_data.hh	(revision 415)
+++ /trunk/nv/interface/mesh_data.hh	(revision 416)
@@ -11,5 +11,5 @@
 #include <nv/stl/math.hh>
 #include <nv/stl/string.hh>
-#include <nv/interface/data_descriptor.hh>
+#include <nv/interface/data_channel.hh>
 #include <nv/gfx/animation.hh>
 
@@ -20,127 +20,5 @@
 	struct index_u32 { uint32 index; };
 
-	// TODO: friend mesh_data_creator class?
-	// TODO: private const etc
-
-	class mesh_data
-	{
-		friend class mesh_creator;
-		friend class mesh_data_creator;
-	public:
-		explicit mesh_data() : m_index_channel( nullptr ) {}
-		explicit mesh_data( const std::string& name ) : m_name(name), m_index_channel( nullptr ) {}
-
-		void add_channel( raw_data_channel* channel )
-		{
-			NV_ASSERT( channel, "nullptr passed to add_channel!" );
-			m_channels.push_back( channel );
-			if ( channel->size() > 0 && channel->descriptor()[0].vslot == slot::INDEX )
-			{
-				NV_ASSERT( !m_index_channel, "second index channel!" );
-				m_index_channel = 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 raw_data_channel* get_channel( size_t index ) const
-		{ 
-			if ( m_channels.size() > index ) return m_channels[index];
-			return nullptr;
-		}
-
-		const raw_data_channel* get_channel( slot s ) const
-		{ 
-			for ( auto ch : m_channels )
-				if ( ch->has_slot( s ) )
-					return ch;
-			return nullptr;
-		}
-
-		int get_channel_index( slot s ) const 
-		{ 
-			for ( uint32 c = 0; c < m_channels.size(); ++c )
-				if ( m_channels[c]->has_slot( s ) ) 
-					return int( c );
-			return -1;
-		}
-
-
-		// TODO: this should be "size"
-		size_t get_count() const 
-		{
-			if ( m_index_channel ) return m_index_channel->size();
-			if ( m_channels.size() > 0 ) return m_channels[0]->size();
-			return 0;
-		}
-
-		size_t get_count( size_t channel ) const 
-		{
-			if ( m_channels.size() > channel ) return m_channels[channel]->size();
-			return 0;
-		}
-
-		template < typename VTX >
-		const raw_data_channel* get_channel() const
-		{
-			data_descriptor compare;
-			compare.initialize<VTX>();
-			for ( auto ch : m_channels )
-			{
-				if ( ch->descriptor() == compare )
-				{
-					return ch;
-				}
-			}
-			return nullptr;
-		}
-
-		template < typename VTX >
-		const VTX* get_channel_data() const
-		{
-			data_descriptor compare;
-			compare.initialize<VTX>();
-			for ( auto ch : m_channels )
-			{
-				if ( ch->descriptor() == compare )
-				{
-					return ch->data_cast< VTX >();
-				}
-			}
-			return nullptr;
-		}
-
-		void set_name( const std::string& name ) { m_name = name; }
-		const std::string& get_name() const { return m_name; }
-
-		void move_to( mesh_data& other )
-		{
-			other.m_name          = m_name;
-			other.m_index_channel = m_index_channel;
-			for ( auto c : m_channels )
-			{
-				other.m_channels.push_back( c );
-			}
-			m_channels.clear();
-			m_index_channel = nullptr;
-		}
-
-		void destroy()
-		{
-			for ( auto channel : m_channels ) delete channel;
-			m_channels.clear();
-			m_index_channel = nullptr;
-		}
-
-		virtual ~mesh_data()
-		{
-			destroy();
-		}
-	private:
-		std::string                 m_name;
-		vector< raw_data_channel* > m_channels;
-		raw_data_channel*           m_index_channel;
-	};
+	using mesh_data = data_channel_set;
 
 	struct mesh_node_data
@@ -241,13 +119,13 @@
 			return &m_meshes[ index ];
 		}
-		const mesh_data* get_mesh( const std::string& name ) const
-		{
-			for ( uint32 i = 0; i < m_count; ++i )
-			{
-				if ( m_meshes[ i ].get_name() == name )
-					return &m_meshes[ i ];
-			}
-			return nullptr;
-		}
+// 		const mesh_data* get_mesh( const std::string& name ) const
+// 		{
+// 			for ( uint32 i = 0; i < m_count; ++i )
+// 			{
+// 				if ( m_meshes[ i ].get_name() == name )
+// 					return &m_meshes[ i ];
+// 			}
+// 			return nullptr;
+// 		}
 		uint32 get_count() const { return m_count; }
 		const mesh_nodes_data* get_nodes() const { return m_nodes; }
Index: /trunk/nv/interface/mesh_loader.hh
===================================================================
--- /trunk/nv/interface/mesh_loader.hh	(revision 415)
+++ /trunk/nv/interface/mesh_loader.hh	(revision 416)
@@ -30,5 +30,5 @@
 		virtual ~mesh_loader() {}
 		virtual bool load( stream& source ) = 0;
-		virtual mesh_data* release_mesh_data( size_t index = 0 ) = 0;
+		virtual data_channel_set* release_mesh_data( size_t index = 0 ) = 0;
 		virtual mesh_data_pack* release_mesh_data_pack() = 0;
 		virtual size_t get_mesh_count() const = 0;
Index: /trunk/src/formats/assimp_loader.cc
===================================================================
--- /trunk/src/formats/assimp_loader.cc	(revision 415)
+++ /trunk/src/formats/assimp_loader.cc	(revision 416)
@@ -6,4 +6,6 @@
 
 #include "nv/formats/assimp_loader.hh"
+
+#include "nv/interface/data_channel_access.hh"
 #include "nv/stl/unordered_map.hh"
 #include "nv/lib/assimp.hh"
@@ -103,16 +105,15 @@
 }
 
-mesh_data* nv::assimp_loader::release_mesh_data( size_t index /*= 0 */ )
+data_channel_set* nv::assimp_loader::release_mesh_data( size_t index /*= 0 */ )
 {
 	if ( index >= m_mesh_count ) return nullptr;
-	mesh_data* result = new mesh_data;
+	data_channel_set* result = data_channel_set_creator::create( 2 );
 	load_mesh_data( result, index );
 	return result;
 }
-void nv::assimp_loader::load_mesh_data( mesh_data* data, size_t index )
+void nv::assimp_loader::load_mesh_data( data_channel_set* data, size_t index )
 {
 	const aiScene* scene = reinterpret_cast<const aiScene*>( m_scene );
 	const aiMesh*  mesh  = scene->mMeshes[ index ];
-	data->set_name( mesh->mName.data );
 
 	bool skinned = mesh->mNumBones > 0;
@@ -180,6 +181,9 @@
 		}
 	}
-	data->add_channel( channel.release() );
-	data->add_channel( ichannel.release() );
+
+	data_channel_set_creator maccess( data );
+	maccess.set_name( mesh->mName.data );
+	maccess.add_channel( channel.release() );
+	maccess.add_channel( ichannel.release() );
 }
 
@@ -283,5 +287,5 @@
 }
 
-mesh_nodes_data* nv::assimp_loader::release_merged_bones( mesh_data* meshes )
+mesh_nodes_data* nv::assimp_loader::release_merged_bones( data_channel_set* meshes )
 {
 	const aiScene* scene = reinterpret_cast<const aiScene*>( m_scene );
@@ -317,5 +321,5 @@
 			if ( m > 0 && bones.size() > 0 )
 			{
-				data_channel_creator< assimp_skinned_vtx > channel( meshes[m].get_raw_channels()[0] );
+				data_channel_creator< assimp_skinned_vtx > channel( const_cast< raw_data_channel* >( meshes[m].get_channel(0) ) );
 				for ( unsigned v = 0; v < channel.size(); ++v )
 				{
@@ -456,7 +460,7 @@
 // 		}
 // 	}
-	data->data->add_channel( pchannel_creator.release() );
-	data->data->add_channel( rchannel_creator.release() );
-//	data->data->add_channel( schannel_creator.release() );
+	data->data->add_key_channel( pchannel_creator.release() );
+	data->data->add_key_channel( rchannel_creator.release() );
+//	data->data->add_key_channel( schannel_creator.release() );
 }
 
@@ -466,9 +470,9 @@
 	const aiScene* scene = reinterpret_cast<const aiScene*>( m_scene );
 	bool has_bones = false;
-	mesh_data* meshes = new mesh_data[ m_mesh_count ];
+	data_channel_set* meshes = data_channel_set_creator::create_array( m_mesh_count, 2 );
 	for ( size_t m = 0; m < m_mesh_count; ++m )
 	{
 		const aiMesh* mesh = scene->mMeshes[ m ];
-		meshes[m].set_name( mesh->mName.data );
+		data_channel_set_creator( &meshes[m] ).set_name( mesh->mName.data );
 		if ( mesh->mNumBones > 0 ) has_bones = true;
 		load_mesh_data(&meshes[m],m);
Index: /trunk/src/formats/md2_loader.cc
===================================================================
--- /trunk/src/formats/md2_loader.cc	(revision 415)
+++ /trunk/src/formats/md2_loader.cc	(revision 416)
@@ -8,4 +8,6 @@
 
 #include "nv/core/logging.hh"
+#include "nv/interface/data_channel_access.hh"
+
 #include <cstring>
 
@@ -309,12 +311,12 @@
 
 
-mesh_data* nv::md2_loader::release_mesh_data( size_t )
-{
-	mesh_data* data = new mesh_data( "md2_mesh" );
+data_channel_set* nv::md2_loader::release_mesh_data( size_t )
+{
+	data_channel_set* data = data_channel_set_creator::create( 3 );
 	release_mesh_frame( data, -1 );
 	return data;
 }
 
-void nv::md2_loader::release_mesh_frame( mesh_data* data, sint32 frame )
+void nv::md2_loader::release_mesh_frame( data_channel_set* data, sint32 frame )
 {
 	md2_t* md2 = reinterpret_cast< md2_t* >( m_md2 );
@@ -364,12 +366,14 @@
 	}
 
-	data->add_channel( mc_pn.release() );
-	data->add_channel( mc_t.release() );
-	data->add_channel( ic.release() );
+	data_channel_set_creator maccess( data );
+
+	maccess.add_channel( mc_pn.release() );
+	maccess.add_channel( mc_t.release() );
+	maccess.add_channel( ic.release() );
 }
 
 mesh_data_pack* nv::md2_loader::release_mesh_data_pack()
 {
-	mesh_data* data = new mesh_data[1];
+	data_channel_set* data = data_channel_set_creator::create_array( 1, 3 );
 	release_mesh_frame( &data[0], -1 );
 	return new mesh_data_pack( 1, data );
Index: /trunk/src/formats/md3_loader.cc
===================================================================
--- /trunk/src/formats/md3_loader.cc	(revision 415)
+++ /trunk/src/formats/md3_loader.cc	(revision 416)
@@ -8,4 +8,5 @@
 
 #include "nv/core/logging.hh"
+#include "nv/interface/data_channel_access.hh"
 
 using namespace nv;
@@ -322,12 +323,12 @@
 };
 
-mesh_data* nv::md3_loader::release_mesh_data( nv::size_t index )
-{
-	mesh_data* data = new mesh_data;
+data_channel_set* nv::md3_loader::release_mesh_data( nv::size_t index )
+{
+	data_channel_set* data = data_channel_set_creator::create(3);
 	release_mesh_frame( data, -1, static_cast< sint32 >( index ) );
 	return data;
 }
 
-void nv::md3_loader::release_mesh_frame( mesh_data* data, sint32 frame, sint32 surface )
+void nv::md3_loader::release_mesh_frame( data_channel_set* data, sint32 frame, sint32 surface )
 {
 	md3_t* md3 = reinterpret_cast< md3_t* >( m_md3 );
@@ -412,8 +413,9 @@
 	}
 
-	data->set_name( reinterpret_cast< char* >( md3->header.name ) );
-	data->add_channel( mc_pn.release() );
-	data->add_channel( mc_t.release() );
-	data->add_channel( ic.release() );
+	data_channel_set_creator maccess( data );
+	maccess.set_name( reinterpret_cast<char*>( md3->header.name ) );
+	maccess.add_channel( mc_pn.release() );
+	maccess.add_channel( mc_t.release() );
+	maccess.add_channel( ic.release() );
 }
 
@@ -436,5 +438,5 @@
 	
 		raw_data_channel* keys = load_tags( name );
-		nodes[i].data->add_channel( keys );
+		nodes[i].data->add_key_channel( keys );
 	}
 	return new mesh_nodes_data( "tags", node_count, nodes );
@@ -445,19 +447,19 @@
 	md3_t* md3 = reinterpret_cast<md3_t*>( m_md3 );
 	int count = 1;
-	mesh_data* data = nullptr;
+	data_channel_set* data = nullptr;
 	if ( m_merge_all )
 	{
-		data = new mesh_data[1];
+		data = data_channel_set_creator::create_array(1,3);
 		release_mesh_frame( &data[0], -1, -1 );
-		data[0].set_name( reinterpret_cast< char* >( md3->header.name ) );
+		data_channel_set_creator( &data[0] ).set_name( reinterpret_cast< char* >( md3->header.name ) );
 	}
 	else
 	{
 		count = md3->header.num_surfaces;
-		data = new mesh_data[ count ];
+		data = data_channel_set_creator::create_array( count, 3 );
 		for ( int i = 0; i < count; ++i )
 		{
 			release_mesh_frame( &data[i], -1, i );
-			data[i].set_name( reinterpret_cast< char* >( md3->surfaces[i].header.name ) );
+			data_channel_set_creator( &data[i] ).set_name( reinterpret_cast< char* >( md3->surfaces[i].header.name ) );
 		}
 	}
Index: /trunk/src/formats/md5_loader.cc
===================================================================
--- /trunk/src/formats/md5_loader.cc	(revision 415)
+++ /trunk/src/formats/md5_loader.cc	(revision 416)
@@ -10,4 +10,5 @@
 #include "nv/stl/vector.hh"
 #include "nv/io/std_stream.hh"
+#include "nv/interface/data_channel_access.hh"
 
 #include <stdio.h>  // sscanf
@@ -136,5 +137,5 @@
 		{
 			assert( m_type == MESH );
-			mesh_data* mesh = new mesh_data("md5_mesh");
+			data_channel_set_creator mesh;
 
 			uint32 num_verts   = 0;
@@ -163,9 +164,9 @@
 						data_channel_creator<md5_vtx_pntiw> ch_pntiw( num_verts );
 						tdata = ch_t.data();
-						mesh->add_channel( ch_pnt.release() );
-						mesh->add_channel( ch_t.release() );
+						mesh.add_channel( ch_pnt.release() );
+						mesh.add_channel( ch_t.release() );
 						// TODO: hack to prevent rendering
 						//ch_pntiw->m_count = 0;
-						mesh->add_channel( ch_pntiw.release() );
+						mesh.add_channel( ch_pntiw.release() );
 					}
 					weight_info.resize( num_verts );
@@ -210,5 +211,5 @@
 					}              
 
-					mesh->add_channel( ch_i.release() );
+					mesh.add_channel( ch_i.release() );
 				}
 				else if ( command == "numweights" )
@@ -235,7 +236,8 @@
 			}
 
-			prepare_mesh( nodes, weight_info.size(), mesh, weights.data(), weight_info.data() );
-
-			m_meshes[ num_meshes ] = mesh;
+			data_channel_set* mdata = mesh.release();
+			prepare_mesh( nodes, weight_info.size(), mdata, weights.data(), weight_info.data() );
+
+			m_meshes[ num_meshes ] = mdata;
 			num_meshes++;
 		} // mesh
@@ -258,5 +260,5 @@
 				nodes[i].data      = new key_data;
 				data_channel_creator< md5_key_t > fc( num_frames );
-				nodes[i].data->add_channel( fc.release() );
+				nodes[i].data->add_key_channel( fc.release() );
 				next_line( sstream ); 
 			}
@@ -335,5 +337,5 @@
 }
 
-bool md5_loader::prepare_mesh( mesh_node_data* nodes, uint32 vtx_count, mesh_data* mdata, md5_weight* weights, md5_weight_info* weight_info )
+bool md5_loader::prepare_mesh( mesh_node_data* nodes, uint32 vtx_count, data_channel_set* mdata, md5_weight* weights, md5_weight_info* weight_info )
 {
 	assert( m_type == MESH );
@@ -400,9 +402,9 @@
 	}
 
-	const uint32*    idata = reinterpret_cast< uint32* >( const_cast< uint8* >( mdata->get_index_channel()->raw_data() ) );
+	const uint32*    idata = reinterpret_cast< uint32* >( const_cast< uint8* >( mdata->get_channel( slot::INDEX )->raw_data() ) );
 	const md5_vtx_t* tdata = mdata->get_channel_data<md5_vtx_t>();
 
 	// Prepare normals
-	uint32 tri_count = mdata->get_count() / 3;
+	uint32 tri_count = mdata->get_channel_size( slot::INDEX ) / 3;
 	for ( unsigned int i = 0; i < tri_count; ++i )
 	{
@@ -503,7 +505,7 @@
 }
 
-mesh_data* nv::md5_loader::release_mesh_data( size_t index )
-{
-	mesh_data* result = m_meshes[ index ];
+data_channel_set* nv::md5_loader::release_mesh_data( size_t index )
+{
+	data_channel_set* result = m_meshes[ index ];
 	m_meshes[ index ] = nullptr;
 	return result;
@@ -520,8 +522,8 @@
 {
 	uint32 size = m_meshes.size();
-	mesh_data* meshes = new mesh_data[ size ];
+	data_channel_set* meshes = data_channel_set_creator::create_array( size, 4 );
 	for ( uint32 i = 0; i < size; ++i )
 	{
-		m_meshes[i]->move_to( meshes[i] );
+		data_channel_set_creator( m_meshes[i] ).move_to( meshes[i] );
 		delete m_meshes[i];
 		m_meshes[i] = nullptr;
Index: /trunk/src/formats/nmd_loader.cc
===================================================================
--- /trunk/src/formats/nmd_loader.cc	(revision 415)
+++ /trunk/src/formats/nmd_loader.cc	(revision 416)
@@ -8,4 +8,5 @@
 #include "nv/io/std_stream.hh"
 #include "nv/stl/string.hh"
+#include "nv/interface/data_channel_access.hh"
 
 using namespace nv;
@@ -34,5 +35,5 @@
 bool nv::nmd_loader::load_mesh( stream& source, const nmd_element_header& e )
 {
-	mesh_data* mesh = new mesh_data();
+	data_channel_set_creator mesh;
 	for ( uint32 s = 0; s < e.children; ++s )
 	{
@@ -45,15 +46,15 @@
 		raw_data_channel_creator channel_creator( stream_header.format, stream_header.count );
 		source.read( channel_creator.raw_data(), channel_creator.element_size(), channel_creator.size() );
-		mesh->add_channel( channel_creator.release() );
+		mesh.add_channel( channel_creator.release() );
 	}
 	m_mesh_names.push_back( e.name );
-	m_meshes.push_back( mesh );
-	return true;
-}
-
-mesh_data* nv::nmd_loader::release_mesh_data( size_t index )
-{
-	mesh_data* result = m_meshes[ index ];
-	if ( m_strings ) result->set_name( m_strings->get( m_mesh_names[ index ] ) );
+	m_meshes.push_back( mesh.release() );
+	return true;
+}
+
+data_channel_set* nv::nmd_loader::release_mesh_data( size_t index )
+{
+	data_channel_set* result = m_meshes[ index ];
+	if ( m_strings ) data_channel_set_creator( result ).set_name( m_strings->get( m_mesh_names[ index ] ) );
 	m_meshes[ index ] = nullptr;
 	return result;
@@ -63,8 +64,8 @@
 {
 	uint32 size = m_meshes.size();
-	mesh_data* meshes = new mesh_data[ size ];
+	data_channel_set* meshes = data_channel_set_creator::create_array( size, 0 );
 	for ( uint32 i = 0; i < size; ++i )
 	{
-		m_meshes[i]->move_to( meshes[i] );
+		data_channel_set_creator( m_meshes[i] ).move_to( meshes[i] );
 		delete m_meshes[i];
 	}
@@ -130,5 +131,5 @@
 				raw_data_channel_creator channel_creator( cheader.format, cheader.count );
 				source.read( channel_creator.raw_data(), channel_creator.element_size(), channel_creator.size() );
-				kdata->add_channel( channel_creator.release() );
+				kdata->add_key_channel( channel_creator.release() );
 			}
 		}
@@ -160,10 +161,8 @@
 // nmd format dump
 // HACK : TEMPORARY - will go to it's own file, probably nmd_io
-static void nmd_dump_mesh( const mesh_data* mesh, stream& stream_out )
-{
-	array_view< raw_data_channel* > data  = mesh->get_raw_channels();
-
+static void nmd_dump_mesh( const data_channel_set* mesh, stream& stream_out )
+{
 	uint32 size = sizeof( nmd_element_header );
-	for ( auto chan : data )
+	for ( auto chan : *mesh )
 	{
 		size += sizeof( nmd_element_header ) + sizeof( nmd_stream_header );
@@ -174,9 +173,9 @@
 	eheader.type     = nmd_type::MESH;
 	eheader.name     = 0;
-	eheader.children = static_cast< uint16 >( data.size() );
+	eheader.children = static_cast< uint16 >( mesh->size() );
 	eheader.size     = size;
 	stream_out.write( &eheader, sizeof( eheader ), 1 );
 
-	for ( auto chan : data )
+	for ( auto chan : *mesh )
 	{
 		nmd_element_header cheader;
@@ -203,5 +202,5 @@
 		total += sizeof( nmd_element_header ) + sizeof( nmd_node_header );
 		if ( node->data )
-			for ( uint32 c = 0; c < node->data->get_channel_count(); ++c )
+			for ( uint32 c = 0; c < node->data->size(); ++c )
 			{
 				total += sizeof( nmd_element_header ) + sizeof( nmd_stream_header );
@@ -227,5 +226,5 @@
 		const mesh_node_data* node = nodes->get_node(i);
 		uint32 chan_size  = 0;
-		uint32 chan_count = ( node->data ? node->data->get_channel_count() : 0 );
+		uint32 chan_count = ( node->data ? node->data->size() : 0 );
 		for ( uint32 c = 0; c < chan_count; ++c )
 		{
@@ -280,5 +279,5 @@
 	for ( uint32 i = 0; i < model->get_count(); ++i )
 	{
-		const mesh_data* mesh = model->get_mesh(i);
+		const data_channel_set* mesh = model->get_mesh(i);
 		nmd_dump_mesh( mesh, stream_out );
 	}
Index: /trunk/src/formats/obj_loader.cc
===================================================================
--- /trunk/src/formats/obj_loader.cc	(revision 415)
+++ /trunk/src/formats/obj_loader.cc	(revision 416)
@@ -7,4 +7,6 @@
 #include "nv/formats/obj_loader.hh"
 #include "nv/io/std_stream.hh"
+#include "nv/interface/data_channel_access.hh"
+
 #include <sstream>
 
@@ -330,7 +332,7 @@
 		}
 
-		mesh_data* mesh = new mesh_data(reader->name);
-		mesh->add_channel( channel.release() );
-		m_meshes.push_back( mesh );
+		data_channel_set_creator result;// ( reader->name );
+		result.add_channel( channel.release() );
+		m_meshes.push_back( result.release() );
 
 		reader->reset();
@@ -341,7 +343,7 @@
 }
 
-mesh_data* nv::obj_loader::release_mesh_data( size_t index )
-{
-	mesh_data* result = m_meshes[ index ];
+data_channel_set* nv::obj_loader::release_mesh_data( size_t index )
+{
+	data_channel_set* result = m_meshes[ index ];
 	m_meshes[ index ] = nullptr;
 	return result;
@@ -356,8 +358,8 @@
 {
 	uint32 size = m_meshes.size();
-	mesh_data* meshes = new mesh_data[ size ];
+	data_channel_set* meshes = data_channel_set_creator::create_array( size, 1 );
 	for ( uint32 i = 0; i < size; ++i )
 	{
-		m_meshes[i]->move_to( meshes[i] );
+		data_channel_set_creator( m_meshes[i] ).move_to( meshes[i] );
 		delete m_meshes[i];
 	}
Index: /trunk/src/gfx/keyframed_mesh.cc
===================================================================
--- /trunk/src/gfx/keyframed_mesh.cc	(revision 415)
+++ /trunk/src/gfx/keyframed_mesh.cc	(revision 416)
@@ -23,5 +23,5 @@
 	, m_active( false )
 {
-	m_index_count  = m_mesh_data->get_index_channel()->size();
+	m_index_count  = m_mesh_data->get_channel( slot::INDEX )->size();
 	m_vertex_count = m_mesh_data->get_channel<vertex_t>()->size();
 	m_vchannel     = m_mesh_data->get_channel<vertex_pnt>();
@@ -190,8 +190,7 @@
 	m_context->add_vertex_buffers( m_va, vb, m_mesh_data->get_channel<vertex_t>() );
 
-	const raw_data_channel* index_channel = m_mesh_data->get_index_channel();
+	const raw_data_channel* index_channel = m_mesh_data->get_channel( slot::INDEX );
 	buffer  ib = m_context->get_device()->create_buffer( INDEX_BUFFER, STATIC_DRAW, index_channel->raw_size(), index_channel->raw_data() );
-
-	m_context->set_index_buffer( m_va, ib, m_mesh_data->get_index_channel()->descriptor()[0].etype, true );
+	m_context->set_index_buffer( m_va, ib, index_channel->descriptor()[0].etype, true );
 
 	m_data = new uint8[ m_vertex_count * m_vsize ];
Index: /trunk/src/gfx/mesh_creator.cc
===================================================================
--- /trunk/src/gfx/mesh_creator.cc	(revision 415)
+++ /trunk/src/gfx/mesh_creator.cc	(revision 416)
@@ -6,4 +6,6 @@
 
 #include "nv/gfx/mesh_creator.hh"
+
+#include "nv/interface/data_channel_access.hh"
 
 struct nv_key_transform { nv::transform tform; };
@@ -22,5 +24,5 @@
 		size_t pcount    = ( pkeys ? pkeys->get_channel(0)->size() : 0 );
 		max_frames = nv::max<uint32>( count, max_frames );
-		if ( pkeys && pkeys->get_channel_count() > 0 && keys && keys->get_channel_count() > 0 )
+		if ( pkeys && pkeys->size() > 0 && keys && keys->size() > 0 )
 		{
 			data_channel_creator< nv_key_transform > channel_creator( const_cast< raw_data_channel* >( keys->get_channel( 0 ) ) );
@@ -54,7 +56,7 @@
 	{
 		key_data* old_keys = m_data->m_nodes[i].data;
-		if ( old_keys && old_keys->get_channel_count() > 0 )
-		{
-			size_t chan_count = old_keys->get_channel_count();
+		if ( old_keys && old_keys->size() > 0 )
+		{
+			size_t chan_count = old_keys->size();
 			if ( chan_count == 1 
 				&& old_keys->get_channel(0)->descriptor().size() == 1
@@ -85,5 +87,5 @@
 
 			delete old_keys;
-			new_keys->add_channel( kt_channel.release() );
+			new_keys->add_key_channel( kt_channel.release() );
 			m_data->m_nodes[i].data = new_keys;
 		}
@@ -104,5 +106,5 @@
 		{
 			key_data* kdata  = node.data;
-			for ( size_t c = 0; c < kdata->get_channel_count(); ++c )
+			for ( size_t c = 0; c < kdata->size(); ++c )
 			{
 				raw_data_channel_creator channel( const_cast< raw_data_channel* >( kdata->get_channel( c ) ) );
@@ -123,7 +125,7 @@
 	mat3 normal_transform  = r33;
 
-	for ( uint32 c = 0; c < m_data->get_channel_count(); ++c )
-	{
-		raw_data_channel_creator channel( m_data->m_channels[ c ] );
+	for ( uint32 c = 0; c < m_data->size(); ++c )
+	{
+		raw_data_channel_creator channel( m_data, c );
 		const data_descriptor&  desc    = channel.descriptor();
 		uint8* raw_data = channel.raw_data();
@@ -173,5 +175,5 @@
 	size_t n_offset = 0;
 	if ( ch_n == -1 ) return;
-	raw_data_channel_creator channel( m_data->m_channels[ unsigned( ch_n ) ] );
+	raw_data_channel_creator channel( m_data, unsigned( ch_n ) );
 	for ( const auto& cslot : channel.descriptor() )
 		if ( cslot.vslot == slot::NORMAL )
@@ -201,5 +203,5 @@
 	const raw_data_channel* i_channel = nullptr;
 
-	for ( uint32 c = 0; c < m_data->get_channel_count(); ++c )
+	for ( uint32 c = 0; c < m_data->size(); ++c )
 	{
 		const raw_data_channel* channel = m_data->get_channel(c);
@@ -219,5 +221,5 @@
 				{
 					n_offset  = int( cslot.offset );
-					n_channel = m_data->m_channels[ c ];
+					n_channel = data_channel_set_creator( m_data )[ c ];
 					n_channel_index = c;
 				}
@@ -331,9 +333,9 @@
 	delete tangents2;
 
-	m_data->m_channels[ n_channel_index ] = merge_channels( n_channel, g_channel.channel() );
+	( data_channel_set_creator( m_data ))[ n_channel_index ] = merge_channels( n_channel, g_channel.channel() );
 	delete n_channel;
 }
 
-nv::raw_data_channel* nv::mesh_data_creator::merge_channels( raw_data_channel* a, raw_data_channel* b )
+nv::raw_data_channel* nv::mesh_data_creator::merge_channels( const raw_data_channel* a, const raw_data_channel* b )
 {
 	NV_ASSERT( a->size() == b->size(), "merge_channel - bad channels!" );
@@ -351,5 +353,5 @@
 }
 
-nv::raw_data_channel* nv::mesh_data_creator::append_channels( raw_data_channel* a, raw_data_channel* b, uint32 frame_count )
+nv::raw_data_channel* nv::mesh_data_creator::append_channels( const raw_data_channel* a, const raw_data_channel* b, uint32 frame_count )
 {
 	if ( a->descriptor() != b->descriptor() ) return nullptr;
@@ -389,6 +391,6 @@
 bool nv::mesh_data_creator::is_same_format( mesh_data* other )
 {
-	if ( m_data->get_channel_count() != other->get_channel_count() ) return false;
-	for ( uint32 c = 0; c < m_data->get_channel_count(); ++c )
+	if ( m_data->size() != other->size() ) return false;
+	for ( uint32 c = 0; c < m_data->size(); ++c )
 	{
 		if ( m_data->get_channel(c)->descriptor() != other->get_channel(c)->descriptor() )
@@ -406,18 +408,20 @@
 	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) ]->size();
-	size_t osize  =  other->m_channels[ unsigned(och_ti) ]->size();
-	size_t count  = m_data->m_channels[ unsigned(ch_pi) ]->size();
-	size_t ocount =  other->m_channels[ unsigned(och_pi) ]->size();
+	size_t size   = m_data->get_channel_size( unsigned(ch_ti) );
+	size_t osize  =  other->get_channel_size( unsigned(och_ti) );
+	size_t count  = m_data->get_channel_size( unsigned(ch_pi) );
+	size_t ocount =  other->get_channel_size( unsigned(och_pi) );
 	if ( count % size != 0 || ocount % osize != 0 ) return;
 	if ( count / size != ocount / osize ) return;
 	
-	for ( uint32 c = 0; c < m_data->get_channel_count(); ++c )
-	{
-		raw_data_channel* old = m_data->m_channels[c];
+	data_channel_set_creator data( m_data );
+
+	for ( uint32 c = 0; c < m_data->size(); ++c )
+	{
+		const raw_data_channel* old = m_data->get_channel( c );
 		bool old_is_index = old->size() > 0 && old->descriptor()[0].vslot == slot::INDEX;
 		size_t frame_count = ( old_is_index ? 1 : old->size() / size );
-		m_data->m_channels[c] = append_channels( old, other->m_channels[c], frame_count );
-		NV_ASSERT( m_data->m_channels[c], "Merge problem!" );
+		data[c] = append_channels( old, other->get_channel(c), frame_count );
+		NV_ASSERT( data[c], "Merge problem!" );
 		if ( old_is_index )
 		{
@@ -427,5 +431,5 @@
 				{
 					NV_ASSERT( size + osize < uint16(-1), "Index out of range!" );
-					raw_data_channel_creator ic( m_data->m_channels[c] );
+					raw_data_channel_creator ic( data[c] );
 					uint16* indexes = reinterpret_cast<uint16*>( ic.raw_data() );
 					for ( uint16 i = uint16( old->size() ); i < ic.size(); ++i )
@@ -436,5 +440,5 @@
 			case UINT   : 
 				{
-					raw_data_channel_creator ic( m_data->m_channels[c] );
+					raw_data_channel_creator ic( data[c] );
 					uint32* indexes = reinterpret_cast<uint32*>( ic.raw_data() );
 					for ( uint32 i = old->size(); i < ic.size(); ++i )
@@ -444,7 +448,16 @@
 			default : NV_ASSERT( false, "Unsupported index type!" ); break;
 			}
-			m_data->m_index_channel = m_data->m_channels[c];
 		}
 		delete old;
 	}
 }
+
+void nv::mesh_creator::delete_mesh( uint32 index )
+{
+	if ( index < m_pack->get_count() )
+	{
+		data_channel_set_creator( &m_pack->m_meshes[index] ).destroy();
+		data_channel_set_creator( &m_pack->m_meshes[m_pack->m_count - 1] ).move_to( m_pack->m_meshes[index] );
+		m_pack->m_count--;
+	}
+}
Index: /trunk/src/gfx/skeletal_mesh.cc
===================================================================
--- /trunk/src/gfx/skeletal_mesh.cc	(revision 415)
+++ /trunk/src/gfx/skeletal_mesh.cc	(revision 416)
@@ -27,11 +27,11 @@
 
 	m_vtx_data  = a_mesh_data->get_channel_data<md5_vtx_pntiw>();
-	m_indices   = a_mesh_data->get_count();
+	m_indices   = a_mesh_data->get_channel_size( slot::INDEX );
 	m_va        = a_context->create_vertex_array();
 
-	array_view< raw_data_channel* > channels = a_mesh_data->get_raw_channels();
-	for ( uint32 ch = 0; ch < channels.size(); ++ch )
-	{
-		const raw_data_channel* channel = channels[ch];
+	//array_view< raw_data_channel* > channels = a_mesh_data->get_raw_channels();
+	for ( auto channel : *a_mesh_data )
+	{
+		//const raw_data_channel* channel = channels[ch];
 		if ( channel->size() > 0 && channel != pntiw_chan )
 		{
@@ -218,5 +218,5 @@
 {
 	m_va          = a_context->create_vertex_array( a_mesh, nv::STATIC_DRAW );
-	m_index_count = a_mesh->get_count();
+	m_index_count = a_mesh->get_channel_size( slot::INDEX );
 	if ( m_bone_data )
 	{
