Index: trunk/nv/formats/md3_loader.hh
===================================================================
--- trunk/nv/formats/md3_loader.hh	(revision 416)
+++ trunk/nv/formats/md3_loader.hh	(revision 417)
@@ -41,5 +41,6 @@
 	private:
 		void release_mesh_frame( data_channel_set* data, sint32 frame, sint32 surface );
-		raw_data_channel* load_tags( const string_view& tag );
+		void load_tags( raw_data_channel* channel, const string_view& tag );
+
 		bool m_merge_all;
 		void* m_md3;
Index: trunk/nv/gfx/animation.hh
===================================================================
--- trunk/nv/gfx/animation.hh	(revision 416)
+++ trunk/nv/gfx/animation.hh	(revision 417)
@@ -20,18 +20,7 @@
 {
 
-	class key_data : public data_channel_set
-	{
-	public:
-		key_data() {}
-
-		void add_key_channel( raw_data_channel* channel ) 
-		{
-			NV_ASSERT( channel, "nullptr passed to add_channel!" );
-			add_channel( channel );
-			for ( const auto& cslot : channel->descriptor() )
-				if ( cslot.vslot != slot::TIME )
-					m_final_key.push_slot( cslot.etype, cslot.vslot );
-		}
-
+	class key_channel_set : public data_channel_set
+	{
+	public:
 		mat4 get_raw_matrix( uint32 index ) const 
 		{
@@ -151,4 +140,8 @@
 
 	private:
+		friend class key_channel_set_creator;
+
+		key_channel_set() {}
+
 		data_descriptor m_final_key;
 	};
Index: trunk/nv/gfx/keyframed_mesh.hh
===================================================================
--- trunk/nv/gfx/keyframed_mesh.hh	(revision 416)
+++ trunk/nv/gfx/keyframed_mesh.hh	(revision 417)
@@ -52,5 +52,4 @@
 		const mesh_data*        m_mesh_data;
 		const mesh_nodes_data*  m_tag_map;
-		const raw_data_channel* m_vchannel;
 
 		buffer       m_pbuffer;
Index: trunk/nv/interface/context.hh
===================================================================
--- trunk/nv/interface/context.hh	(revision 416)
+++ trunk/nv/interface/context.hh	(revision 417)
@@ -155,10 +155,10 @@
 		}
 
-		void add_vertex_buffers( vertex_array va, buffer buf, const raw_data_channel* channel )
-		{
-			for ( const auto& cslot : channel->descriptor() )
+		void add_vertex_buffers( vertex_array va, buffer buf, const data_descriptor& descriptor )
+		{
+			for ( const auto& cslot : descriptor )
 			{
 				const datatype_info& info = get_datatype_info( cslot.etype );
-				add_vertex_buffer( va, cslot.vslot, buf, info.base, info.elements, cslot.offset, channel->descriptor().element_size(), false );
+				add_vertex_buffer( va, cslot.vslot, buf, info.base, info.elements, cslot.offset, descriptor.element_size(), false );
 			}
 		}
@@ -300,9 +300,6 @@
 		{
 			vertex_array  va = create_vertex_array();
-			//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 )
 				{
@@ -317,5 +314,5 @@
 					{
 						buffer b = m_device->create_buffer( VERTEX_BUFFER, hint, channel->raw_size(), channel->raw_data() );
-						add_vertex_buffers( va, b, channel );
+						add_vertex_buffers( va, b, desc );
 					}
 				}
Index: trunk/nv/interface/data_descriptor.hh
===================================================================
--- trunk/nv/interface/data_descriptor.hh	(revision 416)
+++ trunk/nv/interface/data_descriptor.hh	(revision 417)
@@ -39,5 +39,5 @@
 	{
 		datatype etype = NONE;
-		uint32   offset = 0;
+		uint8    offset = 0;
 		slot     vslot = slot::POSITION;
 	};
@@ -277,5 +277,5 @@
 			m_slots[m_size].offset = m_element_size;
 			m_slots[m_size].vslot = vslot;
-			m_element_size += get_datatype_info( etype ).size;
+			m_element_size += static_cast< uint8 >( get_datatype_info( etype ).size );
 			m_size++;
 		}
@@ -288,5 +288,5 @@
 				m_slots[m_size].offset = m_element_size;
 				m_slots[m_size].vslot = dslot.vslot;
-				m_element_size += get_datatype_info( dslot.etype ).size;
+				m_element_size += static_cast< uint8 >( get_datatype_info( dslot.etype ).size );
 				m_size++;
 			}
@@ -304,6 +304,6 @@
 
 		data_descriptor_slot m_slots[uint16( slot::MAX_STORE )];
-		uint32               m_size = 0;
-		uint32               m_element_size = 0;
+		uint8                m_size = 0;
+		uint8                m_element_size = 0;
 
 		template < typename Struct, slot Slot >
Index: trunk/nv/interface/mesh_data.hh
===================================================================
--- trunk/nv/interface/mesh_data.hh	(revision 416)
+++ trunk/nv/interface/mesh_data.hh	(revision 417)
@@ -28,5 +28,5 @@
 		sint16    parent_id;
 		mat4      transform;
-		key_data* data;
+		key_channel_set* data;
 	};
 
@@ -75,7 +75,7 @@
 		}
 
