Index: trunk/nv/common.hh
===================================================================
--- trunk/nv/common.hh	(revision 260)
+++ trunk/nv/common.hh	(revision 261)
@@ -109,4 +109,5 @@
 
 #include <typeinfo>
+#include <iterator>
 #include <cstddef>
 #include <cstdint>
Index: trunk/nv/formats/md5_loader.hh
===================================================================
--- trunk/nv/formats/md5_loader.hh	(revision 260)
+++ trunk/nv/formats/md5_loader.hh	(revision 261)
@@ -15,6 +15,5 @@
 
 #include <nv/common.hh>
-#include <unordered_map>
-#include <vector>
+#include <nv/array.hh>
 #include <nv/interface/mesh_loader.hh>
 
@@ -69,5 +68,5 @@
 
 		bool load_animation( stream& source );
-		void update_skeleton( std::vector<transform>& skeleton, float anim_time ) const;
+		void update_skeleton( transform* skeleton, float anim_time ) const;
 		
 		size_t get_num_joints() const { return m_num_joints; }
@@ -93,18 +92,16 @@
 		friend class md5_mesh_data;
 	public:
-		const void* data() const { return m_pntdata; }
+		const void* data() const { return m_pntdata.data(); }
 		uint32 get_index_count() const { return m_indices; }
-		size_t size() const { return m_size * sizeof( md5_vtx_pnt ); }
-		void apply( const std::vector< transform >& skeleton );
+		size_t size() const { return m_pntdata.raw_size(); }
+		void apply( const transform* skeleton );
 		const md5_mesh_data* get_mesh_data() const { return m_data; }
-		~md5_mesh_instance() { delete[] m_pntdata; }
 	private:
 		md5_mesh_instance( const md5_mesh_data* a_data );
 
-		uint32                   m_size;
-		uint32                   m_indices;
-		md5_vtx_pnt*             m_pntdata;
-		std::vector< transform > m_pos_offset;
-		const md5_mesh_data*     m_data;
+		uint32                       m_indices;
+		dynamic_array< md5_vtx_pnt > m_pntdata;
+		dynamic_array< transform >   m_pos_offset;
+		const md5_mesh_data*         m_data;
 	};
 
@@ -116,10 +113,10 @@
 		md5_mesh_instance* spawn() const;
 	private:
-		uint32*                     m_idata;
-		md5_vtx_t*                  m_tdata;
-		md5_vtx_pnt*                m_pntdata;
-		std::string                 m_shader;
-		std::vector< transform >    m_bone_offset;
-		std::vector< md5_vtx_data > m_vtx_data;
+		uint32*                       m_idata;
+		md5_vtx_t*                    m_tdata;
+		md5_vtx_pnt*                  m_pntdata;
+		std::string                   m_shader;
+		dynamic_array< transform >    m_bone_offset;
+		dynamic_array< md5_vtx_data > m_vtx_data;
 	};
 
@@ -154,5 +151,5 @@
 		};
 	protected:
-		bool prepare_mesh( md5_mesh_data* mdata, std::vector< md5_weight >& weights, std::vector< md5_weight_info >& weight_info );
+		bool prepare_mesh( md5_mesh_data* mdata, md5_weight* weights, md5_weight_info* weight_info );
 	protected:
 		uint32 m_md5_version;
@@ -160,6 +157,6 @@
 		uint32 m_num_meshes;
 
-		std::vector<md5_joint>      m_joints;
-		std::vector<md5_mesh_data*> m_meshes;
+		dynamic_array<md5_joint>      m_joints;
+		dynamic_array<md5_mesh_data*> m_meshes;
 	};
 
Index: trunk/nv/transform.hh
===================================================================
--- trunk/nv/transform.hh	(revision 260)
+++ trunk/nv/transform.hh	(revision 261)
@@ -71,5 +71,5 @@
 		}
 
