I think you want per vertex tangent space, don't you ?
here it is :
bool CMeshOptimizer::CalculateTangentArray( CMesh *Mesh)
{
//////////////////////////////
// check for mesh validity
if ( Mesh==NULL )
return false ;
if ( Mesh->Assert()==false )
return false;
int i;
int p1,p2,p3;
int i1,i2,i3;
int Vertices;
int Surfaces;
float r,w;
float x1,y1,z1;
float x2,y2,z2;
float s1,t1;
float s2,t2;
Vec3f V1,V2,V3;
Vec2f T1,T2,T3;
Vec3f Sdir,Tdir;
Vec3f *TanU,*TanV;
Vec3f n,t,d;
CSurface *Surface;
/////////////////////////////////////
Vertices=Mesh->GetVertexCount();
Surfaces=Mesh->GetSurfaceCount();
// tangent vertex coordinates
if ( Mesh->VertexTangent.Reserve( Vertices , 4 ) ==false )
return false;
////////////////////////////////////////
// allocate arrays
if ( (TanU= new Vec3f [ Vertices ])==NULL)
return false;
if ( ( TanV= new Vec3f [ Vertices ])==NULL )
return false;
/////////////////////////
// init vertex arrays
for ( i=0; i<Vertices; i++ )
{
TanU[i].zero();
TanV[i].zero(); }
//////////////////////////////////
for ( i = 0; i < Surfaces; i++)
{
Surface=Mesh->GetSurfaceAt( i );
p1=Surface->P1;
p2=Surface->P2;
p3=Surface->P3;
i1=Surface->T1;
i2=Surface->T2;
i3=Surface->T3;
V1.set( Mesh->VertexCoord.x(p1),
Mesh->VertexCoord.y(p1),
Mesh->VertexCoord.z(p1) );
V2.set( Mesh->VertexCoord.x(p2),
Mesh->VertexCoord.y(p2),
Mesh->VertexCoord.z(p2) );
V3.set( Mesh->VertexCoord.x(p3),
Mesh->VertexCoord.y(p3),
Mesh->VertexCoord.z(p3) );
T1.set( Mesh->VertexTexCoord.x(i1),
Mesh->VertexTexCoord.y(i1) );
T2.set( Mesh->VertexTexCoord.x(i2),
Mesh->VertexTexCoord.y(i2) );
T3.set( Mesh->VertexTexCoord.x(i3),
Mesh->VertexTexCoord.y(i3) );
x1 = V2[0] - V1[0];
x2 = V3[0] - V1[0];
y1 = V2[1] - V1[1];
y2 = V3[1] - V1[1];
z1 = V2[2] - V1[2];
z2 = V3[2] - V1[2];
s1 = T2[0] - T1[0];
s2 = T3[0] - T1[0];
t1 = T2[1] - T1[1];
t2 = T3[1] - T1[1];
r = 1.0f / (s1 * t2 - s2 * t1);
Sdir.set( (t2 * x1 - t1 * x2) * r,
(t2 * y1 - t1 * y2) * r,
(t2 * z1 - t1 * z2) * r );
Tdir.set( (s1 * x2 - s2 * x1) * r,
(s1 * y2 - s2 * y1) * r,
(s1 * z2 - s2 * z1) * r );
TanU[p1] += Sdir;
TanU[p2] += Sdir;
TanU[p3] += Sdir;
TanV[p1] += Tdir;
TanV[p2] += Tdir;
TanV[p3] += Tdir;
}
////////////////////////////////////
// compute tangent space for
// each vertex
for ( i = 0; i < Vertices; i++)
{
n.set( Mesh->VertexNormal.x( i ),
Mesh->VertexNormal.y( i ),
Mesh->VertexNormal.z( i ) );
t.set( TanU[i][0],TanU[i][1],TanU[i][2] );
// Gram-Schmidt orthogonalize
d=(t - n * dot(n, t));
d.normalize();
// Calculate handedness
w = (dot(cross(n, t), TanV[i]) < 0.0F) ? -1.0F : 1.0F;
Mesh->AddTangentVertex( d,w );
}
/////////////////////
// frees memory
delete TanU;
delete TanV;
///////////////////////////////////////
// setting flag for triangle connectivity
Mesh->SetBitFlag( _VT_TANGENT_SPACE_COMPUTED_,true);
return true;
}
Note that i still have to polish and optimize a little bit,
i am working on other components of my engine right now