Index: trunk/src/gfx/skeleton_instance.cc
===================================================================
--- trunk/src/gfx/skeleton_instance.cc	(revision 485)
+++ trunk/src/gfx/skeleton_instance.cc	(revision 486)
@@ -8,4 +8,5 @@
 
 #include "nv/core/profiler.hh"
+#include "nv/interface/interpolate.hh"
 
 void nv::skeleton_binding::assign( const skeleton_binding& other )
@@ -78,44 +79,4 @@
 }
 
-
-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.xforms();
-	for ( uint32 n = 0; n < skeleton.size(); ++n )
-	{
- 		transform tr( bones.m_offsets[n] );
- 		tr.set_orientation( normalize( tr.get_orientation() ) );
- 		m_matrix[n] = ( transforms[n] * tr ).extract();
-	//	m_matrix[n] = transforms[n].extract() * bones.m_offsets[n];
-	}
-}
-
-void nv::skeleton_instance::assign( const bone_transforms& bones )
-{
-	if ( bones.size() != m_matrix.size() )
-		m_matrix.resize( bones.size() );
-}
-
 void nv::skeleton_transforms::assign( const data_node_list* node_data )
 {
@@ -125,136 +86,81 @@
 	for ( uint32 n = 0; n < node_data->size(); ++n )
 	{
-		const data_node_info& info = (*node_data)[ n ];
-		m_transforms[n] = transform( info.transform );
+		m_transforms[n] = transform( ( *node_data )[n].transform );
 	}
 }
 
-void nv::skeleton_transforms::interpolate_linear( const skeleton_transforms& a, const skeleton_transforms& b, float t )
+void nv::skeleton_transforms::assign( const skeleton_transforms& other, const array_view< bool >& mask )
+{
+	if ( m_transforms.size() != other.size() ) m_transforms.resize( other.size() );
+	if ( mask.size() == 0 )
+		m_transforms.assign( other.m_transforms );
+	else
+		for ( uint32 i = 0; i < other.size(); ++i )
+			if ( mask[i] )
+				m_transforms[i] = other.m_transforms[i];
+}
+
+void nv::skeleton_transforms::interpolate( const skeleton_transforms& a, const skeleton_transforms& b, float t, interpolation i )
+{
+	if ( m_transforms.size() != a.size() ) m_transforms.resize( a.size() );
+	::nv::interpolate( m_transforms, t, i, a.m_transforms, b.m_transforms );
+}
+
+void nv::skeleton_transforms::interpolate( const skeleton_transforms& a, const skeleton_transforms& b, float t, interpolation i, const array_view< bool >& mask )
+{
+	if ( m_transforms.size() != a.size() ) m_transforms.resize( a.size() );
+	if ( mask.size() > 0 )
+		::nv::interpolate( m_transforms, t, i, mask, a.m_transforms, b.m_transforms );
+	else
+		::nv::interpolate( m_transforms, t, i, a.m_transforms, b.m_transforms );
+}
+
+void nv::skeleton_transforms::interpolate( const skeleton_transforms& s1, const skeleton_transforms& v1, const skeleton_transforms& v2, const skeleton_transforms& s2, float t, interpolation i )
+{
+	if ( m_transforms.size() != s1.size() ) m_transforms.resize( s1.size() );
+	::nv::interpolate( m_transforms, t, i, s1.m_transforms, v1.m_transforms, v2.m_transforms, s2.m_transforms );
+}
+
+void nv::skeleton_transforms::interpolate( const skeleton_transforms& s1, const skeleton_transforms& v1, const skeleton_transforms& v2, const skeleton_transforms& s2, float t, interpolation i, const array_view< bool >& mask )
+{
+	if ( m_transforms.size() != s1.size() ) m_transforms.resize( s1.size() );
+	if ( mask.size() > 0 )
+		::nv::interpolate( m_transforms, t, i, mask, s1.m_transforms, v1.m_transforms, v2.m_transforms, s2.m_transforms );
+	else
+		::nv::interpolate( m_transforms, t, i, s1.m_transforms, v1.m_transforms, v2.m_transforms, s2.m_transforms );
+}
+
+void nv::skeleton_transforms::blend( const skeleton_transforms& a, const skeleton_transforms& b, float t, interpolation i, float blend, interpolation bi )
 {
 	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 )
-	{
-		m_transforms[n] = transform(
-			math::mix( a.m_transforms[n].get_position(), b.m_transforms[n].get_position(), t ),
-			math::lerp( a.m_transforms[n].get_orientation(), b.m_transforms[n].get_orientation(), t )
-			);
-	}
-
-//  	if ( m_transforms.size() > 0 )
-//  		m_transforms[0] = nv::interpolate( a.m_transforms[0], b.m_transforms[0], t, interpolation::SPHERICAL );
+	::nv::interpolate( m_transforms, t, i, blend, bi, a.m_transforms, b.m_transforms );
 }
 
-void nv::skeleton_transforms::interpolate_nlerp( const skeleton_transforms& a, const skeleton_transforms& b, float t )
+void nv::skeleton_transforms::blend( const skeleton_transforms& a, const skeleton_transforms& b, float t, interpolation i, float blend, interpolation bi, const array_view< bool >& mask )
 {
 	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 )
