Index: trunk/src/formats/assimp_loader.cc
===================================================================
--- trunk/src/formats/assimp_loader.cc	(revision 425)
+++ trunk/src/formats/assimp_loader.cc	(revision 427)
@@ -190,5 +190,5 @@
 }
 
-bool nv::assimp_loader::load_bones( size_t index, array_ref< mesh_node_data > bones )
+bool nv::assimp_loader::load_bones( size_t index, array_ref< data_channel_set* > bones )
 {
 	if ( m_scene == nullptr ) return false;
@@ -200,6 +200,6 @@
 		aiBone* bone   = mesh->mBones[m];
 		mat4    offset = assimp_mat4_cast( bone->mOffsetMatrix );
-		bones[m].data = data_channel_set_creator::create_set( 0 );
-		data_channel_set_creator access( bones[m].data );
+		bones[m] = data_channel_set_creator::create_set( 0 );
+		data_channel_set_creator access( bones[m] );
 		const char* name = bone->mName.data;
 		access.set_name( make_name( name ) );
@@ -287,10 +287,10 @@
 {
 	const aiScene* scene = reinterpret_cast<const aiScene*>( m_scene );
-	vector< mesh_node_data > final_bones;
+	mesh_nodes_data* result = new mesh_nodes_data( make_name( "bones" ) );
 	unordered_map< uint64, uint16 > names;
 	for ( unsigned int m = 0; m < m_mesh_count; ++m )
 	{
 		uint16 translate[MAX_BONES];
-		vector< mesh_node_data > bones;
+		vector< data_channel_set* > bones;
 		const aiMesh*  mesh  = scene->mMeshes[ m ];
 		if ( mesh->mNumBones != 0 )
@@ -301,12 +301,12 @@
 			{
 
-				mesh_node_data& bone = bones[b];
-				auto iname = names.find( bone.data->get_name() );
+				data_channel_set* bone = bones[b];
+				auto iname = names.find( bone->get_name() );
 				if ( iname == names.end() )
 				{
-					NV_ASSERT( final_bones.size() < MAX_BONES, "Too many bones to merge!" );
-					uint16 index = uint16( final_bones.size() );
-					final_bones.push_back( bone );
-					names[ bone.data->get_name() ] = index;
+					NV_ASSERT( result->get_count() < MAX_BONES, "Too many bones to merge!" );
+					uint16 index = uint16( result->get_count() );
+					result->push_back( bone );
+					names[ bone->get_name() ] = index;
 					translate[b] = index;
 				}
@@ -334,7 +334,6 @@
 		}	
 	}
-	mesh_node_data* bones = new mesh_node_data[ final_bones.size() ];
-	raw_copy( final_bones.begin(), final_bones.end(), bones );
-	return new mesh_nodes_data( make_name( "bones" ), final_bones.size(), bones );
+
+	return result;
 }
 
@@ -349,5 +348,4 @@
 
 	uint32 count = count_nodes( scene->mRootNode );
-	mesh_node_data* data    = new mesh_node_data[count];
 
 	uint16 frame_rate     = static_cast<uint16>( anim->mTicksPerSecond );
@@ -355,7 +353,15 @@
 	bool   flat           = false;
 
-	load_node( index, data, root, 0, -1 );
-
-	return new mesh_nodes_data( make_name( static_cast<const char*>( anim->mName.data ) ), count, data, frame_rate, duration, flat );
+	data_channel_set** temp = new data_channel_set*[ count ];
+	array_ref< data_channel_set* > temp_ref( temp, count );
+	load_node( index, temp_ref, root, 0, -1 );
+
+	mesh_nodes_data* result = new mesh_nodes_data( make_name( static_cast<const char*>( anim->mName.data ) ), frame_rate, duration, flat );
+	for ( auto set : temp_ref )
+	{
+		result->push_back( set );
+	}
+	delete temp;
+	return result;
 }
 
@@ -371,5 +377,5 @@
 }
 
-nv::sint16 nv::assimp_loader::load_node( uint32 anim_id, mesh_node_data* nodes, const void* vnode, sint16 this_id, sint16 parent_id )
+nv::sint16 nv::assimp_loader::load_node( uint32 anim_id, array_ref< data_channel_set* > nodes, const void* vnode, sint16 this_id, sint16 parent_id )
 {
 	const aiScene* scene = reinterpret_cast<const aiScene*>( m_scene );
@@ -386,12 +392,7 @@
 	}
 
