Index: /trunk/nv/formats/assimp_loader.hh
===================================================================
--- /trunk/nv/formats/assimp_loader.hh	(revision 290)
+++ /trunk/nv/formats/assimp_loader.hh	(revision 291)
@@ -16,76 +16,28 @@
 namespace nv 
 {
-	struct assimp_key_p  { float time; vec3 position; };
-	struct assimp_key_r  { float time; quat rotation; };
-	struct assimp_key_s  { float time; vec3 scale; };
-	struct assimp_key_tr { transform tform; };
-
-
-	struct assimp_bone
-	{
-		string name;
-		mat4   offset;
-
-		assimp_bone(){}
-		assimp_bone( const string& n, const mat4& m ) : name(n), offset(m) {}
-	};
-
-	struct assimp_model
-	{
-		std::vector< mesh_data* >  meshes;
-		std::vector< assimp_bone > bones;
-	};
-
-	struct assimp_animated_node_data
-	{
-		std::string           name;
-		sint32                parent_id;
-		mat4                  transform;
-		key_data*             data;
-
-		assimp_animated_node_data() 
-			: name(), parent_id( -1 ), data( nullptr )
-		{
-		}
-		~assimp_animated_node_data() 
-		{
-			if ( data ) delete data;
-		}
-	};
-
-	struct assimp_animation
-	{
-		uint16 frame_rate;
-		float  duration;
-		bool   flat;
-		uint32 max_frames;
-		dynamic_array< assimp_animated_node_data > nodes;
-	};
 
 	class assimp_loader : public mesh_loader
 	{
 	public:
-		assimp_loader( const string& a_ext, const mat3& a_rotate_transform, float a_scale, uint32 a_assimp_flags = 0 );
-		explicit assimp_loader( const string& a_ext, uint32 a_assimp_flags = 0 );
+		assimp_loader( const string& a_ext, const mat3& a_rotate_transform, float a_scale, bool pre_transform, uint32 a_assimp_flags = 0 );
+		assimp_loader( const string& a_ext, bool pre_transform, uint32 a_assimp_flags = 0 );
 		virtual bool load( stream& source );
 		virtual mesh_data* release_mesh_data( size_t index = 0 );
 		virtual size_t get_mesh_count() const { return m_mesh_count; }
 		virtual ~assimp_loader();
-		// TODO: remove
-		assimp_model* release_merged_model();
-		// TODO: implement release_mesh_nodes_data
 		virtual mesh_data_pack* release_mesh_data_pack();
-		assimp_animation* release_animation( size_t index, bool pre_transform );
-		// TODO: implement
-		virtual mesh_nodes_data* release_mesh_nodes_data();
-		bool load_bones( size_t index, std::vector< assimp_bone >& bones );
+		virtual size_t get_nodes_data_count() const;
+		virtual mesh_nodes_data* release_mesh_nodes_data( size_t index = 0 );
+		mesh_nodes_data* release_animation( size_t index );
 		void scene_report() const;
 	private:
+		mesh_nodes_data* release_merged_bones( mesh_data* meshes );
+		bool load_bones( size_t index, std::vector< mesh_node_data >& bones );
 		void load_mesh_data( mesh_data* data, size_t index );
 		void initialize( const string& a_ext, const mat3& a_rotate_transform, float a_scale, uint32 a_assimp_flags );
-		uint32 load_node( assimp_animation* data, const void* vnode, sint32 this_id, sint32 parent_id );
+		sint16 load_node( uint32 anim_id, mesh_node_data* nodes, const void* vnode, sint16 this_id, sint16 parent_id, uint32& max_frames );
 		uint32 count_nodes( const void* node ) const;
-		void create_transformed_keys( assimp_animated_node_data* data, const void* vnode, const assimp_animated_node_data* parent );
-		void create_direct_keys( assimp_animated_node_data* data, const void* vnode );
+		void create_transformed_keys( mesh_node_data* data, const void* vnode, const mesh_node_data* parent );
+		void create_direct_keys( mesh_node_data* data, const void* vnode );
 
 		string_table_creator m_strings;
@@ -95,6 +47,7 @@
 		float  m_scale;
 		uint32 m_assimp_flags;
+		const void* m_scene;
 		size_t m_mesh_count;
-		const void* m_scene;
+		bool   m_flat;
 	};
 
Index: /trunk/nv/formats/md3_loader.hh
===================================================================
--- /trunk/nv/formats/md3_loader.hh	(revision 290)
+++ /trunk/nv/formats/md3_loader.hh	(revision 291)
@@ -39,5 +39,6 @@
 		virtual size_t get_mesh_count() const { return 1; }
 		size_t get_max_frames() const;
-		virtual mesh_nodes_data* release_mesh_nodes_data();
+		virtual size_t get_nodes_data_count() const { return 1; }
+		virtual mesh_nodes_data* release_mesh_nodes_data( size_t = 0 );
 	private:
 		void release_mesh_frame( mesh_data* data, sint32 frame );
Index: /trunk/nv/formats/md5_loader.hh
===================================================================
--- /trunk/nv/formats/md5_loader.hh	(revision 290)
+++ /trunk/nv/formats/md5_loader.hh	(revision 291)
@@ -56,5 +56,6 @@
 		virtual bool load( stream& source );
 		virtual mesh_data* release_mesh_data( size_t index = 0 );
-		virtual mesh_nodes_data* release_mesh_nodes_data();
+		virtual size_t get_nodes_data_count() const { return 1; }
+		virtual mesh_nodes_data* release_mesh_nodes_data( size_t = 0 );
 		virtual mesh_data_pack* release_mesh_data_pack();
 		virtual size_t get_mesh_count() const { return m_meshes.size(); }
Index: /trunk/nv/formats/nmd_loader.hh
===================================================================
--- /trunk/nv/formats/nmd_loader.hh	(revision 290)
+++ /trunk/nv/formats/nmd_loader.hh	(revision 291)
@@ -72,5 +72,6 @@
 		virtual bool load( stream& source );
 		virtual mesh_data* release_mesh_data( size_t index = 0 );
-		virtual mesh_nodes_data* release_mesh_nodes_data();
+		virtual size_t get_nodes_data_count() const { return 1; }
+		virtual mesh_nodes_data* release_mesh_nodes_data( size_t = 0 );
 		virtual mesh_data_pack* release_mesh_data_pack();
 		virtual size_t get_mesh_count() const { return m_meshes.size(); }
@@ -90,19 +91,4 @@
 	};
 
