Index: trunk/src/formats/md5_loader.cc
===================================================================
--- trunk/src/formats/md5_loader.cc	(revision 258)
+++ trunk/src/formats/md5_loader.cc	(revision 259)
@@ -47,4 +47,6 @@
 	std_stream sstream( &source );
 	std::string command;
+	std::vector< md5_weight > weights;
+	std::vector< md5_weight_info > weight_info;
 
 	sstream >> command;
@@ -120,4 +122,5 @@
 					}
 					mesh->m_vtx_data.resize( num_verts );
+					weight_info.resize( num_verts );
 
 					next_line( sstream );
@@ -125,5 +128,4 @@
 					for ( int i = 0; i < num_verts; ++i )
 					{
-						md5_vtx_data& vdata = mesh->m_vtx_data[i];
 						size_t weight_count;
 						size_t start_weight;
@@ -132,6 +134,6 @@
 						std::getline( sstream, line );
 						sscanf( line.c_str(), "%*s %*u ( %f %f ) %u %u", &(texcoord.x), &(texcoord.y), &(start_weight), &(weight_count) );
-						vdata.start_weight = start_weight;
-						vdata.weight_count = weight_count;
+						weight_info[i].start_weight = start_weight;
+						weight_info[i].weight_count = weight_count;
 						mesh->m_tdata[i].texcoord = texcoord;
 					}  
@@ -166,5 +168,5 @@
 				{
 					sstream >> num_weights;
-					mesh->m_weights.reserve( num_weights );
+					weights.reserve( num_weights );
 					next_line( sstream );
 					std::string line;
@@ -175,5 +177,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));
- 						mesh->m_weights.push_back(weight);
+ 						weights.push_back(weight);
 					}
 				}
@@ -186,5 +188,5 @@
 			}
 
-			prepare_mesh( mesh );
+			prepare_mesh( mesh, weights, weight_info );
 
 			m_meshes.push_back(mesh);
@@ -198,11 +200,19 @@
 }
 
-bool md5_loader::prepare_mesh( md5_mesh_data* mdata )
+bool md5_loader::prepare_mesh( md5_mesh_data* mdata, std::vector< md5_weight >& weights, std::vector< 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());
+	}
+
 	for ( uint32 i = 0; i < vtx_count; ++i )
 	{
+		size_t start_weight = weight_info[i].start_weight;
+		size_t weight_count = weight_info[i].weight_count;
 		md5_vtx_data& vdata = mdata->m_vtx_data[i];
 		md5_vtx_pnt& vtc = vtcs[i];
@@ -212,30 +222,45 @@
 		vtc.tangent  = glm::vec3(0);
 
-		std::sort( mdata->m_weights.begin() + vdata.start_weight, mdata->m_weights.begin() + vdata.start_weight + vdata.weight_count, [](const md5_weight& a, const md5_weight& b) -> bool { return a.bias > b.bias; } );
-
-		if ( vdata.weight_count > 4 )
+		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; } );
+
+		if ( weight_count > 4 )
 		{
 			float sum = 0.0f;
 			for ( size_t j = 0; j < 4; ++j )
 			{
-				sum += mdata->m_weights[vdata.start_weight + j].bias;
+				sum += weights[start_weight + j].bias;
 			}
 			float ratio = 1.0f / sum;
 			for ( size_t j = 0; j < 4; ++j )
 			{
-				mdata->m_weights[vdata.start_weight + j].bias = 
-					ratio * mdata->m_weights[vdata.start_weight + j].bias;
-			}
-			vdata.weight_count = 4;
-		}
-
-		for ( size_t j = 0; j < vdata.weight_count; ++j )
-		{
-			md5_weight& weight = mdata->m_weights[vdata.start_weight + j];
-			md5_joint&  joint  = m_joints[weight.joint_id];
-
-			glm::vec3 rot_pos = joint.orient * weight.pos;
-
-			vtc.position += ( joint.pos + rot_pos ) * weight.bias;
+				weights[start_weight + j].bias = ratio * weights[start_weight + j].bias;
+			}
+			weight_count = 4;
+		}
+
+		for ( size_t j = 0; j < 4; ++j )
+		{
+			if ( j < weight_count )
+			{
+				vdata.boneindex[j]  = weights[start_weight + j].joint_id;
+				vdata.boneweight[j] = weights[start_weight + j].bias;
+			}
+			else
+			{
+				vdata.boneindex[j]  = 0;
+				vdata.boneweight[j] = 0.0f;
+			}
+		}
+
+		for ( size_t j = 0; j < 4; ++j )
+		{
+			if ( j < weight_count )
+			{
+				md5_weight& weight = weights[start_weight + j];
+				md5_joint&  joint  = m_joints[weight.joint_id];
+				glm::vec3 rot_pos = joint.orient * weight.pos;
+
+				vtc.position += ( joint.pos + rot_pos ) * weight.bias;
+			}
 		}
 	}
@@ -286,13 +311,13 @@
 		vtcs[i].tangent  = tangent;
 
- 		vdata.normal  = glm::vec3(0);
- 		vdata.tangent = glm::vec3(0);
+		vdata.position = vtcs[i].position;
+		vdata.normal   = glm::vec3(0);
+ 		vdata.tangent  = glm::vec3(0);
  
- 		for ( size_t j = 0; j < vdata.weight_count; ++j )
+ 		for ( size_t j = 0; j < 4; ++j )
  		{
- 			const md5_weight& weight = mdata->m_weights[vdata.start_weight + j];
- 			const md5_joint&  joint  = m_joints[weight.joint_id];
- 			vdata.normal  += ( normal  * joint.orient ) * weight.bias;
- 			vdata.tangent += ( tangent * joint.orient ) * weight.bias;
+ 			const md5_joint&  joint  = m_joints[vdata.boneindex[j]];
+ 			vdata.normal  += ( normal  * joint.orient ) * vdata.boneweight[j];
+ 			vdata.tangent += ( tangent * joint.orient ) * vdata.boneweight[j];
  		}
 	}
@@ -537,4 +562,10 @@
 {
 	NV_PROFILE("md5::apply");
+	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 );
@@ -544,15 +575,14 @@
 		md5_vtx_pnt& result = m_pntdata[i];
 
-		for ( size_t j = 0; j < vert.weight_count; ++j )
-		{
-			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;
-		}
-	}
-}
+		for ( size_t j = 0; j < 4; ++j )
+		{
+			int   index  = vert.boneindex[j];
+			float weight = vert.boneweight[j];
+			transform joint  = skeleton[index];
+			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;
+		}
+	}
+}
