Index: trunk/nv/formats/md5_loader.hh
===================================================================
--- trunk/nv/formats/md5_loader.hh	(revision 411)
+++ trunk/nv/formats/md5_loader.hh	(revision 412)
@@ -84,5 +84,5 @@
 		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( md5_vtx_pntiw* vtx_data, mesh_node_data* nodes, uint32 vtx_count, mesh_data* mdata, md5_weight* weights, md5_weight_info* weight_info );
 	protected:
 		file_type m_type;
Index: trunk/nv/gfx/animation.hh
===================================================================
--- trunk/nv/gfx/animation.hh	(revision 411)
+++ trunk/nv/gfx/animation.hh	(revision 412)
@@ -29,7 +29,5 @@
 			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 );
+			m_final_key.append( channel->descriptor() );
 		}
 
@@ -180,16 +178,17 @@
 			data_descriptor desc;
 			desc.initialize<KEY>();
-			NV_ASSERT( data->desc == desc, "Bad channel passed!" );
+			NV_ASSERT( data->descriptor() == desc, "Bad channel passed!" );
 		}
 		void get_interpolated( KEY& result, float frame ) const
 		{
 			NV_ASSERT( m_data, "Data is null!" );
-			if ( m_data->count == 0 ) return;
-			if ( m_data->count == 1 ) 
+			uint32 count = m_data->element_count();
+			if ( count == 0 ) return;
+			if ( count == 1 )
 			{
 				result = reinterpret_cast<KEY*>(m_data->data)[0];
 				return;
 			}
-			size_t index = glm::clamp<size_t>( size_t( frame ), 0, m_data->count - 2 );
+			size_t index = glm::clamp<size_t>( size_t( frame ), 0, count - 2 );
 			float factor = glm::clamp<float> ( frame - index, 0.0f, 1.0f );
 			KEY* keys = reinterpret_cast<KEY*>( m_data->data );
@@ -212,13 +211,14 @@
 			data_descriptor desc;
 			desc.initialize<KEY>();
-			NV_ASSERT( data->desc == desc, "Bad channel passed!" );
+			NV_ASSERT( data->descriptor() == desc, "Bad channel passed!" );
 		}
 		void get_interpolated( KEY& result, float time ) const
 		{
 			// TODO: this probably could be optimized
-			const KEY* keys = reinterpret_cast<const KEY*>(m_data->data);
 			NV_ASSERT( m_data, "Data is null!" );
-			if ( m_data->count == 0 ) return;
-			if ( m_data->count == 1 ) 
+			const KEY* keys = reinterpret_cast<const KEY*>( m_data->data );
+			uint32 count = m_data->element_count();
+			if ( count == 0 ) return;
+			if ( count == 1 ) 
 			{
 				result = keys[0];
@@ -226,5 +226,5 @@
 			}
 			int index = -1;
-			for ( int i = 0 ; i < int( m_data->count ) - 1 ; i++ )
+			for ( int i = 0 ; i < int( count ) - 1 ; i++ )
 			{
 				if ( time < keys[i + 1].time ) { index = i; break; }
@@ -274,5 +274,8 @@
 		}
 		size_t size() const { return 0; } // TODO: remove?
-		bool empty() const { return m_pchannel->element_count() == 0 && m_rchannel->count == 0 && m_schannel->count == 0; }
+		bool empty() const { 
+			return m_pchannel->element_count() == 0 
+				&& m_rchannel->element_count() == 0 
+				&& m_schannel->element_count() == 0; }
 		virtual mat4 get_matrix( float time ) const
 		{
@@ -327,5 +330,5 @@
 			data_descriptor kd;
 			kd.initialize<key>();
-			NV_ASSERT( kd == channel->desc, "bad channel!" );
+			NV_ASSERT( kd == channel->descriptor(), "bad channel!" );
 			m_channel = channel;
 			m_interpolator.set_data( m_channel );
Index: trunk/nv/gfx/skeletal_mesh.hh
===================================================================
--- trunk/nv/gfx/skeletal_mesh.hh	(revision 411)
+++ trunk/nv/gfx/skeletal_mesh.hh	(revision 412)
@@ -59,5 +59,4 @@
 		dynamic_array< transform >   m_bone_offset;
 
-		const mesh_data*             m_data;
 		const md5_vtx_pntiw*         m_vtx_data;
 		dynamic_array< transform >   m_transform;
Index: trunk/nv/interface/context.hh
===================================================================
--- trunk/nv/interface/context.hh	(revision 411)
+++ trunk/nv/interface/context.hh	(revision 412)
@@ -157,8 +157,8 @@
 		void add_vertex_buffers( vertex_array va, buffer buf, const raw_data_channel* channel )
 		{
-			for ( const auto& cslot : channel->desc )
+			for ( const auto& cslot : channel->descriptor() )
 			{
 				const datatype_info& info = get_datatype_info( cslot.etype );
-				add_vertex_buffer( va, cslot.vslot, buf, info.base, info.elements, cslot.offset, channel->desc.element_size(), false );
+				add_vertex_buffer( va, cslot.vslot, buf, info.base, info.elements, cslot.offset, channel->descriptor().element_size(), false );
 			}
 		}
@@ -304,15 +304,16 @@
 			{
 				const raw_data_channel* channel = channels[ch];
-				if ( channel->count > 0 )
-				{
-					buffer_type type = channel->get_buffer_type();
-					buffer b = m_device->create_buffer( type, hint, channel->size(), channel->data );
+				if ( channel->element_count() > 0 )
+				{
+					const data_descriptor& desc = channel->descriptor();
 					// TODO: no if switch
-					if ( type == INDEX_BUFFER )
-					{
-						set_index_buffer( va, b, channel->desc[0].etype, true );
+					if ( desc[0].vslot == slot::INDEX )
+					{
+						buffer b = m_device->create_buffer( INDEX_BUFFER, hint, channel->raw_size(), channel->raw_data() );
+						set_index_buffer( va, b, desc[0].etype, true );
 					}
 					else
 					{
+						buffer b = m_device->create_buffer( VERTEX_BUFFER, hint, channel->raw_size(), channel->raw_data() );
 						add_vertex_buffers( va, b, channel );
 					}
Index: trunk/nv/interface/data_descriptor.hh
===================================================================
--- trunk/nv/interface/data_descriptor.hh	(revision 411)
+++ trunk/nv/interface/data_descriptor.hh	(revision 412)
@@ -14,10 +14,4 @@
 namespace nv
 {
-	// TODO: move somewhere else, or change to generic buffer_type
-	enum buffer_type
-	{
-		VERTEX_BUFFER,
-		INDEX_BUFFER,
-	};
 
 	enum class slot : uint8
@@ -228,12 +222,11 @@
 		bool operator==( const data_descriptor& rhs ) const
 		{
-//			if ( flags != rhs.flags ) return false;
-			if ( size  != rhs.size )  return false;
-			if ( count != rhs.count ) return false;
-			for ( uint32 i = 0; i < count; ++i )
+			if ( m_size  != rhs.m_size )  return false;
+			if ( m_count != rhs.m_count ) return false;
+			for ( uint32 i = 0; i < m_count; ++i )
 			{
-				if ( slots[i].etype  != rhs.slots[i].etype )  return false;
-				if ( slots[i].offset != rhs.slots[i].offset ) return false;
-				if ( slots[i].vslot  != rhs.slots[i].vslot )  return false;
+				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;
 			}
 			return true;
@@ -243,5 +236,5 @@
 		void initialize()
 		{
-			count = 0;
+			m_count = 0;
 			initialize_slot< Struct, slot::POSITION >();
 			initialize_slot< Struct, slot::TEXCOORD >();
@@ -251,4 +244,5 @@
 			initialize_slot< Struct, slot::BONEWEIGHT >();
 			initialize_slot< Struct, slot::COLOR >();
+			initialize_slot< Struct, slot::INDEX >();
 			initialize_slot< Struct, slot::TIME >();
 			initialize_slot< Struct, slot::TRANSLATION >();
@@ -256,40 +250,43 @@
 			initialize_slot< Struct, slot::SCALE >();
 			initialize_slot< Struct, slot::TFORM >();
-			size = sizeof( Struct );
-		}
-
-		uint32 element_size() const { return size; }
-		uint32 slot_count() const { return count; }
-
-		const_iterator begin() const { return &slots[0]; }
-		const_iterator end() const { return &slots[count]; }
+			m_size = sizeof( Struct );
+		}
+
+		uint32 element_size() const { return m_size; }
+		uint32 slot_count() const { return m_count; }
+
+		bool has_slot( slot vslot ) const
+		{
+			for ( const auto& dslot : *this )
+				if ( dslot.vslot == vslot ) return true;
+			return false;
+		}
+
+		const_iterator begin() const { return &m_slots[0]; }
+		const_iterator end() const { return &m_slots[m_count]; }
 
 		const data_descriptor_slot& operator []( uint32 i ) const
 		{
-			NV_ASSERT( i < count, "data_descriptor indexing failure!" );
-			return slots[i];
-		}
-
-		void push_slot( datatype etype, slot vslot )
-		{
-			slots[count].etype  = etype;
-			slots[count].offset = size;
-			slots[count].vslot  = vslot;
-			size += get_datatype_info( etype ).size;
-			count++;
+			NV_ASSERT( i < m_count, "data_descriptor indexing failure!" );
+			return m_slots[i];
+		}
+
+		void append( const data_descriptor& desc )
+		{
+			for ( const auto& dslot : desc )
+			{
+				m_slots[m_count].etype  = dslot.etype;
+				m_slots[m_count].offset = m_size;
+				m_slots[m_count].vslot  = dslot.vslot;
+				m_size += get_datatype_info( dslot.etype ).size;
+				m_count++;
+			}
 		}
 
 	protected:
-		// 		enum flag_type : uint32
-		// 		{
-		// 			NONE   = 0b0000,
-		// 			VERTEX = 0b0001,
-		// 			INDEX  = 0b0010,
-		// 			KEY    = 0b0100
-		// 		};
-		data_descriptor_slot slots[uint16( slot::MAX_STORE )];
-		uint32               count = 0;
-		uint32               size = 0;
-		//		flag_type            flags = NONE;
+
+		data_descriptor_slot m_slots[uint16( slot::MAX_STORE )];
+		uint32               m_count = 0;
+		uint32               m_size = 0;
 
 		template < typename Struct, slot Slot >
@@ -297,10 +294,10 @@
 		{
 			typedef slot_info< Struct, Slot > sinfo;
-			slots[count].etype = sinfo::etype;
-			if ( slots[count].etype != datatype::NONE )
+			m_slots[m_count].etype = sinfo::etype;
+			if ( m_slots[m_count].etype != datatype::NONE )
 			{
-				slots[count].vslot  = Slot;
-				slots[count].offset = sinfo::offset;
-				count++;
+				m_slots[m_count].vslot  = Slot;
+				m_slots[m_count].offset = sinfo::offset;
+				m_count++;
 			}
 		}
@@ -309,5 +306,5 @@
 	struct raw_data_channel
 	{
-		raw_data_channel() : data( nullptr ), count( 0 ) {}
+		raw_data_channel() : data( nullptr ), m_count( 0 ) {}
 		~raw_data_channel()
 		{
@@ -315,18 +312,11 @@
 		}
 
-		// 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(); }
+		const data_descriptor& descriptor() const { return m_desc;  }
+		uint32 element_size() const { return m_desc.element_size(); }
+		uint32 element_count() const { return m_count; }
+		uint32 raw_size() const { return m_count * m_desc.element_size(); }
+		const uint8* raw_data() const { return data; }
+
+		bool has_slot( slot vslot ) const { return m_desc.has_slot( vslot ); }
 
 		template < typename VTX >
@@ -334,43 +324,25 @@
 		{
 			raw_data_channel* result = new raw_data_channel();
-			result->desc.initialize<VTX>();
-			result->count = count;
-			result->data = ( count > 0 ? ( new uint8[result->size()] ) : nullptr );
+			result->m_desc.initialize<VTX>();
+			result->m_count = count;
+			result->data = ( count > 0 ? ( new uint8[result->raw_size()] ) : nullptr );
 			return result;
 		}
-		static raw_data_channel* create( const data_descriptor& vtxdesc, uint32 count = 0 )
+		static raw_data_channel* create( const data_descriptor& desc, 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 );
+			result->m_desc = desc;
+			result->m_count = count;
+			result->data = ( count > 0 ? ( new uint8[result->raw_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;
+		friend class mesh_data_creator;
+
 		uint8*          data;
-		uint32          count;
+	protected:
+		data_descriptor m_desc;
+		uint32          m_count;
 
 	};
Index: trunk/nv/interface/device.hh
===================================================================
--- trunk/nv/interface/device.hh	(revision 411)
+++ trunk/nv/interface/device.hh	(revision 412)
@@ -120,4 +120,10 @@
 		STREAM_DRAW,
 		DYNAMIC_DRAW
+	};
+
+	enum buffer_type
+	{
+		VERTEX_BUFFER,
+		INDEX_BUFFER,
 	};
 
Index: trunk/nv/interface/mesh_data.hh
===================================================================
--- trunk/nv/interface/mesh_data.hh	(revision 411)
+++ trunk/nv/interface/mesh_data.hh	(revision 412)
@@ -17,4 +17,7 @@
 {
 
+	struct index_u16 { uint16 index; };
+	struct index_u32 { uint32 index; };
+
 	// TODO: friend mesh_data_creator class?
 	// TODO: private const etc
@@ -32,5 +35,5 @@
 			NV_ASSERT( channel, "nullptr passed to add_channel!" );
 			m_channels.push_back( channel );
-			if ( channel->get_buffer_type() == INDEX_BUFFER )
+			if ( channel->element_count() > 0 && channel->descriptor()[0].vslot == slot::INDEX )
 			{
 				NV_ASSERT( !m_index_channel, "second index channel!" );
@@ -51,9 +54,6 @@
 		{ 
 			for ( auto ch : m_channels )
-			{
-				for ( auto slot : ch->desc )
-					if ( slot.vslot == s )
-						return ch;
-			}
+				if ( ch->has_slot( s ) )
+					return ch;
 			return nullptr;
 		}
@@ -62,9 +62,6 @@
 		{ 
 			for ( uint32 c = 0; c < m_channels.size(); ++c )
-			{
-				for ( auto slot : m_channels[c]->desc )
-					if ( slot.vslot == s )
-						return int( c );
-			}
+				if ( m_channels[c]->has_slot( s ) ) 
+					return int( c );
 			return -1;
 		}
@@ -73,6 +70,6 @@
 		size_t get_count() const 
 		{
-			if ( m_index_channel ) return m_index_channel->count;
-			if ( m_channels.size() > 0 ) return m_channels[0]->count;
+			if ( m_index_channel ) return m_index_channel->element_count();
+			if ( m_channels.size() > 0 ) return m_channels[0]->element_count();
 			return 0;
 		}
@@ -80,5 +77,5 @@
 		size_t get_count( size_t channel ) const 
 		{
-			if ( m_channels.size() > channel ) return m_channels[channel]->count;
+			if ( m_channels.size() > channel ) return m_channels[channel]->element_count();
 			return 0;
 		}
@@ -91,5 +88,5 @@
 			for ( auto ch : m_channels )
 			{
-				if ( ch->desc == compare )
+				if ( ch->descriptor() == compare )
 				{
 					return ch;
@@ -106,5 +103,5 @@
 			for ( auto ch : m_channels )
 			{
-				if ( ch->desc == compare )
+				if ( ch->descriptor() == compare )
 				{
 					return reinterpret_cast<VTX*>( ch->data );
Index: trunk/src/formats/assimp_loader.cc
===================================================================
--- trunk/src/formats/assimp_loader.cc	(revision 411)
+++ trunk/src/formats/assimp_loader.cc	(revision 412)
@@ -169,5 +169,5 @@
 	}
 
-	raw_data_channel* ichannel = raw_data_channel::create_index( USHORT, mesh->mNumFaces * 3 );
+	raw_data_channel* ichannel = raw_data_channel::create< index_u16 >( mesh->mNumFaces * 3 );
 	data->add_channel( ichannel );
 	uint16* indices = reinterpret_cast<uint16*>( ichannel->data );
@@ -317,5 +317,5 @@
 				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 )
+				for ( unsigned v = 0; v < channel->element_count(); ++v )
 				{
 					assimp_skinned_vtx& vertex = va[v];
Index: trunk/src/formats/md2_loader.cc
===================================================================
--- trunk/src/formats/md2_loader.cc	(revision 411)
+++ trunk/src/formats/md2_loader.cc	(revision 412)
@@ -357,5 +357,5 @@
 	}
 
-	raw_data_channel* ic = raw_data_channel::create_index< uint16 >( m_new_indexes.size() );
+	raw_data_channel* ic = raw_data_channel::create< index_u16 >( m_new_indexes.size() );
 	if ( m_new_indexes.size() > 0 )
 	{
Index: trunk/src/formats/md3_loader.cc
===================================================================
--- trunk/src/formats/md3_loader.cc	(revision 411)
+++ trunk/src/formats/md3_loader.cc	(revision 412)
@@ -354,5 +354,5 @@
 	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 ) );
+	raw_data_channel* ic = raw_data_channel::create< index_u16 >( 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 );
Index: trunk/src/formats/md5_loader.cc
===================================================================
--- trunk/src/formats/md5_loader.cc	(revision 411)
+++ trunk/src/formats/md5_loader.cc	(revision 412)
@@ -137,4 +137,5 @@
 			assert( m_type == MESH );
 			mesh_data* mesh = new mesh_data("md5_mesh");
+			raw_data_channel* ch_pntiw = nullptr;
 
 			uint32 num_verts   = 0;
@@ -161,10 +162,10 @@
 						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 );
+						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 );
 						mesh->add_channel( ch_t );
 						// TODO: hack to prevent rendering
-						ch_pntiw->count = 0;
+						//ch_pntiw->m_count = 0;
 						mesh->add_channel( ch_pntiw );
 					}
@@ -190,5 +191,5 @@
 					sstream >> num_tris;
 
-					raw_data_channel* ch_i = raw_data_channel::create_index<uint32>( num_tris * 3 );
+					raw_data_channel* ch_i = raw_data_channel::create<index_u32>( num_tris * 3 );
 					uint32* vtx_i                = reinterpret_cast< uint32* >( ch_i->data );
 					uint32 idx = 0;
@@ -234,5 +235,5 @@
 			}
 
-			prepare_mesh( nodes, weight_info.size(), mesh, weights.data(), weight_info.data() );
+			prepare_mesh( reinterpret_cast< md5_vtx_pntiw* >( ch_pntiw->data ), nodes, weight_info.size(), mesh, weights.data(), weight_info.data() );
 
 			m_meshes[ num_meshes ] = mesh;
@@ -333,9 +334,8 @@
 }
 
-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( md5_vtx_pntiw* vtx_data, mesh_node_data* nodes, uint32 vtx_count, mesh_data* mdata, md5_weight* weights, md5_weight_info* weight_info )
 {
 	assert( m_type == MESH );
 	md5_vtx_pnt* vtcs       = reinterpret_cast< md5_vtx_pnt* >( mdata->get_channel< md5_vtx_pnt >()->data ); 
-	md5_vtx_pntiw* vtx_data = reinterpret_cast< md5_vtx_pntiw* >( mdata->get_channel< md5_vtx_pntiw >()->data );
 
 	for ( uint32 i = 0; i < vtx_count; ++i )
@@ -486,5 +486,5 @@
 			const transform* ptv = reinterpret_cast< const transform* >( pjoint.data->get_channel(0)->data );
 			transform ptr;
-			if ( pjoint.data->get_channel(0)->count > index ) ptr = ptv[ index ];
+			if ( pjoint.data->get_channel(0)->element_count() > index ) ptr = ptv[ index ];
 			vec3 rot_pos = ptr.get_orientation() * pos;
 
Index: trunk/src/formats/nmd_loader.cc
===================================================================
--- trunk/src/formats/nmd_loader.cc	(revision 411)
+++ trunk/src/formats/nmd_loader.cc	(revision 412)
@@ -129,5 +129,5 @@
 				source.read( &cheader, sizeof( cheader ), 1 );
 				raw_data_channel* channel = raw_data_channel::create( cheader.format, cheader.count );
-				source.read( channel->data, channel->desc.element_size(), channel->count );
+				source.read( channel->data, channel->element_size(), channel->element_count() );
 				kdata->add_channel( channel );
 			}
@@ -168,5 +168,5 @@
 	{
 		size += sizeof( nmd_element_header ) + sizeof( nmd_stream_header );
-		size += chan->size();
+		size += chan->raw_size();
 	}
 
@@ -184,12 +184,12 @@
 		cheader.type     = nmd_type::STREAM;
 		cheader.children = 0;
-		cheader.size     = chan->size() + sizeof( nmd_stream_header );
+		cheader.size     = chan->raw_size() + sizeof( nmd_stream_header );
 		stream_out.write( &cheader, sizeof( cheader ), 1 );
 
 		nmd_stream_header sheader;
-		sheader.format = chan->desc;
-		sheader.count  = chan->count;
+		sheader.format = chan->descriptor();
+		sheader.count  = chan->element_count();
 		stream_out.write( &sheader, sizeof( sheader ), 1 );
-		stream_out.write( chan->data, chan->desc.element_size(), chan->count );
+		stream_out.write( chan->raw_data(), chan->element_size(), chan->element_count() );
 	}
 }
@@ -206,5 +206,5 @@
 			{
 				total += sizeof( nmd_element_header ) + sizeof( nmd_stream_header );
-				total += node->data->get_channel(c)->size();
+				total += node->data->get_channel(c)->raw_size();
 			}
 	}
@@ -231,5 +231,5 @@
 		{
 			chan_size += sizeof( nmd_element_header ) + sizeof( nv::nmd_stream_header );
-			chan_size += node->data->get_channel(c)->size();
+			chan_size += node->data->get_channel(c)->raw_size();
 		}
 
@@ -252,12 +252,12 @@
 			eheader.type     = nmd_type::KEY_CHANNEL;
 			eheader.children = 0;
-			eheader.size     = sizeof( nmd_stream_header ) + channel->size();
+			eheader.size     = sizeof( nmd_stream_header ) + channel->raw_size();
 			stream_out.write( &eheader, sizeof( eheader ), 1 );
 
 			nmd_stream_header cheader;
-			cheader.format    = channel->desc;
-			cheader.count     = channel->count;
+			cheader.format    = channel->descriptor();
+			cheader.count     = channel->element_count();
 			stream_out.write( &cheader, sizeof( cheader ), 1 );
-			stream_out.write( channel->data, channel->desc.element_size(), channel->count );
+			stream_out.write( channel->raw_data(), channel->element_size(), channel->element_count() );
 		}
 	}
Index: trunk/src/formats/obj_loader.cc
===================================================================
--- trunk/src/formats/obj_loader.cc	(revision 411)
+++ trunk/src/formats/obj_loader.cc	(revision 412)
@@ -324,15 +324,9 @@
 		}
 	
-		raw_data_channel* channel = new raw_data_channel();
-		nv::uint8* data = nullptr;
-
-		if ( reader->raw_size() > 0 ) 
-		{
-			data = new uint8[ reader->raw_size() ];
-			raw_copy_n( reader->raw_pointer(), reader->raw_size(), data );
-		}
-		channel->data  = data;
-		channel->desc  = m_descriptor;
-		channel->count = reader->size * 3;
+		raw_data_channel* channel = raw_data_channel::create( m_descriptor, reader->size * 3 );
+		if ( reader->raw_size() > 0 )
+		{
+			raw_copy_n( reader->raw_pointer(), reader->raw_size(), channel->data );
+		}
 
 		mesh_data* mesh = new mesh_data(reader->name);
Index: trunk/src/gfx/keyframed_mesh.cc
===================================================================
--- trunk/src/gfx/keyframed_mesh.cc	(revision 411)
+++ trunk/src/gfx/keyframed_mesh.cc	(revision 412)
@@ -23,6 +23,6 @@
 	, m_active( false )
 {
-	m_index_count  = m_mesh_data->get_index_channel()->count;
-	m_vertex_count = m_mesh_data->get_channel<vertex_t>()->count;
+	m_index_count  = m_mesh_data->get_index_channel()->element_count();
+	m_vertex_count = m_mesh_data->get_channel<vertex_t>()->element_count();
 	m_vchannel     = m_mesh_data->get_channel<vertex_pnt>();
 	m_vsize        = sizeof( vertex_pnt );
@@ -34,5 +34,5 @@
 		m_vsize        = sizeof( vertex_pn );
 	}
-	m_frame_count  = m_vchannel->count / m_vertex_count;
+	m_frame_count  = m_vchannel->element_count() / m_vertex_count;
 	m_pbuffer      = buffer();
 }