-		key_data* release_node_data( size_t i )
+		key_channel_set* release_node_data( size_t i )
 		{
-			key_data* result = m_nodes[i].data;
+			key_channel_set* result = m_nodes[i].data;
 			m_nodes[i].data = nullptr;
 			return result;
Index: trunk/nv/stl/math.hh
===================================================================
--- trunk/nv/stl/math.hh	(revision 416)
+++ trunk/nv/stl/math.hh	(revision 417)
@@ -112,5 +112,5 @@
 	};
 
-	enum datatype
+	enum datatype : uint8
 	{
 		NONE,
Index: trunk/src/formats/assimp_loader.cc
===================================================================
--- trunk/src/formats/assimp_loader.cc	(revision 416)
+++ trunk/src/formats/assimp_loader.cc	(revision 417)
@@ -124,6 +124,8 @@
 	else
 		desc.initialize< assimp_plain_vtx >();
-	raw_data_channel_creator channel( desc, mesh->mNumVertices );
-	uint8* cdata = channel.raw_data();
+	data_channel_set_creator maccess( data );
+	maccess.set_name( mesh->mName.data );
+	uint8*  cdata   = maccess.add_channel( desc, mesh->mNumVertices ).raw_data();
+	uint16* indices = reinterpret_cast<uint16*>( maccess.add_channel< index_u16 >( mesh->mNumFaces * 3 ).raw_data() );
 
 	if ( mesh->mTangents && mesh->mBitangents )
@@ -171,6 +173,4 @@
 	}
 
-	data_channel_creator< index_u16 > ichannel( mesh->mNumFaces * 3 );
-	uint16* indices = reinterpret_cast<uint16*>( ichannel.raw_data() );
 	for (unsigned int i=0; i<mesh->mNumFaces; i++)
 	{
@@ -182,8 +182,4 @@
 	}
 
-	data_channel_set_creator maccess( data );
-	maccess.set_name( mesh->mName.data );
-	maccess.add_channel( channel.release() );
-	maccess.add_channel( ichannel.release() );
 }
 
@@ -321,5 +317,5 @@
 			if ( m > 0 && bones.size() > 0 )
 			{
-				data_channel_creator< assimp_skinned_vtx > channel( const_cast< raw_data_channel* >( meshes[m].get_channel(0) ) );
+				data_channel_access< assimp_skinned_vtx > channel( const_cast< raw_data_channel* >( meshes[m].get_channel(0) ) );
 				for ( unsigned v = 0; v < channel.size(); ++v )
 				{
@@ -422,12 +418,10 @@
 	}
 
-	data->data = new key_data;
-	data_channel_creator< assimp_key_p > pchannel_creator( node->mNumPositionKeys );
-	data_channel_creator< assimp_key_r > rchannel_creator( node->mNumRotationKeys );
-//	data_channel_creator< assimp_key_s > schannel_creator( node->mNumScalingKeys );
-
-	assimp_key_p* pchannel = pchannel_creator.data();
-	assimp_key_r* rchannel = rchannel_creator.data();
-	//assimp_key_s* schannel = ((assimp_key_s*)(raw_schannel->data));
+	data->data = key_channel_set_creator::create( 2 );
+	key_channel_set_creator key_set( data->data );
+
+	assimp_key_p* pchannel = key_set.add_channel< assimp_key_p >( node->mNumPositionKeys ).data();
+	assimp_key_r* rchannel = key_set.add_channel< assimp_key_r >( node->mNumRotationKeys ).data();
+//	assimp_key_s* schannel = key_set.add_channel< assimp_key_s >( node->mNumScalingKeys ).data();
 
 	for ( unsigned np = 0; np < node->mNumPositionKeys; ++np )
@@ -460,7 +454,5 @@
 // 		}
 // 	}
-	data->data->add_key_channel( pchannel_creator.release() );
-	data->data->add_key_channel( rchannel_creator.release() );
-//	data->data->add_key_channel( schannel_creator.release() );
+
 }
 
