Index: trunk/src/gfx/skeleton_instance.cc
===================================================================
--- trunk/src/gfx/skeleton_instance.cc	(revision 475)
+++ trunk/src/gfx/skeleton_instance.cc	(revision 477)
@@ -7,78 +7,74 @@
 #include "nv/gfx/skeleton_instance.hh"
 
-void nv::skeleton_instance::prepare( const mesh_nodes_data* bones )
+void nv::skeleton_binding::prepare( const mesh_nodes_data* node_data, const mesh_nodes_data* bone_data )
 {
-	if ( m_offsets || m_indices ) return;
-	hash_store< shash64, uint16 > bone_names;
-	m_offsets = new mat4[bones->size()];
-	m_indices = new sint16[m_data->size()];
+	if ( !m_offsets || !m_indices )
+	{
+		// TODO: either fixed size struct or static allocator
+		hash_store< shash64, uint16 > bone_names;
+		m_offsets = new mat4[bone_data->size()];
+		m_indices = new sint16[node_data->size()];
 
-	for ( nv::uint16 bi = 0; bi < bones->size(); ++bi )
-	{
-		const data_channel_set* bone = ( *bones )[bi];
-		bone_names[bone->get_name()] = bi;
-		m_offsets[bi] = bone->get_transform();
+		for ( nv::uint16 bi = 0; bi < bone_data->size(); ++bi )
+		{
+			const data_channel_set* bone = ( *bone_data )[bi];
+			bone_names[bone->get_name()] = bi;
+			m_offsets[bi] = bone->get_transform();
+		}
+
+		for ( uint32 n = 0; n < node_data->size(); ++n )
+		{
+			const data_channel_set* node = ( *node_data )[n];
+			sint16 bone_id = -1;
+
+			auto bi = bone_names.find( node->get_name() );
+			if ( bi != bone_names.end() )
+			{
+				bone_id = sint16( bi->second );
+			}
+			m_indices[n] = bone_id;
+
+		}
 	}
 
-	for ( uint32 n = 0; n < m_data->size(); ++n )
+	if ( m_key.size() == 0 )
 	{
-		const data_channel_set* node = ( *m_data )[n];
-		sint16 bone_id = -1;
+		for ( uint32 n = 0; n < node_data->size(); ++n )
+			if ( ( *node_data )[n]->size() > 0 )
+			{
+				m_key = ( *node_data )[n]->get_interpolation_key();
+				break;
+			}
+	}
 
-		auto bi = bone_names.find( node->get_name() );
-		if ( bi != bone_names.end() )
+}
+
+void nv::skeleton_instance::animate( const mesh_nodes_data* node_data, const skeleton_binding& binding, float frame )
+{
+	if ( m_transform.size() > 0 )
+	{
+		if ( node_data->is_flat() )
 		{
-			bone_id = sint16( bi->second );
+			animate_flat( node_data, binding, frame );
 		}
-		m_indices[n] = bone_id;
-
-		if ( m_key.size() == 0 && node->size() > 0 )
-			m_key = node->get_interpolation_key();
+		else
+		{
+			for ( uint32 n = 0; n < node_data->size(); ++n )
+				if ( ( *node_data )[n]->get_parent_id() == -1 )
+					animate_rec( node_data, binding, frame, n, mat4() );
+		}
 	}
 }
 
-void nv::skeleton_instance::animate( mat4* data, float frame ) const
-{
-	if ( m_data->is_flat() )
-	{
-		animate_flat( data, frame );
-	}
-	else
-	{
-		for ( uint32 n = 0; n < m_data->size(); ++n )
-			if ( ( *m_data )[n]->get_parent_id() == -1 )
-				animate_rec( data, frame, n, mat4() );
-	}
-}
-
-void nv::skeleton_instance::animate_flat( mat4* data, float frame ) const
-{
-	for ( uint32 n = 0; n < m_data->size(); ++n )
-		if ( m_indices[n] >= 0 )
-		{
-			const data_channel_set* node = ( *m_data )[n];
-			nv::mat4 node_mat( node->get_transform() );
-
-			if ( node->size() > 0 )
-			{
-				raw_channel_interpolator interpolator( node, m_key );
-				node_mat = interpolator.get< mat4 >( frame );
-			}
-
-			sint16 bone_id = m_indices[n];
-			data[bone_id] = node_mat * m_offsets[bone_id];
-		}
-}
-
-void nv::skeleton_instance::animate_rec( mat4* data, float frame, uint32 id, const mat4& parent ) const
+void nv::skeleton_instance::animate_rec( const mesh_nodes_data* node_data, const skeleton_binding& binding, float frame, uint32 id, const mat4& parent ) 
 {
 	// TODO: fix transforms, which are now embedded,
 	//       see note in assimp_loader.cc:load_node
-	const data_channel_set* node = ( *m_data )[id];
+	const data_channel_set* node = ( *node_data )[id];
 	mat4 node_mat( node->get_transform() );
 
 	if ( node->size() > 0 )
 	{
-		raw_channel_interpolator interpolator( node, m_key );
+		raw_channel_interpolator interpolator( node, binding.m_key );
 		node_mat = interpolator.get< mat4 >( frame );
 	}
@@ -86,13 +82,32 @@
 	mat4 global_mat = parent * node_mat;
 
-	sint16 bone_id = m_indices[id];
+	sint16 bone_id = binding.m_indices[id];
 	if ( bone_id >= 0 )
 	{
-		data[bone_id] = global_mat * m_offsets[bone_id];
+		m_transform[bone_id] = global_mat * binding.m_offsets[bone_id];
 	}
 
-	for ( auto child : m_data->children( id ) )
+	for ( auto child : node_data->children( id ) )
 	{
-		animate_rec( data, frame, child, global_mat );
+		animate_rec( node_data, binding, frame, child, global_mat );
 	}
 }
+
+void nv::skeleton_instance::animate_flat( const mesh_nodes_data* node_data, const skeleton_binding& binding, float frame ) 
+{
+	for ( uint32 n = 0; n < node_data->size(); ++n )
+		if ( binding.m_indices[n] >= 0 )
+		{
+			const data_channel_set* node = ( *node_data )[n];
+			nv::mat4 node_mat( node->get_transform() );
+
+			if ( node->size() > 0 )
+			{
+				raw_channel_interpolator interpolator( node, binding.m_key );
+				node_mat = interpolator.get< mat4 >( frame );
+			}
+
+			sint16 bone_id = binding.m_indices[n];
+			m_transform[bone_id] = node_mat * binding.m_offsets[bone_id];
+		}
+}
