Index: trunk/src/formats/assimp_loader.cc
===================================================================
--- trunk/src/formats/assimp_loader.cc	(revision 287)
+++ 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 );
+}
+