Index: trunk/src/formats/md2_loader.cc
===================================================================
--- trunk/src/formats/md2_loader.cc	(revision 416)
+++ trunk/src/formats/md2_loader.cc	(revision 417)
@@ -326,6 +326,8 @@
 	size_t frame_count   = ( frame == -1 ? num_frames : 1 );
 
-	data_channel_creator< vtx_md2_pn > mc_pn( num_verts * frame_count );
-	vtx_md2_pn* vtx_pn = mc_pn.data();
+	data_channel_set_creator maccess( data );
+	vtx_md2_pn* vtx_pn = maccess.add_channel< vtx_md2_pn >( num_verts * frame_count ).data();
+	vtx_md2_t* vtx_t   = maccess.add_channel< vtx_md2_t >( num_verts ).data();
+	uint16* icp        = &maccess.add_channel< index_u16 >( m_new_indexes.size() ).data()->index;
 
 	uint32 index = 0;
@@ -349,7 +351,4 @@
 	}
 
-	data_channel_creator< vtx_md2_t > mc_t( num_verts );
-	vtx_md2_t* vtx_t = mc_t.data();
-
 	vec2 scale( 1.0f / static_cast<float>( md2->header.skinwidth ), 1.0f / static_cast<float>( md2->header.skinheight ) );
 	for (size_t i = 0; i < num_verts; ++i )
@@ -359,16 +358,9 @@
 	}
 
-	data_channel_creator< index_u16 > ic( m_new_indexes.size() );
 	if ( m_new_indexes.size() > 0 )
 	{
-		uint16* icp = reinterpret_cast< uint16* >( ic.raw_data() );
 		raw_copy_n( m_new_indexes.data(), m_new_indexes.size(), icp );
 	}
 
-	data_channel_set_creator maccess( data );
-
-	maccess.add_channel( mc_pn.release() );
-	maccess.add_channel( mc_t.release() );
-	maccess.add_channel( ic.release() );
 }
 
Index: trunk/src/formats/md3_loader.cc
===================================================================
--- trunk/src/formats/md3_loader.cc	(revision 416)
+++ trunk/src/formats/md3_loader.cc	(revision 417)
@@ -287,8 +287,8 @@
 }
 
-nv::raw_data_channel* nv::md3_loader::load_tags( const string_view& tag )
+void nv::md3_loader::load_tags( raw_data_channel* channel, const string_view& tag )
 {
 	md3_t* md3 = reinterpret_cast< md3_t* >( m_md3 );
-	data_channel_creator< md3_key > result( uint32( md3->header.num_frames ) );
+	data_channel_access< md3_key > access( channel );
 	// TODO: is this brain damaged in efficiency (loop nest order) or what?
 	for ( sint32 f = 0; f < md3->header.num_frames; ++f )
@@ -304,10 +304,9 @@
 				vec3 axisy  ( md3_vec3( rtag.axis[2] ) );
 				vec3 origin ( md3_vec3( rtag.origin )  );
-				result.data()[f].tform = transform( origin, quat( mat3( axisx, axisy, axisz ) ) );
+				access.data()[f].tform = transform( origin, quat( mat3( axisx, axisy, axisz ) ) );
 			}
 		}
 
 	}
-	return result.release();
 }
 
