Index: trunk/nv/formats/nmd_loader.hh
===================================================================
--- trunk/nv/formats/nmd_loader.hh	(revision 419)
+++ trunk/nv/formats/nmd_loader.hh	(revision 420)
@@ -20,9 +20,8 @@
 	{
 		MESH,
-		STREAM,
+		ANIMATION,
 		NODE,
-		STRING_TABLE,
-		ANIMATION,
-		KEY_CHANNEL,
+		STRINGS,
+		DATA
 	};
 
@@ -32,12 +31,32 @@
 		uint32 version;
 		uint32 elements;
+		uint32 attributes;
 	};
+
+	enum class nmd_datatype : uint16
+	{
+		STRING,
+		INTEGER,
+		FLOAT
+	};
+
+	struct nmd_attribute
+	{
+		uint64       key;
+		uint8        data[22];
+		nmd_datatype type;
+	};
+	static_assert( sizeof( nmd_attribute ) == 32, "alignment issue!" );
+
 
 	struct nmd_element_header
 	{
 		nmd_type type;
-		uint16   name;
 		uint16   children;
 		uint32   size;
+		uint64   name_hash;
+		mat4     transform;
+		sint16   parent_id;
+		uint16   attributes;
 	};
 
@@ -49,11 +68,5 @@
 	};
 
-	struct nmd_node_header
-	{
-		sint16 parent_id;
-		mat4   transform;
-	};
-
-	struct nmd_stream_header
+	struct nmd_channel_header
 	{
 		data_descriptor format;
@@ -64,5 +77,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 );
@@ -74,13 +87,17 @@
 	private:
 		void reset();
+		void skip_attributes( stream& source, uint32 count );
 		bool load_mesh( stream& source, const nmd_element_header& e );
 		bool load_strings( stream& source ); 
 		bool load_animation( stream& source, const nmd_element_header& e );
+		bool load_node( stream& source, mesh_node_data* data, const nmd_element_header& e );
+		bool load_channel( stream& source, data_channel_set* channel_set );
+		bool load_channel_set( stream& source, data_channel_set* channel_set, const nmd_element_header& e );
 
 		mesh_nodes_data*            m_node_data;
 		mesh_node_data*             m_node_array;
-		string_table*               m_strings;
-		vector< uint16 >            m_mesh_names;
-		vector< uint16 >            m_node_names;
+//		string_table*               m_strings;
+//		vector< uint16 >            m_mesh_names;
+//		vector< uint16 >            m_node_names;
 		vector< data_channel_set* > m_meshes;
 	};
Index: trunk/nv/interface/mesh_data.hh
===================================================================
--- trunk/nv/interface/mesh_data.hh	(revision 419)
+++ trunk/nv/interface/mesh_data.hh	(revision 420)
@@ -24,6 +24,5 @@
 	struct mesh_node_data
 	{
-		std::string    name;
-		sint16    target_id;
+		uint64    name_hash;
 		sint16    parent_id;
 		mat4      transform;
@@ -55,9 +54,9 @@
 		}
 
-		const mesh_node_data* get_node( const std::string& name ) const 
+		const mesh_node_data* get_node_by_hash( uint64 h ) const
 		{
 			for ( uint32 i = 0; i < m_count; ++i )
 			{
-				if ( m_nodes[ i ].name == name )
+				if ( m_nodes[ i ].name_hash == h )
 					return &m_nodes[ i ];
 			}
@@ -65,9 +64,9 @@
 		}
 
-		int get_node_index( const std::string& name ) const 
+		int get_node_index_by_hash( uint64 h ) const
 		{
 			for ( uint32 i = 0; i < m_count; ++i )
 			{
-				if ( m_nodes[ i ].name == name )
+				if ( m_nodes[ i ].name_hash == h )
 					return int( i );
 			}
@@ -75,5 +74,5 @@
 		}
 
-		data_channel_set* release_node_data( size_t i )
+		data_channel_set* rlease_node_data( size_t i )
 		{
 			data_channel_set* result = m_nodes[i].data;
@@ -119,13 +118,4 @@
 			return &m_meshes[ index ];
 		}
