Index: trunk/src/gfx/skeleton_instance.cc
===================================================================
--- trunk/src/gfx/skeleton_instance.cc	(revision 484)
+++ trunk/src/gfx/skeleton_instance.cc	(revision 485)
@@ -8,4 +8,11 @@
 
 #include "nv/core/profiler.hh"
+
+void nv::skeleton_binding::assign( const skeleton_binding& other )
+{
+	m_indices.assign( other.m_indices );
+	m_key        = other.m_key;
+	m_bone_count = other.m_bone_count;
+}
 
 void nv::skeleton_binding::prepare( const mesh_nodes_data* node_data, const data_node_list& bone_data )
@@ -45,9 +52,55 @@
 }
 
+void nv::skeleton_binding::prepare( const data_node_list& pose_data, const data_node_list& bone_data )
+{
+	if ( m_indices.empty() )
+	{
+		// TODO: either fixed size struct or static allocator
+		hash_store< shash64, uint16 > bone_names;
+		m_indices.resize( pose_data.size() );
+
+		for ( nv::uint16 bi = 0; bi < bone_data.size(); ++bi )
+			bone_names[bone_data[bi].name] = bi;
+
+		for ( uint32 n = 0; n < pose_data.size(); ++n )
+		{
+			sint16 bone_id = -1;
+			auto bi = bone_names.find( pose_data[ n ].name );
+			if ( bi != bone_names.end() )
+			{
+				bone_id = sint16( bi->second );
+			}
+			m_indices[n] = bone_id;
+
+		}
+		m_bone_count = bone_data.size();
+	}
+}
+
+
+void nv::skeleton_instance::assign( const skeleton_transforms& skeleton, const skeleton_binding& binding, const bone_transforms& bones )
+{
+	if ( bones.size() != m_matrix.size() )
+		m_matrix.resize( bones.size() );
+	const transform* transforms = skeleton.xforms();
+	for ( uint32 n = 0; n < skeleton.size(); ++n )
+	{
+		sint16 bone_id = binding.m_indices[n];
+		if ( bone_id >= 0 )
+		{
+			int too_complex;
+			transform tr( bones.m_offsets[bone_id] );
+			tr.set_orientation( normalize( tr.get_orientation() ) );
+			m_matrix[bone_id] = ( transforms[n] * tr ).extract();
+		}
+	}
+}
+
+
 void nv::skeleton_instance::assign( const skeleton_transforms& skeleton, const bone_transforms& bones )
 {
 	if ( bones.size() != m_matrix.size() ) 
 		m_matrix.resize( bones.size() );
-	const transform* transforms = skeleton.transforms();
+	const transform* transforms = skeleton.xforms();
 	for ( uint32 n = 0; n < skeleton.size(); ++n )
 	{
@@ -90,6 +143,6 @@
 	}
 
-	if ( m_transforms.size() > 0 )
-		m_transforms[0] = nv::interpolate( a.m_transforms[0], b.m_transforms[0], t );
+//  	if ( m_transforms.size() > 0 )
+//  		m_transforms[0] = nv::interpolate( a.m_transforms[0], b.m_transforms[0], t, interpolation::SPHERICAL );
 }
 
@@ -107,7 +160,4 @@
 			);
 	}
-
-	if ( m_transforms.size() > 0 )
-		m_transforms[0] = nv::interpolate( a.m_transforms[0], b.m_transforms[0], t );
 }
 
@@ -120,7 +170,21 @@
 	for ( uint32 n = 0; n < a.size(); ++n )
 	{
-		m_transforms[n] = nv::interpolate( a.m_transforms[n], b.m_transforms[n], t );
-	}
-}
+		m_transforms[n] = nv::interpolate( a.m_transforms[n], b.m_transforms[n], t, interpolation::SPHERICAL );
+	}
+}
+
+void nv::skeleton_transforms::blend_slerp( const skeleton_transforms& a, const skeleton_transforms& b, float t, float blend )
+{
+	NV_ASSERT( a.size() == b.size(), "!!!" );
+	if ( m_transforms.size() != a.size() )
+		m_transforms.resize( a.size() );
+	for ( uint32 n = 0; n < a.size(); ++n )
+	{
+		transform tr    = nv::interpolate( a.m_transforms[n], b.m_transforms[n], t, interpolation::SPHERICAL );
+		m_transforms[n] = nv::interpolate( m_transforms[n], tr, blend, interpolation::SPHERICAL );
+	}
+}
+
+
 
 void nv::skeleton_transforms::interpolate4( const skeleton_transforms& s1, const skeleton_transforms& v1, const skeleton_transforms& v2, const skeleton_transforms& s2, float t )