@@ -353,10 +352,10 @@
 		}
 
-	data_channel_creator< vtx_md3_pn > mc_pn( static_cast< uint32 >( num_verts * frame_count ) );
-	data_channel_creator< vtx_md3_t > mc_t( static_cast< uint32 >( num_verts ) );
-	data_channel_creator< index_u16 > ic( static_cast< uint32 >( index_count ) );
-	vtx_md3_pn* vtx_pn = mc_pn.data();
-	vtx_md3_t*  vtx_t = mc_t.data();
-	uint16*     icp    = &(ic.data()[0].index);
+	data_channel_set_creator maccess( data );
+	maccess.set_name( reinterpret_cast<char*>( md3->header.name ) );
+
+	vtx_md3_pn* vtx_pn = maccess.add_channel< vtx_md3_pn >( static_cast< uint32 >( num_verts * frame_count ) ).data();
+	vtx_md3_t*  vtx_t  = maccess.add_channel< vtx_md3_t >( static_cast< uint32 >( num_verts ) ).data();
+	uint16*     icp    = reinterpret_cast< uint16* >( maccess.add_channel< index_u16 >( static_cast< uint32 >( index_count ) ).data() );
 
 	uint32 index  = 0;
@@ -413,9 +412,4 @@
 	}
 
-	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() );
 }
 
@@ -435,8 +429,6 @@
 		nodes[i].parent_id = -1;
 		nodes[i].target_id = -1;
-		nodes[i].data      = new key_data;
-	
-		raw_data_channel* keys = load_tags( name );
-		nodes[i].data->add_key_channel( keys );
+		nodes[i].data      = key_channel_set_creator::create( 1 );
+		load_tags( key_channel_set_creator( nodes[i].data ).add_channel<md3_key>( uint32( md3->header.num_frames ) ).channel(), name );
 	}
 	return new mesh_nodes_data( "tags", node_count, nodes );
Index: trunk/src/formats/md5_loader.cc
===================================================================
--- trunk/src/formats/md5_loader.cc	(revision 416)
+++ trunk/src/formats/md5_loader.cc	(revision 417)
@@ -137,5 +137,6 @@
 		{
 			assert( m_type == MESH );
-			data_channel_set_creator mesh;
+			data_channel_set* mesh = data_channel_set_creator::create( 4 );
+			data_channel_set_creator maccess( mesh );
 
 			uint32 num_verts   = 0;
@@ -160,13 +161,7 @@
 					md5_vtx_t* tdata = nullptr;
 					{
-						data_channel_creator<md5_vtx_pnt>   ch_pnt( num_verts );
-						data_channel_creator<md5_vtx_t>     ch_t( num_verts );
-						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() );
-						// TODO: hack to prevent rendering
-						//ch_pntiw->m_count = 0;
-						mesh.add_channel( ch_pntiw.release() );
+						maccess.add_channel<md5_vtx_pnt>( num_verts );
+						tdata = maccess.add_channel<md5_vtx_t>( num_verts ).data();
+						maccess.add_channel<md5_vtx_pntiw>( num_verts );
 					}
 					weight_info.resize( num_verts );
@@ -191,6 +186,5 @@
 					sstream >> num_tris;
 
-					data_channel_creator< index_u32 > ch_i( num_tris * 3 );
-					uint32* vtx_i                = reinterpret_cast< uint32* >( ch_i.raw_data() );
+					uint32* vtx_i = reinterpret_cast< uint32* >( maccess.add_channel< index_u32 >( num_tris * 3 ).raw_data() );
 					uint32 idx = 0;
 
@@ -211,5 +205,4 @@
 					}              
 
-					mesh.add_channel( ch_i.release() );
 				}
 				else if ( command == "numweights" )
@@ -236,8 +229,7 @@
 			}
 
-			data_channel_set* mdata = mesh.release();
-			prepare_mesh( nodes, weight_info.size(), mdata, weights.data(), weight_info.data() );
-
-			m_meshes[ num_meshes ] = mdata;
+			prepare_mesh( nodes, weight_info.size(), mesh, weights.data(), weight_info.data() );
+
+			m_meshes[ num_meshes ] = mesh;
 			num_meshes++;
 		} // mesh
