diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index f9ab61c160c603fb4b4afe5705b660a40a8038ba..66cedaea5a1becc4ddc4ac5b19718da16b93a6f6 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -55,8 +55,7 @@
 #include "llmeshoptimizer.h"
 #include "lltimer.h"
 
-#include "mikktspace/mikktspace.h"
-#include "mikktspace/mikktspace.c" // insert mikktspace implementation into llvolume object file
+#include "mikktspace/mikktspace.hh"
 
 #define DEBUG_SILHOUETTE_BINORMALS 0
 #define DEBUG_SILHOUETTE_NORMALS 0 // TomY: Use this to display normals using the silhouette
@@ -5458,25 +5457,25 @@ class LLVCacheLRU
 struct MikktData
 {
     LLVolumeFace* face;
-    std::vector<LLVector3> p;
-    std::vector<LLVector3> n;
-    std::vector<LLVector2> tc;
-    std::vector<LLVector4> w;
-    std::vector<LLVector4> t;
+    std::vector<LLVector3> p_data;
+    std::vector<LLVector3> n_data;
+    std::vector<LLVector2> tc_data;
+    std::vector<LLVector4> w_data;
+    std::vector<LLVector4> t_data;
 
     MikktData(LLVolumeFace* f)
         : face(f)
     {
         U32 count = face->mNumIndices;
 
-        p.resize(count);
-        n.resize(count);
-        tc.resize(count);
-        t.resize(count);
+        p_data.resize(count);
+        n_data.resize(count);
+        tc_data.resize(count);
+        t_data.resize(count);
 
         if (face->mWeights)
         {
-            w.resize(count);
+            w_data.resize(count);
         }
 
 
@@ -5487,12 +5486,12 @@ struct MikktData
         {
             U32 idx = face->mIndices[i];
 
-            p[i].set(face->mPositions[idx].getF32ptr());
-            p[i].scaleVec(face->mNormalizedScale); //put mesh in original coordinate frame when reconstructing tangents
-            n[i].set(face->mNormals[idx].getF32ptr());
-            n[i].scaleVec(inv_scale);
-            n[i].normalize();
-            tc[i].set(face->mTexCoords[idx]);
+            p_data[i].set(face->mPositions[idx].getF32ptr());
+            p_data[i].scaleVec(face->mNormalizedScale); //put mesh in original coordinate frame when reconstructing tangents
+            n_data[i].set(face->mNormals[idx].getF32ptr());
+            n_data[i].scaleVec(inv_scale);
+            n_data[i].normalize();
+            tc_data[i].set(face->mTexCoords[idx]);
 
             if (idx >= face->mNumVertices)
             {
@@ -5507,12 +5506,45 @@ struct MikktData
 
             if (face->mWeights)
             {
-                w[i].set(face->mWeights[idx].getF32ptr());
+                w_data[i].set(face->mWeights[idx].getF32ptr());
             }
         }
     }
-};
 
+	uint32_t GetNumFaces()
+	{
+		return uint32_t(face->mNumIndices / 3);
+	}
+
+	uint32_t GetNumVerticesOfFace(const uint32_t face_num)
+	{
+		return 3;
+	}
+
+	mikk::float3 GetPosition(const uint32_t face_num, const uint32_t vert_num)
+	{
+		F32* v = p_data[face_num * 3 + vert_num].mV;
+		return mikk::float3(v);
+	}
+
+	mikk::float3 GetTexCoord(const uint32_t face_num, const uint32_t vert_num)
+	{
+		F32* uv = tc_data[face_num * 3 + vert_num].mV;
+		return mikk::float3(uv[0], uv[1], 1.0f);
+	}
+
+	mikk::float3 GetNormal(const uint32_t face_num, const uint32_t vert_num)
+	{
+		F32* normal = n_data[face_num * 3 + vert_num].mV;
+		return mikk::float3(normal);
+	}
+
+	void SetTangentSpace(const uint32_t face_num, const uint32_t vert_num, mikk::float3 T, bool orientation)
+	{
+		S32 i = face_num * 3 + vert_num;
+		t_data[i].set(T.x, T.y, T.z, orientation ? 1.0f : -1.0f);
+	}
+};
 
 bool LLVolumeFace::cacheOptimize(bool gen_tangents)
 { //optimize for vertex cache according to Forsyth method: 
@@ -5520,95 +5552,37 @@ bool LLVolumeFace::cacheOptimize(bool gen_tangents)
 	llassert(!mOptimized);
 	mOptimized = TRUE;
 
-	if (mNumVertices < 3 || mNumIndices < 3)
-	{ //nothing to do
-		return true;
-	}
-
     if (gen_tangents && mNormals && mTexCoords)
     { // generate mikkt space tangents before cache optimizing since the index buffer may change
         // a bit of a hack to do this here, but this function gets called exactly once for the lifetime of a mesh
         // and is executed on a background thread
-        SMikkTSpaceInterface ms;
-
-        ms.m_getNumFaces = [](const SMikkTSpaceContext* pContext)
-        {
-            MikktData* data = (MikktData*)pContext->m_pUserData;
-            LLVolumeFace* face = data->face;
-            return face->mNumIndices / 3;
-        };
-
-        ms.m_getNumVerticesOfFace = [](const SMikkTSpaceContext* pContext, const int iFace)
-        {
-            return 3;
-        };
-
-        ms.m_getPosition = [](const SMikkTSpaceContext* pContext, float fvPosOut[], const int iFace, const int iVert)
-        {
-            MikktData* data = (MikktData*)pContext->m_pUserData;
-            F32* v = data->p[iFace * 3 + iVert].mV;
-            fvPosOut[0] = v[0];
-            fvPosOut[1] = v[1];
-            fvPosOut[2] = v[2];
-        };
-
-        ms.m_getNormal = [](const SMikkTSpaceContext* pContext, float fvNormOut[], const int iFace, const int iVert)
-        {
-            MikktData* data = (MikktData*)pContext->m_pUserData;
-            F32* n = data->n[iFace * 3 + iVert].mV;
-            fvNormOut[0] = n[0];
-            fvNormOut[1] = n[1];
-            fvNormOut[2] = n[2];
-        };
-
-        ms.m_getTexCoord = [](const SMikkTSpaceContext* pContext, float fvTexcOut[], const int iFace, const int iVert)
-        {
-            MikktData* data = (MikktData*)pContext->m_pUserData;
-            F32* tc = data->tc[iFace * 3 + iVert].mV;
-            fvTexcOut[0] = tc[0];
-            fvTexcOut[1] = tc[1];
-        };
-
-        ms.m_setTSpaceBasic = [](const SMikkTSpaceContext* pContext, const float fvTangent[], const float fSign, const int iFace, const int iVert)
-        {
-            MikktData* data = (MikktData*)pContext->m_pUserData;
-            S32 i = iFace * 3 + iVert;
-            
-            data->t[i].set(fvTangent);
-            data->t[i].mV[3] = fSign;
-        };
-
-        ms.m_setTSpace = nullptr;
-
         MikktData data(this);
-
-        SMikkTSpaceContext ctx = { &ms, &data };
-
-        genTangSpaceDefault(&ctx);
+		mikk::Mikktspace ctx(data);
+		ctx.genTangSpace();
 
         //re-weld
         meshopt_Stream mos[] =
         {
-            { &data.p[0], sizeof(LLVector3), sizeof(LLVector3) },
-            { &data.n[0], sizeof(LLVector3), sizeof(LLVector3) },
-            { &data.t[0], sizeof(LLVector4), sizeof(LLVector4) },
-            { &data.tc[0], sizeof(LLVector2), sizeof(LLVector2) },
-            { data.w.empty() ? nullptr : &data.w[0], sizeof(LLVector4), sizeof(LLVector4) }
+            { &data.p_data[0], sizeof(LLVector3), sizeof(LLVector3) },
+            { &data.n_data[0], sizeof(LLVector3), sizeof(LLVector3) },
+            { &data.t_data[0], sizeof(LLVector4), sizeof(LLVector4) },
+            { &data.tc_data[0], sizeof(LLVector2), sizeof(LLVector2) },
+            { data.w_data.empty() ? nullptr : &data.w_data[0], sizeof(LLVector4), sizeof(LLVector4) }
         };
 
         std::vector<U32> remap;
-        remap.resize(data.p.size());
+        remap.resize(data.p_data.size());
 
-        U32 stream_count = data.w.empty() ? 4 : 5;
+        U32 stream_count = data.w_data.empty() ? 4 : 5;
 
-        U32 vert_count = meshopt_generateVertexRemapMulti(&remap[0], nullptr, data.p.size(), data.p.size(), mos, stream_count);
+        U32 vert_count = meshopt_generateVertexRemapMulti(&remap[0], nullptr, data.p_data.size(), data.p_data.size(), mos, stream_count);
 
         if (vert_count < 65535)
         {
             //copy results back into volume
             resizeVertices(vert_count);
 
-            if (!data.w.empty())
+            if (!data.w_data.empty())
             {
                 allocateWeights(vert_count);
             }
@@ -5621,15 +5595,15 @@ bool LLVolumeFace::cacheOptimize(bool gen_tangents)
                 U32 dst_idx = remap[i];
                 mIndices[i] = dst_idx;
 
-                mPositions[dst_idx].load3(data.p[src_idx].mV);
-                mNormals[dst_idx].load3(data.n[src_idx].mV);
-                mTexCoords[dst_idx] = data.tc[src_idx];
+                mPositions[dst_idx].load3(data.p_data[src_idx].mV);
+                mNormals[dst_idx].load3(data.n_data[src_idx].mV);
+                mTexCoords[dst_idx] = data.tc_data[src_idx];
 
-                mTangents[dst_idx].loadua(data.t[src_idx].mV);
+                mTangents[dst_idx].loadua(data.t_data[src_idx].mV);
 
                 if (mWeights)
                 {
-                    mWeights[dst_idx].loadua(data.w[src_idx].mV);
+                    mWeights[dst_idx].loadua(data.w_data[src_idx].mV);
                 }
             }