Index: trunk/src/formats/nmd_loader.cc
===================================================================
--- trunk/src/formats/nmd_loader.cc	(revision 285)
+++ trunk/src/formats/nmd_loader.cc	(revision 287)
@@ -7,4 +7,5 @@
 #include "nv/formats/nmd_loader.hh"
 #include "nv/io/std_stream.hh"
+#include "nv/string.hh"
 
 using namespace nv;
@@ -24,5 +25,4 @@
 		case nmd_type::MESH           : load_mesh( source, element_header ); break;
 		case nmd_type::ANIMATION      : load_animation( source, element_header ); break;
-		case nmd_type::BONE_ARRAY     : load_bones( source, element_header ); break;
 		case nmd_type::STRING_TABLE   : load_strings( source ); break;
 		default: NV_ASSERT( false, "UNKNOWN NMD ELEMENT!" ); break;
@@ -47,4 +47,5 @@
 		mesh->add_channel( channel );
 	}
+	m_mesh_names.push_back( e.name );
 	m_meshes.push_back( mesh );
 	return true;
@@ -54,6 +55,20 @@
 {
 	mesh_data* result = m_meshes[ index ];
+	if ( m_strings ) result->set_name( m_strings->get( m_mesh_names[ index ] ) );
 	m_meshes[ index ] = nullptr;
 	return result;
+}
+
+mesh_data_pack* nv::nmd_loader::release_mesh_data_pack()
+{
+	uint32 size = m_meshes.size();
+	mesh_data* meshes = new mesh_data[ size ];
+	for ( uint32 i = 0; i < size; ++i )
+	{
+		m_meshes[i]->move_to( meshes[i] );
+		delete m_meshes[i];
+	}
+	m_meshes.clear();
+	return new mesh_data_pack( size, meshes, release_mesh_nodes_data() );
 }
 
@@ -61,11 +76,13 @@
 {
 	for ( auto mesh : m_meshes ) if ( mesh ) delete mesh;
-	if ( m_animation ) delete m_animation;
 	if ( m_strings )   delete m_strings;
-	if ( m_bone_data ) delete m_bone_data;
+	if ( m_node_data ) delete m_node_data;
 	m_meshes.clear();
-	m_animation = nullptr;
-	m_bone_data = nullptr;
-	m_strings   = nullptr;
+	m_mesh_names.clear();
+	m_node_names.clear();
+
+	m_node_data  = nullptr;
+	m_node_array = nullptr;
+	m_strings    = nullptr;
 }
 
@@ -82,70 +99,32 @@
 }
 
-bool nv::nmd_loader::load_bones( stream& source, const nmd_element_header& e )
-{
-	NV_ASSERT( m_bone_data == nullptr, "MULTIPLE BONE ENTRIES!" );
-	m_bone_data = new nmd_bone_data;
-	m_bone_data->bones = new nmd_bone[ e.children ];
-	m_bone_data->count = (uint16)e.children;
-	source.read( m_bone_data->bones, sizeof( nmd_bone ), e.children );
-	return true;
-}
-
-nmd_animation* nv::nmd_loader::release_animation()
-{
-	nmd_animation* result = m_animation;
-	m_animation = nullptr;
-	return result;
-}
-
-nmd_bone_data* nv::nmd_loader::release_bone_data()
-{
-	nmd_bone_data* result = m_bone_data;
-	m_bone_data = nullptr;
-	return result;
-}
-
-string_table* nv::nmd_loader::release_string_table()
-{
-	string_table* result = m_strings;
-	m_strings = nullptr;
-	return result;
-}
-
-
 bool nv::nmd_loader::load_animation( stream& source, const nmd_element_header& e )
 {
-	NV_ASSERT( m_animation == nullptr, "MULTIPLE ANIMATION ENTRIES!" );
-	nmd_animation_header header;
-	source.read( &header, sizeof( header ), 1 );
-	m_animation = new nmd_animation;
-	m_animation->fps        = header.fps;
-	m_animation->duration   = header.duration;
-	m_animation->flat       = header.flat;
-	m_animation->node_count = (uint16)e.children;
-	m_animation->nodes      = new nmd_node[ e.children ];
+	NV_ASSERT( m_node_data == nullptr, "MULTIPLE NODE ENTRIES!" );
+	nmd_animation_header animation_header;
+	source.read( &animation_header, sizeof( animation_header ), 1 );
+	m_node_array = new mesh_node_data[ e.children ];
 	for ( uint32 i = 0; i < e.children; ++i )
 	{
 		nmd_element_header element_header;
 		source.read( &element_header, sizeof( element_header ), 1 );
-		NV_ASSERT( element_header.type == nmd_type::ANIMATION_NODE, "ANIMATION_NODE expected!" );
-		m_animation->nodes[i].name          = element_header.name;
-
+		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_animation_node_header node_header;
+		nmd_node_header node_header;
 		source.read( &node_header, sizeof( node_header ), 1 );
-		m_animation->nodes[i].parent_id     = node_header.parent_id;
-		m_animation->nodes[i].transform     = node_header.transform;
-		m_animation->nodes[i].data          = nullptr;
+		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 )
 		{
 			key_data* kdata = new key_data;
-			m_animation->nodes[i].data = 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::ANIMATION_CHANNEL, "ANIMATION_CHANNEL expected!" );
-				nv::nmd_animation_channel_header cheader;
+				NV_ASSERT( element_header.type == nmd_type::KEY_CHANNEL, "CHANNEL expected!" );
+				nv::nmd_key_channel_header cheader;
 				source.read( &cheader, sizeof( cheader ), 1 );
 				key_raw_channel* channel = key_raw_channel::create( cheader.format, cheader.count );
@@ -155,116 +134,30 @@
 		}
 	}