@@ -258,8 +250,7 @@
 				nodes[i].transform = mat4();
 				nodes[i].target_id = -1;
-				nodes[i].data      = new key_data;
-				data_channel_creator< md5_key_t > fc( num_frames );
-				nodes[i].data->add_key_channel( fc.release() );
-				next_line( sstream ); 
+				nodes[i].data = key_channel_set_creator::create( 1 );
+				key_channel_set_creator( nodes[i].data ).add_channel< md5_key_t >( num_frames );
+				next_line( sstream );
 			}
 			discard( sstream, "}" );
@@ -340,6 +331,6 @@
 {
 	assert( m_type == MESH );
-	data_channel_creator< md5_vtx_pnt >   pnt  ( const_cast< raw_data_channel* >( mdata->get_channel< md5_vtx_pnt >() ) );
-	data_channel_creator< md5_vtx_pntiw > pntiw( const_cast< raw_data_channel* >( mdata->get_channel< md5_vtx_pntiw >() ) );
+	data_channel_access< md5_vtx_pnt >   pnt  ( const_cast< raw_data_channel* >( mdata->get_channel< md5_vtx_pnt >() ) );
+	data_channel_access< md5_vtx_pntiw > pntiw( const_cast< raw_data_channel* >( mdata->get_channel< md5_vtx_pntiw >() ) );
 	md5_vtx_pntiw* vtx_data = pntiw.data();
 	md5_vtx_pnt* vtcs = pnt.data();
Index: trunk/src/formats/nmd_loader.cc
===================================================================
--- trunk/src/formats/nmd_loader.cc	(revision 416)
+++ trunk/src/formats/nmd_loader.cc	(revision 417)
@@ -35,5 +35,6 @@
 bool nv::nmd_loader::load_mesh( stream& source, const nmd_element_header& e )
 {
-	data_channel_set_creator mesh;
+	data_channel_set* mesh = data_channel_set_creator::create( e.children );
+	data_channel_set_creator mcreator( mesh );
 	for ( uint32 s = 0; s < e.children; ++s )
 	{
@@ -44,10 +45,9 @@
 		nmd_stream_header stream_header;
 		source.read( &stream_header, sizeof( stream_header ), 1 );
-		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() );
+		raw_data_channel_access channel( mcreator.add_channel( stream_header.format, stream_header.count ) );
+		source.read( channel.raw_data(), channel.element_size(), channel.size() );
 	}
 	m_mesh_names.push_back( e.name );
-	m_meshes.push_back( mesh.release() );
+	m_meshes.push_back( mesh );
 	return true;
 }
@@ -121,5 +121,6 @@
 		if ( ch_count > 0 )
 		{
-			key_data* kdata = new key_data;
+			key_channel_set* kdata = key_channel_set_creator::create( ch_count );
+			key_channel_set_creator kaccess( kdata );
 			m_node_array[i].data = kdata;
 			for ( uint32 c = 0; c < ch_count; ++c )
@@ -129,7 +130,6 @@
 				nv::nmd_stream_header cheader;
 				source.read( &cheader, sizeof( cheader ), 1 );
-				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_key_channel( channel_creator.release() );
+				raw_data_channel_access channel( kaccess.add_channel( cheader.format, cheader.count ) );
+				source.read( channel.raw_data(), channel.element_size(), channel.size() );
 			}
 		}
Index: trunk/src/formats/obj_loader.cc
===================================================================
--- trunk/src/formats/obj_loader.cc	(revision 416)
+++ trunk/src/formats/obj_loader.cc	(revision 417)
@@ -326,13 +326,14 @@
 		}
 	
-		raw_data_channel_creator channel( m_descriptor, reader->size * 3 );
+		data_channel_set* result = data_channel_set_creator::create( 1 );
+		data_channel_set_creator raccess( result );// ( reader->name );
+		uint8* rdata = raccess.add_channel( m_descriptor, reader->size * 3 ).raw_data();
+
 		if ( reader->raw_size() > 0 )
 		{
-			raw_copy_n( reader->raw_pointer(), reader->raw_size(), channel.raw_data() );
-		}
-
-		data_channel_set_creator result;// ( reader->name );
-		result.add_channel( channel.release() );
-		m_meshes.push_back( result.release() );
+			raw_copy_n( reader->raw_pointer(), reader->raw_size(), rdata );
+		}
+
+		m_meshes.push_back( result );
 
 		reader->reset();