-// 		const mesh_data* get_mesh( const std::string& name ) const
-// 		{
-// 			for ( uint32 i = 0; i < m_count; ++i )
-// 			{
-// 				if ( m_meshes[ i ].get_name() == name )
-// 					return &m_meshes[ i ];
-// 			}
-// 			return nullptr;
-// 		}
 		uint32 get_count() const { return m_count; }
 		const mesh_nodes_data* get_nodes() const { return m_nodes; }
Index: trunk/src/formats/assimp_loader.cc
===================================================================
--- trunk/src/formats/assimp_loader.cc	(revision 419)
+++ trunk/src/formats/assimp_loader.cc	(revision 420)
@@ -199,8 +199,9 @@
 		aiBone* bone   = mesh->mBones[m];
 		mat4    offset = assimp_mat4_cast( bone->mOffsetMatrix );
-		bones[m].name = bone->mName.data;
+//		bones[m].name = bone->mName.data;
+		bones[m].name_hash = hash_string< uint64 >( bone->mName.data );
 		bones[m].data = nullptr;
 		bones[m].parent_id = -1;
-		bones[m].target_id = -1;
+//		bones[m].target_id = -1;
 		bones[m].transform = offset;
 	}
@@ -287,5 +288,5 @@
 	const aiScene* scene = reinterpret_cast<const aiScene*>( m_scene );
 	vector< mesh_node_data > final_bones;
-	unordered_map< std::string, uint16 > names;
+	unordered_map< uint64, uint16 > names;
 	for ( unsigned int m = 0; m < m_mesh_count; ++m )
 	{
@@ -301,5 +302,5 @@
 
 				mesh_node_data& bone = bones[b];
-				auto iname = names.find( bone.name );
+				auto iname = names.find( bone.name_hash );
 				if ( iname == names.end() )
 				{
@@ -307,5 +308,5 @@
 					uint16 index = uint16( final_bones.size() );
 					final_bones.push_back( bone );
-					names[ bone.name ] = index;
+					names[ bone.name_hash] = index;
 					translate[b] = index;
 				}
@@ -387,6 +388,6 @@
 	mesh_node_data& a_data = nodes[ this_id ];
 
-	a_data.name      = name;
-	a_data.target_id = -1;
+//	a_data.name      = name;
+	a_data.name_hash = 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 419)
+++ trunk/src/formats/md3_loader.cc	(revision 420)
@@ -426,7 +426,6 @@
 
 		nodes[i].transform = mat4();
-		nodes[i].name      = name.to_string();
+		nodes[i].name_hash = hash_string< uint64 >( name.data() );
 		nodes[i].parent_id = -1;
