Index: trunk/src/formats/md3_loader.cc
===================================================================
--- trunk/src/formats/md3_loader.cc	(revision 240)
+++ trunk/src/formats/md3_loader.cc	(revision 241)
@@ -285,8 +285,7 @@
 }
 
-void nv::md3_loader::load_tags( std::vector<transform>& t, const std::string& tag )
+void nv::md3_loader::load_tags( transform_vector& t, const std::string& tag )
 {
 	md3_t* md3 = (md3_t*)m_md3;
-	t.clear();
 	for ( sint32 f = 0; f < md3->header.num_frames; ++f )
 	{
@@ -301,5 +300,5 @@
 				vec3 axisy  ( md3_vec3( rtag.axis[2] ) );
 				vec3 origin ( md3_vec3( rtag.origin )  );
-				t.emplace_back( origin, quat( mat3( axisx, axisy, axisz ) ) );
+				t.insert( transform( origin, quat( mat3( axisx, axisy, axisz ) ) ) );
 			}
 		}
Index: trunk/src/formats/md5_loader.cc
===================================================================
--- trunk/src/formats/md5_loader.cc	(revision 240)
+++ trunk/src/formats/md5_loader.cc	(revision 241)
@@ -75,5 +75,6 @@
 			for ( size_t i = 0; i < m_num_joints; ++i )
 			{
-				sstream >> joint.name >> joint.parent_id;
+				int parent_id;
+				sstream >> joint.name >> parent_id;
 				discard( sstream, "(" );
 				sstream >> joint.pos.x >> joint.pos.y >> joint.pos.z;
@@ -290,5 +291,4 @@
 	, m_anim_duration( 0 )
 	, m_frame_duration( 0 )
-	, m_anim_time( 0 )
 {
 
@@ -302,9 +302,6 @@
 bool md5_animation::load_animation( stream& source )
 {
-	m_joint_infos.clear();
-	m_bounds.clear();
-	m_base_frames.clear();
-	m_frames.clear();
-	m_animated_skeleton.joints.clear();
+	std::vector<md5_joint_info> joint_infos;
+	std::vector<transform>      base_frames;
 	m_num_frames = 0;
 
@@ -332,4 +329,5 @@
 		{
 			sstream >> m_num_joints;
+			m_joints.reserve( m_num_joints );
 			next_line( sstream ); 
 		}
@@ -352,5 +350,6 @@
 				sstream >> joint.name >> joint.parent_id >> joint.flags >> joint.start_index;
 				remove_quotes( joint.name );
-				m_joint_infos.push_back( joint );
+				joint_infos.push_back( joint );
+				m_joints.push_back( md5_joint( joint.parent_id, m_num_frames ) );
 				next_line( sstream ); 
 			}
@@ -363,35 +362,36 @@
 			for ( size_t i = 0; i < m_num_frames; ++i ) 
 			{
-				md5_bound bound;
+//  				vec3 min;
+//  				vec3 max;
+//  				discard( sstream, "(" );
+//  				sstream >> min.x >> min.y >> min.z;
+//  				discard( sstream, ")" );
+//  				discard( sstream, "(" );
+//  				sstream >> max.x >> max.y >> max.z;
+// 				m_bounds.push_back( bound );
+				next_line( sstream ); 
+			}
+
+			discard( sstream, "}" );
+			next_line( sstream ); 
+		}
+		else if ( command == "baseframe" )
+		{
+			discard( sstream, "{" );
+			next_line( sstream ); 
+
+			for ( size_t i = 0; i < m_num_joints; ++i )
+			{
+				transform base_frame;
+				vec3 pos;
+				quat orient;
 				discard( sstream, "(" );
-				sstream >> bound.min.x >> bound.min.y >> bound.min.z;
+				sstream >> pos.x >> pos.y >> pos.z;
 				discard( sstream, ")" );
 				discard( sstream, "(" );
-				sstream >> bound.max.x >> bound.max.y >> bound.max.z;
-
-				m_bounds.push_back( bound );
-
+				sstream >> orient.x >> orient.y >> orient.z;
 				next_line( sstream ); 
-			}
-
-			discard( sstream, "}" );
-			next_line( sstream ); 
-		}
-		else if ( command == "baseframe" )
-		{
-			discard( sstream, "{" );
-			next_line( sstream ); 
-
-			for ( size_t i = 0; i < m_num_joints; ++i )
-			{
-				md5_base_frame base_frame;
-				discard( sstream, "(" );
-				sstream >> base_frame.pos.x >> base_frame.pos.y >> base_frame.pos.z;
-				discard( sstream, ")" );
-				discard( sstream, "(" );
-				sstream >> base_frame.orient.x >> base_frame.orient.y >> base_frame.orient.z;
-				next_line( sstream ); 
-
-				m_base_frames.push_back( base_frame );
+
+				base_frames.emplace_back( pos, orient );
 			}
 			discard( sstream, "}" );
@@ -400,20 +400,19 @@
 		else if ( command == "frame" )
 		{
-			md5_frame_data frame;
-			sstream >> frame.frame_id;
+			std::vector<float> frame;
+			int frame_id;
+			sstream >> frame_id;
 			discard( sstream, "{" );
 			next_line( sstream ); 
 
-			frame.frame_data.reserve( m_num_animated_components );
+			frame.reserve( m_num_animated_components );
 			char buf[50];
 			for ( size_t i = 0; i < m_num_animated_components; ++i )
 			{
 				sstream >> buf;
-				frame.frame_data.push_back((float)atof(buf));
+				frame.push_back((float)atof(buf));
 			}
 
-			m_frames.push_back(frame);
-
-			build_frame_skeleton( m_skeletons, m_joint_infos, m_base_frames, frame );
+			build_frame_skeleton( joint_infos, base_frames, frame );
 
 			discard( sstream, "}" );
@@ -424,29 +423,17 @@
 	} 
 
-	m_animated_skeleton.joints.assign( m_num_joints, md5_skeleton_joint() );
 
 	m_frame_duration = 1.0f / (float)m_frame_rate;
 	m_anim_duration = ( m_frame_duration * (float)m_num_frames );
-	m_anim_time = 0.0f;
-
-	assert( m_joint_infos.size() == m_num_joints );
-	assert( m_bounds.size()      == m_num_frames );
-	assert( m_base_frames.size() == m_num_joints );
-	assert( m_frames.size()      == m_num_frames );
-	assert( m_skeletons.size()   == m_num_frames );
 
 	return true;
 }
 
-void md5_animation::update( float delta_time )
-{
-	if ( m_num_frames < 1 ) return;
-
-	m_anim_time += delta_time;
-
-	while ( m_anim_time > m_anim_duration ) m_anim_time -= m_anim_duration;
-	while ( m_anim_time < 0.0f ) m_anim_time += m_anim_duration;
-
-	float frame_num = m_anim_time * (float)m_frame_rate;
+
+void nv::md5_animation::update_skeleton( std::vector<transform>& skeleton, float anim_time ) const
+{
+	NV_ASSERT( skeleton.size() == m_num_joints, "Incompatible skeleton passed!" );
+	anim_time = glm::clamp( anim_time, 0.0f, m_anim_duration );
+	float frame_num = anim_time * (float)m_frame_rate;
 	size_t frame0 = (size_t)floorf( frame_num );
 	size_t frame1 = (size_t)ceilf( frame_num );
@@ -454,13 +441,16 @@
 	frame1 = frame1 % m_num_frames;
 
-	float interpolate = fmodf( m_anim_time, m_frame_duration ) / m_frame_duration;
-
-	interpolate_skeletons( m_animated_skeleton, m_skeletons[frame0], m_skeletons[frame1], interpolate );
-}
-
-void md5_animation::build_frame_skeleton( md5_frame_skeleton_list& skeletons, const md5_joint_info_list& joint_infos, const md5_base_frame_list& base_frames, const md5_frame_data& frame_data )
-{
-	md5_frame_skeleton skeleton;
-
+	float interpolation = fmodf( anim_time, m_frame_duration ) / m_frame_duration;
+
+	for ( size_t i = 0; i < m_num_joints; ++i )
+	{
+		const transform_vector& keys = m_joints[i].keys;
+		skeleton[i] = interpolate( keys.get(frame0), keys.get(frame1), interpolation );
+	}
+}
+
+void md5_animation::build_frame_skeleton( const std::vector<md5_joint_info>& joint_infos, const std::vector<transform>& base_frames, const std::vector<float>& frame_data )
+{
+	size_t index = m_joints[0].keys.size();
 	for ( unsigned int i = 0; i < joint_infos.size(); ++i )
 	{
@@ -468,68 +458,33 @@
 
 		const md5_joint_info& jinfo = joint_infos[i];
-		md5_skeleton_joint animated_joint = base_frames[i];
-
-		animated_joint.parent = jinfo.parent_id;
-
-		if ( jinfo.flags & 1 )  animated_joint.pos.x    = frame_data.frame_data[ jinfo.start_index + j++ ];
-		if ( jinfo.flags & 2 )  animated_joint.pos.y    = frame_data.frame_data[ jinfo.start_index + j++ ];
-		if ( jinfo.flags & 4 )  animated_joint.pos.z    = frame_data.frame_data[ jinfo.start_index + j++ ];
-		if ( jinfo.flags & 8 )  animated_joint.orient.x = frame_data.frame_data[ jinfo.start_index + j++ ];
-		if ( jinfo.flags & 16 ) animated_joint.orient.y = frame_data.frame_data[ jinfo.start_index + j++ ];
-		if ( jinfo.flags & 32 )	animated_joint.orient.z = frame_data.frame_data[ jinfo.start_index + j++ ];
-
-		unit_quat_w( animated_joint.orient );
-
-		if ( animated_joint.parent >= 0 ) // Has a parent joint
-		{
-			md5_skeleton_joint& pjoint = skeleton.joints[static_cast< size_t >( animated_joint.parent ) ];
-			glm::vec3 rot_pos = pjoint.orient * animated_joint.pos;
-
-			animated_joint.pos    = pjoint.pos + rot_pos;
-			animated_joint.orient = pjoint.orient * animated_joint.orient;
-
-			animated_joint.orient = glm::normalize( animated_joint.orient );
-		}
-
-		skeleton.joints.push_back( animated_joint );
-	}
-
-	skeletons.push_back( skeleton );
-}
-
-void md5_animation::interpolate_skeletons( md5_frame_skeleton& final_skeleton, const md5_frame_skeleton& skeleton0, const md5_frame_skeleton& skeleton1, float interpolate )
-{
-	for ( size_t i = 0; i < m_num_joints; ++i )
-	{
-		md5_skeleton_joint& final_joint = final_skeleton.joints[i];
-		const md5_skeleton_joint& joint0 = skeleton0.joints[i]; 
-		const md5_skeleton_joint& joint1 = skeleton1.joints[i];
-
-		final_joint.parent = joint0.parent;
-
-		final_joint.orient = glm::slerp( joint0.orient, joint1.orient, interpolate );
-		final_joint.pos    = glm::mix( joint0.pos, joint1.pos, interpolate );
-	}
-}
-
-bool md5_loader::check_animation( const md5_animation& animation ) const
-{
-	if ( m_num_joints != animation.get_num_joints() )
-	{
-		return false;
-	}
-
-	for ( uint32 i = 0; i < m_joints.size(); ++i )
-	{
-		const md5_joint& mjoint = m_joints[i];
-		const md5_animation::md5_joint_info& ajoint = animation.get_joint_info( i );
-
-		if ( mjoint.name != ajoint.name || mjoint.parent_id != ajoint.parent_id )
-		{
-			return false;
-		}
-	}
-
-	return true;
+
+
+		int parent_id = jinfo.parent_id;
+
+		vec3 pos    = base_frames[i].get_position();
+		quat orient = base_frames[i].get_orientation();
+		if ( jinfo.flags & 1 )  pos.x    = frame_data[ jinfo.start_index + j++ ];
+		if ( jinfo.flags & 2 )  pos.y    = frame_data[ jinfo.start_index + j++ ];
+		if ( jinfo.flags & 4 )  pos.z    = frame_data[ jinfo.start_index + j++ ];
+		if ( jinfo.flags & 8 )  orient.x = frame_data[ jinfo.start_index + j++ ];
+		if ( jinfo.flags & 16 ) orient.y = frame_data[ jinfo.start_index + j++ ];
+		if ( jinfo.flags & 32 )	orient.z = frame_data[ jinfo.start_index + j++ ];
+		unit_quat_w( orient );
+
+		if ( parent_id >= 0 ) // Has a parent joint
+		{
+			const transform_vector& ptv = m_joints[ size_t( parent_id ) ].keys;
+			transform ptr;
+			if ( ptv.size() > index ) ptr = ptv.get( index );
+			glm::vec3 rot_pos = ptr.get_orientation() * pos;
+
+			pos    = ptr.get_position() + rot_pos;
+			orient = ptr.get_orientation() * orient;
+
+			orient = glm::normalize( orient );
+		}
+
+		m_joints[i].keys.insert( transform( pos, orient ) );
+	}
 }
 
@@ -541,11 +496,28 @@
 }
 
