Index: trunk/nv/formats/nmd_loader.hh
===================================================================
--- trunk/nv/formats/nmd_loader.hh	(revision 422)
+++ trunk/nv/formats/nmd_loader.hh	(revision 423)
@@ -30,4 +30,5 @@
 		uint32 id;
 		uint32 version;
+		uint64 name;
 		uint32 elements;
 		uint32 attributes;
@@ -55,5 +56,5 @@
 		uint16   children;
 		uint32   size;
-		uint64   name_hash;
+		uint64   name;
 		mat4     transform;
 		sint16   parent_id;
@@ -77,5 +78,5 @@
 	{
 	public:
-		nmd_loader() : m_node_data( nullptr ), m_node_array( nullptr ) {} //, m_strings( nullptr ) {}
+		nmd_loader() : m_node_data( nullptr ), m_node_array( nullptr ), m_strings( nullptr ) {}
 		virtual bool load( stream& source );
 		virtual data_channel_set* release_mesh_data( size_t index = 0 );
@@ -97,5 +98,5 @@
 		mesh_nodes_data*            m_node_data;
 		mesh_node_data*             m_node_array;
-//		string_table*               m_strings;
+		string_table*               m_strings;
 //		vector< uint16 >            m_mesh_names;
 //		vector< uint16 >            m_node_names;
@@ -104,5 +105,9 @@
 
 	// HACK : TEMPORARY - will go to it's own file, probably nmd_io
-	void nmd_dump( const nv::mesh_data_pack* model, stream& stream_out );
+	void nmd_dump_header( stream& stream_out, uint32 elements, uint64 name );
+	void nmd_dump_strings( stream& stream_out, const string_table& strings );
+	void nmd_dump_mesh( stream& stream_out, const data_channel_set& mesh );
+	void nmd_dump_nodes( stream& stream_out, const mesh_nodes_data& nodes );
+	void nmd_dump( stream& stream_out, const mesh_data_pack* model, const string_table* strings = nullptr, uint64 name = 0 );
 
 }
Index: trunk/nv/gfx/animation.hh
===================================================================
--- trunk/nv/gfx/animation.hh	(revision 422)
+++ trunk/nv/gfx/animation.hh	(revision 423)
@@ -10,5 +10,5 @@
 #include <nv/common.hh>
 #include <nv/stl/vector.hh>
-#include <nv/interface/stream.hh>
+#include <nv/stl/stream.hh>
 #include <nv/stl/math.hh>
 #include <nv/interface/data_channel.hh>