-	// TODO: Temporary, find a better way and remove!
-	class nmd_temp_model_data
-	{
-		friend class nmd_temp_animation_data;
-	public:
-		nmd_temp_model_data( nmd_loader* loader );
-		const mesh_data* get_data( uint32 index ) const { return m_mesh_data[index]; }
-		uint32 get_count() const { return m_mesh_data.size(); }
-		const mesh_nodes_data* get_node_data() const { return m_node_data; }
-		~nmd_temp_model_data();
-	private:
-		std::vector< mesh_data*> m_mesh_data;
-		mesh_nodes_data*         m_node_data;
-	};
-
 }
 
Index: /trunk/nv/interface/mesh_loader.hh
===================================================================
--- /trunk/nv/interface/mesh_loader.hh	(revision 290)
+++ /trunk/nv/interface/mesh_loader.hh	(revision 291)
@@ -123,5 +123,6 @@
 		virtual mesh_data_pack* release_mesh_data_pack() = 0;
 		virtual size_t get_mesh_count() const = 0;
-		virtual mesh_nodes_data* release_mesh_nodes_data() { return nullptr; }
+		virtual size_t get_nodes_data_count() const { return 0; }
+		virtual mesh_nodes_data* release_mesh_nodes_data( size_t = 0 ) { return nullptr; }
 	};
 