@@ -155,7 +219,4 @@
 		qr = normalize( qr );
 
- 		if ( n == 0 ) 
-			qr = nv::math::slerp( v1.m_transforms[n].get_orientation(), v2.m_transforms[n].get_orientation(), t );
-
 		m_transforms[n] = transform(
 			weights[0] * s1.m_transforms[n].get_position() +
@@ -181,13 +242,12 @@
 		nv::quat ss1 = s1.m_transforms[n].get_orientation();
 		nv::quat ss2 = s2.m_transforms[n].get_orientation();
+		nv::quat sv1 = v1.m_transforms[n].get_orientation();
+		nv::quat sv2 = v2.m_transforms[n].get_orientation();
+
 		nv::quat q = normalize( nv::math::squad(
-			v1.m_transforms[n].get_orientation(),
-			v2.m_transforms[n].get_orientation(),
-			nv::math::intermediate( ss1, v1.m_transforms[n].get_orientation(), v2.m_transforms[n].get_orientation() ),
-			nv::math::intermediate( v1.m_transforms[n].get_orientation(), v2.m_transforms[n].get_orientation(), ss2 ),
+			sv1, sv2,
+			nv::math::intermediate( ss1, sv1, sv2 ),
+			nv::math::intermediate( sv1, sv2, ss2 ),
 			t ) );
-		if ( n == 0 ) q = nv::math::slerp(
-			v1.m_transforms[n].get_orientation(),
-			v2.m_transforms[n].get_orientation(), t );
 
 		m_transforms[n] = transform(
@@ -196,5 +256,5 @@
 			);
 	}
-
+	
 }
 
@@ -204,102 +264,85 @@
 }
 