-	mesh_node_data& a_data = nodes[ this_id ];
-
-	if (anode) 
-		create_keys( &a_data, anode );
-	else
-		a_data.data = data_channel_set_creator::create_set( 0 );
-
-	data_channel_set_creator access( a_data.data );
+	nodes[ this_id ] = anode ? create_keys( anode ) : data_channel_set_creator::create_set( 0 );
+
+	data_channel_set_creator access( nodes[this_id] );
 	access.set_name( make_name( name ) );
 	access.set_parent_id( parent_id );
@@ -412,14 +413,14 @@
 }
 
-void nv::assimp_loader::create_keys( mesh_node_data* data, const void* vnode )
+data_channel_set* nv::assimp_loader::create_keys( const void* vnode )
 {
 	const aiNodeAnim* node = reinterpret_cast< const aiNodeAnim* >( vnode );
 	if ( node->mNumPositionKeys == 0 && node->mNumRotationKeys == 0 && node->mNumScalingKeys == 0 )
 	{
-		return;
-	}
-
-	data->data = data_channel_set_creator::create_set( 2 );
-	data_channel_set_creator key_set( data->data );
+		return data_channel_set_creator::create_set( 0 );
+	}
+	
+	data_channel_set* set = data_channel_set_creator::create_set( 2 );
+	data_channel_set_creator key_set( set );
 
 	assimp_key_p* pchannel = key_set.add_channel< assimp_key_p >( node->mNumPositionKeys ).data();
@@ -456,5 +457,5 @@
 // 		}
 // 	}
-
+	return set;
 }
 
Index: trunk/src/formats/md3_loader.cc
===================================================================
--- trunk/src/formats/md3_loader.cc	(revision 425)
+++ trunk/src/formats/md3_loader.cc	(revision 427)
@@ -420,15 +420,16 @@
 	uint32 node_count = uint32( md3->header.num_tags );
 	if ( node_count == 0 ) return nullptr;
-	mesh_node_data* nodes = new mesh_node_data[ node_count ];
+	mesh_nodes_data* result = new mesh_nodes_data( m_strings ? m_strings->insert( "tags" ) : 0 );
 	for ( uint32 i = 0; i < node_count; ++i )
 	{
 		const md3_tag_t& rtag = md3->tags[i];
 		string_view name( reinterpret_cast< const char* >(rtag.name) );
-		nodes[i].data      = data_channel_set_creator::create_set( 1 );
-		data_channel_set_creator access( nodes[i].data );
+		data_channel_set* set = data_channel_set_creator::create_set( 1 );
+		data_channel_set_creator access( set );
 		access.set_name( make_name( name ) );
 		load_tags( access.add_channel<md3_key>( uint32( md3->header.num_frames ) ).channel(), name );
-	}
-	return new mesh_nodes_data( m_strings ? m_strings->insert( "tags" ) : 0, node_count, nodes );
+		result->push_back( set );
+	}
+	return result;
 }
 
Index: trunk/src/formats/md5_loader.cc
===================================================================
--- trunk/src/formats/md5_loader.cc	(revision 425)
+++ trunk/src/formats/md5_loader.cc	(revision 427)
@@ -46,5 +46,4 @@
 	std_stream sstream( &source );
 	std::string command;
-	mesh_node_data* nodes = nullptr;
 	size_t num_joints = 0;
 
@@ -111,6 +110,5 @@
 			assert( m_type == MESH );
 			assert( m_nodes == nullptr );
-			nodes = new mesh_node_data[ num_joints ];
-			m_nodes = new mesh_nodes_data( make_name( "md5_bones"), num_joints, nodes );
+			m_nodes = new mesh_nodes_data( make_name( "md5_bones") );
 			discard( sstream, "{" );
 			for ( size_t i = 0; i < m_nodes->get_count(); ++i )
@@ -128,10 +126,11 @@
 				unit_quat_w( orient );
 				remove_quotes( name );
-				nodes[i].data       = data_channel_set_creator::create_set( 0 );
-				data_channel_set_creator access( nodes[i].data );
+				data_channel_set* set = data_channel_set_creator::create_set( 0 );
+				data_channel_set_creator access( set );
 				access.set_parent_id( parent_id );
 				access.set_transform( transform( pos, orient ).inverse().extract() );
 				access.set_name( make_name( name.c_str() ) );
 				next_line( sstream );