Index: trunk/src/gfx/keyframed_mesh.cc
===================================================================
--- trunk/src/gfx/keyframed_mesh.cc	(revision 416)
+++ trunk/src/gfx/keyframed_mesh.cc	(revision 417)
@@ -23,16 +23,19 @@
 	, m_active( false )
 {
-	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>();
-	m_vsize        = sizeof( vertex_pnt );
-	m_has_tangent  = true;
-	if ( m_vchannel == nullptr )
-	{
-		m_vchannel     = m_mesh_data->get_channel<vertex_pn>();
-		m_has_tangent  = false;
-		m_vsize        = sizeof( vertex_pn );
-	}
-	m_frame_count  = m_vchannel->size() / m_vertex_count;
+	m_index_count   = m_mesh_data->get_channel_size( slot::INDEX );
+	m_vertex_count  = m_mesh_data->get_channel_size<vertex_t>();
+	uint32 pos_size = m_mesh_data->get_channel_size<vertex_pnt>();
+	if ( pos_size == 0 )
+	{
+		pos_size      = m_mesh_data->get_channel_size<vertex_pn>();
+		m_has_tangent = false;
+		m_vsize       = sizeof( vertex_pn );
+	}
+	else
+	{
+		m_has_tangent = true;
+		m_vsize       = sizeof( vertex_pnt );
+	}
+	m_frame_count  = pos_size / m_vertex_count;
 	m_pbuffer      = buffer();
 }
@@ -47,5 +50,5 @@
 	if ( !m_tag_map ) return transform();
 	NV_ASSERT( node_id < m_tag_map->get_count(), "TAGMAP FAIL" );
-	const key_data* data = m_tag_map->get_node( node_id )->data;
+	const key_channel_set* data = m_tag_map->get_node( node_id )->data;
 	NV_ASSERT( data, "TAG FAIL" );
 	transform last = data->get_raw_transform( m_last_frame );
@@ -183,10 +186,11 @@
 	: keyframed_mesh( a_context, a_data, a_tag_map )
 {
+	const raw_data_channel* vchannel = m_has_tangent ? a_data->get_channel< vertex_pnt >() : a_data->get_channel< vertex_pn >();
 	m_va      = m_context->create_vertex_array();
-	m_pbuffer = m_context->get_device()->create_buffer( VERTEX_BUFFER, STATIC_DRAW, m_vertex_count * m_vsize, m_vchannel->raw_data() );
-	m_context->add_vertex_buffers( m_va, m_pbuffer, m_vchannel );
+	m_pbuffer = m_context->get_device()->create_buffer( VERTEX_BUFFER, STATIC_DRAW, m_vertex_count * m_vsize, vchannel->raw_data() );
+	m_context->add_vertex_buffers( m_va, m_pbuffer, vchannel->descriptor() );
 
 	buffer  vb = m_context->get_device()->create_buffer( VERTEX_BUFFER, STATIC_DRAW, m_vertex_count * sizeof( vec2 ), m_mesh_data->get_channel_data<vertex_t>() );
-	m_context->add_vertex_buffers( m_va, vb, m_mesh_data->get_channel<vertex_t>() );
+	m_context->add_vertex_buffers( m_va, vb, m_mesh_data->get_channel<vertex_t>()->descriptor() );
 
 	const raw_data_channel* index_channel = m_mesh_data->get_channel( slot::INDEX );
Index: trunk/src/gfx/mesh_creator.cc
===================================================================
--- trunk/src/gfx/mesh_creator.cc	(revision 416)
+++ trunk/src/gfx/mesh_creator.cc	(revision 417)
@@ -19,12 +19,12 @@
 	{
 		sint16 parent_id = m_data->m_nodes[i].parent_id;
-		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)->size() : 0 );
-		size_t pcount    = ( pkeys ? pkeys->get_channel(0)->size() : 0 );
+		key_channel_set* keys   = m_data->m_nodes[i].data;
+		key_channel_set* pkeys  = ( parent_id != -1 ? m_data->m_nodes[parent_id].data : nullptr );
+		size_t count     = ( keys ? keys->get_channel_size(0) : 0 );
+		size_t pcount    = ( pkeys ? pkeys->get_channel_size(0) : 0 );
 		max_frames = nv::max<uint32>( count, max_frames );
 		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 ) ) );