-void nv::md5_mesh_data::apply( const md5_animation& animation )
-{
-	const md5_animation::md5_frame_skeleton& skeleton = animation.get_skeleton();
-
-	for ( unsigned int i = 0; i < m_vtx_data.size(); ++i )
-	{
-		const md5_vtx_data& vert = m_vtx_data[i];
+md5_mesh_instance* nv::md5_mesh_data::spawn() const
+{
+	return new md5_mesh_instance( this );
+}
+
+nv::md5_loader::~md5_loader()
+{
+	for ( auto m : m_meshes ) { if (m) delete m; }
+}
+
+nv::md5_mesh_instance::md5_mesh_instance( const md5_mesh_data* a_data ) 
+	: m_data( a_data ), m_size( 0 ), m_indices( 0 ), m_pntdata( nullptr )
+{
+	m_size = m_data->m_vtx_data.size();
+	m_indices = m_data->get_count();
+	m_pntdata = new md5_vtx_pnt[ m_size ];
+	std::copy_n( m_data->m_pntdata, m_size, m_pntdata );
+}
+
+void nv::md5_mesh_instance::apply( const std::vector< transform >& skeleton )
+{
+	for ( unsigned int i = 0; i < m_size; ++i )
+	{
+		const md5_vtx_data& vert = m_data->m_vtx_data[i];
 		md5_vtx_pnt& result = m_pntdata[i];
 
@@ -556,18 +528,13 @@
 		for ( size_t j = 0; j < vert.weight_count; ++j )
 		{
-			const md5_weight& weight = m_weights[vert.start_weight + j];
-			const md5_animation::md5_skeleton_joint& joint = skeleton.joints[weight.joint_id];
-
-			glm::vec3 rot_pos = joint.orient * weight.pos;
-			result.position += ( joint.pos + rot_pos ) * weight.bias;
-
-			result.normal  += ( joint.orient * vert.normal  ) * weight.bias;
-			result.tangent += ( joint.orient * vert.tangent ) * weight.bias;
-		}
-	}
-}
-
-nv::md5_loader::~md5_loader()
-{
-	for ( auto m : m_meshes ) { if (m) delete m; }
-}
+			const md5_weight& weight = m_data->m_weights[vert.start_weight + j];
+			const transform& joint = skeleton[weight.joint_id];
+
+			glm::vec3 rot_pos = joint.get_orientation() * weight.pos;
+			result.position += ( joint.get_position() + rot_pos ) * weight.bias;
+
+			result.normal  += ( joint.get_orientation() * vert.normal  ) * weight.bias;
+			result.tangent += ( joint.get_orientation() * vert.tangent ) * weight.bias;
+		}
+	}
+}
Index: trunk/src/gfx/keyframed_mesh.cc
===================================================================
--- trunk/src/gfx/keyframed_mesh.cc	(revision 240)
+++ trunk/src/gfx/keyframed_mesh.cc	(revision 241)
@@ -44,7 +44,7 @@
 {
 	NV_ASSERT( m_tag_map, "TAGMAP FAIL" );
-	const std::vector< transform >* transforms = m_tag_map->get_tag( tag );
+	const transform_vector* transforms = m_tag_map->get_tag( tag );
 	NV_ASSERT( transforms, "TAG FAIL" );
-	return interpolate( (*transforms)[ m_last_frame ], (*transforms)[ m_next_frame ], m_interpolation );
+	return interpolate( transforms->get( m_last_frame ), transforms->get( m_next_frame ), m_interpolation  );
 }
 
