Index: trunk/src/formats/assimp_loader.cc
===================================================================
--- trunk/src/formats/assimp_loader.cc	(revision 280)
+++ trunk/src/formats/assimp_loader.cc	(revision 282)
@@ -314,5 +314,5 @@
 }
 
-assimp_animation* nv::assimp_loader::release_animation( size_t, bool pre_transform, const std::vector< assimp_bone >* bone_data )
+assimp_animation* nv::assimp_loader::release_animation( size_t, bool pre_transform )
 {
 	if ( m_scene == nullptr ) return nullptr;
@@ -332,30 +332,4 @@
 
 	load_node( result, root, 0, -1 );
-	// TODO: this is not used when pretransformed, is it used otherwise?
-
-	if ( bone_data )
-	{
-		std::unordered_map< std::string, uint16 > names;
-		for ( uint16 bi = 0; bi < bone_data->size(); ++bi )
-		{
-			names[ (*bone_data)[bi].name ] = bi;
-		}
-
-		for ( unsigned i = 0; i < result->nodes.size(); ++i )
-		{
-			assimp_animated_node_data& node = result->nodes[i];
-			node.bone_id = -1;
-			auto bi = names.find( node.name );
-			if ( bi != names.end() )
-			{
-				node.bone_id = bi->second;
-			}
-			if ( node.parent_id != -1 ) 
-			{
-				result->nodes[ node.parent_id ].children.push_back( &node );
-			}
-		}
-	}
-
 	return result;
 }
@@ -391,5 +365,4 @@
 	a_data.name      = name;
 	a_data.parent_id = parent_id;
-	a_data.bone_id = -1;
 	// This value is ignored by the create_transformed_keys, but needed by create_direct_keys!
 	// TODO: find a common solution!
@@ -397,4 +370,5 @@
 	//       node's without keys
 	a_data.transform = nv::assimp_mat4_cast( node->mTransformation );
+	a_data.channel_count = 0;
 
 	if (anode) 
@@ -402,9 +376,9 @@
 		if ( data->pretransformed )
 		{
-			a_data.keys = create_transformed_keys( anode, parent_id >= 0 ? data->nodes[ parent_id ].keys : nullptr );
+			create_transformed_keys( &a_data, anode, parent_id >= 0 ? &(data->nodes[ parent_id ]) : nullptr );
 		}
 		else
 		{
-			a_data.keys = create_direct_keys( anode );
+			create_direct_keys( &a_data, anode );
 		}
 	}
@@ -418,9 +392,13 @@
 }
 
-key_animation_data* nv::assimp_loader::create_transformed_keys( const void* vnode, const key_animation_data* parent_keys )
+void nv::assimp_loader::create_transformed_keys( assimp_animated_node_data* data, const void* vnode, const assimp_animated_node_data* parent )
 {
 	const aiNodeAnim* node = (const aiNodeAnim*)vnode;
 	size_t max_keys = glm::max( node->mNumPositionKeys, node->mNumRotationKeys );
-	nv::transform_vector* keys = new nv::transform_vector;
+
+	data->channel_count = 1;
+	data->channels[0] = key_raw_channel::create<assimp_key_tr>( max_keys );
+	assimp_key_tr* channel = ((assimp_key_tr*)(data->channels[0]->data));
+
 	for ( unsigned n = 0; n < max_keys; ++n )
 	{
@@ -431,29 +409,44 @@
 		// TODO: only do the calculation when a rotate transform is present!
 		nv::transform ptr( vec3(), glm::quat_cast( m_rotate_transform ) );
-		if ( parent_keys )
-		{
-			const nv::transform_vector* pv = (const nv::transform_vector*)parent_keys;
-			if ( pv && pv->size() > 0 ) ptr = pv->get( glm::min( n, pv->size()-1 ) );
+		if ( parent )
+		{
+			key_raw_channel* pchannel = parent->channels[0];
+			if ( parent->channels[0] && parent->channels[0]->count > 0 )
+			{
+				ptr = ((assimp_key_tr*)pchannel->data)[ glm::min( n, parent->channels[0]->count-1 ) ].tform;
+			}
 		}
 		nv::transform key( ptr * nv::transform( pos * m_scale, rot ) );
-		keys->insert( key );
-	}
-	return keys;
-}
-
-key_animation_data* nv::assimp_loader::create_direct_keys( const void* vnode )
-{
+		channel[n].tform = key;
+	}
+}
+
+void nv::assimp_loader::create_direct_keys( assimp_animated_node_data* data, const void* vnode )
+{
+	data->channel_count = 0;
 	// TODO : support for m_rotate_transform and m_scale! ( should be easy )
 	const aiNodeAnim* node = (const aiNodeAnim*)vnode;
-	if ( node->mNumPositionKeys == 0 && node->mNumRotationKeys == 0 && node->mNumScalingKeys == 0 ) return nullptr;
-	key_vectors_prs* keys = new key_vectors_prs;
+	if ( node->mNumPositionKeys == 0 && node->mNumRotationKeys == 0 && node->mNumScalingKeys == 0 )
+	{
+		return;
+	}
+
+	data->channel_count = 3;
+	data->channels[0] = key_raw_channel::create<assimp_key_p>( node->mNumPositionKeys );
+	data->channels[1] = key_raw_channel::create<assimp_key_r>( node->mNumRotationKeys );
+	data->channels[2] = key_raw_channel::create<assimp_key_s>( node->mNumScalingKeys );
+	assimp_key_p* pchannel = ((assimp_key_p*)(data->channels[0]->data));
+	assimp_key_r* rchannel = ((assimp_key_r*)(data->channels[1]->data));
+	assimp_key_s* schannel = ((assimp_key_s*)(data->channels[2]->data));
 
 	for ( unsigned np = 0; np < node->mNumPositionKeys; ++np )
 	{
-		keys->insert_position( (float)node->mPositionKeys[np].mTime, m_scale * assimp_vec3_cast(node->mPositionKeys[np].mValue) );
+		pchannel[np].time     = (float)node->mPositionKeys[np].mTime;
+		pchannel[np].position = assimp_vec3_cast(node->mPositionKeys[np].mValue);
 	}
 	for ( unsigned np = 0; np < node->mNumRotationKeys; ++np )
 	{
-		keys->insert_rotation( (float)node->mRotationKeys[np].mTime, assimp_quat_cast(node->mRotationKeys[np].mValue) );
+		rchannel[np].time     = (float)node->mRotationKeys[np].mTime;
+		rchannel[np].rotation = assimp_quat_cast(node->mRotationKeys[np].mValue);
 	}
 	if ( node->mNumScalingKeys > 0 )
@@ -466,9 +459,9 @@
 			for ( unsigned np = 0; np < node->mNumRotationKeys; ++np )
 			{
-				keys->insert_scale( (float)node->mScalingKeys[np].mTime, assimp_vec3_cast(node->mScalingKeys[np].mValue) );
-			}
-		}
-	}
-	return keys;
-}
-
+				schannel[np].time  = (float)node->mScalingKeys[np].mTime;
+				schannel[np].scale = assimp_vec3_cast(node->mScalingKeys[np].mValue);
+			}
+		}
+	}
+}
+
Index: trunk/src/formats/md3_loader.cc
===================================================================
--- trunk/src/formats/md3_loader.cc	(revision 280)
+++ trunk/src/formats/md3_loader.cc	(revision 282)
@@ -275,6 +275,4 @@
 bool nv::md3_loader::load( stream& source )
 {
-	m_tags.clear();
-
 	m_md3 = (void*)(new md3_t);
 	if ( !read_md3( (md3_t*)m_md3, source ) )
@@ -285,7 +283,9 @@
 }
 