Index: trunk/nv/gfx/skeletal_mesh.hh
===================================================================
--- trunk/nv/gfx/skeletal_mesh.hh	(revision 422)
+++ trunk/nv/gfx/skeletal_mesh.hh	(revision 423)
@@ -38,10 +38,10 @@
 	{
 	public:
-		skeletal_animation_entry_cpu( const std::string& name, const mesh_nodes_data* a_animation, bool a_looping ) 
+		skeletal_animation_entry_cpu( uint64 name, const mesh_nodes_data* a_animation, bool a_looping )
 			: animation_entry( name, a_looping, a_animation->get_frame_rate(), 0.0f, a_animation->get_duration() ), m_node_data( a_animation )
 		{
 			initialize();
 		}
-		skeletal_animation_entry_cpu( const std::string& name, mesh_nodes_data* a_animation, float time_start, float time_end, bool a_looping )
+		skeletal_animation_entry_cpu( uint64 name, mesh_nodes_data* a_animation, float time_start, float time_end, bool a_looping )
 			: animation_entry( name, a_looping, a_animation->get_frame_rate(), time_start, time_end ), m_node_data( a_animation )
 		{
@@ -75,5 +75,5 @@
  	{
  	public:
- 		skeletal_animation_entry_gpu( const std::string& name, const mesh_nodes_data* anim, bool a_looping )
+ 		skeletal_animation_entry_gpu( uint64 name, const mesh_nodes_data* anim, bool a_looping )
 			: animation_entry( name, a_looping, anim->get_frame_rate(), 0.0f, anim->get_duration() )
 			, m_node_data( anim )
@@ -82,5 +82,5 @@
 		}
 
-		skeletal_animation_entry_gpu( const std::string& name, const mesh_nodes_data* anim, float time_start, float time_end, bool a_looping )
+		skeletal_animation_entry_gpu( uint64 name, const mesh_nodes_data* anim, float time_start, float time_end, bool a_looping )
 			: animation_entry( name, a_looping, anim->get_frame_rate(), time_start, time_end )
 			, m_node_data( anim )
Index: trunk/nv/interface/animated_mesh.hh
===================================================================
--- trunk/nv/interface/animated_mesh.hh	(revision 422)
+++ trunk/nv/interface/animated_mesh.hh	(revision 423)
@@ -25,7 +25,7 @@
 	{
 	public:
-		animation_entry( const std::string& name, bool looping, uint32 frame_rate, float a_start, float a_end ) : m_name( name ), m_looping( looping ), m_frame_rate( frame_rate ),
+		animation_entry( uint64 name, bool looping, uint32 frame_rate, float a_start, float a_end ) : m_name( name ), m_looping( looping ), m_frame_rate( frame_rate ),
 		m_start( a_start ), m_end( a_end ), m_duration( m_end - m_start ), m_material_idx(0) {}
-		const std::string& get_name() const { return m_name; }
+		uint64 get_name() const { return m_name; }
 		uint32 get_frame_rate() const { return m_frame_rate; }
 		float get_duration() const { return m_duration; }
@@ -47,5 +47,5 @@
 		virtual ~animation_entry() {}
 	protected:
-		std::string m_name;
+		uint64 m_name;
 		bool   m_looping;
 		uint32 m_frame_rate;
Index: trunk/nv/interface/mesh_data.hh
===================================================================
--- trunk/nv/interface/mesh_data.hh	(revision 422)
+++ trunk/nv/interface/mesh_data.hh	(revision 423)
@@ -24,5 +24,5 @@
 	struct mesh_node_data
 	{
-		uint64    name_hash;
+		uint64    name;
 		sint16    parent_id;
 		mat4      transform;
@@ -35,10 +35,10 @@
 		friend class mesh_nodes_creator;
 	public:
-		explicit mesh_nodes_data( const std::string& name, uint32 count, mesh_node_data* nodes )
+		explicit mesh_nodes_data( uint64 name, uint32 count, mesh_node_data* nodes )
 			: m_name( name ), m_count( count ), m_nodes( nodes ), m_frame_rate(0), m_duration(0.0f), m_flat( false )
 		{
 		}
 
-		explicit mesh_nodes_data( const std::string& name, uint32 count, mesh_node_data* nodes,
+		explicit mesh_nodes_data( uint64 name, uint32 count, mesh_node_data* nodes,
 			uint16 a_fps, float a_frames, bool a_flat )
 			: m_name( name ), m_count( count ), m_nodes( nodes ), m_frame_rate(a_fps), m_duration(a_frames), m_flat( a_flat )
@@ -58,5 +58,5 @@
 			for ( uint32 i = 0; i < m_count; ++i )
 			{
-				if ( m_nodes[ i ].name_hash == h )
+				if ( m_nodes[ i ].name == h )
 					return &m_nodes[ i ];
 			}
@@ -68,5 +68,5 @@
 			for ( uint32 i = 0; i < m_count; ++i )
 			{
-				if ( m_nodes[ i ].name_hash == h )
+				if ( m_nodes[ i ].name == h )
 					return int( i );
 			}
@@ -84,6 +84,6 @@
 		uint16 get_frame_rate() const { return m_frame_rate; }
 		float get_duration() const { return m_duration; }
-		void set_name( const std::string& name ) { m_name = name; }
-		const std::string& get_name() const { return m_name; }
+		void set_name( uint64 name ) { m_name = name; }
+		uint64 get_name() const { return m_name; }
 
 		~mesh_nodes_data()
@@ -95,5 +95,5 @@
 
 	private:
-		std::string m_name;
+		uint64 m_name;
 		uint32 m_count;
 		mesh_node_data* m_nodes;
@@ -120,4 +120,5 @@
 		uint32 get_count() const { return m_count; }
 		const mesh_nodes_data* get_nodes() const { return m_nodes; }
+		uint32 get_node_count() const { return m_nodes ? m_nodes->get_count() : 0; }
 		~mesh_data_pack()
 		{
Index: trunk/nv/interface/mesh_loader.hh
===================================================================
--- trunk/nv/interface/mesh_loader.hh	(revision 422)
+++ trunk/nv/interface/mesh_loader.hh	(revision 423)
@@ -19,5 +19,5 @@
 #include <nv/gfx/animation.hh>
 #include <nv/interface/mesh_data.hh>
-#include <nv/interface/stream.hh>
+#include <nv/stl/stream.hh>
 
 namespace nv 
Index: trunk/src/formats/assimp_loader.cc
===================================================================
--- trunk/src/formats/assimp_loader.cc	(revision 422)
+++ trunk/src/formats/assimp_loader.cc	(revision 423)
@@ -200,5 +200,5 @@
 		mat4    offset = assimp_mat4_cast( bone->mOffsetMatrix );
 //		bones[m].name = bone->mName.data;
-		bones[m].name_hash = hash_string< uint64 >( bone->mName.data );
+		bones[m].name = hash_string< uint64 >( bone->mName.data );
 		bones[m].data = nullptr;
 		bones[m].parent_id = -1;
@@ -302,5 +302,5 @@
 
 				mesh_node_data& bone = bones[b];
-				auto iname = names.find( bone.name_hash );
+				auto iname = names.find( bone.name );
 				if ( iname == names.end() )
 				{
@@ -308,5 +308,5 @@
 					uint16 index = uint16( final_bones.size() );
 					final_bones.push_back( bone );
-					names[ bone.name_hash] = index;
+					names[ bone.name] = index;
 					translate[b] = index;
 				}
@@ -336,5 +336,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( "bones", final_bones.size(), bones );
+	int name_;
+	return new mesh_nodes_data( /*"bones"*/0, final_bones.size(), bones );
 }
 
@@ -357,5 +358,6 @@
 	load_node( index, data, root, 0, -1 );
 
-	return new mesh_nodes_data( anim->mName.data, count, data, frame_rate, duration, flat );
+	int name;
+	return new mesh_nodes_data( /*anim->mName.data*/0, count, data, frame_rate, duration, flat );
 }
 
@@ -389,5 +391,5 @@
 
 //	a_data.name      = name;
-	a_data.name_hash = hash_string< uint64 >( name.c_str() );
+	a_data.name = hash_string< uint64 >( name.c_str() );
 	a_data.parent_id = parent_id;
 	// This value is ignored by the create_transformed_keys, but needed by create_direct_keys!
Index: trunk/src/formats/md3_loader.cc
===================================================================
--- trunk/src/formats/md3_loader.cc	(revision 422)
+++ trunk/src/formats/md3_loader.cc	(revision 423)
@@ -426,10 +426,11 @@
 
 		nodes[i].transform = mat4();
-		nodes[i].name_hash = hash_string< uint64 >( name.data() );
+		nodes[i].name = hash_string< uint64 >( name.data() );
 		nodes[i].parent_id = -1;
 		nodes[i].data      = data_channel_set_creator::create( 1 );
 		load_tags( data_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 );
+	int name_;
+	return new mesh_nodes_data( 0,/*"tags"*/ node_count, nodes );
 }
 
Index: trunk/src/formats/md5_loader.cc
===================================================================
--- trunk/src/formats/md5_loader.cc	(revision 422)
+++ trunk/src/formats/md5_loader.cc	(revision 423)
@@ -112,5 +112,6 @@
 			assert( m_nodes == nullptr );
 			nodes = new mesh_node_data[ num_joints ];
-			m_nodes = new mesh_nodes_data( "md5_bones", num_joints, nodes );
+			int name_; //"md5_bones"
+			m_nodes = new mesh_nodes_data( 0, num_joints, nodes );
 			discard( sstream, "{" );
 			for ( size_t i = 0; i < m_nodes->get_count(); ++i )
@@ -128,5 +129,5 @@
 				remove_quotes( name );
 //				nodes[i].name = name;
-				nodes[i].name_hash = hash_string< uint64 >( name.c_str() );
+				nodes[i].name = hash_string< uint64 >( name.c_str() );
 //				nodes[i].target_id       = -1;
 				nodes[i].parent_id       = -1;
@@ -242,5 +243,6 @@
 			assert( nodes == nullptr );
 			nodes = new mesh_node_data[ num_joints ];
-			m_nodes = new mesh_nodes_data( "md5_animation", num_joints, nodes, static_cast< nv::uint16 >( frame_rate ), static_cast< float >( num_frames ), true );
+			int name_;
+			m_nodes = new mesh_nodes_data( 0/*"md5_animation"*/, num_joints, nodes, static_cast< nv::uint16 >( frame_rate ), static_cast< float >( num_frames ), true );
 			joint_infos.resize( num_joints );
 
@@ -252,5 +254,5 @@
 				remove_quotes( name );
 //				nodes[i].name = name;
-				nodes[i].name_hash = hash_string< uint64 >( name.c_str() );
+				nodes[i].name = hash_string< uint64 >( name.c_str() );
 				nodes[i].transform = mat4();
 				nodes[i].data = data_channel_set_creator::create( 1 );
Index: trunk/src/formats/nmd_loader.cc
===================================================================
--- trunk/src/formats/nmd_loader.cc	(revision 422)
+++ trunk/src/formats/nmd_loader.cc	(revision 423)
@@ -28,5 +28,5 @@
 		case nmd_type::MESH           : load_mesh( source, element_header ); break;
 		case nmd_type::ANIMATION      : load_animation( source, element_header ); break;
-//		case nmd_type::STRING_TABLE   : load_strings( source ); break;
+		case nmd_type::STRINGS        : load_strings( source ); break;
 		default: NV_ASSERT( false, "UNKNOWN NMD ELEMENT!" ); break;
 		}
@@ -68,5 +68,5 @@
 {
 	for ( auto mesh : m_meshes ) if ( mesh ) delete mesh;
-//	if ( m_strings )   delete m_strings;
+	if ( m_strings )   delete m_strings;
 	if ( m_node_data ) delete m_node_data;
 	m_meshes.clear();
@@ -76,5 +76,5 @@
 	m_node_data  = nullptr;
 	m_node_array = nullptr;
-//	m_strings    = nullptr;
+	m_strings    = nullptr;
 }
 
@@ -90,8 +90,9 @@
 }
 
-bool nv::nmd_loader::load_strings( stream& /*source*/ )
-{
-//	NV_ASSERT( m_strings == nullptr, "MULTIPLE STRING ENTRIES!" );
-//	m_strings = new string_table( &source );
+bool nv::nmd_loader::load_strings( stream& source )
+{
+	NV_ASSERT( m_strings == nullptr, "MULTIPLE STRING ENTRIES!" );
+	// TODO: load strings optionally
+	m_strings = new string_table( source );
 	return true;
 }
@@ -112,5 +113,5 @@
 		load_node( source, &m_node_array[i], element_header );
 	}
-	m_node_data = new mesh_nodes_data( "animation", e.children, m_node_array, animation_header.frame_rate, animation_header.duration, animation_header.flat );
+	m_node_data = new mesh_nodes_data( e.name, e.children, m_node_array, animation_header.frame_rate, animation_header.duration, animation_header.flat );
 	return true;
 }
