Index: /trunk/nv/gfx/animation.hh
===================================================================
--- /trunk/nv/gfx/animation.hh	(revision 417)
+++ /trunk/nv/gfx/animation.hh	(revision 418)
@@ -69,21 +69,21 @@
 		const data_descriptor& get_final_key() const { return m_final_key; }
 
-		static uint32 get_raw( const raw_data_channel* channel, uint32 index, float* result )
-		{
-			if ( channel->size() == 0 ) return 0;
-			uint32 keyfsize = channel->element_size() / 4;
-			const float* fdata = reinterpret_cast<const float*>( channel->raw_data() ) + keyfsize * index;
+		static uint32 get_raw( const raw_data_channel& channel, uint32 index, float* result )
+		{
+			if ( channel.size() == 0 ) return 0;
+			uint32 keyfsize = channel.element_size() / 4;
+			const float* fdata = reinterpret_cast<const float*>( channel.raw_data() ) + keyfsize * index;
 			uint32 mod = 0;
-			if ( channel->descriptor()[0].vslot == slot::TIME ) mod = 1;
+			if ( channel.descriptor()[0].vslot == slot::TIME ) mod = 1;
 			raw_copy_n( fdata + mod, keyfsize - mod, result );
 			return keyfsize - mod;
 		}
 
-		static uint32 interpolate_raw( const raw_data_channel* channel, float time, float* result )
-		{
-			if ( channel->size() == 0 ) return 0;
-			uint32 keyfsize = channel->element_size() / 4;
+		static uint32 interpolate_raw( const raw_data_channel& channel, float time, float* result )
+		{
+			if ( channel.size() == 0 ) return 0;
+			uint32 keyfsize = channel.element_size() / 4;
 			uint32 keyfresult = keyfsize;
-			const float* fdata = reinterpret_cast<const float*>( channel->raw_data() );
+			const float* fdata = reinterpret_cast<const float*>( channel.raw_data() );
 
 			uint32 slot = 0;
@@ -91,15 +91,15 @@
 			int index1 = -1;
 			float factor = 1.0f;
-			if ( channel->descriptor()[0].vslot == slot::TIME )
-			{
-				NV_ASSERT( channel->descriptor()[0].offset == 0, "time offset not zero!" );
+			if ( channel.descriptor()[0].vslot == slot::TIME )
+			{
+				NV_ASSERT( channel.descriptor()[0].offset == 0, "time offset not zero!" );
 				slot++;
 				keyfresult--;
-				if ( channel->size() == 1 )
+				if ( channel.size() == 1 )
 				{
 					raw_copy_n( fdata + 1, keyfresult, result );
 					return keyfresult;
 				}
-				for ( unsigned i = 1; i < channel->size(); i++ )
+				for ( unsigned i = 1; i < channel.size(); i++ )
 				{
 					if ( time < fdata[i * keyfsize] )
@@ -118,20 +118,20 @@
 			else
 			{
-				if ( channel->size() == 1 )
+				if ( channel.size() == 1 )
 				{
 					raw_copy_n( fdata, keyfresult, result );
 					return keyfresult;
 				}
-				index0 = glm::clamp<int>( int( time ), 0, int( channel->size() ) - 2 );
+				index0 = glm::clamp<int>( int( time ), 0, int( channel.size() ) - 2 );
 				index1 = index0 + 1;
 				factor = glm::clamp<float>( time - index0, 0.0f, 1.0f );
 			}
 			uint32 ret = 0;
-			for ( ; slot < channel->descriptor().size(); ++slot )
+			for ( ; slot < channel.descriptor().size(); ++slot )
 			{
 				ret += nv::interpolate_raw(
-					channel->descriptor()[slot], factor,
-					fdata + index0 * static_cast<int>( keyfsize ) + channel->descriptor()[slot].offset / 4,
-					fdata + index1 * static_cast<int>( keyfsize ) + channel->descriptor()[slot].offset / 4,
+					channel.descriptor()[slot], factor,
+					fdata + index0 * static_cast<int>( keyfsize ) + channel.descriptor()[slot].offset / 4,
+					fdata + index1 * static_cast<int>( keyfsize ) + channel.descriptor()[slot].offset / 4,
 					result + ret );
 			}
Index: /trunk/nv/gfx/mesh_creator.hh
===================================================================
--- /trunk/nv/gfx/mesh_creator.hh	(revision 417)
+++ /trunk/nv/gfx/mesh_creator.hh	(revision 418)
@@ -27,6 +27,6 @@
 		void merge( mesh_data* other );
 	private:
-		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 );
+		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;
Index: /trunk/nv/interface/context.hh
===================================================================
--- /trunk/nv/interface/context.hh	(revision 417)
+++ /trunk/nv/interface/context.hh	(revision 418)
@@ -300,18 +300,18 @@
 		{
 			vertex_array  va = create_vertex_array();
-			for ( auto channel : *data )
-			{
-				if ( channel->size() > 0 )
-				{
-					const data_descriptor& desc = channel->descriptor();
+			for ( auto& channel : *data )
+			{
+				if ( channel.size() > 0 )
+				{
+					const data_descriptor& desc = channel.descriptor();
 					// TODO: no if switch
 					if ( desc[0].vslot == slot::INDEX )
 					{
-						buffer b = m_device->create_buffer( INDEX_BUFFER, hint, channel->raw_size(), channel->raw_data() );
+						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() );
+						buffer b = m_device->create_buffer( VERTEX_BUFFER, hint, channel.raw_size(), channel.raw_data() );
 						add_vertex_buffers( va, b, desc );
 					}
Index: /trunk/nv/interface/data_channel.hh
===================================================================
--- /trunk/nv/interface/data_channel.hh	(revision 418)
+++ /trunk/nv/interface/data_channel.hh	(revision 418)
@@ -0,0 +1,184 @@
+// Copyright (C) 2012-2015 ChaosForge Ltd
+// http://chaosforge.org/
+//
+// This file is part of Nova libraries. 
+// For conditions of distribution and use, see copying.txt file in root folder.
+
+#ifndef NV_INTERFACE_DATA_CHANNEL_HH
+#define NV_INTERFACE_DATA_CHANNEL_HH
+
+#include <nv/common.hh>
+#include <nv/stl/vector.hh>
+#include <nv/interface/data_descriptor.hh>
+
+namespace nv
+{
+
+	struct raw_data_channel
+	{
+		raw_data_channel( raw_data_channel&& other )
+		{
+			m_data = other.m_data;
+			m_size = other.m_size;
+			m_desc = other.m_desc;
+			other.m_data = nullptr;
+			other.m_size = 0;
+		}
+
+		raw_data_channel& operator=( raw_data_channel&& other )
+		{
+			if ( this != &other )
+			{
+				if ( m_data != nullptr ) delete[] m_data;
+				m_data = other.m_data;
+				m_size = other.m_size;
+				m_desc = other.m_desc;
+				other.m_data = nullptr;
+				other.m_size = 0;
+			}
+			return *this;
+		}
+
+
+		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 ); }
+
+		~raw_data_channel()
+		{
+			if ( m_data != nullptr ) delete[] m_data;
+		}
+
+	protected:
+
+		template < typename Struct >
+		friend class data_channel_access;
+		friend class raw_data_channel_access;
+		friend class data_channel_creator;
+		friend class data_channel_set;
+		friend class key_channel_set_creator;
+
+		raw_data_channel() : m_data( nullptr ), m_size( 0 ) {}
+		raw_data_channel( const raw_data_channel& ) = delete;
+		raw_data_channel& operator=( const raw_data_channel& ) = delete;
+
+		uint8*          m_data;
+		uint32          m_size;
+		data_descriptor m_desc;
+	};
+
+	class data_channel_set
+	{
+	public:
+		friend class data_channel_set_creator;
+		friend class raw_data_channel_access;
+
+		typedef const raw_data_channel* const_iterator;
+
+		size_t size() const { return m_size; }
+
+		const raw_data_channel* get_channel( size_t index ) const
+		{
+			if ( m_size > index ) return &m_channels[index];
+			return nullptr;
+		}
+
+		const raw_data_channel* get_channel( slot s ) const
+		{
+			for ( uint32 c = 0; c < m_size; ++c )
+				if ( m_channels[c].has_slot( s ) )
+				return &m_channels[c];
+			return nullptr;
+		}
+
+		template < typename Struct >
+		const raw_data_channel* get_channel() const
+		{
+			data_descriptor compare;
+			compare.initialize<Struct>();
+			for ( uint32 c = 0; c < m_size; ++c )
+			{
+				if ( m_channels[c].descriptor() == compare )
+				{
+					return &m_channels[c];
+				}
+			}
+			return nullptr;
+		}
+
+		size_t get_channel_size( slot s ) const
+		{
+			const raw_data_channel* channel = get_channel( s );
+			return channel ? channel->size() : 0;
+		}
+
+		size_t get_channel_size( size_t channel ) const
+		{
+			if ( m_size > channel ) return m_channels[channel].size();
+			return 0;
+		}
+
+ 		template < typename Struct >
+		size_t get_channel_size() const
+		{
+			data_descriptor compare;
+			compare.initialize<Struct>();
+			for ( uint32 c = 0; c < m_size; ++c )
+			{
+				if ( m_channels[c].descriptor() == compare )
+				{
+					return m_channels[c].size();
+				}
+			}
+			return 0;
+		}
+
+		template < typename VTX >
+		const VTX* get_channel_data() const
+		{
+			data_descriptor compare;
+			compare.initialize<VTX>();
+			for ( uint32 c = 0; c < m_size; ++c )
+			{
+				if ( m_channels[c].descriptor() == compare )
+				{
+					return m_channels[c].data_cast<VTX>( );
+				}
+			}
+			return nullptr;
+		}
+
+		int get_channel_index( slot s ) const
+		{
+			for ( uint32 c = 0; c < m_size; ++c )
+				if ( m_channels[c].has_slot( s ) )
+				return int( c );
+			return -1;
+		}
+
+		const_iterator begin() const { return &m_channels[0]; }
+		const_iterator end()   const { return &m_channels[ m_size ]; }
+	protected:
+
+		data_channel_set()
+		{
+			m_size = 0;
+		}
+		raw_data_channel m_channels[4];
+		uint32 m_size;
+	};
+
+}
+
+#endif // NV_INTERFACE_DATA_CHANNEL_HH
Index: /trunk/nv/interface/data_channel_access.hh
===================================================================
--- /trunk/nv/interface/data_channel_access.hh	(revision 418)
+++ /trunk/nv/interface/data_channel_access.hh	(revision 418)
@@ -0,0 +1,216 @@
+// Copyright (C) 2012-2015 ChaosForge Ltd
+// http://chaosforge.org/
+//
+// This file is part of Nova libraries. 
+// For conditions of distribution and use, see copying.txt file in root folder.
+
+#ifndef NV_INTERFACE_DATA_CHANNEL_ACCESS_HH
+#define NV_INTERFACE_DATA_CHANNEL_ACCESS_HH
+
+#include <nv/common.hh>
+#include <nv/interface/data_channel.hh>
+#include <nv/gfx/animation.hh> // TODO: remove, key creator separate file?
+
+namespace nv
+{
+
+
+	class raw_data_channel_access
+	{
+	public:
+		explicit raw_data_channel_access( raw_data_channel* channel )
+		{
+			m_channel = channel;
+		}
+
+		raw_data_channel_access( data_channel_set* set, uint32 index )
+		{
+			m_channel = &set->m_channels[index];
+		}
+
+		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; }
+	protected:
+		raw_data_channel* m_channel;
+	};
+
+	template < typename Struct >
+	class data_channel_access : public raw_data_channel_access
+	{
+	public:
+
+		// TODO - descriptor check
+		explicit data_channel_access( raw_data_channel* channel )
+			: raw_data_channel_access( channel )
+		{
+		}
+		data_channel_access( data_channel_set* set, uint32 index )
+			: raw_data_channel_access( set, index )
+		{
+		}
+
+		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];
+		}
+	};
+
+	class data_channel_creator
+	{
+	public:
+		template< typename Struct >
+		static raw_data_channel create( uint32 size )
+		{
+			raw_data_channel channel;
+			channel.m_desc = data_descriptor::create< Struct >();
+			channel.m_size = size;
+			channel.m_data = ( size > 0 ? ( new uint8[channel.raw_size()] ) : nullptr );
+			return channel;
+		}
+
+		static raw_data_channel create( const data_descriptor& desc, uint32 size )
+		{
+			raw_data_channel channel;
+			channel.m_desc = desc;
+			channel.m_size = size;
+			channel.m_data = ( size > 0 ? ( new uint8[channel.raw_size()] ) : nullptr );
+			return channel;
+		}
+	};
+
+
+	class data_channel_set_creator
+	{
+		typedef data_channel_set::const_iterator const_iterator;
+	public:
+
+		static data_channel_set* create( size_t )
+		{
+			return new data_channel_set;
+		}
+
+		static data_channel_set* create_array( size_t size, size_t )
+		{
+			return new data_channel_set[ size ];
+		}
+
+		explicit data_channel_set_creator( data_channel_set* set ) : m_set( set ) {}
+
+		void set_channel( uint32 i, raw_data_channel&& channel )
+		{
+			m_set->m_channels[i] = move( channel );
+		}
+
+		template < typename Struct >
+		data_channel_access< Struct > add_channel( uint32 size )
+		{
+			raw_data_channel channel = data_channel_creator::create( data_descriptor::create< Struct >(), size );
+			uint32 index = m_set->m_size;
+			m_set->m_channels[index] = move( channel );
+			m_set->m_size++;
+			return data_channel_access< Struct >( &m_set->m_channels[index] );
+		}
+		
+		raw_data_channel_access add_channel( const data_descriptor& desc, uint32 size )
+		{
+			raw_data_channel channel = data_channel_creator::create( desc, size );
+			uint32 index = m_set->m_size;
+			m_set->m_channels[index] = move( channel );
+			m_set->m_size++;
+			return raw_data_channel_access( &m_set->m_channels[ index ] );
+		}
+
+		raw_data_channel* operator []( uint32 i ) const { return &m_set->m_channels[i]; }
+		const_iterator begin() const { return m_set->begin(); }
+		const_iterator end()   const { return m_set->end(); }
+
+		void set_name( const char* /*name*/ ) {}// { m_name = name; }
+													   //const std::string& get_name() const { return m_name; }
+
+		void move_to( data_channel_set& other )
+		{
+			//			other.m_name          = m_name;
+			for ( uint32 c = 0; c < m_set->m_size; ++c )
+			{
+//				if ( other.m_channels[c] ) delete other.m_channels[c];
+				other.m_channels[c] = move( m_set->m_channels[c] );
+			}
+			other.m_size = m_set->m_size;
+			m_set->m_size = 0;
+		}
+
+	protected:
+		data_channel_set* m_set;
+	};
+
+
+	class key_channel_set_creator
+	{
+		typedef data_channel_set::const_iterator const_iterator;
+	public:
+
+		static key_channel_set* create( size_t )
+		{
+			return new key_channel_set;
+		}
+
+		static key_channel_set* create_array( size_t size, size_t )
+		{
+			return new key_channel_set[size];
+		}
+
+		explicit key_channel_set_creator( key_channel_set* set ) : m_set( set ) {}
+
+		template < typename Struct >
+		data_channel_access< Struct > add_channel( uint32 size )
+		{
+			raw_data_channel channel = data_channel_creator::create( data_descriptor::create< Struct >(), size );
+			for ( const auto& cslot : channel.descriptor() )
+				if ( cslot.vslot != slot::TIME )
+				m_set->m_final_key.push_slot( cslot.etype, cslot.vslot );
+			uint32 index = m_set->m_size;
+			m_set->m_channels[index] = move( channel );
+			m_set->m_size++;
+			return data_channel_access< Struct >( &m_set->m_channels[index] );
+		}
+
+		raw_data_channel_access add_channel( const data_descriptor& desc, uint32 size )
+		{
+			raw_data_channel channel = data_channel_creator::create( desc, size );
+			for ( const auto& cslot : channel.descriptor() )
+				if ( cslot.vslot != slot::TIME )
+				m_set->m_final_key.push_slot( cslot.etype, cslot.vslot );
+			uint32 index = m_set->m_size;
+			m_set->m_channels[index] = move( channel );
+			m_set->m_size++;
+			return raw_data_channel_access( &m_set->m_channels[index] );
+		}
+
+		const raw_data_channel* operator []( uint32 i ) const { return &m_set->m_channels[i]; }
+		const_iterator begin() const { return m_set->begin(); }
+		const_iterator end()   const { return m_set->end(); }
+
+	protected:
+		key_channel_set* m_set;
+	};
+
+}
+
+#endif // NV_INTERFACE_DATA_CHANNEL_ACCESS_HH
Index: /trunk/src/formats/nmd_loader.cc
===================================================================
--- /trunk/src/formats/nmd_loader.cc	(revision 417)
+++ /trunk/src/formats/nmd_loader.cc	(revision 418)
@@ -164,8 +164,8 @@
 {
 	uint32 size = sizeof( nmd_element_header );
-	for ( auto chan : *mesh )
+	for ( auto& chan : *mesh )
 	{
 		size += sizeof( nmd_element_header ) + sizeof( nmd_stream_header );
-		size += chan->raw_size();
+		size += chan.raw_size();
 	}
 
@@ -177,5 +177,5 @@
 	stream_out.write( &eheader, sizeof( eheader ), 1 );
 
-	for ( auto chan : *mesh )
+	for ( auto& chan : *mesh )
 	{
 		nmd_element_header cheader;
@@ -183,12 +183,12 @@
 		cheader.type     = nmd_type::STREAM;
 		cheader.children = 0;
-		cheader.size     = chan->raw_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->descriptor();
-		sheader.count  = chan->size();
+		sheader.format = chan.descriptor();
+		sheader.count  = chan.size();
 		stream_out.write( &sheader, sizeof( sheader ), 1 );
-		stream_out.write( chan->raw_data(), chan->element_size(), chan->size() );
+		stream_out.write( chan.raw_data(), chan.element_size(), chan.size() );
 	}
 }
Index: /trunk/src/gfx/mesh_creator.cc
===================================================================
--- /trunk/src/gfx/mesh_creator.cc	(revision 417)
+++ /trunk/src/gfx/mesh_creator.cc	(revision 418)
@@ -82,6 +82,6 @@
 				for ( uint16 c = 0; c < chan_count; ++c )
 				{
-					size_t idx = nv::min( old_keys->get_channel(c)->size() - 1, n );
-					pkey += old_keys->get_raw( old_keys->get_channel(c), idx, pkey );
+					size_t idx = nv::min( old_keys->get_channel_size(c) - 1, n );
+					pkey += old_keys->get_raw( *old_keys->get_channel(c), idx, pkey );
 				}
 				kt_channel.data()[n].tform = extract_transform_raw( final_key, key );
@@ -252,6 +252,6 @@
 	}
 
-	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 );
+	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;
@@ -334,19 +334,18 @@
 	delete tangents2;
 
-	data_channel_set_creator( m_data ).set_channel( n_channel_index, merge_channels( n_channel, g_channel ) );
-	delete g_channel;
-}
-
-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!" );
-	data_descriptor desc  = a->descriptor();
-	desc.append( b->descriptor() );
-
-	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(), 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() );
+	data_channel_set_creator( m_data ).set_channel( n_channel_index, merge_channels( *n_channel, g_channel ) );
+}
+
+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!" );
+	data_descriptor desc  = a.descriptor();
+	desc.append( b.descriptor() );
+
+	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(), 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() );
 	}
 