Index: /trunk/src/formats/assimp_loader.cc
===================================================================
--- /trunk/src/formats/assimp_loader.cc	(revision 290)
+++ /trunk/src/formats/assimp_loader.cc	(revision 291)
@@ -15,10 +15,18 @@
 const int MAX_BONES = 64;
 
-nv::assimp_loader::assimp_loader( const string& a_ext, const mat3& a_rotate_transform, float a_scale, uint32 a_assimp_flags /*= 0 */ ) : m_mesh_count(0), m_scene( nullptr )
+struct assimp_key_p  { float time; vec3 position; };
+struct assimp_key_r  { float time; quat rotation; };
+struct assimp_key_s  { float time; vec3 scale; };
+struct assimp_key_tr { transform tform; };
+
+
+nv::assimp_loader::assimp_loader( const string& a_ext, const mat3& a_rotate_transform, float a_scale, bool pre_transform, uint32 a_assimp_flags /*= 0 */ ) 
+	: m_scene( nullptr ), m_flat( pre_transform ), m_mesh_count(0)
 {
 	initialize( a_ext, a_rotate_transform, a_scale, a_assimp_flags );
 }
 
-nv::assimp_loader::assimp_loader( const string& a_ext, uint32 a_assimp_flags /*= 0 */ ) : m_mesh_count(0), m_scene( nullptr )
+nv::assimp_loader::assimp_loader( const string& a_ext, bool pre_transform, uint32 a_assimp_flags /*= 0 */ ) 
+	: m_scene( nullptr ), m_flat( pre_transform ), m_mesh_count(0)
 {
 	initialize( a_ext, mat3(), 1.0f, a_assimp_flags );
@@ -162,10 +170,9 @@
 }
 
-bool nv::assimp_loader::load_bones( size_t index, std::vector< assimp_bone >& bones )
+bool nv::assimp_loader::load_bones( size_t index, std::vector< mesh_node_data >& bones )
 {
 	if ( m_scene == nullptr ) return false;
 	const aiScene* scene = (const aiScene*)m_scene;
 	const aiMesh*  mesh  = scene->mMeshes[ index ];
-	if ( mesh->mNumBones == 0 ) return false;
 
 	mat4 bone_transform     = mat4( ( 1.f/m_scale * m_ri33 ) ); 
@@ -176,5 +183,9 @@
 		aiBone* bone   = mesh->mBones[m];
 		mat4    offset = bone_pre_transform * assimp_mat4_cast( bone->mOffsetMatrix ) * bone_transform;
-		bones.emplace_back( bone->mName.data, offset );
+		bones[m].name = bone->mName.data;
+		bones[m].data = nullptr;
+		bones[m].parent_id = -1;
+		bones[m].target_id = -1;
+		bones[m].transform = offset;
 	}
 	return true;
@@ -256,89 +267,88 @@
 }
 
