Exemplo n.º 1
0
/*! 
SLMesh::calcTangents computes the tangent and bi-tangent per vertex used for 
GLSL normal map bumb mapping. The code and mathematical derivation is in detail 
explained in: http://www.terathon.com/code/tangent.html
*/
void SLMesh::calcTangents()
{
   if (P && N && Tc)
   {
      // allocat tangents
      delete[] T;
      T = new SLVec4f[numV];
      
      // allocate temp arrays for tangents
      SLVec3f* T1 = new SLVec3f[numV * 2];
      SLVec3f* T2 = T1 + numV;
      memset(T1, 0, numV * sizeof(SLVec3f) * 2);

      for (SLuint m = 0; m < numM; ++m)
      {  for (SLuint f = 0; f < M[m].numF; ++f)
         {
            // Get the 3 vertex indexes
            SLushort iVA = F[M[m].startF + f].iA;
            SLushort iVB = F[M[m].startF + f].iB;
            SLushort iVC = F[M[m].startF + f].iC;

            float x1 = P[iVB].x - P[iVA].x;
            float x2 = P[iVC].x - P[iVA].x;
            float y1 = P[iVB].y - P[iVA].y;
            float y2 = P[iVC].y - P[iVA].y;
            float z1 = P[iVB].z - P[iVA].z;
            float z2 = P[iVC].z - P[iVA].z;

            float s1 = Tc[iVB].x - Tc[iVA].x;
            float s2 = Tc[iVC].x - Tc[iVA].x;
            float t1 = Tc[iVB].y - Tc[iVA].y;
            float t2 = Tc[iVC].y - Tc[iVA].y;

            float r = 1.0F / (s1*t2 - s2*t1);
            SLVec3f sdir((t2*x1 - t1*x2) * r, (t2*y1 - t1*y2) * r, (t2*z1 - t1*z2) * r);
            SLVec3f tdir((s1*x2 - s2*x1) * r, (s1*y2 - s2*y1) * r, (s1*z2 - s2*z1) * r);

            T1[iVA] += sdir;
            T1[iVB] += sdir;
            T1[iVC] += sdir;

            T2[iVA] += tdir;
            T2[iVB] += tdir;
            T2[iVC] += tdir;
         }
      }
       
       for (SLuint i=0; i < numV; ++i)
       {
           // Gram-Schmidt orthogonalize
           T[i] = T1[i] - N[i] * N[i].dot(T1[i]);
           T[i].normalize();
           
           // Calculate temp. bitangent and store its handedness in T.w
           SLVec3f bitangent;
           bitangent.cross(N[i], T1[i]);
           T[i].w = (bitangent.dot(T2[i]) < 0.0f) ? -1.0f : 1.0f;
       }
       
       delete[] T1;
    }
}