-void nv::skeleton_transforms::animate_local( const mesh_nodes_data* node_data, const skeleton_binding& binding, float frame )
-{
-	if ( m_transforms.size() != binding.skeleton_size() )
-		m_transforms.resize( binding.skeleton_size() );
-	for ( uint32 n = 0; n < node_data->size(); ++n )
-	{
-		const data_channel_set* node = ( *node_data )[n];
-		sint16 bone_id = binding.m_indices[n];
-		if ( bone_id >= 0 )
-		{
-			if ( node->size() > 0 )
-			{
-				m_transforms[bone_id] = raw_channel_interpolator( node, binding.m_key ).get< transform >( frame );
-			}
-			int confirm_that_not_needed;
-// 			else
-// 				m_transforms[bone_id] = transform( node->get_transform() );
-		}
-	}
-}
-
-void nv::skeleton_transforms::blend_local( const mesh_nodes_data* node_data, const skeleton_binding& binding, float frame, float blend )
-{
-	if ( m_transforms.size() != binding.skeleton_size() )
-		m_transforms.resize( binding.skeleton_size() );
-	for ( uint32 n = 0; n < node_data->size(); ++n )
-	{
-		const data_channel_set* node = ( *node_data )[n];
-		sint16 bone_id = binding.m_indices[n];
-		if ( bone_id >= 0 )
-		{
-			
-			transform tr = node->size() > 0 ? raw_channel_interpolator( node, binding.m_key ).get< transform >( frame ) : transform( /*node->get_transform()*/ ); int confirm_that_not_needed;
-			m_transforms[bone_id] = nv::interpolate( m_transforms[bone_id], tr, blend );
-		}
-	}
-}
-
-void nv::skeleton_transforms::delocalize_rec( const data_node_tree& node_data, const skeleton_binding& binding, uint32 id, const transform& parent )
-{
-	sint16 bone_id = binding.m_indices[id];
+// void nv::skeleton_transforms::blend_local( const mesh_nodes_data* node_data, float frame, float blend )
+// {
+// 	if ( m_transforms.size() != node_data->size() )
+// 		m_transforms.resize( node_data->size() );
+// 	for ( uint32 n = 0; n < node_data->size(); ++n )
+// 	{
+// 		const data_channel_set* node = ( *node_data )[n];
+// 		int inefficient_store_key;
+// 
+// 		transform tr = node->size() > 0 ? raw_channel_interpolator( node ).get< transform >( frame ) : transform( /*node->get_transform()*/ ); int confirm_that_not_needed;
+// 		m_transforms[n] = nv::interpolate( m_transforms[n], tr, blend, interpolation::SPHERICAL );
+// 	}
+// }
+// 
+// void nv::skeleton_transforms::animate_local( const mesh_nodes_data* node_data, float frame )
+// {
+// 	if ( m_transforms.size() != node_data->size() )
+// 		m_transforms.resize( node_data->size() );
+// 	for ( uint32 n = 0; n < node_data->size(); ++n )
+// 	{
+// 		const data_channel_set* node = ( *node_data )[n];
+// 		if ( node->size() > 0 )
+// 		{
+// 			int inefficient_store_key;
+// 			m_transforms[n] = raw_channel_interpolator( node ).get< transform >( frame );
+// 		}
+// 	}
+// }
+
+void nv::skeleton_transforms::delocalize_rec( const data_node_tree& node_data, uint32 id, const transform& parent )
+{
 	transform global_mat = parent;
-	if ( bone_id >= 0 )
-	{
-		global_mat *= m_transforms[bone_id];
-		m_transforms[bone_id] = global_mat;
-	}
+	global_mat *= m_transforms[id];
+	m_transforms[id] = global_mat;
 	for ( auto child : node_data.children( id ) )
 	{
-		delocalize_rec( node_data, binding, child, global_mat );
-	}
-}
-
-void nv::skeleton_transforms::animate_rec( const mesh_nodes_data* node_data, const skeleton_binding& binding, float frame, uint32 id, const transform& parent, bool local )
-{
-	const data_channel_set* node = ( *node_data )[id];
-	transform node_mat;
-
-	if ( node->size() > 0 )
-		node_mat = raw_channel_interpolator( node, binding.m_key ).get< transform >( frame );
-	int confirm_that_not_needed;
-	// 	else
-// 		node_mat = transform( node->get_transform() );
-	sint16 bone_id = binding.m_indices[id];
-	transform global_mat = parent * node_mat;
-	if ( bone_id >= 0 )
-	{
-		m_transforms[bone_id] = local ? node_mat : global_mat;
-	}
-	for ( auto child : node_data->children( id ) )
-	{
-		animate_rec( node_data, binding, frame, child, global_mat, local );
-	}
-}
-
-void nv::skeleton_transforms::blend_rec( const mesh_nodes_data* node_data, const skeleton_binding& binding, float frame, uint32 id, const transform& parent, bool local, float blend )
-{
-	const data_channel_set* node = ( *node_data )[id];
-	int confirm_that_not_needed;
-	transform node_mat/*( node->get_transform() )*/;
-
-	if ( node->size() > 0 )
-	{
-		raw_channel_interpolator interpolator( node, binding.m_key );
-		node_mat = interpolator.get< transform >( frame );
-	}
-	sint16 bone_id = binding.m_indices[id];
-	transform global_mat = parent * node_mat;
-	if ( bone_id >= 0 )
-	{
-		m_transforms[bone_id] = nv::interpolate( m_transforms[bone_id], local ? node_mat : global_mat, blend );
-	}
-	for ( auto child : node_data->children( id ) )
-	{
-		blend_rec( node_data, binding, frame, child, global_mat, local, blend );
-	}
-}
-
+		delocalize_rec( node_data, child, global_mat );
+	}
+}
+
+// void nv::skeleton_transforms::blend_rec( const mesh_nodes_data* node_data, float frame, uint32 id, const transform& parent, bool local, float blend )
+// {
+// 	const data_channel_set* node = ( *node_data )[id];
+// 	int confirm_that_not_needed;
+// 	transform node_mat/*( node->get_transform() )*/;
+// 
+// 	if ( node->size() > 0 )
+// 	{
+// 		int inefficient_store_key;
+// 
+// 		raw_channel_interpolator interpolator( node );
+// 		node_mat = interpolator.get< transform >( frame );
+// 	}
+// 	transform global_mat = parent * node_mat;
+// 	m_transforms[id] = nv::interpolate( m_transforms[id], local ? node_mat : global_mat, blend, interpolation::SPHERICAL );
+// 	for ( auto child : node_data->children( id ) )
+// 	{
+// 		blend_rec( node_data, frame, child, global_mat, local, blend );
+// 	}
+// 
+// }
+// 
+// void nv::skeleton_transforms::animate_rec( const mesh_nodes_data* node_data, float frame, uint32 id, const transform& parent, bool local )
+// {
+// 	const data_channel_set* node = ( *node_data )[id];
+// 	transform node_mat;
+// 	int inefficient_store_key;
+// 
+// 	if ( node->size() > 0 )
+// 		node_mat = raw_channel_interpolator( node ).get< transform >( frame );
+// 	int confirm_that_not_needed;
+// 	// 	else
+// 	// 		node_mat = transform( node->get_transform() );
+// 	transform global_mat = parent * node_mat;
+// 	m_transforms[id] = local ? node_mat : global_mat;
+// 	for ( auto child : node_data->children( id ) )
+// 	{
+// 		animate_rec( node_data, frame, child, global_mat, local );
+// 	}
+// 
+// }
 
 void nv::bone_transforms::prepare( const data_node_list& bone_data )