-assimp_model* nv::assimp_loader::release_merged_model()
-{
-	if ( m_scene == nullptr || m_mesh_count == 0 ) return nullptr;
-	assimp_model* model = new assimp_model;
-
-	for ( size_t m = 0; m < m_mesh_count; ++m )
-	{
-		model->meshes.push_back( release_mesh_data(m) );
-	}
-
+mesh_nodes_data* nv::assimp_loader::release_merged_bones( mesh_data* meshes )
+{
+	const aiScene* scene = (const aiScene*)m_scene;
+	std::vector< mesh_node_data > final_bones;
 	std::unordered_map< std::string, uint16 > names;
-	for ( unsigned int m = 0; m < model->meshes.size(); ++m )
+	for ( unsigned int m = 0; m < m_mesh_count; ++m )
 	{
 		sint16 translate[MAX_BONES];
-		std::vector< assimp_bone > bones;
-		load_bones( m, bones );
-		for ( unsigned int b = 0; b < bones.size(); ++b )
-		{
-
-			assimp_bone& bone = bones[b];
-			auto iname = names.find( bone.name );
-			if ( iname == names.end() )
+		std::vector< mesh_node_data > bones;
+		const aiMesh*  mesh  = scene->mMeshes[ m ];
+		if ( mesh->mNumBones != 0 )
+		{
+			bones.resize( mesh->mNumBones );
+			load_bones( m, bones );
+			for ( unsigned int b = 0; b < mesh->mNumBones; ++b )
 			{
-				NV_ASSERT( model->bones.size() < MAX_BONES, "Too many bones to merge!" );
-				sint16 index = (sint16)model->bones.size();
-				model->bones.push_back( bone );
-				names[ bone.name ] = index;
-				translate[b] = index;
+
+				mesh_node_data& bone = bones[b];
+				auto iname = names.find( bone.name );
+				if ( iname == names.end() )
+				{
+					NV_ASSERT( final_bones.size() < MAX_BONES, "Too many bones to merge!" );
+					sint16 index = (sint16)final_bones.size();
+					final_bones.push_back( bone );
+					names[ bone.name ] = index;
+					translate[b] = index;
+				}
+				else
+				{
+					translate[b] = (sint16)iname->second;
+				}
 			}
-			else
+			if ( m > 0 && bones.size() > 0 )
 			{
-				translate[b] = (sint16)iname->second;
-			}
-		}
-		if ( m > 0 && bones.size() > 0 )
-		{
-			mesh_data* mesh = model->meshes[m];
-			mesh_raw_channel* channel = mesh->get_raw_channels()[0];
-			NV_ASSERT( !channel->is_index(), "index channel in release_merged!" );
-			assimp_skinned_vtx* va = (assimp_skinned_vtx*)channel->data;
-			for ( unsigned v = 0; v < channel->count; ++v )
-			{
-				assimp_skinned_vtx& vertex = va[v];
-
-				for (uint32 i = 0 ; i < 4; ++i)
+				mesh_raw_channel* channel = meshes[m].get_raw_channels()[0];
+				NV_ASSERT( !channel->is_index(), "index channel in release_merged!" );
+				assimp_skinned_vtx* va = (assimp_skinned_vtx*)channel->data;
+				for ( unsigned v = 0; v < channel->count; ++v )
 				{
-					if ( vertex.boneweight[i] > 0.0f ) 
+					assimp_skinned_vtx& vertex = va[v];
+
+					for (uint32 i = 0 ; i < 4; ++i)
 					{
-						vertex.boneindex[i] = translate[vertex.boneindex[i]];
+						if ( vertex.boneweight[i] > 0.0f ) 
+						{
+							vertex.boneindex[i] = translate[vertex.boneindex[i]];
+						}
 					}
 				}
 			}
-		}
-	}
-	return model;
-}
-
-assimp_animation* nv::assimp_loader::release_animation( size_t, bool pre_transform )
+		}	
+	}
+	mesh_node_data* bones = new mesh_node_data[ final_bones.size() ];
+	std::copy( final_bones.begin(), final_bones.end(), bones );
+	return new mesh_nodes_data( "bones", final_bones.size(), bones );
+}
+
+mesh_nodes_data* nv::assimp_loader::release_animation( size_t index )
 {
 	if ( m_scene == nullptr ) return nullptr;
 	const aiScene* scene = (const aiScene*)m_scene;
-	if ( scene->mRootNode == nullptr || scene->mAnimations == nullptr || scene->mAnimations[0] == nullptr) return nullptr;
-	assimp_animation* result = new assimp_animation;
-
-	// need resize not to copy!
-	result->nodes.resize( count_nodes( scene->mRootNode ) );
+	if ( scene->mRootNode == nullptr || scene->mAnimations == nullptr || scene->mAnimations[index] == nullptr) return nullptr;
 
 	const aiNode*      root = scene->mRootNode;
-	const aiAnimation* anim = scene->mAnimations[0]; // if implemented, change in load_node also
-
-	result->frame_rate     = (uint16)anim->mTicksPerSecond;
-	result->duration       = (float)anim->mDuration;
-	result->flat           = pre_transform;
-	result->max_frames     = 0;
-
-	load_node( result, root, 0, -1 );
+	const aiAnimation* anim = scene->mAnimations[index];
+
+	uint32 count = count_nodes( scene->mRootNode );
+	mesh_node_data* data    = new mesh_node_data[count];
+
+	uint16 frame_rate     = (uint16)anim->mTicksPerSecond;
+	float  duration       = (float)anim->mDuration;
+	bool   flat           = m_flat;
+	uint32 max_frames     = 0;
+
+	load_node( index, data, root, 0, -1, max_frames );
 
 	// DAE pre_transform hack
-	if ( result->flat && result->frame_rate == 1 )
-	{
-		result->frame_rate = 32;
-		result->duration   = (float)result->max_frames;
-	}
-
-	return result;
+	if ( m_flat && frame_rate == 1 )
+	{
+		frame_rate = 32;
+		duration   = (float)max_frames;
+	}
+
+	return new mesh_nodes_data( anim->mName.data, count, data, frame_rate, duration, flat ) ;
 }
 