+			data_channel_access< nv_key_transform > channel_creator( keys, 0 );
 			nv_key_transform* channel = channel_creator.data();
 			const nv_key_transform* pchannel = pkeys->get_channel(0)->data_cast< nv_key_transform >();
@@ -55,5 +55,5 @@
 	for ( size_t i = 0; i < m_data->get_count(); ++i )
 	{
-		key_data* old_keys = m_data->m_nodes[i].data;
+		key_channel_set* old_keys = m_data->m_nodes[i].data;
 		if ( old_keys && old_keys->size() > 0 )
 		{
@@ -69,6 +69,8 @@
 			}
 
-			data_channel_creator< nv_key_transform > kt_channel( max_keys );
-			key_data* new_keys = new key_data;
+			key_channel_set* new_keys = key_channel_set_creator::create( 1 );
+			key_channel_set_creator nk_access( new_keys );
+			data_channel_access< nv_key_transform > kt_channel( nk_access.add_channel<nv_key_transform>( max_keys ) );
+
 			data_descriptor final_key = old_keys->get_final_key();
 
@@ -87,5 +89,4 @@
 
 			delete old_keys;
-			new_keys->add_key_channel( kt_channel.release() );
 			m_data->m_nodes[i].data = new_keys;
 		}
@@ -105,8 +106,8 @@
 		if ( node.data )
 		{
-			key_data* kdata  = node.data;
+			key_channel_set* kdata  = node.data;
 			for ( size_t c = 0; c < kdata->size(); ++c )
 			{
-				raw_data_channel_creator channel( const_cast< raw_data_channel* >( kdata->get_channel( c ) ) );
+				raw_data_channel_access channel( kdata, c );
 				size_t key_size = channel.element_size();
 				for ( size_t n = 0; n < channel.size(); ++n )
@@ -127,5 +128,5 @@
 	for ( uint32 c = 0; c < m_data->size(); ++c )
 	{
-		raw_data_channel_creator channel( m_data, c );
+		raw_data_channel_access channel( m_data, c );
 		const data_descriptor&  desc    = channel.descriptor();
 		uint8* raw_data = channel.raw_data();
@@ -175,5 +176,5 @@
 	size_t n_offset = 0;
 	if ( ch_n == -1 ) return;
-	raw_data_channel_creator channel( m_data, unsigned( ch_n ) );
+	raw_data_channel_access channel( m_data, unsigned( ch_n ) );
 	for ( const auto& cslot : channel.descriptor() )
 		if ( cslot.vslot == slot::NORMAL )
@@ -251,6 +252,6 @@
 	}
 
-	data_channel_creator< vertex_g > g_channel( p_channel->size() );
-	vec4* tangents              = &( g_channel.data()[0].tangent );
+	raw_data_channel* g_channel = data_channel_creator::create< vertex_g >( p_channel->size() );
+	vec4* tangents              = &( data_channel_access< vertex_g >( g_channel ).data()[0].tangent );
 	vec3* tangents2             = new vec3[ p_channel->size() ];
 	uint32 tri_count = i_channel ? i_channel->size() / 3 : t_channel->size() / 3;
@@ -333,6 +334,6 @@
 	delete tangents2;
 
-	( data_channel_set_creator( m_data ))[ n_channel_index ] = merge_channels( n_channel, g_channel.channel() );
-	delete n_channel;
+	data_channel_set_creator( m_data ).set_channel( n_channel_index, merge_channels( n_channel, g_channel ) );
+	delete g_channel;
 }
 
@@ -343,12 +344,12 @@
 	desc.append( b->descriptor() );
 
-	raw_data_channel_creator result( desc, a->size() );
+	raw_data_channel* result = data_channel_creator::create( desc, a->size() );
 	for ( uint32 i = 0; i < a->size(); ++i )
 	{
-		raw_copy_n( a->raw_data() + i * a->element_size(), a->element_size(), result.raw_data() + i*desc.element_size() );
-		raw_copy_n( b->raw_data() + i * b->element_size(), b->element_size(), result.raw_data() + i*desc.element_size() + a->element_size() );
-	}
-
-	return result.release();
+		raw_copy_n( a->raw_data() + i * a->element_size(), a->element_size(), raw_data_channel_access( result ).raw_data() + i*desc.element_size() );
+		raw_copy_n( b->raw_data() + i * b->element_size(), b->element_size(), raw_data_channel_access( result ).raw_data() + i*desc.element_size() + a->element_size() );
+	}
+
+	return result;
 }
 