-		vec3 transformed( const vec3 v ) const
+		vec3 transformed( const vec3& v ) const
 		{
 			return m_orientation * v + m_position;
Index: trunk/src/formats/md5_loader.cc
===================================================================
--- trunk/src/formats/md5_loader.cc	(revision 260)
+++ trunk/src/formats/md5_loader.cc	(revision 261)
@@ -45,8 +45,9 @@
 bool md5_loader::load( stream& source )
 {
+	NV_PROFILE( "Load MD5" ); // 16XXms original
 	std_stream sstream( &source );
 	std::string command;
-	std::vector< md5_weight > weights;
-	std::vector< md5_weight_info > weight_info;
+	dynamic_array< md5_weight > weights;
+	dynamic_array< md5_weight_info > weight_info;
 
 	sstream >> command;
@@ -65,10 +66,11 @@
 		{
 			sstream >> m_num_joints;
-			m_joints.reserve( m_num_joints );
+			m_joints.resize( m_num_joints );
 		}
 		else if ( command == "numMeshes" )
 		{
 			sstream >> m_num_meshes;
-			m_meshes.reserve( m_num_meshes );
+			m_meshes.resize( m_num_meshes );
+			m_num_meshes = 0;
 		}
 		else if ( command == "joints" )
@@ -87,5 +89,5 @@
 				remove_quotes( joint.name );
 				unit_quat_w( joint.orient );
-				m_joints.push_back( joint );
+				m_joints[i] = joint;
 				next_line( sstream );
 			}
@@ -168,5 +170,5 @@
 				{
 					sstream >> num_weights;
-					weights.reserve( num_weights );
+					weights.resize( num_weights );
 					next_line( sstream );
 					std::string line;
@@ -177,5 +179,5 @@
 						std::getline( sstream, line );
 						sscanf( line.c_str(), "%*s %*u %u %f ( %f %f %f )", &(weight.joint_id), &(weight.bias), &(weight.pos.x), &(weight.pos.y), &(weight.pos.z));
- 						weights.push_back(weight);
+ 						weights[i] = weight;
 					}
 				}
@@ -188,25 +190,25 @@
 			}
 
-			prepare_mesh( mesh, weights, weight_info );
-
-			m_meshes.push_back(mesh);
+			prepare_mesh( mesh, weights.data(), weight_info.data() );
+
+			m_meshes[ m_num_meshes ] = mesh;
+			m_num_meshes++;
 		}
 		sstream >> command;
 	}
 
-	assert( m_joints.size() == m_num_joints );
-	assert( m_meshes.size() == m_num_meshes );
 	return true;
 }
 