-		nodes[i].target_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 );
Index: trunk/src/formats/md5_loader.cc
===================================================================
--- trunk/src/formats/md5_loader.cc	(revision 419)
+++ trunk/src/formats/md5_loader.cc	(revision 420)
@@ -116,5 +116,6 @@
 			for ( size_t i = 0; i < m_nodes->get_count(); ++i )
 			{
-				sstream >> nodes[i].name >> nodes[i].parent_id;
+				std::string name;
+				sstream >> name >> nodes[i].parent_id;
 				vec3 pos;
 				quat orient;
@@ -125,6 +126,8 @@
 				sstream >> orient.x >> orient.y >> orient.z;
 				unit_quat_w( orient );
-				remove_quotes( nodes[i].name );
-				nodes[i].target_id       = -1;
+				remove_quotes( name );
+//				nodes[i].name = name;
+				nodes[i].name_hash = hash_string< uint64 >( name.c_str() );
+//				nodes[i].target_id       = -1;
 				nodes[i].parent_id       = -1;
 				nodes[i].transform       = transform( pos, orient ).inverse().extract();
@@ -246,8 +249,9 @@
 			{
 				std::string    name;
-				sstream >> nodes[i].name >> nodes[i].parent_id >> joint_infos[i].flags >> joint_infos[i].start_index;
+				sstream >> name >> nodes[i].parent_id >> joint_infos[i].flags >> joint_infos[i].start_index;
 				remove_quotes( name );
+//				nodes[i].name = name;
+				nodes[i].name_hash = hash_string< uint64 >( name.c_str() );
 				nodes[i].transform = mat4();
-				nodes[i].target_id = -1;
 				nodes[i].data = data_channel_set_creator::create( 1 );
 				data_channel_set_creator( nodes[i].data ).add_channel< md5_key_t >( num_frames );
Index: trunk/src/formats/nmd_loader.cc
===================================================================
--- trunk/src/formats/nmd_loader.cc	(revision 419)
+++ trunk/src/formats/nmd_loader.cc	(revision 420)
@@ -18,13 +18,15 @@
 	nmd_header root_header;
 	source.read( &root_header, sizeof( root_header ), 1 );
+	skip_attributes( source, root_header.attributes );
 	for ( uint32 i = 0; i < root_header.elements; ++i )
 	{
 		nmd_element_header element_header;
 		source.read( &element_header, sizeof( element_header ), 1 );
+		skip_attributes( source, element_header.attributes );
 		switch ( element_header.type )
 		{
 		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::STRING_TABLE   : load_strings( source ); break;
 		default: NV_ASSERT( false, "UNKNOWN NMD ELEMENT!" ); break;
 		}
@@ -36,17 +38,6 @@
 {
 	data_channel_set* mesh = data_channel_set_creator::create( e.children );
-	data_channel_set_creator mcreator( mesh );
-	for ( uint32 s = 0; s < e.children; ++s )
-	{
-		nmd_element_header element_header;
-		source.read( &element_header, sizeof( element_header ), 1 );
-		NV_ASSERT( element_header.type == nmd_type::STREAM, "STREAM expected!" );
-
-		nmd_stream_header stream_header;
-		source.read( &stream_header, sizeof( stream_header ), 1 );
-		raw_data_channel_access channel( mcreator.add_channel( stream_header.format, stream_header.count ) );
-		source.read( channel.raw_data(), channel.element_size(), channel.size() );
-	}
-	m_mesh_names.push_back( e.name );
+	load_channel_set( source, mesh, e );
+//	m_mesh_names.push_back( e.name );
 	m_meshes.push_back( mesh );
 	return true;
@@ -56,5 +47,5 @@
 {
 	data_channel_set* result = m_meshes[ index ];
-	if ( m_strings ) data_channel_set_creator( result ).set_name( m_strings->get( m_mesh_names[ index ] ) );
+//	if ( m_strings ) data_channel_set_creator( result ).set_name( m_strings->get( m_mesh_names[ index ] ) );
 	m_meshes[ index ] = nullptr;
 	return result;
@@ -77,13 +68,19 @@
 {
 	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();
-	m_mesh_names.clear();
-	m_node_names.clear();
+//	m_mesh_names.clear();
+//	m_node_names.clear();
 
 	m_node_data  = nullptr;
 	m_node_array = nullptr;
-	m_strings    = nullptr;
+//	m_strings    = nullptr;
+}
+
+void nv::nmd_loader::skip_attributes( stream& source, uint32 count )
+{
+	if ( count == 0 ) return;
+	source.seek( count * sizeof( nmd_attribute ), origin::CUR );
 }
 
@@ -93,8 +90,8 @@
 }
 
-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!" );
+//	m_strings = new string_table( &source );
 	return true;
 }
@@ -110,28 +107,8 @@
 		nmd_element_header element_header;
 		source.read( &element_header, sizeof( element_header ), 1 );
+		skip_attributes( source, element_header.attributes );
 		NV_ASSERT( element_header.type == nmd_type::NODE, "NODE expected!" );
-		m_node_names.push_back( element_header.name );
-		uint16 ch_count = element_header.children;
-
-		nmd_node_header node_header;
-		source.read( &node_header, sizeof( node_header ), 1 );
-		m_node_array[i].parent_id     = node_header.parent_id;
-		m_node_array[i].transform     = node_header.transform;
-		m_node_array[i].data          = nullptr;
-		if ( ch_count > 0 )
-		{
-			data_channel_set* kdata = data_channel_set_creator::create( ch_count );
-			data_channel_set_creator kaccess( kdata );
-			m_node_array[i].data = kdata;
-			for ( uint32 c = 0; c < ch_count; ++c )
-			{
-				source.read( &element_header, sizeof( element_header ), 1 );
-				NV_ASSERT( element_header.type == nmd_type::KEY_CHANNEL, "CHANNEL expected!" );
-				nv::nmd_stream_header cheader;
-				source.read( &cheader, sizeof( cheader ), 1 );
-				raw_data_channel_access channel( kaccess.add_channel( cheader.format, cheader.count ) );
-				source.read( channel.raw_data(), channel.element_size(), channel.size() );
-			}
-		}
+//		m_node_names.push_back( element_header.name );
+		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 );
@@ -139,15 +116,50 @@
 }
 
+bool nv::nmd_loader::load_node( stream& source, mesh_node_data* data, const nmd_element_header& e )
+{
+	data->name_hash = e.name_hash;
+	data->parent_id = e.parent_id;
+	data->transform = e.transform;
+	data->data = nullptr;
+	if ( e.children > 0 )
+	{
+		data->data = data_channel_set_creator::create( e.children );
+		load_channel_set( source, data->data, e );
+	}
+	return true;
+}
+
+bool nv::nmd_loader::load_channel( stream& source, data_channel_set* channel_set )
+{
+	data_channel_set_creator kaccess( channel_set );
+	nmd_channel_header cheader;
+	source.read( &cheader, sizeof( cheader ), 1 );
+	raw_data_channel_access channel( kaccess.add_channel( cheader.format, cheader.count ) );
+	source.read( channel.raw_data(), channel.element_size(), channel.size() );
+	return true;
+}
+
+bool nv::nmd_loader::load_channel_set( stream& source, data_channel_set* channel_set, const nmd_element_header& e )
+{
+	data_channel_set_creator kaccess( channel_set );
+	for ( uint32 c = 0; c < e.children; ++c )
+	{
+		load_channel( source, channel_set );
+	}
+	return true;
+}
+
 mesh_nodes_data* nv::nmd_loader::release_mesh_nodes_data( size_t )
 {
 	if ( m_node_data )
 	{
-		if ( m_strings )
-		{
-			for ( uint32 i = 0; i < m_node_data->get_count(); ++i )
-			{
-				m_node_array[i].name = m_strings->get( m_node_names[i] );
-			}
-		}
+// 		if ( m_strings )
+// 		{
+// 			for ( uint32 i = 0; i < m_node_data->get_count(); ++i )
+// 			{
+// 				m_node_array[i].name = m_strings->get( m_node_names[i] );
+// 				m_node_array[i].name_hash = hash_string< uint64 >( m_strings->get( m_node_names[i] ) );
+// 			}
+// 		}
 		mesh_nodes_data* result = m_node_data;
 		m_node_data = nullptr;
@@ -161,38 +173,67 @@
 // 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_mesh( const data_channel_set* mesh, stream& stream_out )
 {
-	uint32 size = sizeof( nmd_element_header );
+	uint32 size = 0;
 	for ( auto& chan : *mesh )
 	{
-		size += sizeof( nmd_element_header ) + sizeof( nmd_stream_header );
+		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.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 );
-
-	for ( auto& chan : *mesh )
-	{
-		nmd_element_header cheader;
-		eheader.name     = 0;
-		cheader.type     = nmd_type::STREAM;
-		cheader.children = 0;
-		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();
-		stream_out.write( &sheader, sizeof( sheader ), 1 );
-		stream_out.write( chan.raw_data(), chan.element_size(), chan.size() );
-	}
-}
-
-static void nmd_dump_nodes_data( const mesh_nodes_data* nodes, stream& stream_out, string_table_creator* strings )
+	nmd_dump_channel_set( mesh, 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.name     = strings->insert( node->name );
+	eheader.children   = static_cast<uint16>( chan_count );
+	eheader.size       = chan_size;
+	eheader.name_hash  = node->name_hash;
+	eheader.parent_id  = node->parent_id;
+	eheader.transform  = node->transform;
+	eheader.attributes = 0;
+	stream_out.write( &eheader, sizeof( eheader ), 1 );
+	if ( node->data ) nmd_dump_channel_set( node->data, stream_out );
+}
+
+static void nmd_dump_nodes_data( const mesh_nodes_data* nodes, stream& stream_out, string_table_creator* /*strings*/ )
 {
 	uint32 total = sizeof( nmd_animation_header );
@@ -200,9 +241,9 @@
 	{
 		const mesh_node_data* node = nodes->get_node(i);
-		total += sizeof( nmd_element_header ) + sizeof( nmd_node_header );
+		total += sizeof( nmd_element_header );
 		if ( node->data )
 			for ( uint32 c = 0; c < node->data->size(); ++c )
 			{
-				total += sizeof( nmd_element_header ) + sizeof( nmd_stream_header );
+				total += sizeof( nmd_channel_header );
 				total += node->data->get_channel(c)->raw_size();
 			}
@@ -210,8 +251,13 @@
 
 	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       = 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.attributes = 0;
+
 	stream_out.write( &header, sizeof( header ), 1 );
 
@@ -224,40 +270,5 @@
 	for ( uint32 i = 0; i < nodes->get_count(); ++i )
 	{
-		const mesh_node_data* node = nodes->get_node(i);
-		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_element_header ) + sizeof( nv::nmd_stream_header );
-			chan_size += node->data->get_channel(c)->raw_size();
-		}
-
-		nmd_element_header eheader;
-		eheader.type     = nmd_type::NODE;
-		eheader.name     = strings->insert( node->name );
-		eheader.children = static_cast< uint16 >( chan_count );
-		eheader.size     = sizeof( nmd_node_header ) + chan_size;
-		stream_out.write( &eheader, sizeof( eheader ), 1 );
-
-		nmd_node_header nheader;
-		nheader.parent_id = node->parent_id;
-		nheader.transform = node->transform;
-		stream_out.write( &nheader, sizeof( nheader ), 1 );
-
-		for ( uint32 c = 0; c < chan_count; ++c )
-		{
-			const raw_data_channel* channel = node->data->get_channel(c);
-
-			eheader.type     = nmd_type::KEY_CHANNEL;
-			eheader.children = 0;
-			eheader.size     = sizeof( nmd_stream_header ) + channel->raw_size();
-			stream_out.write( &eheader, sizeof( eheader ), 1 );
-
-			nmd_stream_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() );
-		}
+		nmd_dump_node( nodes->get_node( i ), stream_out );
 	}
 }
@@ -269,9 +280,10 @@
 		nmd_header header;
 		header.id       = four_cc<'n','m','f','1'>::value;
-		header.elements = 1; // +1 string array
+		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 );
 	}