@@ -354,10 +364,10 @@
 }
 
-nv::uint32 nv::assimp_loader::load_node( assimp_animation* data, const void* vnode, sint32 this_id, sint32 parent_id )
+nv::sint16 nv::assimp_loader::load_node( uint32 anim_id, mesh_node_data* nodes, const void* vnode, sint16 this_id, sint16 parent_id, uint32& max_frames )
 {
 	const aiScene* scene = (const aiScene*)m_scene;
 	const aiNode*  node  = (const aiNode*)vnode;
 	string name( node->mName.data );
-	const aiAnimation* anim  = scene->mAnimations[0];
+	const aiAnimation* anim  = scene->mAnimations[anim_id];
 	const aiNodeAnim*  anode = nullptr;
 
@@ -369,7 +379,8 @@
 	}
 
-	assimp_animated_node_data& a_data = data->nodes[ this_id ];
+	mesh_node_data& a_data = nodes[ this_id ];
 
 	a_data.name      = name;
+	a_data.target_id = -1;
 	a_data.parent_id = parent_id;
 	// This value is ignored by the create_transformed_keys, but needed by create_direct_keys!
@@ -384,7 +395,7 @@
 	if (anode) 
 	{
-		if ( data->flat )
-		{
-			create_transformed_keys( &a_data, anode, parent_id >= 0 ? &(data->nodes[ parent_id ]) : nullptr );
+		if ( m_flat )
+		{
+			create_transformed_keys( &a_data, anode, parent_id >= 0 ? &(nodes[ parent_id ]) : nullptr );
 		}
 		else
@@ -392,11 +403,11 @@
 			create_direct_keys( &a_data, anode );
 		}
-		data->max_frames = glm::max<uint32>( a_data.data->get_channel(0)->count, data->max_frames );
-	}
-
-	nv::uint32 next = this_id + 1;
+		max_frames = glm::max<uint32>( a_data.data->get_channel(0)->count, max_frames );
+	}
+
+	nv::sint16 next = this_id + 1;
 	for ( unsigned i = 0; i < node->mNumChildren; ++i )
 	{
-		next = load_node( data, node->mChildren[i], next, this_id );
+		next = load_node( anim_id, nodes, node->mChildren[i], next, this_id, max_frames );
 	}
 
@@ -404,5 +415,5 @@
 }
 
-void nv::assimp_loader::create_transformed_keys( assimp_animated_node_data* data, const void* vnode, const assimp_animated_node_data* parent )
+void nv::assimp_loader::create_transformed_keys( mesh_node_data* data, const void* vnode, const mesh_node_data* parent )
 {
 	const aiNodeAnim* node = (const aiNodeAnim*)vnode;
@@ -436,5 +447,5 @@
 }
 