-	{
-		m_transforms[n] = transform(
-			math::mix( a.m_transforms[n].get_position(), b.m_transforms[n].get_position(), t ),
-			math::nlerp( a.m_transforms[n].get_orientation(), b.m_transforms[n].get_orientation(), t )
-			);
-	}
+	if ( mask.size() > 0 )
+		::nv::interpolate( m_transforms, t, i, blend, bi, mask, a.m_transforms, b.m_transforms );
+	else
+		::nv::interpolate( m_transforms, t, i, blend, bi, a.m_transforms, b.m_transforms );
 }
 
-
-void nv::skeleton_transforms::interpolate_slerp( const skeleton_transforms& a, const skeleton_transforms& b, float t )
+void nv::skeleton_transforms::blend( const skeleton_transforms& s1, const skeleton_transforms& v1, const skeleton_transforms& v2, const skeleton_transforms& s2, float t, interpolation i, float blend, interpolation bi )
 {
-	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 )
-	{
-		m_transforms[n] = nv::interpolate( a.m_transforms[n], b.m_transforms[n], t, interpolation::SPHERICAL );
-	}
+	if ( m_transforms.size() != s1.size() ) m_transforms.resize( s1.size() );
+	::nv::interpolate( m_transforms, t, i, blend, bi, s1.m_transforms, v1.m_transforms, v2.m_transforms, s2.m_transforms );
 }
 
-void nv::skeleton_transforms::blend_slerp( const skeleton_transforms& a, const skeleton_transforms& b, float t, float blend )
+void nv::skeleton_transforms::blend( const skeleton_transforms& s1, const skeleton_transforms& v1, const skeleton_transforms& v2, const skeleton_transforms& s2, float t, interpolation i, float blend, interpolation bi, const array_view< bool >& mask )
 {
-	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 )
-{
-	NV_ASSERT( s1.size() == s2.size(), "!!!" );
-	NV_ASSERT( v1.size() == v2.size(), "!!!" );
-	NV_ASSERT( s1.size() == v1.size(), "!!!" );
-	if ( m_transforms.size() != s1.size() )
-		m_transforms.resize( s1.size() );
-	float interp_squared = t*t;
-	float interp_cubed = interp_squared*t;
-	float weights[4];
-	weights[0] = 0.5f * ( -interp_cubed + 2.0f * interp_squared - t );
-	weights[1] = 0.5f * ( 3.0f * interp_cubed - 5.0f * interp_squared + 2.0f );
-	weights[2] = 0.5f * ( -3.0f * interp_cubed + 4.0f * interp_squared + t );
-	weights[3] = 0.5f * ( interp_cubed - interp_squared );
-
-	for ( uint32 n = 0; n < s1.size(); ++n )
-	{
-		quat qs1 = s1.m_transforms[n].get_orientation();
-		quat qs2 = s2.m_transforms[n].get_orientation();
-		quat qv1 = v1.m_transforms[n].get_orientation();
-		quat qv2 = v2.m_transforms[n].get_orientation();
-
-		float a = dot( qv1, qv2 ) > 0.0f ? 1.0f : -1.0f;
-
-		quat qr = weights[0] * qs1 
-				+ weights[1] * (a * qv1 )
-				+ weights[2] * qv2 
-				+ weights[3] * qs2;
-
-		qr = normalize( qr );
-
-		m_transforms[n] = transform(
-			weights[0] * s1.m_transforms[n].get_position() +
-			weights[1] * v1.m_transforms[n].get_position() +
-			weights[2] * v2.m_transforms[n].get_position() +
-			weights[3] * s2.m_transforms[n].get_position(),
-			qr
-		);
-	}
-}
-
-
-void nv::skeleton_transforms::interpolate_squad( const skeleton_transforms& s1, const skeleton_transforms& v1, const skeleton_transforms& v2, const skeleton_transforms& s2, float t )
-{
-	NV_ASSERT( s1.size() == s2.size(), "!!!" );
-	NV_ASSERT( v1.size() == v2.size(), "!!!" );
-	NV_ASSERT( s1.size() == v1.size(), "!!!" );
-	if ( m_transforms.size() != s1.size() )
-		m_transforms.resize( s1.size() );
-
-	for ( uint32 n = 0; n < s1.size(); ++n )
-	{
-		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(
-			sv1, sv2,
-			nv::math::intermediate( ss1, sv1, sv2 ),
-			nv::math::intermediate( sv1, sv2, ss2 ),
-			t ) );
-
-		m_transforms[n] = transform(
-			mix( v1.m_transforms[n].get_position(), v2.m_transforms[n].get_position(), t ),
-			q
-			);
-	}
-	
+	if ( m_transforms.size() != s1.size() ) m_transforms.resize( s1.size() );
+	if ( mask.size() > 0 )
+		::nv::interpolate( m_transforms, t, i, blend, bi, mask, s1.m_transforms, v1.m_transforms, v2.m_transforms, s2.m_transforms );
+	else
+		::nv::interpolate( m_transforms, t, i, blend, bi, s1.m_transforms, v1.m_transforms, v2.m_transforms, s2.m_transforms );
 }
 
@@ -264,32 +170,4 @@
 }
 
-// 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 )
@@ -304,51 +182,2 @@
 }
 
-// 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 )
-{
-	m_offsets.resize( bone_data.size() );
-
-	for ( nv::uint16 bi = 0; bi < bone_data.size(); ++bi )
-		m_offsets[bi] = bone_data[bi].transform;
-}