@@ -190,7 +190,8 @@
 	m_context->add_vertex_buffers( m_va, vb, m_mesh_data->get_channel<vertex_t>() );
 
-	buffer  ib = m_context->get_device()->create_buffer( INDEX_BUFFER, STATIC_DRAW, m_mesh_data->get_index_channel()->size(), m_mesh_data->get_index_channel()->data );
-
-	m_context->set_index_buffer( m_va, ib, m_mesh_data->get_index_channel()->desc[0].etype, true );
+	const raw_data_channel* index_channel = m_mesh_data->get_index_channel();
+	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_data = new uint8[ m_vertex_count * m_vsize ];
Index: trunk/src/gfx/mesh_creator.cc
===================================================================
--- trunk/src/gfx/mesh_creator.cc	(revision 411)
+++ trunk/src/gfx/mesh_creator.cc	(revision 412)
@@ -57,11 +57,11 @@
 			size_t chan_count = old_keys->get_channel_count();
 			if ( chan_count == 1 
-				&& old_keys->get_channel(0)->desc.slot_count() == 1 
-				&& old_keys->get_channel(0)->desc[0].etype == TRANSFORM ) continue;
+				&& old_keys->get_channel(0)->descriptor().slot_count() == 1 
+				&& old_keys->get_channel(0)->descriptor()[0].etype == TRANSFORM ) continue;
 
 			size_t max_keys = 0;
 			for ( size_t c = 0; c < chan_count; ++c )
 			{
-				max_keys = nv::max( max_keys, old_keys->get_channel(c)->count );
+				max_keys = nv::max( max_keys, old_keys->get_channel(c)->element_count() );
 			}
 