+	m_node_data = new mesh_nodes_data( "animation", e.children, m_node_array, animation_header.frame_rate, animation_header.duration, animation_header.flat );
 	return true;
 }
 
+mesh_nodes_data* nv::nmd_loader::release_mesh_nodes_data()
+{
+	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] );
+			}
+		}
+		mesh_nodes_data* result = m_node_data;
+		m_node_data = nullptr;
+		m_node_array = nullptr;
+		return result;
+	}
+	return nullptr;
+}
 
 // TEMPORARY
-nv::nmd_temp_animation::nmd_temp_animation( nmd_loader* loader )
-{
-	m_animation = loader->release_animation();
-	m_strings   = loader->release_string_table();
 
-	for ( uint32 n = 0; n < m_animation->node_count; ++n )
-	{
-		nmd_node& node = m_animation->nodes[n];
-		m_data.push_back( node.data );
-		node.data = nullptr;
-	}
-
-	if ( !m_animation->flat )
-	{
-		m_children.resize( m_animation->node_count );
-		for ( nv::uint32 n = 0; n < m_animation->node_count; ++n )
-		{
-			const nmd_node& node = m_animation->nodes[n];
-			if ( node.parent_id != -1 )
-			{
-				m_children[ node.parent_id ].push_back( n );
-			}
-		}
-	}
-
-	m_bone_ids.resize( m_animation->node_count );
-}
-
-nv::nmd_temp_animation::~nmd_temp_animation()
-{
-	for ( auto node : m_data ) delete node;
-	delete m_animation;
-	delete m_strings;
-}
-
-void nv::nmd_temp_animation::prepare( const nmd_temp_model* model )
-{
-	m_offsets = model->m_bone_offsets.data();
-	for ( uint32 n = 0; n < m_animation->node_count; ++n )
-	{
-		const nmd_node& node = m_animation->nodes[n];
-		sint16 bone_id = -1;
-
-		auto bi = model->m_bone_names.find( m_strings->get( node.name ) );
-		if ( bi != model->m_bone_names.end() )
-		{
-			bone_id = bi->second;
-		}
-		m_bone_ids[n] = bone_id;
-	}
-}
-
-void nv::nmd_temp_animation::animate( mat4* data, uint32 time )
-{
-	float tick_time = ( time / 1000.0f ) * m_animation->fps;
-	float anim_time = fmodf( tick_time, m_animation->duration );
-
-	if ( !m_animation->flat )
-	{
-		animate_rec( data, anim_time, 0, mat4() );
-		return;
-	}
-
-	for ( uint32 n = 0; n < m_animation->node_count; ++n )
-		if ( m_bone_ids[n] >= 0 )
-		{
-			const nmd_node* node = &m_animation->nodes[ n ];
-			nv::mat4 node_mat( node->transform );
-
-			if ( m_data[n] )
-			{
-				node_mat = m_data[n]->get_matrix( anim_time );
-			}
-
-			sint16 bone_id = m_bone_ids[n];
-			data[ bone_id ] = node_mat * m_offsets[ bone_id ];
-		}
-
-}
-
-void nv::nmd_temp_animation::animate_rec( mat4* data, float time, uint32 node_id, const mat4& parent_mat )
-{
-	// TODO: fix transforms, which are now embedded,
-	//       see note in assimp_loader.cc:load_node
-	const nmd_node* node = &m_animation->nodes[ node_id ];
-	mat4 node_mat( node->transform );
-
-	if ( m_data[ node_id ] )
-	{
-		node_mat = m_data[ node_id ]->get_matrix( time );
-	}
-
-	mat4 global_mat = parent_mat * node_mat;
-
-	sint16 bone_id = m_bone_ids[ node_id ];
-	if ( bone_id >= 0 )
-	{
-		data[ bone_id ] = global_mat * m_offsets[ bone_id ];
-	}
-
-	for ( auto child : m_children[ node_id ] )
-	{
-		animate_rec( data, time, child, global_mat );
-	}
-}
-
-nv::nmd_temp_model::nmd_temp_model( nmd_loader* loader )
+nv::nmd_temp_model_data::nmd_temp_model_data( nmd_loader* loader )
 {
 	for ( unsigned m = 0; m < loader->get_mesh_count(); ++m )
@@ -272,18 +165,8 @@
 		m_mesh_data.push_back(loader->release_mesh_data(m));
 	}
-	nmd_bone_data* bone_data = loader->release_bone_data();
-	string_table*  strings   = loader->release_string_table();
-
-	for ( nv::uint16 bi = 0; bi < bone_data->count; ++bi )
-	{
-		m_bone_names[ strings->get( bone_data->bones[bi].name ) ] = bi;
-		m_bone_offsets.push_back( bone_data->bones[bi].offset );
-	}
-
-	delete bone_data;
-	delete strings;
+	m_node_data = loader->release_mesh_nodes_data();
 }
 
-nv::nmd_temp_model::~nmd_temp_model()
+nv::nmd_temp_model_data::~nmd_temp_model_data()
 {
 	for ( unsigned m = 0; m < m_mesh_data.size(); ++m )
@@ -291,3 +174,4 @@
 		delete m_mesh_data[m];
 	}
+	delete m_node_data;
 }