@@ -354,24 +353,24 @@
 }
 
-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;
-	if ( a->size() % frame_count != 0 ) return nullptr;
-	if ( b->size() % frame_count != 0 ) return nullptr;
-	size_t vtx_size = a->element_size();
-
-	raw_data_channel* result = data_channel_creator::create( a->descriptor(), a->size() + b->size() );
-	uint8* rdata = raw_data_channel_access( result ).raw_data();
+nv::raw_data_channel nv::mesh_data_creator::append_channels( const raw_data_channel& a, const raw_data_channel& b, uint32 frame_count )
+{
+	NV_ASSERT( a.descriptor() == b.descriptor(), "Merge - append not compatible format!" );
+	NV_ASSERT( a.size() % frame_count == 0, "Merge - append first mesh empty!" );
+	NV_ASSERT( b.size() % frame_count == 0, "Merge - append second mesh empty!" );
+	size_t vtx_size = a.element_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, rdata );
-		raw_copy_n( b->raw_data(), vtx_size * b->size(), rdata + a_size );
+		size_t a_size = vtx_size * 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
 	{
-		size_t frame_size_a = ( a->size() / frame_count ) * vtx_size;
-		size_t frame_size_b = ( b->size() / frame_count ) * vtx_size;
+		size_t frame_size_a = ( a.size() / frame_count ) * vtx_size;
+		size_t frame_size_b = ( b.size() / frame_count ) * vtx_size;
 		size_t pos_a = 0;
 		size_t pos_b = 0;
@@ -379,6 +378,6 @@
 		for ( size_t i = 0; i < frame_count; ++i )
 		{
-			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;
+			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;
@@ -422,11 +421,12 @@
 	{
 		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 );
-		data.set_channel( c, append_channels( old, other->get_channel(c), frame_count ) );
-		NV_ASSERT( data[c], "Merge problem!" );
+		uint32 old_size = old->size();
+		data_descriptor old_desc = old->descriptor();
+		bool old_is_index = old_size > 0 && old_desc[0].vslot == slot::INDEX;
+		size_t frame_count = ( old_is_index ? 1 : old_size / size );
+		data.set_channel( c, append_channels( *old, *other->get_channel(c), frame_count ) );
 		if ( old_is_index )
 		{
-			switch ( old->descriptor()[0].etype )
+			switch ( old_desc[0].etype )
 			{
 			case USHORT : 
@@ -435,5 +435,5 @@
 					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 )
+					for ( uint16 i = uint16( old_size ); i < ic.size(); ++i )
 						indexes[i] += uint16( size );
 
@@ -444,5 +444,5 @@
 					raw_data_channel_access ic( data[c] );
 					uint32* indexes = reinterpret_cast<uint32*>( ic.raw_data() );
-					for ( uint32 i = old->size(); i < ic.size(); ++i )
+					for ( uint32 i = old_size; i < ic.size(); ++i )
 						indexes[i] += size;
 				}
@@ -451,5 +451,4 @@
 			}
 		}
-		delete old;
 	}
 }
@@ -459,5 +458,4 @@
 	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 417)
+++ /trunk/src/gfx/skeletal_mesh.cc	(revision 418)
@@ -31,18 +31,18 @@
 
 	//array_view< raw_data_channel* > channels = a_mesh_data->get_raw_channels();
-	for ( auto channel : *a_mesh_data )
+	for ( auto& channel : *a_mesh_data )
 	{
 		//const raw_data_channel* channel = channels[ch];
-		if ( channel->size() > 0 && channel != pntiw_chan )
-		{
-			const data_descriptor& desc = channel->descriptor();
+		if ( channel.size() > 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() );
+				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() );
+				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, desc );
 			}