+				m_nodes->push_back( set );
 			}
 			discard( sstream, "}" );
@@ -233,5 +232,5 @@
 			}
 
-			prepare_mesh( nodes, weight_info.size(), mesh, weights.data(), weight_info.data() );
+			prepare_mesh( m_nodes, weight_info.size(), mesh, weights.data(), weight_info.data() );
 
 			m_meshes[ num_meshes ] = mesh;
@@ -241,7 +240,6 @@
 		{
 			assert( m_type == ANIMATION );
-			assert( nodes == nullptr );
-			nodes = new mesh_node_data[ num_joints ];
-			m_nodes = new mesh_nodes_data( make_name( "md5_animation" ), num_joints, nodes, static_cast< nv::uint16 >( frame_rate ), static_cast< float >( num_frames ), true );
+			assert( m_nodes == nullptr );
+			m_nodes = new mesh_nodes_data( make_name( "md5_animation" ), static_cast< nv::uint16 >( frame_rate ), static_cast< float >( num_frames ), true );
 			joint_infos.resize( num_joints );
 
@@ -253,9 +251,10 @@
 				sstream >> name >> parent_id >> joint_infos[i].flags >> joint_infos[i].start_index;
 				remove_quotes( name );
-				nodes[i].data = data_channel_set_creator::create_set( 1 );
-				data_channel_set_creator access( nodes[i].data );
+				data_channel_set* set = data_channel_set_creator::create_set( 1 );
+				data_channel_set_creator access( set );
 				access.add_channel< md5_key_t >( num_frames );
 				access.set_name( make_name( name.c_str() ) );
 				access.set_parent_id( parent_id );
+				m_nodes->push_back( set );
 				next_line( sstream );
 			}
@@ -322,5 +321,5 @@
 			}
 
-			build_frame_skeleton( nodes, frame_id, joint_infos, base_frames, frame );
+			build_frame_skeleton( m_nodes, frame_id, joint_infos, base_frames, frame );
 
 			discard( sstream, "}" );
@@ -334,5 +333,5 @@
 }
 
-bool md5_loader::prepare_mesh( mesh_node_data* nodes, uint32 vtx_count, data_channel_set* mdata, md5_weight* weights, md5_weight_info* weight_info )
+bool md5_loader::prepare_mesh( mesh_nodes_data* nodes, uint32 vtx_count, data_channel_set* mdata, md5_weight* weights, md5_weight_info* weight_info )
 {
 	assert( m_type == MESH );
@@ -389,7 +388,7 @@
 			if ( j < weight_count )
 			{
-				md5_weight& weight           = weights[start_weight + j];
-				const mesh_node_data&  joint = nodes[weight.joint_id];
-				const transform tr = transform( joint.data->get_transform() ).inverse();
+				md5_weight& weight             = weights[start_weight + j];
+				const data_channel_set*  joint = (*nodes)[weight.joint_id];
+				const transform tr = transform( joint->get_transform() ).inverse();
 				vec3 rot_pos = tr.get_orientation() * weight.pos;
 
@@ -453,6 +452,6 @@
  		for ( int j = 0; j < 4; ++j )
  		{
-			const mesh_node_data&  joint = nodes[vdata.boneindex[j]];
-			const transform tr = transform( joint.data->get_transform() ).inverse();
+			const data_channel_set*  joint = ( *nodes )[vdata.boneindex[j]];
+			const transform tr = transform( joint->get_transform() ).inverse();
  			vdata.normal  += ( normal  * tr.get_orientation() ) * vdata.boneweight[j];
  			vdata.tangent += ( tangent * tr.get_orientation() ) * vdata.boneweight[j];
@@ -463,5 +462,5 @@
 }
 
-void md5_loader::build_frame_skeleton( mesh_node_data* nodes, uint32 index, const array_view<md5_joint_info>& joint_infos, const array_view<transform>& base_frames, const array_view<float>& frame_data )
+void md5_loader::build_frame_skeleton( mesh_nodes_data* nodes, uint32 index, const array_view<md5_joint_info>& joint_infos, const array_view<transform>& base_frames, const array_view<float>& frame_data )
 {
 	assert( m_type == ANIMATION );
@@ -471,6 +470,6 @@
 
 		const md5_joint_info& jinfo = joint_infos[i];
-		mesh_node_data& joint = nodes[i];
-		int parent_id         = joint.data->get_parent_id();
+		const data_channel_set* joint = (*nodes)[i];
+		int parent_id         = joint->get_parent_id();
 
 		vec3 pos    = base_frames[i].get_position();
@@ -486,8 +485,8 @@
 		if ( parent_id >= 0 ) // Has a parent joint
 		{
-			const mesh_node_data& pjoint = nodes[parent_id];
-			const transform* ptv = reinterpret_cast< const transform* >( pjoint.data->get_channel(0)->raw_data() );
+			const data_channel_set* pjoint = ( *nodes )[i];
+			const transform* ptv = reinterpret_cast< const transform* >( pjoint->get_channel(0)->raw_data() );
 			transform ptr;
-			if ( pjoint.data->get_channel(0)->size() > index ) ptr = ptv[ index ];
+			if ( pjoint->get_channel(0)->size() > index ) ptr = ptv[ index ];
 			vec3 rot_pos = ptr.get_orientation() * pos;
 
@@ -498,5 +497,5 @@
 		}
 
-		reinterpret_cast< transform* >( const_cast< uint8* >( joint.data->get_channel(0)->raw_data() ) )[index] = transform( pos, orient );
+		reinterpret_cast< transform* >( const_cast< uint8* >( joint->get_channel(0)->raw_data() ) )[index] = transform( pos, orient );
 	}
 }
Index: trunk/src/formats/nmd_loader.cc
===================================================================
--- trunk/src/formats/nmd_loader.cc	(revision 425)
+++ trunk/src/formats/nmd_loader.cc	(revision 427)
@@ -71,5 +71,4 @@
 
 	m_node_data  = nullptr;
-	m_node_array = nullptr;
 }
 