-bool md5_loader::prepare_mesh( md5_mesh_data* mdata, std::vector< md5_weight >& weights, std::vector< md5_weight_info >& weight_info )
+bool md5_loader::prepare_mesh( md5_mesh_data* mdata, md5_weight* weights, md5_weight_info* weight_info )
 {
 	uint32 vtx_count = mdata->m_vtx_data.size();
 	md5_vtx_pnt* vtcs = mdata->m_pntdata;
 
-	for ( auto joint : m_joints )
-	{
-		transform j( joint.pos, joint.orient );
-		mdata->m_bone_offset.push_back(j.inverse());
+	mdata->m_bone_offset.resize( m_joints.size() );
+	for ( uint32 i = 0; i < m_joints.size(); ++i )
+	{
+		transform j( m_joints[i].pos, m_joints[i].orient );
+		mdata->m_bone_offset[i] = j.inverse();
 	}
 
@@ -222,5 +224,5 @@
 		vtc.tangent  = glm::vec3(0);
 
-		std::sort( weights.begin() + start_weight, weights.begin() + start_weight + weight_count, [](const md5_weight& a, const md5_weight& b) -> bool { return a.bias > b.bias; } );
+		std::sort( weights + start_weight, weights + start_weight + weight_count, [](const md5_weight& a, const md5_weight& b) -> bool { return a.bias > b.bias; } );
 
 		if ( weight_count > 4 )
@@ -475,7 +477,6 @@
 
 
-void nv::md5_animation::update_skeleton( std::vector<transform>& skeleton, float anim_time ) const
-{
-	NV_ASSERT( skeleton.size() == m_num_joints, "Incompatible skeleton passed!" );
+void nv::md5_animation::update_skeleton( transform* skeleton, float anim_time ) const
+{
 	anim_time = glm::clamp( anim_time, 0.0f, m_anim_duration );
 	float frame_num = anim_time * (float)m_frame_rate;
@@ -551,24 +552,23 @@
 
 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_data( a_data ), m_indices( 0 )
+{
 	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 )
+	m_pntdata.assign( m_data->m_pntdata, m_data->m_vtx_data.size() );
+}
+
+void nv::md5_mesh_instance::apply( const transform* skeleton )
 {
 	NV_PROFILE("md5::apply");
-	m_pos_offset.resize( skeleton.size() );
-	for ( unsigned int i = 0; i < skeleton.size(); ++i )
+	size_t skeleton_size = m_data->m_bone_offset.size();
+	size_t vertex_count  = m_pntdata.size();
+	m_pos_offset.resize( skeleton_size );
+	for ( unsigned int i = 0; i < skeleton_size; ++i )
 	{
 		m_pos_offset[i] = skeleton[i] * m_data->m_bone_offset[i];
 	}
 
-	char* fill_ptr = (char*)&(m_pntdata[0]);
-	std::fill( fill_ptr, fill_ptr + m_size * ( sizeof( md5_vtx_pnt ) ), 0 );
-	for ( unsigned int i = 0; i < m_size; ++i )
+	std::fill( m_pntdata.raw_data(), m_pntdata.raw_data() + m_pntdata.raw_size(), 0 );
+	for ( unsigned int i = 0; i < vertex_count; ++i )
 	{
 		const md5_vtx_data& vert = m_data->m_vtx_data[i];
@@ -579,10 +579,10 @@
 			int   index  = vert.boneindex[j];
 			float weight = vert.boneweight[j];
-			transform joint  = skeleton[index];
-			transform offset = m_pos_offset[index];
+			const quat& orient      = skeleton[index].get_orientation();
+			const transform& offset = m_pos_offset[index];
 			result.position += offset.transformed( vert.position )        * weight;
-			result.normal   += ( joint.get_orientation() * vert.normal  ) * weight;
-			result.tangent  += ( joint.get_orientation() * vert.tangent ) * weight;
-		}
-	}
-}
+			result.normal   += ( orient * vert.normal  ) * weight;
+			result.tangent  += ( orient * vert.tangent ) * weight;
+		}
+	}
+}
Index: trunk/src/gfx/skeletal_mesh.cc
===================================================================
--- trunk/src/gfx/skeletal_mesh.cc	(revision 260)
+++ trunk/src/gfx/skeletal_mesh.cc	(revision 261)
@@ -41,6 +41,6 @@
 		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 );
+		m_animation->update_skeleton( m_transform.data(), (float)m_animation_time * 0.001f );
+		m_mesh_data->apply( m_transform.data() );
 		vertex_buffer* vb = m_va->find_buffer( nv::POSITION );
 		vb->bind();
Index: trunk/tests/md5_test/md5_test.cc
===================================================================
--- trunk/tests/md5_test/md5_test.cc	(revision 260)
+++ trunk/tests/md5_test/md5_test.cc	(revision 261)
@@ -103,5 +103,5 @@
 	}
 
-	load_animation( "data/idle02.md5anim" );
+	load_animation( "data/walk.md5anim" );
 	return true;
 }
@@ -135,5 +135,5 @@
 			NV_PROFILE( "update_sh" );
 
-			glm::vec3 source( 150.0f, 0.0f, 0.0f );
+			glm::vec3 source( 250.0f, 0.0f, 0.0f );
 			glm::vec3 eye = glm::rotate( source, (ticks / 20.f), glm::vec3( 0.0,1.0,0.0 ) );
 