@@ -288,10 +300,11 @@
 	}
 
-	nmd_element_header sheader;
-	sheader.type     = nv::nmd_type::STRING_TABLE;
-	sheader.name     = 0;
-	sheader.size     = strings.dump_size();
-	sheader.children = 0;
-	stream_out.write( &sheader, sizeof( sheader ), 1 );
-	strings.dump( &stream_out );
-}
+// 	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 );
+}
Index: trunk/src/gfx/skeletal_mesh.cc
===================================================================
--- trunk/src/gfx/skeletal_mesh.cc	(revision 419)
+++ trunk/src/gfx/skeletal_mesh.cc	(revision 420)
@@ -173,10 +173,10 @@
 {
 	if ( m_prepared ) return;
-	unordered_map< std::string, nv::uint16 > bone_names;
+	unordered_map< uint64, uint16 > bone_names;
 	m_offsets = new mat4[ bones->get_count() ];
 	for ( nv::uint16 bi = 0; bi < bones->get_count(); ++bi )
 	{
 		const mesh_node_data* bone = bones->get_node(bi);
-		bone_names[ bone->name ] = bi;
+		bone_names[ bone->name_hash ] = bi;
 		m_offsets[bi] = bone->transform;
 	}
@@ -187,5 +187,5 @@
 		sint16 bone_id = -1;
 
-		auto bi = bone_names.find( node->name );
+		auto bi = bone_names.find( node->name_hash );
 		if ( bi != bone_names.end() )
 		{