@@ -100,5 +99,5 @@
 	nmd_animation_header animation_header;
 	source.read( &animation_header, sizeof( animation_header ), 1 );
-	m_node_array = new mesh_node_data[ e.children ];
+	m_node_data = new mesh_nodes_data( e.name, animation_header.frame_rate, animation_header.duration, animation_header.flat );
 	for ( uint32 i = 0; i < e.children; ++i )
 	{
@@ -107,8 +106,8 @@
 		skip_attributes( source, element_header.attributes );
 		NV_ASSERT( element_header.type == nmd_type::NODE, "NODE expected!" );
-		m_node_array[i].data = data_channel_set_creator::create_set( element_header.children );
-		load_channel_set( source, m_node_array[i].data, element_header );
-	}
-	m_node_data = new mesh_nodes_data( e.name, e.children, m_node_array, animation_header.frame_rate, animation_header.duration, animation_header.flat );
+		data_channel_set* set = data_channel_set_creator::create_set( element_header.children );
+		load_channel_set( source, set, element_header );
+		m_node_data->push_back( set );
+	}
 	return true;
 }
@@ -144,5 +143,4 @@
 		mesh_nodes_data* result = m_node_data;
 		m_node_data = nullptr;
-		m_node_array = nullptr;
 		return result;
 	}
@@ -153,42 +151,4 @@
 // nmd format dump
 // HACK : TEMPORARY - will go to it's own file, probably nmd_io
-static void nmd_dump_channel( const raw_data_channel* channel , stream& stream_out )
-{
-	nmd_channel_header sheader;
-	sheader.format = channel->descriptor();
-	sheader.count = channel->size();
-	stream_out.write( &sheader, sizeof( sheader ), 1 );
-	stream_out.write( channel->raw_data(), channel->element_size(), channel->size() );
-}
-
-static void nmd_dump_channel_set( const data_channel_set* channel_set, stream& stream_out )
-{
-	for ( auto& channel : *channel_set )
-	{
-		nmd_dump_channel( &channel, stream_out );
-	}
-}
-
-static void nmd_dump_node( const mesh_node_data* node, stream& stream_out )
-{
-	uint32 chan_size = 0;
-	uint32 chan_count = ( node->data ? node->data->size() : 0 );
-	for ( uint32 c = 0; c < chan_count; ++c )
-	{
-		chan_size += sizeof( nmd_channel_header );
-		chan_size += node->data->get_channel( c )->raw_size();
-	}
-
-	nmd_element_header eheader;
-	eheader.type = nmd_type::NODE;
-	eheader.children   = static_cast<uint16>( chan_count );
-	eheader.size       = chan_size;
-	eheader.name       = node->data->get_name();
-	eheader.parent_id  = node->data->get_parent_id();
-	eheader.transform  = node->data->get_transform();
-	eheader.attributes = 0;
-	stream_out.write( &eheader, sizeof( eheader ), 1 );
-	if ( chan_count > 0 ) nmd_dump_channel_set( node->data, stream_out );
-}
 
 void nv::nmd_dump_header( stream& stream_out, uint32 elements, uint64 name )