@@ -360,11 +361,12 @@
 	size_t vtx_size = a->element_size();
 
-	raw_data_channel_creator result( a->descriptor(), a->size() + b->size() );
+	raw_data_channel* result = data_channel_creator::create( a->descriptor(), a->size() + b->size() );
+	uint8* rdata = raw_data_channel_access( result ).raw_data();
 
 	if ( frame_count == 1 )
 	{
 		size_t a_size = vtx_size * a->size();
-		raw_copy_n( a->raw_data(), a_size, result.raw_data() );
-		raw_copy_n( b->raw_data(), vtx_size * b->size(), result.raw_data() + a_size );
+		raw_copy_n( a->raw_data(), a_size, rdata );
+		raw_copy_n( b->raw_data(), vtx_size * b->size(), rdata + a_size );
 	}
 	else
@@ -377,6 +379,6 @@
 		for ( size_t i = 0; i < frame_count; ++i )
 		{
-			raw_copy_n( a->raw_data() + pos_a, frame_size_a, result.raw_data() + pos );
-			raw_copy_n( b->raw_data() + pos_b, frame_size_b, result.raw_data() + pos + frame_size_a );				pos_a += frame_size_a;
+			raw_copy_n( a->raw_data() + pos_a, frame_size_a, rdata + pos );
+			raw_copy_n( b->raw_data() + pos_b, frame_size_b, rdata + pos + frame_size_a );				pos_a += frame_size_a;
 			pos_b += frame_size_b; 
 			pos   += frame_size_a + frame_size_b;
@@ -384,5 +386,5 @@
 	}
 
-	return result.release();
+	return result;
 }
 
@@ -422,5 +424,5 @@
 		bool old_is_index = old->size() > 0 && old->descriptor()[0].vslot == slot::INDEX;
 		size_t frame_count = ( old_is_index ? 1 : old->size() / size );
-		data[c] = append_channels( old, other->get_channel(c), frame_count );
+		data.set_channel( c, append_channels( old, other->get_channel(c), frame_count ) );
 		NV_ASSERT( data[c], "Merge problem!" );
 		if ( old_is_index )
@@ -431,5 +433,5 @@
 				{
 					NV_ASSERT( size + osize < uint16(-1), "Index out of range!" );
-					raw_data_channel_creator ic( data[c] );
+					raw_data_channel_access ic( data[c] );
 					uint16* indexes = reinterpret_cast<uint16*>( ic.raw_data() );
 					for ( uint16 i = uint16( old->size() ); i < ic.size(); ++i )
@@ -440,5 +442,5 @@
 			case UINT   : 
 				{
-					raw_data_channel_creator ic( data[c] );
+					raw_data_channel_access ic( data[c] );
 					uint32* indexes = reinterpret_cast<uint32*>( ic.raw_data() );
 					for ( uint32 i = old->size(); i < ic.size(); ++i )
Index: trunk/src/gfx/skeletal_mesh.cc
===================================================================
--- trunk/src/gfx/skeletal_mesh.cc	(revision 416)
+++ trunk/src/gfx/skeletal_mesh.cc	(revision 417)
@@ -45,5 +45,5 @@
 			{
 				buffer b = a_context->get_device()->create_buffer( VERTEX_BUFFER, STREAM_DRAW, channel->raw_size(), channel->raw_data() );
-				a_context->add_vertex_buffers( m_va, b, channel );
+				a_context->add_vertex_buffers( m_va, b, desc );
 			}
 		}