-void nv::md3_loader::load_tags( transform_vector& t, const std::string& tag )
+nv::key_raw_channel* nv::md3_loader::load_tags( const std::string& tag )
 {
 	md3_t* md3 = (md3_t*)m_md3;
+	key_raw_channel* result = key_raw_channel::create<md3_key>( md3->header.num_frames );
+	// TODO: is this brain damaged in efficiency (loop nest order) or what?
 	for ( sint32 f = 0; f < md3->header.num_frames; ++f )
 	{
@@ -300,9 +300,10 @@
 				vec3 axisy  ( md3_vec3( rtag.axis[2] ) );
 				vec3 origin ( md3_vec3( rtag.origin )  );
-				t.insert( transform( origin, quat( mat3( axisx, axisy, axisz ) ) ) );
+				((md3_key*)(result->data))[f].tform = transform( origin, quat( mat3( axisx, axisy, axisz ) ) );
 			}
 		}
 
 	}
+	return result;
 }
 
@@ -408,5 +409,6 @@
 		const md3_tag_t& rtag = md3->tags[i + md3->header.num_tags];
 		std::string name( (char*)(rtag.name) );
-		load_tags( result->get_map()[ name ], name );
+		nv::key_raw_channel* keys = load_tags( name );
+		result->insert( name, keys );
 	}
 	return result;
Index: trunk/src/formats/md5_loader.cc
===================================================================
--- trunk/src/formats/md5_loader.cc	(revision 280)
+++ trunk/src/formats/md5_loader.cc	(revision 282)
@@ -397,5 +397,5 @@
 				remove_quotes( joint.name );
 				joint_infos.push_back( joint );
-				m_joints.push_back( md5_joint( joint.parent_id, m_num_frames ) );
+				m_joints.emplace_back( joint.parent_id );
 				next_line( sstream ); 
 			}
@@ -490,6 +490,6 @@
 	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 );
+		const std::vector< transform >& keys = m_joints[i].keys;
+		skeleton[i] = interpolate( keys[frame0], keys[frame1], interpolation );
 	}
 }
@@ -519,7 +519,7 @@
 		if ( parent_id >= 0 ) // Has a parent joint
 		{
-			const transform_vector& ptv = m_joints[ size_t( parent_id ) ].keys;
+			const std::vector< transform >& ptv = m_joints[ size_t( parent_id ) ].keys;
 			transform ptr;
-			if ( ptv.size() > index ) ptr = ptv.get( index );
+			if ( ptv.size() > index ) ptr = ptv[ index ];
 			glm::vec3 rot_pos = ptr.get_orientation() * pos;
 
@@ -530,5 +530,5 @@
 		}
 
-		m_joints[i].keys.insert( transform( pos, orient ) );
+		m_joints[i].keys.push_back( transform( pos, orient ) );
 	}
 }