-void nv::assimp_loader::create_direct_keys( assimp_animated_node_data* data, const void* vnode )
+void nv::assimp_loader::create_direct_keys( mesh_node_data* data, const void* vnode )
 {
 	const aiNodeAnim* node = (const aiNodeAnim*)vnode;
@@ -489,16 +500,30 @@
 mesh_data_pack* nv::assimp_loader::release_mesh_data_pack()
 {
+	if ( m_scene == nullptr || m_mesh_count == 0 ) return nullptr;
+	const aiScene* scene = (const aiScene*)m_scene;
+	bool has_bones = false;
 	mesh_data* meshes = new mesh_data[ m_mesh_count ];
-	for ( uint32 i = 0; i < m_mesh_count; ++i )
-	{
-		load_mesh_data(&meshes[i],i);
-	}
-	return new mesh_data_pack( m_mesh_count, meshes, release_mesh_nodes_data() );
-}
-
-mesh_nodes_data* nv::assimp_loader::release_mesh_nodes_data()
-{
-	// TODO: implement
-	return nullptr;
-}
-
+	for ( size_t m = 0; m < m_mesh_count; ++m )
+	{
+		const aiMesh* mesh = scene->mMeshes[ m ];
+		meshes[m].set_name( mesh->mName.data );
+		if ( mesh->mNumBones > 0 ) has_bones = true;
+		load_mesh_data(&meshes[m],m);
+	}
+
+	mesh_nodes_data* nodes = ( has_bones ? release_merged_bones( meshes ) : release_animation(0) );
+	return new mesh_data_pack( m_mesh_count, meshes, nodes );
+}
+
+size_t nv::assimp_loader::get_nodes_data_count() const
+{
+	if ( m_scene == nullptr ) return 0;
+	const aiScene* scene = (const aiScene*)m_scene;
+	return scene->mNumAnimations;	
+}
+
+mesh_nodes_data* nv::assimp_loader::release_mesh_nodes_data( size_t index /*= 0 */ )
+{
+	return release_animation( index );
+}
+
Index: /trunk/src/formats/md3_loader.cc
===================================================================
--- /trunk/src/formats/md3_loader.cc	(revision 290)
+++ /trunk/src/formats/md3_loader.cc	(revision 291)
@@ -402,5 +402,5 @@
 }
 
-mesh_nodes_data* nv::md3_loader::release_mesh_nodes_data()
+mesh_nodes_data* nv::md3_loader::release_mesh_nodes_data( size_t )
 {
 	md3_t* md3 = (md3_t*)m_md3;
Index: /trunk/src/formats/md5_loader.cc
===================================================================
--- /trunk/src/formats/md5_loader.cc	(revision 290)
+++ /trunk/src/formats/md5_loader.cc	(revision 291)
@@ -504,5 +504,5 @@
 }
 
-mesh_nodes_data* nv::md5_loader::release_mesh_nodes_data()
+mesh_nodes_data* nv::md5_loader::release_mesh_nodes_data( size_t )
 {
 	mesh_nodes_data* nodes = m_nodes;
Index: /trunk/src/formats/nmd_loader.cc
===================================================================
--- /trunk/src/formats/nmd_loader.cc	(revision 290)
+++ /trunk/src/formats/nmd_loader.cc	(revision 291)
@@ -138,5 +138,5 @@
 }
 
-mesh_nodes_data* nv::nmd_loader::release_mesh_nodes_data()
+mesh_nodes_data* nv::nmd_loader::release_mesh_nodes_data( size_t )
 {
 	if ( m_node_data )
@@ -157,21 +157,2 @@
 }
 
-// TEMPORARY
-
-nv::nmd_temp_model_data::nmd_temp_model_data( nmd_loader* loader )
-{
-	for ( unsigned m = 0; m < loader->get_mesh_count(); ++m )
-	{
-		m_mesh_data.push_back(loader->release_mesh_data(m));
-	}
-	m_node_data = loader->release_mesh_nodes_data();
-}
-
-nv::nmd_temp_model_data::~nmd_temp_model_data()
-{
-	for ( unsigned m = 0; m < m_mesh_data.size(); ++m )
-	{
-		delete m_mesh_data[m];
-	}
-	delete m_node_data;
-}