@@ -118,5 +119,5 @@
 bool nv::nmd_loader::load_node( stream& source, mesh_node_data* data, const nmd_element_header& e )
 {
-	data->name_hash = e.name_hash;
+	data->name = e.name;
 	data->parent_id = e.parent_id;
 	data->transform = e.transform;
@@ -190,26 +191,4 @@
 }
 
-static void nmd_dump_mesh( const data_channel_set* mesh, stream& stream_out )
-{
-	uint32 size = 0;
-	for ( auto& chan : *mesh )
-	{
-		size += sizeof( nmd_channel_header );
-		size += chan.raw_size();
-	}
-
-	nmd_element_header eheader;
-	eheader.type       = nmd_type::MESH;
-//	eheader.name       = 0;
-	eheader.children   = static_cast< uint16 >( mesh->size() );
-	eheader.size       = size;
-	eheader.name_hash  = 0;
-	eheader.transform  = mat4();
-	eheader.parent_id  = -1;
-	eheader.attributes = 0;
-	stream_out.write( &eheader, sizeof( eheader ), 1 );
-	nmd_dump_channel_set( mesh, stream_out );
-}
-
 static void nmd_dump_node( const mesh_node_data* node, stream& stream_out )
 {
@@ -227,5 +206,5 @@
 	eheader.children   = static_cast<uint16>( chan_count );
 	eheader.size       = chan_size;
-	eheader.name_hash  = node->name_hash;
+	eheader.name       = node->name;
 	eheader.parent_id  = node->parent_id;
 	eheader.transform  = node->transform;
@@ -235,10 +214,46 @@
 }
 