@@ -203,8 +163,8 @@
 }
 
-void nv::nmd_dump_mesh( stream& stream_out, const data_channel_set& mesh )
+void nv::nmd_dump_element( stream& stream_out, const data_channel_set& data, nmd_type type )
 {
 	uint32 size = 0;
-	for ( auto& chan : mesh )
+	for ( auto& chan : data )
 	{
 		size += sizeof( nmd_channel_header );
@@ -213,13 +173,20 @@
 
 	nmd_element_header eheader;
-	eheader.type       = nmd_type::MESH;
-	eheader.children   = static_cast<uint16>( mesh.size() );
+	eheader.type       = type;
+	eheader.children   = static_cast<uint16>( data.size() );
 	eheader.size       = size;
-	eheader.name       = mesh.get_name();
-	eheader.transform  = mesh.get_transform();
-	eheader.parent_id  = mesh.get_parent_id();
+	eheader.name       = data.get_name();
+	eheader.transform  = data.get_transform();
+	eheader.parent_id  = data.get_parent_id();
 	eheader.attributes = 0;
 	stream_out.write( &eheader, sizeof( eheader ), 1 );
-	nmd_dump_channel_set( &mesh, stream_out );
+	for ( auto& channel : data )
+	{
+		nmd_channel_header cheader;
+		cheader.format = channel.descriptor();
+		cheader.count = channel.size();
+		stream_out.write( &cheader, sizeof( cheader ), 1 );
+		stream_out.write( channel.raw_data(), channel.element_size(), channel.size() );
+	}
 }
 
@@ -227,14 +194,12 @@
 {
 	uint32 total = sizeof( nmd_animation_header );
-	for ( uint32 i = 0; i < nodes.get_count(); ++i )
-	{
-		const mesh_node_data* node = nodes.get_node( i );
+	for ( auto node : nodes )
+	{
 		total += sizeof( nmd_element_header );
-		if ( node->data )
-			for ( uint32 c = 0; c < node->data->size(); ++c )
-			{
-				total += sizeof( nmd_channel_header );
-				total += node->data->get_channel( c )->raw_size();
-			}
+		for ( uint32 c = 0; c < node->size(); ++c )
+		{
+			total += sizeof( nmd_channel_header );
+			total += node->get_channel( c )->raw_size();
+		}
 	}
 
@@ -256,7 +221,7 @@
 	stream_out.write( &aheader, sizeof( aheader ), 1 );
 
-	for ( uint32 i = 0; i < nodes.get_count(); ++i )
-	{
-		nmd_dump_node( nodes.get_node( i ), stream_out );
+	for ( auto node : nodes )
+	{
+		nmd_dump_element( stream_out, *node, nv::nmd_type::NODE );
 	}
 }
@@ -284,5 +249,5 @@
 	for ( uint32 i = 0; i < model->get_count(); ++i )
 	{
-		nmd_dump_mesh( stream_out, *model->get_mesh( i ) );
+		nmd_dump_element( stream_out, *model->get_mesh( i ), nv::nmd_type::MESH );
 	}
 
Index: trunk/src/formats/obj_loader.cc
===================================================================
--- trunk/src/formats/obj_loader.cc	(revision 425)
+++ trunk/src/formats/obj_loader.cc	(revision 427)
@@ -363,5 +363,5 @@
 	for ( uint32 i = 0; i < size; ++i )
 	{
-		data_channel_set_creator( m_meshes[i] ).move_to( meshes[i] );
+		meshes[i] = move( *m_meshes[i] );
 		delete m_meshes[i];
 	}