@@ -79,5 +79,5 @@
 				for ( uint16 c = 0; c < chan_count; ++c )
 				{
-					size_t idx = nv::min( old_keys->get_channel(c)->count - 1, n );
+					size_t idx = nv::min( old_keys->get_channel(c)->element_count() - 1, n );
 					pkey += old_keys->get_raw( old_keys->get_channel(c), idx, pkey );
 				}
@@ -107,8 +107,8 @@
 			{
 				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 )
-				{
-					transform_key_raw( channel->desc, channel->data + n * key_size, scale, r33, ri33 );
+				size_t key_size = channel->element_size();
+				for ( size_t n = 0; n < channel->element_count(); ++n )
+				{
+					transform_key_raw( channel->descriptor(), channel->data + n * key_size, scale, r33, ri33 );
 				}
 			}
@@ -126,5 +126,5 @@
 	{
 		const raw_data_channel* channel = m_data->get_channel(c);
-		const data_descriptor&  desc    = channel->desc;
+		const data_descriptor&  desc    = channel->descriptor();
 		uint8* raw_data = channel->data;
 		uint32 vtx_size = desc.element_size();
@@ -142,5 +142,5 @@
 
 		if ( p_offset != -1 )
-			for ( uint32 i = 0; i < channel->count; i++)
+			for ( uint32 i = 0; i < channel->element_count(); i++)
 			{
 				vec3& p = *reinterpret_cast<vec3*>( raw_data + vtx_size*i + p_offset );
@@ -149,5 +149,5 @@
 
 		if ( n_offset != -1 )
-			for ( uint32 i = 0; i < channel->count; i++)
+			for ( uint32 i = 0; i < channel->element_count(); i++)
 			{
 				vec3& n = *reinterpret_cast<vec3*>( raw_data + vtx_size*i + n_offset );
@@ -155,5 +155,5 @@
 			}
 		if ( t_offset != -1 )
-			for ( uint32 i = 0; i < channel->count; i++)
+			for ( uint32 i = 0; i < channel->element_count(); i++)
 			{
 				vec4& t = *reinterpret_cast<vec4*>(raw_data + vtx_size*i + t_offset );
@@ -174,5 +174,5 @@
 	if ( ch_n == -1 ) return;
 	raw_data_channel* channel = m_data->m_channels[ unsigned( ch_n ) ];
-	for ( const auto& cslot : channel->desc )
+	for ( const auto& cslot : channel->descriptor() )
 		if ( cslot.vslot == slot::NORMAL )
 		{
@@ -180,7 +180,7 @@
 		}
 
-	for ( uint32 i = 0; i < channel->count; ++i )
-	{
-		vec3& normal = *reinterpret_cast<vec3*>( channel->data + channel->desc.element_size() * i + n_offset );
+	for ( uint32 i = 0; i < channel->element_count(); ++i )
+	{
+		vec3& normal = *reinterpret_cast<vec3*>( channel->data + channel->element_size() * i + n_offset );
 		normal = -normal;
 	}
@@ -205,5 +205,5 @@
 		const raw_data_channel* channel = m_data->get_channel(c);
 
-		for ( const auto& cslot : channel->desc )
+		for ( const auto& cslot : channel->descriptor() )
 		switch ( cslot.vslot )
 		{
@@ -242,15 +242,17 @@
 	if ( !p_channel || !n_channel || !t_channel ) return;
 
-	if ( p_channel->count != n_channel->count || p_channel->count % t_channel->count != 0 || ( i_type != UINT && i_type != USHORT && i_type != NONE ) )
+	if ( p_channel->element_count() != n_channel->element_count() 
+		|| p_channel->element_count() % t_channel->element_count() != 0 
+		|| ( i_type != UINT && i_type != USHORT && i_type != NONE ) )
 	{
 		return;
 	}
 
-	raw_data_channel* g_channel = raw_data_channel::create<vertex_g>( p_channel->count );
+	raw_data_channel* g_channel = raw_data_channel::create<vertex_g>( p_channel->element_count() );
 	vec4* tangents              = reinterpret_cast<vec4*>( g_channel->data );
-	vec3* tangents2             = new vec3[ p_channel->count ];
-	uint32 tri_count = i_channel ? i_channel->count / 3 : t_channel->count / 3;
-	uint32 vtx_count = p_channel->count;
-	uint32 sets      = p_channel->count / t_channel->count;
+	vec3* tangents2             = new vec3[ p_channel->element_count() ];
+	uint32 tri_count = i_channel ? i_channel->element_count() / 3 : t_channel->element_count() / 3;
+	uint32 vtx_count = p_channel->element_count();
+	uint32 sets      = p_channel->element_count() / t_channel->element_count();
 
 	for ( unsigned int i = 0; i < tri_count; ++i )
@@ -280,7 +282,7 @@
 		}
 
-		const vec2& w1 = *reinterpret_cast<vec2*>(t_channel->data + t_channel->desc.element_size()*ti0 + t_offset );
-		const vec2& w2 = *reinterpret_cast<vec2*>(t_channel->data + t_channel->desc.element_size()*ti1 + t_offset );
-		const vec2& w3 = *reinterpret_cast<vec2*>(t_channel->data + t_channel->desc.element_size()*ti2 + t_offset );
+		const vec2& w1 = *reinterpret_cast<vec2*>(t_channel->data + t_channel->element_size()*ti0 + t_offset );
+		const vec2& w2 = *reinterpret_cast<vec2*>(t_channel->data + t_channel->element_size()*ti1 + t_offset );
+		const vec2& w3 = *reinterpret_cast<vec2*>(t_channel->data + t_channel->element_size()*ti2 + t_offset );
 		vec2 st1 = w3 - w1;
 		vec2 st2 = w2 - w1;
@@ -290,10 +292,10 @@
 		for ( uint32 set = 0; set < sets; ++set )
 		{
-			uint32 nti0 = t_channel->count * set + ti0;
-			uint32 nti1 = t_channel->count * set + ti1;
-			uint32 nti2 = t_channel->count * set + ti2;
-			vec3 v1 = *reinterpret_cast<vec3*>(p_channel->data + p_channel->desc.element_size()*nti0 + p_offset );
-			vec3 v2 = *reinterpret_cast<vec3*>(p_channel->data + p_channel->desc.element_size()*nti1 + p_offset );
-			vec3 v3 = *reinterpret_cast<vec3*>(p_channel->data + p_channel->desc.element_size()*nti2 + p_offset );
+			uint32 nti0 = t_channel->element_count() * set + ti0;
+			uint32 nti1 = t_channel->element_count() * set + ti1;
+			uint32 nti2 = t_channel->element_count() * set + ti2;
+			vec3 v1 = *reinterpret_cast<vec3*>(p_channel->data + p_channel->element_size()*nti0 + p_offset );
+			vec3 v2 = *reinterpret_cast<vec3*>(p_channel->data + p_channel->element_size()*nti1 + p_offset );
+			vec3 v3 = *reinterpret_cast<vec3*>(p_channel->data + p_channel->element_size()*nti2 + p_offset );
 			vec3 xyz1 = v3 - v1;
 			vec3 xyz2 = v2 - v1;
@@ -319,5 +321,5 @@
 	for ( unsigned int i = 0; i < vtx_count; ++i )
 	{
-		const vec3 n = *reinterpret_cast<vec3*>( n_channel->data + n_channel->desc.element_size()*i + n_offset );
+		const vec3 n = *reinterpret_cast<vec3*>( n_channel->data + n_channel->element_size()*i + n_offset );
 		const vec3 t = vec3(tangents[i]);
 		if ( ! ( t.x == 0.0f && t.y == 0.0f && t.z == 0.0f ) )
@@ -336,23 +338,18 @@
 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!" );
-	data_descriptor adesc = a->desc;
-	data_descriptor bdesc = b->desc;
-	uint32          count = a->count;
-
-	data_descriptor desc  = a->desc;
-	for ( auto bslot : bdesc )
-	{
-		desc.push_slot( bslot.etype, bslot.vslot );
-	}
-	uint8* data = new uint8[ count * desc.element_size() ];
-	for ( uint32 i = 0; i < count; ++i )
-	{
-		raw_copy_n( a->data + i * adesc.element_size(), adesc.element_size(), data + i*desc.element_size() );
-		raw_copy_n( b->data + i * bdesc.element_size(), bdesc.element_size(), data + i*desc.element_size() + adesc.element_size() );
-	}
+	NV_ASSERT( a->element_count() == b->element_count(), "merge_channel - bad channels!" );
+	data_descriptor desc  = a->descriptor();
+	desc.append( b->descriptor() );
+
+	uint8* data = new uint8[a->element_count() * desc.element_size() ];
+	for ( uint32 i = 0; i < a->element_count(); ++i )
+	{
+		raw_copy_n( a->data + i * a->element_size(), a->element_size(), data + i*desc.element_size() );
+		raw_copy_n( b->data + i * b->element_size(), b->element_size(), data + i*desc.element_size() + a->element_size() );
+	}
+
 	raw_data_channel* result = new raw_data_channel;
-	result->count = count;
-	result->desc  = desc;
+	result->m_count = a->element_count();
+	result->m_desc  = desc;
 	result->data  = data;
 	return result;
@@ -361,22 +358,22 @@
 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;
-	if ( a->count % frame_count != 0 ) return nullptr;
-	if ( b->count % frame_count != 0 ) return nullptr;
-	size_t vtx_size = a->desc.element_size();
-
-	uint8* data = new uint8[ ( a->count + b->count ) * vtx_size ];
+	if ( a->descriptor() != b->descriptor() ) return nullptr;
+	if ( a->element_count() % frame_count != 0 ) return nullptr;
+	if ( b->element_count() % frame_count != 0 ) return nullptr;
+	size_t vtx_size = a->element_size();
+
+	uint8* data = new uint8[ ( a->element_count() + b->element_count() ) * vtx_size ];
 	
 
 	if ( frame_count == 1 )
 	{
-		size_t a_size = vtx_size * a->count;
+		size_t a_size = vtx_size * a->element_count();
 		raw_copy_n( a->data, a_size, data );
-		raw_copy_n( b->data, vtx_size * b->count, data + a_size );
+		raw_copy_n( b->data, vtx_size * b->element_count(), data + a_size );
 	}
 	else
 	{
-		size_t frame_size_a = ( a->count / frame_count ) * vtx_size;
-		size_t frame_size_b = ( b->count / frame_count ) * vtx_size;
+		size_t frame_size_a = ( a->element_count() / frame_count ) * vtx_size;
+		size_t frame_size_b = ( b->element_count() / frame_count ) * vtx_size;
 		size_t pos_a = 0;
 		size_t pos_b = 0;
@@ -392,6 +389,6 @@
 
 	raw_data_channel* result = new raw_data_channel;
-	result->count = a->element_count() + b->element_count();
-	result->desc  = a->descriptor();
+	result->m_count = a->element_count() + b->element_count();
+	result->m_desc  = a->descriptor();
 	result->data  = data;
 	return result;
@@ -429,10 +426,11 @@
 	{
 		raw_data_channel* old = m_data->m_channels[c];
-		size_t frame_count = ( old->get_buffer_type() == INDEX_BUFFER ? 1 : old->element_count() / size );
+		bool old_is_index = old->element_count() > 0 && old->descriptor()[0].vslot == slot::INDEX;
+		size_t frame_count = ( old_is_index ? 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!" );
-		if ( old->get_buffer_type() == INDEX_BUFFER )
-		{
-			switch ( old->desc[0].etype )
+		if ( old_is_index )
+		{
+			switch ( old->descriptor()[0].etype )
 			{
 			case USHORT : 
Index: trunk/src/gfx/skeletal_mesh.cc
===================================================================
--- trunk/src/gfx/skeletal_mesh.cc	(revision 411)
+++ trunk/src/gfx/skeletal_mesh.cc	(revision 412)
@@ -13,8 +13,9 @@
 nv::skeletal_mesh_cpu::skeletal_mesh_cpu( context* a_context, const mesh_data* a_mesh_data, const mesh_nodes_data* bones )
 	: skeletal_mesh( a_context )
-	, m_data( a_mesh_data )
-{
-	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 );
+{
+	const raw_data_channel* pnt_chan   = a_mesh_data->get_channel<md5_vtx_pnt>();
+	const raw_data_channel* pntiw_chan = a_mesh_data->get_channel<md5_vtx_pntiw>();
+
+	m_pntdata.assign( reinterpret_cast<const md5_vtx_pnt*>( pnt_chan->data ), pnt_chan->element_count() );
 	m_bone_offset.resize( bones->get_count() );
 	m_transform.resize( bones->get_count() );
@@ -24,8 +25,29 @@
 		m_bone_offset[i] = transform( bones->get_node(i)->transform );
 	}
+
 	m_vtx_data  = a_mesh_data->get_channel_data<md5_vtx_pntiw>();
 	m_indices   = a_mesh_data->get_count();
-	m_va        = a_context->create_vertex_array( a_mesh_data, 
-STREAM_DRAW );
+	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];
+		if ( channel->element_count() > 0 && channel != pntiw_chan )
+		{
+			const data_descriptor& desc = channel->descriptor();
+			if ( desc[0].vslot == slot::INDEX )
+			{
+				buffer b = a_context->get_device()->create_buffer( INDEX_BUFFER, STREAM_DRAW, channel->raw_size(), channel->raw_data() );
+				a_context->set_index_buffer( m_va, b, desc[0].etype, true );
+			}
+			else
+			{
+				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 );
+			}
+		}
+	}
+
 	m_pbuffer   = a_context->find_buffer( m_va, slot::POSITION );
 }