-static void nmd_dump_nodes_data( const mesh_nodes_data* nodes, stream& stream_out, string_table_creator* /*strings*/ )
+void nv::nmd_dump_header( stream& stream_out, uint32 elements, uint64 name )
+{
+	nmd_header header;
+	header.id = four_cc<'n', 'm', 'f', '1'>::value;
+	header.elements = elements; // +1 string array
+	header.name = name;
+	header.version = 1;
+	header.attributes = 0;
+	stream_out.write( &header, sizeof( header ), 1 );
+}
+
+void nv::nmd_dump_mesh( stream& stream_out, const data_channel_set& mesh )
+{
+	uint32 size = 0;
+	for ( auto& chan : mesh )
+	{
+		size += sizeof( nmd_channel_header );
+		size += chan.raw_size();
+	}
+
+	nmd_element_header eheader;
+	eheader.type       = nmd_type::MESH;
+	eheader.children   = static_cast<uint16>( mesh.size() );
+	eheader.size       = size;
+	int uncomment;
+// 	eheader.name       = mesh.get_name();
+// 	eheader.transform  = mesh.get_transform();
+// 	eheader.parent_id  = mesh.get_parent_id();
+ 	eheader.name       = 0;
+ 	eheader.transform  = mat4();
+ 	eheader.parent_id  = -1;
+	eheader.attributes = 0;
+	stream_out.write( &eheader, sizeof( eheader ), 1 );
+	nmd_dump_channel_set( &mesh, stream_out );
+}
+
+void nv::nmd_dump_nodes( stream& stream_out, const mesh_nodes_data& nodes )
 {
 	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 ( uint32 i = 0; i < nodes.get_count(); ++i )
+	{
+		const mesh_node_data* node = nodes.get_node( i );
 		total += sizeof( nmd_element_header );
 		if ( node->data )
@@ -246,16 +261,15 @@
 			{
 				total += sizeof( nmd_channel_header );
-				total += node->data->get_channel(c)->raw_size();
+				total += node->data->get_channel( c )->raw_size();
 			}
 	}
 
 	nmd_element_header header;
-//	header.name       = 0;
-	header.type       = nmd_type::ANIMATION;
-	header.children   = static_cast< uint16 >( nodes->get_count() );
-	header.size       = total;
-	header.name_hash  = 0;
-	header.transform  = mat4();
-	header.parent_id  = -1;
+	header.type = nmd_type::ANIMATION;
+	header.children = static_cast<uint16>( nodes.get_count() );
+	header.size = total;
+	header.name = nodes.get_name();
+	header.transform = mat4();
+	header.parent_id = -1;
 	header.attributes = 0;
 
@@ -263,48 +277,48 @@
 
 	nmd_animation_header aheader;
-	aheader.frame_rate  = nodes->get_frame_rate();
-	aheader.duration    = nodes->get_duration();
-	aheader.flat        = nodes->is_flat();
+	aheader.frame_rate = nodes.get_frame_rate();
+	aheader.duration = nodes.get_duration();
+	aheader.flat = nodes.is_flat();
 	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 );
