From 7859a00967501e8bd1b02cd0457669beb062f881 Mon Sep 17 00:00:00 2001
From: Benau <Benau@users.noreply.github.com>
Date: Thu, 11 Jan 2018 13:38:08 +0800
Subject: [PATCH] Remove unused mesh code

---
 lib/irrlicht/include/IAnimatedMesh.h          |   2 -
 lib/irrlicht/include/ISkinnedMesh.h           |   6 +-
 .../Irrlicht/CAnimatedMeshSceneNode.cpp       |   4 +-
 .../source/Irrlicht/CAnimatedMeshSceneNode.h  |   2 +-
 lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp | 465 +++---------------
 lib/irrlicht/source/Irrlicht/CSkinnedMesh.h   |  18 +-
 src/graphics/mesh_tools.cpp                   | 417 +---------------
 src/graphics/mesh_tools.hpp                   |  19 +-
 src/graphics/sp/sp_mesh.hpp                   |   5 +-
 src/graphics/sp/sp_mesh_node.cpp              |   2 +-
 src/graphics/sp/sp_mesh_node.hpp              |   3 +-
 src/tracks/model_definition_loader.cpp        |  10 -
 src/tracks/track.cpp                          |   6 +-
 src/tracks/track_object_presentation.cpp      |  28 +-
 14 files changed, 86 insertions(+), 901 deletions(-)

diff --git a/lib/irrlicht/include/IAnimatedMesh.h b/lib/irrlicht/include/IAnimatedMesh.h
index 7091f3e22..3e08528df 100644
--- a/lib/irrlicht/include/IAnimatedMesh.h
+++ b/lib/irrlicht/include/IAnimatedMesh.h
@@ -8,8 +8,6 @@
 #include "aabbox3d.h"
 #include "IMesh.h"
 
-typedef void (*SkinningCallback)(const irr::core::matrix4& m, int joint, int offset);
-
 namespace irr
 {
 namespace scene
diff --git a/lib/irrlicht/include/ISkinnedMesh.h b/lib/irrlicht/include/ISkinnedMesh.h
index 7a36aa307..59e21dcc4 100644
--- a/lib/irrlicht/include/ISkinnedMesh.h
+++ b/lib/irrlicht/include/ISkinnedMesh.h
@@ -69,11 +69,7 @@ namespace scene
 		virtual void animateMesh(f32 frame, f32 blend)=0;
 
 		//! Preforms a software skin on this mesh based of joint positions
-		virtual void skinMesh(f32 strength=1.f, SkinningCallback sc = NULL, int offset = -1) = 0;
-
-		//! converts the vertex type of all meshbuffers to tangents.
-		/** E.g. used for bump mapping. */
-		virtual void convertMeshToTangents(bool(*predicate)(IMeshBuffer*)) = 0;
+		virtual void skinMesh(f32 strength=1.f) = 0;
 
 		//! Allows to enable hardware skinning.
 		/* This feature is not implementated in Irrlicht yet */
diff --git a/lib/irrlicht/source/Irrlicht/CAnimatedMeshSceneNode.cpp b/lib/irrlicht/source/Irrlicht/CAnimatedMeshSceneNode.cpp
index 157261e70..2d617ca66 100644
--- a/lib/irrlicht/source/Irrlicht/CAnimatedMeshSceneNode.cpp
+++ b/lib/irrlicht/source/Irrlicht/CAnimatedMeshSceneNode.cpp
@@ -176,7 +176,7 @@ void CAnimatedMeshSceneNode::OnRegisterSceneNode()
 	}
 }
 
-IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame(SkinningCallback sc, int offset)
+IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame()
 {
 	if(Mesh->getMeshType() != EAMT_SKINNED)
 	{
@@ -201,7 +201,7 @@ IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame(SkinningCallback sc, int
 			skinnedMesh->animateMesh(getFrameNr(), 1.0f);
 
 		// Update the skinned mesh for the current joint transforms.
-		skinnedMesh->skinMesh(AnimationStrength, sc, offset);
+		skinnedMesh->skinMesh(AnimationStrength);
 
 		if (JointMode == EJUOR_READ)//read from mesh
 		{
diff --git a/lib/irrlicht/source/Irrlicht/CAnimatedMeshSceneNode.h b/lib/irrlicht/source/Irrlicht/CAnimatedMeshSceneNode.h
index 4d09652d6..f17086d01 100644
--- a/lib/irrlicht/source/Irrlicht/CAnimatedMeshSceneNode.h
+++ b/lib/irrlicht/source/Irrlicht/CAnimatedMeshSceneNode.h
@@ -173,7 +173,7 @@ namespace scene
 	protected:
 
 		//! Get a static mesh for the current frame of this animated mesh
-		virtual IMesh* getMeshForCurrentFrame(SkinningCallback sc = NULL, int offset = -1);
+		virtual IMesh* getMeshForCurrentFrame();
 
 		void buildFrameNr(u32 timeMs);
 		virtual void checkJoints();
diff --git a/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp b/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp
index 4493599a8..cc2bec034 100644
--- a/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp
+++ b/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp
@@ -11,55 +11,6 @@
 #include "os.h"
 #include "irrMap.h"
 
-inline irr::s16 float_16(irr::f32 in)
-{
-	irr::s32 i;
-	memcpy(&i, &in, 4);
-	irr::s32 s = (i >> 16) & 0x00008000;
-	irr::s32 e = ((i >> 23) & 0x000000ff) - (127 - 15);
-	irr::s32 m = i & 0x007fffff;
-	if (e <= 0)
-	{
-		if (e < -10)
-		{
-			return irr::s16(s);
-		}
-		m = (m | 0x00800000) >> (1 - e);
-		if (m & 0x00001000)
-			m += 0x00002000;
-		return irr::s16(s | (m >> 13));
-	}
-	else if (e == 0xff - (127 - 15))
-	{
-		if (m == 0)
-		{
-			return irr::s16(s | 0x7c00);
-		}
-		else
-		{
-			m >>= 13;
-			return irr::s16(s | 0x7c00 | m | (m == 0));
-		}
-	}
-	else
-	{
-		if (m &  0x00001000)
-		{
-			m += 0x00002000;
-			if (m & 0x00800000)
-			{
-				m =  0;     // overflow in significand,
-				e += 1;     // adjust exponent
-			}
-		}
-		if (e > 30)
-		{
-            return irr::s16(s | 0x7c00);
-		}
-		return irr::s16(s | (e << 10) | (m >> 13));
-	}
-}
-
 namespace irr
 {
 namespace scene
@@ -72,8 +23,7 @@ CSkinnedMesh::CSkinnedMesh()
 	LastAnimatedFrame(-1), SkinnedLastFrame(false),
 	InterpolationMode(EIM_LINEAR),
 	HasAnimation(false), PreparedForSkinning(false),
-	AnimateNormals(true), HardwareSkinning(false), m_total_joints(0),
-	m_current_joint(0)
+	AnimateNormals(true), HardwareSkinning(false)
 {
 	#ifdef _DEBUG
 	setDebugName("CSkinnedMesh");
@@ -511,7 +461,7 @@ void CSkinnedMesh::getFrameData(f32 frame, SJoint *joint,
 //--------------------------------------------------------------------------
 
 //! Preforms a software skin on this mesh based of joint positions
-void CSkinnedMesh::skinMesh(f32 strength, SkinningCallback sc, int offset)
+void CSkinnedMesh::skinMesh(f32 strength)
 {
 	if (!HasAnimation || SkinnedLastFrame)
 		return;
@@ -522,109 +472,94 @@ void CSkinnedMesh::skinMesh(f32 strength, SkinningCallback sc, int offset)
 	//-----------------
 
 	SkinnedLastFrame=true;
-	m_current_joint = 0;
-	if (HardwareSkinning)
-	{
-		for (u32 i = 0; i < RootJoints.size(); i++)
-			skinJoint(RootJoints[i], 0, strength, sc, offset);
-	}
-	else
-	{
-		//Software skin....
-		u32 i;
 
-		//rigid animation
-		for (i=0; i<AllJoints.size(); ++i)
+	//Software skin....
+	u32 i;
+
+	//rigid animation
+	for (i=0; i<AllJoints.size(); ++i)
+	{
+		for (u32 j=0; j<AllJoints[i]->AttachedMeshes.size(); ++j)
 		{
-			for (u32 j=0; j<AllJoints[i]->AttachedMeshes.size(); ++j)
-			{
-				SSkinMeshBuffer* Buffer=(*SkinningBuffers)[ AllJoints[i]->AttachedMeshes[j] ];
-				Buffer->Transformation=AllJoints[i]->GlobalAnimatedMatrix;
-			}
+			SSkinMeshBuffer* Buffer=(*SkinningBuffers)[ AllJoints[i]->AttachedMeshes[j] ];
+			Buffer->Transformation=AllJoints[i]->GlobalAnimatedMatrix;
 		}
-
-		//clear skinning helper array
-		for (i=0; i<Vertices_Moved.size(); ++i)
-			for (u32 j=0; j<Vertices_Moved[i].size(); ++j)
-				Vertices_Moved[i][j]=false;
-
-		//skin starting with the root joints
-		for (i=0; i<RootJoints.size(); ++i)
-			skinJoint(RootJoints[i], 0, strength);
-
-		for (i=0; i<SkinningBuffers->size(); ++i)
-			(*SkinningBuffers)[i]->setDirty(EBT_VERTEX);
 	}
+
+	//clear skinning helper array
+	for (i=0; i<Vertices_Moved.size(); ++i)
+		for (u32 j=0; j<Vertices_Moved[i].size(); ++j)
+			Vertices_Moved[i][j]=false;
+
+	//skin starting with the root joints
+	for (i=0; i<RootJoints.size(); ++i)
+		skinJoint(RootJoints[i], 0, strength);
+
+	for (i=0; i<SkinningBuffers->size(); ++i)
+		(*SkinningBuffers)[i]->setDirty(EBT_VERTEX);
+
 	updateBoundingBox();
 }
 
-void CSkinnedMesh::skinJoint(SJoint *joint, SJoint *parentJoint, f32 strength,
-							SkinningCallback sc, int offset)
+void CSkinnedMesh::skinJoint(SJoint *joint, SJoint *parentJoint, f32 strength)
 {
 	if (joint->Weights.size())
 	{
 		//Find this joints pull on vertices...
 		core::matrix4 jointVertexPull(core::matrix4::EM4CONST_NOTHING);
 		jointVertexPull.setbyproduct(joint->GlobalAnimatedMatrix, joint->GlobalInversedMatrix);
-		if (HardwareSkinning)
-		{
-			if (sc != NULL) sc(jointVertexPull, m_current_joint, offset);
-			m_current_joint++;
-		}
-		else
-		{
-			core::vector3df thisVertexMove, thisNormalMove;
 
-			core::array<scene::SSkinMeshBuffer*> &buffersUsed=*SkinningBuffers;
+		core::vector3df thisVertexMove, thisNormalMove;
 
-			//Skin Vertices Positions and Normals...
-			for (u32 i=0; i<joint->Weights.size(); ++i)
+		core::array<scene::SSkinMeshBuffer*> &buffersUsed=*SkinningBuffers;
+
+		//Skin Vertices Positions and Normals...
+		for (u32 i=0; i<joint->Weights.size(); ++i)
+		{
+			SWeight& weight = joint->Weights[i];
+
+			// Pull this vertex...
+			jointVertexPull.transformVect(thisVertexMove, weight.StaticPos);
+
+			if (AnimateNormals)
+				jointVertexPull.rotateVect(thisNormalMove, weight.StaticNormal);
+
+			// Apply animation strength
+			if(strength != 1.f)
 			{
-				SWeight& weight = joint->Weights[i];
+				thisVertexMove = core::lerp(weight.StaticPos, thisVertexMove, strength);
+				if(AnimateNormals)
+					thisNormalMove = core::lerp(weight.StaticNormal, thisNormalMove, strength);
+			}
 
-				// Pull this vertex...
-				jointVertexPull.transformVect(thisVertexMove, weight.StaticPos);
+			if (! (*(weight.Moved)) )
+			{
+				*(weight.Moved) = true;
+
+				buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Pos = thisVertexMove * weight.strength;
 
 				if (AnimateNormals)
-					jointVertexPull.rotateVect(thisNormalMove, weight.StaticNormal);
+					buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Normal = thisNormalMove * weight.strength;
 
-				// Apply animation strength
-				if(strength != 1.f)
-				{
-					thisVertexMove = core::lerp(weight.StaticPos, thisVertexMove, strength);
-					if(AnimateNormals)
-						thisNormalMove = core::lerp(weight.StaticNormal, thisNormalMove, strength);
-				}
-
-				if (! (*(weight.Moved)) )
-				{
-					*(weight.Moved) = true;
-
-					buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Pos = thisVertexMove * weight.strength;
-
-					if (AnimateNormals)
-						buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Normal = thisNormalMove * weight.strength;
-
-					//*(weight._Pos) = thisVertexMove * weight.strength;
-				}
-				else
-				{
-					buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Pos += thisVertexMove * weight.strength;
-
-					if (AnimateNormals)
-						buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Normal += thisNormalMove * weight.strength;
-
-					//*(weight._Pos) += thisVertexMove * weight.strength;
-				}
-
-				buffersUsed[weight.buffer_id]->boundingBoxNeedsRecalculated();
+				//*(weight._Pos) = thisVertexMove * weight.strength;
 			}
+			else
+			{
+				buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Pos += thisVertexMove * weight.strength;
+
+				if (AnimateNormals)
+					buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Normal += thisNormalMove * weight.strength;
+
+				//*(weight._Pos) += thisVertexMove * weight.strength;
+			}
+
+			buffersUsed[weight.buffer_id]->boundingBoxNeedsRecalculated();
 		}
 	}
 
 	//Skin all children
 	for (u32 j=0; j<joint->Children.size(); ++j)
-		skinJoint(joint->Children[j], joint, strength, sc, offset);
+		skinJoint(joint->Children[j], joint, strength);
 }
 
 
@@ -1462,278 +1397,6 @@ void CSkinnedMesh::addJoints(core::array<IBoneSceneNode*> &jointChildSceneNodes,
 	SkinnedLastFrame=false;
 }
 
-bool CSkinnedMesh::sortJointInfluenceFunc(const JointInfluence& a, 
-										  const JointInfluence& b)
-{
-	return a.weight > b.weight;
-}
-
-void CSkinnedMesh::convertForSkinning()
-{
-/*	if (HardwareSkinning) return;
-
-	setHardwareSkinning(true);
-	WeightInfluence wi;
-	for (u32 b = 0; b < LocalBuffers.size(); b++)
-	{
-		if (LocalBuffers[b])
-			LocalBuffers[b]->convertForSkinning();
-
-		wi.push_back(core::array<core::array<JointInfluence> > ());
-		for (u32 i = 0; i < LocalBuffers[b]->getVertexCount(); i++)
-			wi[b].push_back(core::array<JointInfluence>());
-	}
-
-	size_t idx = 0;
-	for (u32 i = 0; i < RootJoints.size(); i++)
-		computeWeightInfluence(RootJoints[i], idx, wi);
-
-	for (u32 b = 0; b < LocalBuffers.size(); b++)
-	{
-		if (LocalBuffers[b])
-		{
-			const u32 total = wi[b].size();
-			_IRR_DEBUG_BREAK_IF(LocalBuffers[b]->getVertexCount() != total);
-			for (u32 i = 0; i < total; i++)
-			{
-				core::array<JointInfluence> this_influence;
-				core::array<JointInfluence> reported_weight = wi[b][i];
-				reported_weight.sort(sortJointInfluenceFunc);
-				for (u32 j = 0; j < 4; j++)
-				{
-					JointInfluence influence;
-					influence.joint_idx = -32768;
-					influence.weight = j == 0 ? 1.0f : 0.0f;
-					this_influence.push_back(influence);
-				}
-				float total_weight = 0.0f;
-				const unsigned max_weight =
-					reported_weight.size() > 4 ? 4 : reported_weight.size();
-				for (u32 j = 0; j < max_weight; j++)
-				{
-					total_weight += reported_weight[j].weight;
-					this_influence[j].joint_idx = reported_weight[j].joint_idx;
-					this_influence[j].weight = reported_weight[j].weight;
-				}
-				if (total_weight != 0.0f)
-				{
-					for (u32 j = 0; j < max_weight; j++)
-					{
-						this_influence[j].weight =
-							this_influence[j].weight / total_weight;
-					}
-				}
-				for (int j = 0; j < 4; j++)
-				{
-					LocalBuffers[b]->Vertices_SkinnedMesh[i].m_joint_idx[j] = (s16)this_influence[j].joint_idx;
-					LocalBuffers[b]->Vertices_SkinnedMesh[i].m_weight[j] = float_16
-						(this_influence[j].weight);
-				}
-			}
-		}
-	}
-	SkinnedLastFrame = false;
-	skinMesh();
-	m_total_joints = m_current_joint;*/
-}
-
-void CSkinnedMesh::computeWeightInfluence(SJoint *joint, size_t &index, WeightInfluence& wi)
-{
-	if (!joint->Weights.empty())
-	{
-		for (u32 i = 0; i < joint->Weights.size(); i++)
-		{
-			SWeight& weight = joint->Weights[i];
-			JointInfluence tmp;
-			tmp.joint_idx = (int)index;
-			tmp.weight = weight.strength;
-			wi[weight.buffer_id][weight.vertex_id].push_back(tmp);
-		}
-		index++;
-	}
-
-	for (u32 j = 0; j < joint->Children.size(); j++)
-		computeWeightInfluence(joint->Children[j], index, wi);
-}
-
-void CSkinnedMesh::convertMeshToTangents(bool(*predicate)(IMeshBuffer*))
-{
-/*	bool recalculate_animation = false;
-	toStaticPose();
-	for (u32 b = 0; b < LocalBuffers.size(); b++)
-	{
-		bool recalculate_joints = false;
-		core::map<u32, u32> vert_loc_map;
-		SSkinMeshBuffer* ssmb = LocalBuffers[b];
-		if (ssmb)
-		{
-			if (!predicate(ssmb)) continue;
-            ssmb->Vertices_Tangents.set_used(ssmb->Vertices_Standard.size());
-            for (unsigned i = 0; i < ssmb->Vertices_Tangents.size(); i++)
-            {
-                ssmb->Vertices_Tangents[i] = video::S3DVertexTangents(ssmb->Vertices_Standard[i].Pos,
-                ssmb->Vertices_Standard[i].Normal,ssmb->Vertices_Standard[i].Color,
-                ssmb->Vertices_Standard[i].TCoords);
-                if (!ssmb->m_tangents_map.empty())
-			{
-					ssmb->Vertices_Tangents[i].Tangent = ssmb->m_tangents_map.find(i)->getValue().first;
-					ssmb->Vertices_Tangents[i].Binormal = ssmb->m_tangents_map.find(i)->getValue().second.first;
-					ssmb->Vertices_Tangents[i].m_bitangent_sign = ssmb->m_tangents_map.find(i)->getValue().second.second;
-            }
-            }
-
-
-
-			recalculate_joints = true;
-			recalculate_animation = true;
-			core::map<video::S3DVertexTangents, u32> vert_map;
-			core::array<u16> tmp_indices;
-			for (u32 i = 0; i < ssmb->Indices.size(); i++)
-			{
-				u32 vert_location = 0;
-				const u32 cur_ver_loc = ssmb->Indices[i];
-				const video::S3DVertex& v_old = ssmb->Vertices_Standard[cur_ver_loc];
-				video::S3DVertexTangents v(v_old.Pos, v_old.Normal, v_old.Color, v_old.TCoords);
-				core::map<video::S3DVertexTangents, u32>::Node *n = vert_map.find(v);
-				if (n)
-				{
-					vert_location = n->getValue();
-				}
-				else
-				{
-					vert_location = ssmb->Vertices_Tangents.size();
-					ssmb->Vertices_Tangents.push_back(v);
-					vert_map.insert(v, vert_location);
-				}
-				vert_loc_map[cur_ver_loc] = vert_location;
-				tmp_indices.push_back(vert_location);
-			}
-			const s32 index_count = tmp_indices.size();
-			u16* idx = tmp_indices.pointer();
-			video::S3DVertexTangents* v = ssmb->Vertices_Tangents.pointer();
-			core::vector3df local_normal;
-			if (!ssmb->m_tangents_map.empty())
-			{
-				for (unsigned i = 0; i < ssmb->Vertices_Tangents.size(); i++)
-				{
-				    auto a = ssmb->m_tangents_map.find(v[i].Pos);
-				    if (a)
-				    {
-					v[i].Tangent = a->getValue().first;
-					v[i].Binormal = a->getValue().second.first;
-					v[i].m_bitangent_sign = a->getValue().second.second;
-					}
-					else
-					{
-					    printf("ddd\n");
-					}
-				}
-			}
-			else
-			{
-				for (s32 i = 0; i < index_count; i += 3)
-				{
-					calculateTangents(
-						local_normal,
-						v[idx[i+0]].Tangent,
-						v[idx[i+0]].Binormal,
-						v[idx[i+0]].Pos,
-						v[idx[i+1]].Pos,
-						v[idx[i+2]].Pos,
-						v[idx[i+0]].TCoords,
-						v[idx[i+1]].TCoords,
-						v[idx[i+2]].TCoords);
-
-					calculateTangents(
-						local_normal,
-						v[idx[i+1]].Tangent,
-						v[idx[i+1]].Binormal,
-						v[idx[i+1]].Pos,
-						v[idx[i+2]].Pos,
-						v[idx[i+0]].Pos,
-						v[idx[i+1]].TCoords,
-						v[idx[i+2]].TCoords,
-						v[idx[i+0]].TCoords);
-
-					calculateTangents(
-						local_normal,
-						v[idx[i+2]].Tangent,
-						v[idx[i+2]].Binormal,
-						v[idx[i+2]].Pos,
-						v[idx[i+0]].Pos,
-						v[idx[i+1]].Pos,
-						v[idx[i+2]].TCoords,
-						v[idx[i+0]].TCoords,
-						v[idx[i+1]].TCoords);
-				}
-
-			ssmb->Vertices_Standard.clear();
-			ssmb->VertexType = video::EVT_TANGENTS;
-		}
-		if (recalculate_joints)
-		{
-			Vertices_Moved[b].set_used(ssmb->getVertexCount());
-			for (u32 i = 0; i < AllJoints.size(); i++)
-			{
-				SJoint *joint = AllJoints[i];
-				for (u32 j = 0; j <joint->Weights.size(); j++)
-				{
-					if (joint->Weights[j].buffer_id == b)
-					{
-						core::map<u32, u32>::Node *n =
-							vert_loc_map.find(joint->Weights[j].vertex_id);
-						if (n)
-						{
-							joint->Weights[j].vertex_id = n->getValue();
-						}
-					}
-				}
-			}
-		}
-	}
-	if (recalculate_animation)
-	{
-		PreparedForSkinning = false;
-		checkForAnimation();
-	}*/
-}
-
-void CSkinnedMesh::calculateTangents(
-	core::vector3df& normal,
-	core::vector3df& tangent,
-	core::vector3df& binormal,
-	core::vector3df& vt1, core::vector3df& vt2, core::vector3df& vt3, // vertices
-	core::vector2df& tc1, core::vector2df& tc2, core::vector2df& tc3) // texture coords
-{
-	core::vector3df v1 = vt1 - vt2;
-	core::vector3df v2 = vt3 - vt1;
-	normal = v2.crossProduct(v1);
-	normal.normalize();
-
-	// binormal
-
-	f32 deltaX1 = tc1.X - tc2.X;
-	f32 deltaX2 = tc3.X - tc1.X;
-	binormal = (v1 * deltaX2) - (v2 * deltaX1);
-	binormal.normalize();
-
-	// tangent
-
-	f32 deltaY1 = tc1.Y - tc2.Y;
-	f32 deltaY2 = tc3.Y - tc1.Y;
-	tangent = (v1 * deltaY2) - (v2 * deltaY1);
-	tangent.normalize();
-
-	// adjust
-
-	core::vector3df txb = tangent.crossProduct(binormal);
-	if (txb.dotProduct(normal) < 0.0f)
-	{
-		tangent *= -1.0f;
-		binormal *= -1.0f;
-	}
-}
-
 } // end namespace scene
 } // end namespace irr
 
diff --git a/lib/irrlicht/source/Irrlicht/CSkinnedMesh.h b/lib/irrlicht/source/Irrlicht/CSkinnedMesh.h
index d1044b1b7..d2cc52b2e 100644
--- a/lib/irrlicht/source/Irrlicht/CSkinnedMesh.h
+++ b/lib/irrlicht/source/Irrlicht/CSkinnedMesh.h
@@ -61,7 +61,7 @@ namespace scene
 		virtual void animateMesh(f32 frame, f32 blend);
 
 		//! Preforms a software skin on this mesh based of joint positions
-		virtual void skinMesh(f32 strength=1.f, SkinningCallback sc = NULL, int offset = -1);
+		virtual void skinMesh(f32 strength=1.f);
 
 		//! returns amount of mesh buffers.
 		virtual u32 getMeshBufferCount() const;
@@ -113,9 +113,6 @@ namespace scene
 		//! Sets Interpolation Mode
 		virtual void setInterpolationMode(E_INTERPOLATION_MODE mode);
 
-		//! Convertes the mesh to contain tangent information
-		virtual void convertMeshToTangents(bool(*predicate)(IMeshBuffer*));
-
 		//! Does the mesh have no animation
 		virtual bool isStatic();
 
@@ -172,14 +169,12 @@ namespace scene
 		void convertForSkinning();
 
 		void computeWeightInfluence(SJoint *joint, size_t &index, WeightInfluence& wi);
-
-		void buildAllGlobalAnimatedMatrices(SJoint *Joint=0, SJoint *ParentJoint=0);
 
-		u32 getTotalJoints() const { return m_total_joints; }
+		void buildAllGlobalAnimatedMatrices(SJoint *Joint=0, SJoint *ParentJoint=0);
 
 		f32 AnimationFrames;
-
-		core::array<SJoint*> RootJoints;
+
+		core::array<SJoint*> RootJoints;
 
 private:
 		void toStaticPose();
@@ -197,8 +192,7 @@ private:
 
 		void calculateGlobalMatrices(SJoint *Joint,SJoint *ParentJoint);
 
-		void skinJoint(SJoint *Joint, SJoint *ParentJoint, f32 strength=1.f,
-						SkinningCallback sc = NULL, int offset = -1);
+		void skinJoint(SJoint *Joint, SJoint *ParentJoint, f32 strength=1.f);
 
 		void calculateTangents(core::vector3df& normal,
 			core::vector3df& tangent, core::vector3df& binormal,
@@ -229,8 +223,6 @@ private:
 		bool PreparedForSkinning;
 		bool AnimateNormals;
 		bool HardwareSkinning;
-		u32 m_total_joints;
-		u32 m_current_joint;
 	};
 
 } // end namespace scene
diff --git a/src/graphics/mesh_tools.cpp b/src/graphics/mesh_tools.cpp
index dc5808f54..7f29e36b9 100644
--- a/src/graphics/mesh_tools.cpp
+++ b/src/graphics/mesh_tools.cpp
@@ -16,21 +16,17 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
-#include "graphics/mesh_tools.hpp"
-
-#include "graphics/central_settings.hpp"
-#include "graphics/irr_driver.hpp"
-#include "graphics/shaders.hpp"
-#include "modes/world.hpp"
-#include "tracks/track.hpp"
 #include "utils/log.hpp"
+#include "utils/vec3.hpp"
 
 #include <irrlicht.h>
 #include <IMesh.h>
 #include <IMeshBuffer.h>
 #include <SSkinMeshBuffer.h>
 
-void MeshTools::minMax3D(scene::IMesh* mesh, Vec3 *min, Vec3 *max)
+namespace MeshTools
+{
+void minMax3D(scene::IMesh* mesh, Vec3 *min, Vec3 *max)
 {
     Vec3 extend;
     *min = Vec3( 999999.9f);
@@ -103,407 +99,4 @@ void MeshTools::minMax3D(scene::IMesh* mesh, Vec3 *min, Vec3 *max)
     }  // for i<getMeshBufferCount
 }   // minMax3D
 
-// Copied from irrlicht
-void calculateTangents(
-    core::vector3df& normal,
-    core::vector3df& tangent,
-    core::vector3df& binormal,
-    const core::vector3df& vt1, const core::vector3df& vt2, const core::vector3df& vt3, // vertices
-    const core::vector2df& tc1, const core::vector2df& tc2, const core::vector2df& tc3) // texture coords
-{
-    core::vector3df v1 = vt1 - vt2;
-    core::vector3df v2 = vt3 - vt1;
-    normal = v2.crossProduct(v1);
-    normal.normalize();
-
-    // binormal
-
-    f32 deltaX1 = tc1.X - tc2.X;
-    f32 deltaX2 = tc3.X - tc1.X;
-    binormal = (v1 * deltaX2) - (v2 * deltaX1);
-    binormal.normalize();
-
-    // tangent
-
-    f32 deltaY1 = tc1.Y - tc2.Y;
-    f32 deltaY2 = tc3.Y - tc1.Y;
-    tangent = (v1 * deltaY2) - (v2 * deltaY1);
-    tangent.normalize();
-
-    // adjust
-
-    core::vector3df txb = tangent.crossProduct(binormal);
-    if (txb.dotProduct(normal) < 0.0f)
-    {
-        tangent *= -1.0f;
-        binormal *= -1.0f;
-    }
-}
-
-// Copied from irrlicht
-static inline core::vector3df getAngleWeight(const core::vector3df& v1,
-    const core::vector3df& v2,
-    const core::vector3df& v3)
-{
-    // Calculate this triangle's weight for each of its three vertices
-    // start by calculating the lengths of its sides
-    const f32 a = v2.getDistanceFromSQ(v3);
-    const f32 asqrt = sqrtf(a);
-    const f32 b = v1.getDistanceFromSQ(v3);
-    const f32 bsqrt = sqrtf(b);
-    const f32 c = v1.getDistanceFromSQ(v2);
-    const f32 csqrt = sqrtf(c);
-
-    // use them to find the angle at each vertex
-    return core::vector3df(
-        acosf((b + c - a) / (2.f * bsqrt * csqrt)),
-        acosf((-b + c + a) / (2.f * asqrt * csqrt)),
-        acosf((b - c + a) / (2.f * bsqrt * asqrt)));
-}
-
-// Copied from irrlicht
-template <typename T>
-void recalculateTangentsT(scene::IMeshBuffer* buffer, bool recalculate_normals, bool smooth, bool angle_weighted)
-{
-    if (!buffer || (buffer->getVertexType() != video::EVT_TANGENTS))
-        return;
-
-    const u32 vtxCnt = buffer->getVertexCount();
-    const u32 idxCnt = buffer->getIndexCount();
-
-    T* idx = reinterpret_cast<T*>(buffer->getIndices());
-    video::S3DVertexTangents* v =
-        (video::S3DVertexTangents*)buffer->getVertices();
-
-    if (smooth)
-    {
-        u32 i;
-
-        for (i = 0; i != vtxCnt; ++i)
-        {
-            if (recalculate_normals)
-                v[i].Normal.set(0.f, 0.f, 0.f);
-            v[i].Tangent.set(0.f, 0.f, 0.f);
-            v[i].Binormal.set(0.f, 0.f, 0.f);
-        }
-
-        //Each vertex gets the sum of the tangents and binormals from the faces around it
-        for (i = 0; i<idxCnt; i += 3)
-        {
-            // if this triangle is degenerate, skip it!
-            if (v[idx[i + 0]].Pos == v[idx[i + 1]].Pos ||
-                v[idx[i + 0]].Pos == v[idx[i + 2]].Pos ||
-                v[idx[i + 1]].Pos == v[idx[i + 2]].Pos
-                /*||
-                v[idx[i+0]].TCoords == v[idx[i+1]].TCoords ||
-                v[idx[i+0]].TCoords == v[idx[i+2]].TCoords ||
-                v[idx[i+1]].TCoords == v[idx[i+2]].TCoords */
-                )
-                continue;
-
-            //Angle-weighted normals look better, but are slightly more CPU intensive to calculate
-            core::vector3df weight(1.f, 1.f, 1.f);
-            if (angle_weighted)
-                weight = getAngleWeight(v[i + 0].Pos, v[i + 1].Pos, v[i + 2].Pos);
-            core::vector3df localNormal;
-            core::vector3df localTangent;
-            core::vector3df localBinormal;
-
-            calculateTangents(
-                localNormal,
-                localTangent,
-                localBinormal,
-                v[idx[i + 0]].Pos,
-                v[idx[i + 1]].Pos,
-                v[idx[i + 2]].Pos,
-                v[idx[i + 0]].TCoords,
-                v[idx[i + 1]].TCoords,
-                v[idx[i + 2]].TCoords);
-
-            if (recalculate_normals)
-                v[idx[i + 0]].Normal += localNormal * weight.X;
-            v[idx[i + 0]].Tangent += localTangent * weight.X;
-            v[idx[i + 0]].Binormal += localBinormal * weight.X;
-
-            calculateTangents(
-                localNormal,
-                localTangent,
-                localBinormal,
-                v[idx[i + 1]].Pos,
-                v[idx[i + 2]].Pos,
-                v[idx[i + 0]].Pos,
-                v[idx[i + 1]].TCoords,
-                v[idx[i + 2]].TCoords,
-                v[idx[i + 0]].TCoords);
-
-            if (recalculate_normals)
-                v[idx[i + 1]].Normal += localNormal * weight.Y;
-            v[idx[i + 1]].Tangent += localTangent * weight.Y;
-            v[idx[i + 1]].Binormal += localBinormal * weight.Y;
-
-            calculateTangents(
-                localNormal,
-                localTangent,
-                localBinormal,
-                v[idx[i + 2]].Pos,
-                v[idx[i + 0]].Pos,
-                v[idx[i + 1]].Pos,
-                v[idx[i + 2]].TCoords,
-                v[idx[i + 0]].TCoords,
-                v[idx[i + 1]].TCoords);
-
-            if (recalculate_normals)
-                v[idx[i + 2]].Normal += localNormal * weight.Z;
-            v[idx[i + 2]].Tangent += localTangent * weight.Z;
-            v[idx[i + 2]].Binormal += localBinormal * weight.Z;
-        }
-
-        // Normalize the tangents and binormals
-        if (recalculate_normals)
-        {
-            for (i = 0; i != vtxCnt; ++i)
-                v[i].Normal.normalize();
-        }
-        for (i = 0; i != vtxCnt; ++i)
-        {
-            v[i].Tangent.normalize();
-            v[i].Binormal.normalize();
-        }
-    }
-    else
-    {
-        core::vector3df localNormal;
-        for (u32 i = 0; i<idxCnt; i += 3)
-        {
-            calculateTangents(
-                localNormal,
-                v[idx[i + 0]].Tangent,
-                v[idx[i + 0]].Binormal,
-                v[idx[i + 0]].Pos,
-                v[idx[i + 1]].Pos,
-                v[idx[i + 2]].Pos,
-                v[idx[i + 0]].TCoords,
-                v[idx[i + 1]].TCoords,
-                v[idx[i + 2]].TCoords);
-            if (recalculate_normals)
-                v[idx[i + 0]].Normal = localNormal;
-
-            calculateTangents(
-                localNormal,
-                v[idx[i + 1]].Tangent,
-                v[idx[i + 1]].Binormal,
-                v[idx[i + 1]].Pos,
-                v[idx[i + 2]].Pos,
-                v[idx[i + 0]].Pos,
-                v[idx[i + 1]].TCoords,
-                v[idx[i + 2]].TCoords,
-                v[idx[i + 0]].TCoords);
-            if (recalculate_normals)
-                v[idx[i + 1]].Normal = localNormal;
-
-            calculateTangents(
-                localNormal,
-                v[idx[i + 2]].Tangent,
-                v[idx[i + 2]].Binormal,
-                v[idx[i + 2]].Pos,
-                v[idx[i + 0]].Pos,
-                v[idx[i + 1]].Pos,
-                v[idx[i + 2]].TCoords,
-                v[idx[i + 0]].TCoords,
-                v[idx[i + 1]].TCoords);
-            if (recalculate_normals)
-                v[idx[i + 2]].Normal = localNormal;
-        }
-    }
-}
-
-// Copied from irrlicht
-void recalculateTangents(scene::IMeshBuffer* buffer, bool recalculate_normals, bool smooth, bool angle_weighted)
-{
-    if (buffer && (buffer->getVertexType() == video::EVT_TANGENTS))
-    {
-        if (buffer->getIndexType() == video::EIT_16BIT)
-            recalculateTangentsT<u16>(buffer, recalculate_normals, smooth, angle_weighted);
-        else
-            recalculateTangentsT<u32>(buffer, recalculate_normals, smooth, angle_weighted);
-    }
-}
-
-// Copied from irrlicht
-void recalculateTangents(scene::IMesh* mesh, bool recalculate_normals, bool smooth, bool angle_weighted)
-{
-    if (!mesh)
-        return;
-
-    const u32 mesh_buffer_count = mesh->getMeshBufferCount();
-    for (u32 b = 0; b<mesh_buffer_count; ++b)
-    {
-        recalculateTangents(mesh->getMeshBuffer(b), recalculate_normals, smooth, angle_weighted);
-    }
-}
-
-#ifndef SERVER_ONLY
-bool MeshTools::isNormalMap(scene::IMeshBuffer* mb)
-{
-    if (!CVS->isGLSL())
-        return false;
-    return (mb->getMaterial().MaterialType == Shaders::getShader(ES_NORMAL_MAP) &&
-            mb->getVertexType() != video::EVT_TANGENTS);
-}
-#endif
-
-// Copied from irrlicht
-scene::IMesh* MeshTools::createMeshWithTangents(scene::IMesh* mesh,
-                                                bool(*predicate)(scene::IMeshBuffer*),
-                                                bool recalculate_normals, bool smooth,
-                                                bool angle_weighted,
-                                                bool calculate_tangents)
-{
-    return mesh;
-    if (!mesh)
-        return 0;
-
-    scene::ISkinnedMesh* sm = dynamic_cast<scene::ISkinnedMesh*>(mesh);
-    if (sm)
-    {
-        createSkinnedMeshWithTangents(sm, predicate);
-        return sm;
-    }
-
-    // copy mesh and fill data into SMeshBufferTangents
-
-    const u32 mesh_buffer_count = mesh->getMeshBufferCount();
-
-    bool needs_normal_map = false;
-    for (u32 b = 0; b < mesh_buffer_count; ++b)
-    {
-        scene::IMeshBuffer* original = mesh->getMeshBuffer(b);
-        if (predicate(original))
-        {
-            needs_normal_map = true;
-            break;
-        }
-    }
-
-    if (!needs_normal_map)
-    {
-        return mesh;
-    }
-    scene::SMesh* clone = new scene::SMesh();
-
-    for (u32 b = 0; b<mesh_buffer_count; ++b)
-    {
-        scene::IMeshBuffer* original = mesh->getMeshBuffer(b);
-        const u32 idxCnt = original->getIndexCount();
-        const u16* idx = original->getIndices();
-
-        if (!predicate(original))
-        {
-            clone->addMeshBuffer(original);
-            continue;
-        }
-
-        scene::SMeshBufferTangents* buffer = new scene::SMeshBufferTangents();
-
-        buffer->Material = original->getMaterial();
-        buffer->Vertices.reallocate(idxCnt);
-        buffer->Indices.reallocate(idxCnt);
-
-        core::map<video::S3DVertexTangents, int> vertMap;
-        int vertLocation;
-
-        // copy vertices
-
-        const video::E_VERTEX_TYPE vType = original->getVertexType();
-        video::S3DVertexTangents vNew;
-        for (u32 i = 0; i<idxCnt; ++i)
-        {
-            switch (vType)
-            {
-                case video::EVT_STANDARD:
-                {
-                    const video::S3DVertex* v =
-                        (const video::S3DVertex*)original->getVertices();
-                    vNew = video::S3DVertexTangents(
-                        v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords);
-                }
-                break;
-                case video::EVT_2TCOORDS:
-                {
-                    const video::S3DVertex2TCoords* v =
-                        (const video::S3DVertex2TCoords*)original->getVertices();
-                    vNew = video::S3DVertexTangents(
-                        v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords);
-                }
-                break;
-                case video::EVT_TANGENTS:
-                {
-                        const video::S3DVertexTangents* v =
-                            (const video::S3DVertexTangents*)original->getVertices();
-                        vNew = v[idx[i]];
-                }
-                break;
-                default:
-                break;
-            }
-            core::map<video::S3DVertexTangents, int>::Node* n = vertMap.find(vNew);
-            if (n)
-            {
-                vertLocation = n->getValue();
-            }
-            else
-            {
-                vertLocation = buffer->Vertices.size();
-                buffer->Vertices.push_back(vNew);
-                vertMap.insert(vNew, vertLocation);
-            }
-
-            // create new indices
-            buffer->Indices.push_back(vertLocation);
-        }
-        buffer->recalculateBoundingBox();
-
-        // add new buffer
-        clone->addMeshBuffer(buffer);
-        buffer->drop();
-    }
-
-    clone->recalculateBoundingBox();
-    if (calculate_tangents)
-        recalculateTangents(clone, recalculate_normals, smooth, angle_weighted);
-
-    scene::IMeshCache* meshCache = irr_driver->getSceneManager()->getMeshCache();
-    io::SNamedPath path = meshCache->getMeshName(mesh);
-    if (path.getPath() == "")
-    {
-        // This mesh is not in irrlicht cache, drop it directly
-        assert(mesh->getReferenceCount() == 1);
-        mesh->drop();
-        return clone;
-    }
-    else
-    {
-        // Cache the calcuated tangent mesh with path
-        irr_driver->removeMeshFromCache(mesh);
-        scene::SAnimatedMesh* amesh = new scene::SAnimatedMesh(clone);
-        clone->drop();
-        meshCache->addMesh(path, amesh);
-        Track* track = Track::getCurrentTrack();
-        if (track)
-        {
-            irr_driver->grabAllTextures(amesh);
-            track->addCachedMesh(amesh);
-            return amesh;
-        }
-        amesh->drop();
-        return amesh;
-    }
-
-}
-
-void MeshTools::createSkinnedMeshWithTangents(scene::ISkinnedMesh* mesh,
-                                              bool(*predicate)(scene::IMeshBuffer*))
-{
-    return;
-    mesh->convertMeshToTangents(predicate);
-}
+}   // namespace MeshTools
diff --git a/src/graphics/mesh_tools.hpp b/src/graphics/mesh_tools.hpp
index 8529ef137..e57c15ab8 100644
--- a/src/graphics/mesh_tools.hpp
+++ b/src/graphics/mesh_tools.hpp
@@ -21,30 +21,17 @@
 
 namespace irr
 {
-    namespace scene { class IMesh; class IMeshBuffer; class ISkinnedMesh; }
+    namespace scene { class IMesh; }
 }
 using namespace irr;
-
-#include "utils/vec3.hpp"
+class Vec3;
 
 /**
   * \ingroup graphics
   */
 namespace MeshTools
 {
-    void minMax3D(scene::IMesh* mesh, Vec3 *min, Vec3 *max);
-
-    bool isNormalMap(scene::IMeshBuffer* mb);
-
-    // Copied from irrlicht
-    scene::IMesh* createMeshWithTangents(scene::IMesh* mesh,
-        bool(*predicate)(scene::IMeshBuffer*), bool recalculateNormals = false,
-        bool smooth = false, bool angleWeighted = false,
-        bool calculateTangents = true);
-
-    void createSkinnedMeshWithTangents(scene::ISkinnedMesh* mesh,
-        bool(*predicate)(scene::IMeshBuffer*));
-
+    void minMax3D(scene::IMesh* mesh, Vec3* min, Vec3* max);
 }   // MeshTools
 
 #endif
diff --git a/src/graphics/sp/sp_mesh.hpp b/src/graphics/sp/sp_mesh.hpp
index c340f563d..982382d74 100644
--- a/src/graphics/sp/sp_mesh.hpp
+++ b/src/graphics/sp/sp_mesh.hpp
@@ -69,8 +69,7 @@ public:
     // ------------------------------------------------------------------------
     virtual void animateMesh(f32 frame, f32 blend) {}
     // ------------------------------------------------------------------------
-    virtual void skinMesh(f32 strength=1.f, SkinningCallback sc = NULL,
-                          int offset = -1) {}
+    virtual void skinMesh(f32 strength = 1.0f) {}
     // ------------------------------------------------------------------------
     virtual u32 getMeshBufferCount() const
                                           { return (unsigned)m_buffer.size(); }
@@ -110,8 +109,6 @@ public:
     // ------------------------------------------------------------------------
     virtual void setInterpolationMode(E_INTERPOLATION_MODE mode) {}
     // ------------------------------------------------------------------------
-    virtual void convertMeshToTangents(bool(*predicate)(IMeshBuffer*)) {}
-    // ------------------------------------------------------------------------
     virtual bool isStatic() { return m_all_armatures.empty(); }
     // ------------------------------------------------------------------------
     virtual bool setHardwareSkinning(bool on) { return true; }
diff --git a/src/graphics/sp/sp_mesh_node.cpp b/src/graphics/sp/sp_mesh_node.cpp
index 3d6aa2500..11a03dbf6 100644
--- a/src/graphics/sp/sp_mesh_node.cpp
+++ b/src/graphics/sp/sp_mesh_node.cpp
@@ -149,7 +149,7 @@ void SPMeshNode::OnAnimate(u32 time_ms)
 }   // OnAnimate
 
 // ----------------------------------------------------------------------------
-IMesh* SPMeshNode::getMeshForCurrentFrame(SkinningCallback sc, int offset)
+IMesh* SPMeshNode::getMeshForCurrentFrame()
 {
     if (m_mesh->isStatic() || !m_animated)
     {
diff --git a/src/graphics/sp/sp_mesh_node.hpp b/src/graphics/sp/sp_mesh_node.hpp
index 19f9a7f55..70e4580cb 100644
--- a/src/graphics/sp/sp_mesh_node.hpp
+++ b/src/graphics/sp/sp_mesh_node.hpp
@@ -90,8 +90,7 @@ public:
     // ------------------------------------------------------------------------
     virtual void animateJoints(bool calculate_absolute_positions = true) {}
     // ------------------------------------------------------------------------
-    virtual irr::scene::IMesh* getMeshForCurrentFrame(SkinningCallback sc = NULL,
-                                                      int offset = -1);
+    virtual irr::scene::IMesh* getMeshForCurrentFrame();
     // ------------------------------------------------------------------------
     virtual IBoneSceneNode* getJointNode(const c8* joint_name);
     // ------------------------------------------------------------------------
diff --git a/src/tracks/model_definition_loader.cpp b/src/tracks/model_definition_loader.cpp
index da9f1f8f2..436af70c6 100644
--- a/src/tracks/model_definition_loader.cpp
+++ b/src/tracks/model_definition_loader.cpp
@@ -22,7 +22,6 @@ using namespace irr;
 #include "config/user_config.hpp"
 #include "graphics/irr_driver.hpp"
 #include "graphics/lod_node.hpp"
-#include "graphics/mesh_tools.hpp"
 #include "io/xml_node.hpp"
 #include "modes/world.hpp"
 #include "tracks/track.hpp"
@@ -87,14 +86,6 @@ LODNode* ModelDefinitionLoader::instanciateAsLOD(const XMLNode* node, scene::ISc
                     continue;
                 }
 
-                scene::ISkinnedMesh* sm =
-                    dynamic_cast<scene::ISkinnedMesh*>(a_mesh);
-                if (sm)
-                {
-                    MeshTools::createSkinnedMeshWithTangents(sm,
-                        &MeshTools::isNormalMap);
-                }
-
                 a_mesh->grab();
                 //cache.push_back(a_mesh);
                 irr_driver->grabAllTextures(a_mesh);
@@ -134,7 +125,6 @@ LODNode* ModelDefinitionLoader::instanciateAsLOD(const XMLNode* node, scene::ISc
                     continue;
                 }
 
-                a_mesh = MeshTools::createMeshWithTangents(a_mesh, &MeshTools::isNormalMap);
                 irr_driver->setAllMaterialFlags(a_mesh);
 
                 a_mesh->grab();
diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp
index c1d221bd5..8eea3d338 100644
--- a/src/tracks/track.cpp
+++ b/src/tracks/track.cpp
@@ -1181,8 +1181,7 @@ bool Track::loadMainTrack(const XMLNode &root)
         merged_mesh->addMesh(mesh);
         merged_mesh->finalize();
 #ifndef SERVER_ONLY
-        tangent_mesh = MeshTools::createMeshWithTangents(merged_mesh, &MeshTools::isNormalMap);
-
+        tangent_mesh = merged_mesh;
         adjustForFog(tangent_mesh, NULL);
 #else
         tangent_mesh = merged_mesh;
@@ -1310,9 +1309,6 @@ bool Track::loadMainTrack(const XMLNode &root)
                            full_path.c_str());
                 continue;
             }
-#ifndef SERVER_ONLY
-            a_mesh = MeshTools::createMeshWithTangents(a_mesh, &MeshTools::isNormalMap);
-#endif
 
             // The meshes loaded here are in irrlicht's mesh cache. So we
             // have to keep track of them in order to properly remove them
diff --git a/src/tracks/track_object_presentation.cpp b/src/tracks/track_object_presentation.cpp
index 247d3cbc3..3a7bc830f 100644
--- a/src/tracks/track_object_presentation.cpp
+++ b/src/tracks/track_object_presentation.cpp
@@ -27,7 +27,6 @@
 #include "graphics/irr_driver.hpp"
 #include "graphics/light.hpp"
 #include "graphics/material_manager.hpp"
-#include "graphics/mesh_tools.hpp"
 #include "graphics/particle_emitter.hpp"
 #include "graphics/particle_kind_manager.hpp"
 #include "graphics/stk_particle.hpp"
@@ -433,23 +432,6 @@ TrackObjectPresentationMesh::TrackObjectPresentationMesh(
         throw std::runtime_error("Model '" + model_name + "' cannot be found");
     }
 
-#ifndef SERVER_ONLY
-    if (!animated)
-    {
-        m_mesh = MeshTools::createMeshWithTangents(m_mesh,
-                                                   &MeshTools::isNormalMap);
-    }
-    else
-    {
-        scene::ISkinnedMesh* sm =
-            dynamic_cast<scene::ISkinnedMesh*>(m_mesh);
-        if (sm)
-        {
-            MeshTools::createSkinnedMeshWithTangents(sm,
-                &MeshTools::isNormalMap);
-        }
-    }
-#endif
     init(&xml_node, parent, enabled);
 }   // TrackObjectPresentationMesh
 
@@ -494,18 +476,10 @@ TrackObjectPresentationMesh::TrackObjectPresentationMesh(
         if (animated)
         {
             m_mesh = irr_driver->getAnimatedMesh(model_file);
-            scene::ISkinnedMesh* sm =
-                dynamic_cast<scene::ISkinnedMesh*>(m_mesh);
-            if (sm)
-            {
-                MeshTools::createSkinnedMeshWithTangents(sm,
-                    &MeshTools::isNormalMap);
-            }
         }
         else
         {
-            m_mesh = MeshTools::createMeshWithTangents(
-                irr_driver->getMesh(model_file), &MeshTools::isNormalMap);
+            m_mesh = irr_driver->getMesh(model_file);
         }
     }
 #endif