Index: trunk/src/gfx/skeletal_mesh.cc
===================================================================
--- trunk/src/gfx/skeletal_mesh.cc	(revision 240)
+++ trunk/src/gfx/skeletal_mesh.cc	(revision 241)
@@ -13,8 +13,10 @@
 nv::skeletal_mesh::skeletal_mesh( context* a_context, md5_mesh_data* a_mesh_data )
 	: animated_mesh()
-	, m_mesh_data( a_mesh_data )
+	, m_mesh_data( nullptr )
 	, m_animation( nullptr )
+	, m_animation_time( 0 )
 {
-	m_va = a_context->get_device()->create_vertex_array( a_mesh_data, nv::STREAM_DRAW );
+	m_mesh_data = a_mesh_data->spawn();
+	m_va        = a_context->get_device()->create_vertex_array( a_mesh_data, nv::STREAM_DRAW );
 }
 
@@ -22,20 +24,26 @@
 void nv::skeletal_mesh::setup_animation( md5_animation* a_anim )
 {
-	if ( m_animation ) m_animation->reset_animation();
-	m_animation = a_anim;
-	// TODO : INSTANCE!
-	m_animation->reset_animation();
+	m_animation      = a_anim;
+	m_animation_time = 0;
+	if ( m_animation )
+	{
+		m_transform.resize( m_animation->get_num_joints() );
+		update( 0 );
+	}
 }
 
 void nv::skeletal_mesh::update( uint32 ms )
 {
-	if (m_animation != nullptr)
+	if ( m_animation )
 	{
-		m_animation->update( ms * 0.001f );
-		m_mesh_data->apply( *m_animation );
+		m_animation_time += ms;
+		float frame_duration = 1000.f / (float)m_animation->get_frame_rate();
+		uint32 anim_duration = uint32( frame_duration * (float)m_animation->get_frame_count() );
+		while ( m_animation_time >= anim_duration ) m_animation_time -= anim_duration;
+		m_animation->update_skeleton( m_transform, (float)m_animation_time * 0.001f );
+		m_mesh_data->apply( m_transform );
 		vertex_buffer* vb = m_va->find_buffer( nv::POSITION );
-		const mesh_raw_channel* pch = m_mesh_data->get_channel_data()[0];
 		vb->bind();
-		vb->update( (const void*)pch->data, 0, pch->size );
+		vb->update( m_mesh_data->data(), 0, m_mesh_data->size() );
 		vb->unbind();
 	}
@@ -45,6 +53,5 @@
 {
 	delete m_va;
-	// TODO : INSTANCE!
-	//	delete m_mesh_data;
+	delete m_mesh_data;
 }
 
@@ -52,5 +59,4 @@
 {
 	skeletal_animation_entry * anim = down_cast<skeletal_animation_entry>(a_anim);
-	// TODO : INSTANCE!
 	setup_animation( anim->m_animation );
 }