-	}
-}
-
-void nv::nmd_dump( const mesh_data_pack* model, stream& stream_out )
-{
-	string_table_creator strings;
-	{
-		nmd_header header;
-		header.id       = four_cc<'n','m','f','1'>::value;
-		header.elements = 0; // +1 string array
-		header.elements += model->get_count();
-		if ( model->get_nodes() && model->get_nodes()->get_count() > 0 ) 
-			header.elements += 1;//  +1 bone array
-		header.version  = 1;
-		header.attributes = 0;
-		stream_out.write( &header, sizeof( header ), 1 );
-	}
+	for ( uint32 i = 0; i < nodes.get_count(); ++i )
+	{
+		nmd_dump_node( nodes.get_node( i ), stream_out );
+	}
+}
+
+void nv::nmd_dump_strings( stream& stream_out, const string_table& strings )
+{
+	nmd_element_header sheader;
+	sheader.type       = nv::nmd_type::STRINGS;
+	sheader.children   = 0;
+	sheader.size       = strings.dump_size();
+	sheader.name       = 0;
+	sheader.parent_id  = -1;
+    sheader.attributes = 0;
+	stream_out.write( &sheader, sizeof( sheader ), 1 );
+	strings.dump( stream_out );
+}
+
+void nv::nmd_dump( stream& stream_out, const mesh_data_pack* model, const string_table* strings, uint64 name )
+{
+	uint32 elements = ( strings ? 1 : 0 ) // +1 string array
+		+ model->get_count() // meshes
+		+ ( model->get_node_count() > 0 ? 1 : 0 ); // nodes
+	nmd_dump_header( stream_out, elements, name );
 
 	for ( uint32 i = 0; i < model->get_count(); ++i )
 	{
-		const data_channel_set* mesh = model->get_mesh(i);
-		nmd_dump_mesh( mesh, stream_out );
-	}
-
-	if ( model->get_nodes() && model->get_nodes()->get_count() > 0 )
-	{
-		nmd_dump_nodes_data( model->get_nodes(), stream_out, &strings );
-	}
-
-// 	nmd_element_header sheader;
-// 	sheader.type     = nv::nmd_type::STRING_TABLE;
-// 	sheader.name     = 0;
-// 	sheader.size     = strings.dump_size();
-// 	sheader.children = 0;
-//  sheader.attributes = 0;
-// 	stream_out.write( &sheader, sizeof( sheader ), 1 );
-// 	strings.dump( &stream_out );
-}
+		nmd_dump_mesh( stream_out, *model->get_mesh( i ) );
+	}
+
+	if ( model->get_node_count() > 0 )
+	{
+		nmd_dump_nodes( stream_out, *model->get_nodes() );
+	}
+
+	if ( strings )
+	{
+		nmd_dump_strings( stream_out, *strings );
+	}
+}
Index: trunk/src/gfx/skeletal_mesh.cc
===================================================================
--- trunk/src/gfx/skeletal_mesh.cc	(revision 422)
+++ trunk/src/gfx/skeletal_mesh.cc	(revision 423)
@@ -178,5 +178,5 @@
 	{
 		const mesh_node_data* bone = bones->get_node(bi);
-		bone_names[ bone->name_hash ] = bi;
+		bone_names[ bone->name ] = bi;
 		m_offsets[bi] = bone->transform;
 	}
@@ -187,5 +187,5 @@
 		sint16 bone_id = -1;
 
-		auto bi = bone_names.find( node->name_hash );
+		auto bi = bone_names.find( node->name );
 		if ( bi != bone_names.end() )
 		{
