# Tangent, Binormal Calculations

Hi, I seem to be having trouble with calculating my Tangents and Binormals, possibly even my Normals. I render them out as lines, and everything appears to be in order, but when I combine it with my shaders (GLSL), most of my faces facing the light, act as if they are facing away. eg: [normal (dot) light] is usually less than or equal to zero.

Could someone please check over the following code for me, I can’t seem to find if anything is wrong, and for all I know, my problem is somewhere else.

I was using Bump Mapping Using CG - By Soren Dreijer as a guide for the tangent and binormal calculations.

I also know that I can easily work out the binormal inside my vertex shader, but that gives the same results as if I used my calculated binormals.

``````
typedef struct
{
float x;
float y;
float z;
}VECTOR;

VECTOR T;
VECTOR B;

void calculateTB (float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3,
float x1t, float y1t, float x2t, float y2t, float x3t, float y3t) {

VECTOR v2v1;
VECTOR v3v1;

float c2c1t;
float c2c1b;

float c3c1t;
float c3c1b;

float eMtex;

v2v1.x = x2 - x1;
v2v1.y = y2 - y1;
v2v1.z = z2 - z1;

v3v1.x = x3 - x1;
v3v1.y = y3 - y1;
v3v1.z = z3 - z1;

c2c1t = x2t - x1t;
c2c1b = y2t - y1t;

c3c1t = x3t - x1t;
c3c1b = y3t - y1t;

eMtex = ((c2c1t * c3c1b) - (c3c1t * c2c1b));

if (eMtex != 0.0f)
{
T.x = (1.0f/eMtex) * ((c3c1b * v2v1.x) - (c2c1b * v3v1.x));
T.y = (1.0f/eMtex) * ((c3c1b * v2v1.y) - (c2c1b * v3v1.y));
T.z = (1.0f/eMtex) * ((c3c1b * v2v1.z) - (c2c1b * v3v1.z));

B.x = (1/eMtex) * ((-c3c1t * v2v1.x) + (c2c1t * v3v1.x));
B.y = (1/eMtex) * ((-c3c1t * v2v1.y) + (c2c1t * v3v1.y));
B.z = (1/eMtex) * ((-c3c1t * v2v1.z) + (c2c1t * v3v1.z));
}
}

``````

To use this, I am simply going through a loop of all my triangles and calling the above code for each of the three vertices, using the other two vertices in the polygon.
The following code calculates the normals, tangents and binormals for the first vertex.

``````
calculateTB(
p_object->vertex[p_object->polygon[i].a].x ,p_object->vertex[p_object->polygon[i].a].y,p_object->vertex[p_object->polygon[i].a].z,
p_object->vertex[p_object->polygon[i].b].x ,p_object->vertex[p_object->polygon[i].b].y,p_object->vertex[p_object->polygon[i].b].z,
p_object->vertex[p_object->polygon[i].c].x ,p_object->vertex[p_object->polygon[i].c].y,p_object->vertex[p_object->polygon[i].c].z,
p_object->mapcoord[p_object->polygon[i].a].u, p_object->mapcoord[p_object->polygon[i].a].v,
p_object->mapcoord[p_object->polygon[i].b].u, p_object->mapcoord[p_object->polygon[i].b].v,
p_object->mapcoord[p_object->polygon[i].c].u, p_object->mapcoord[p_object->polygon[i].c].v);

p_object->tangent[p_object->polygon[i].a].x = T.x;
p_object->tangent[p_object->polygon[i].a].y = T.y;
p_object->tangent[p_object->polygon[i].a].z = T.z;

p_object->binormal[p_object->polygon[i].a].x = B.x;
p_object->binormal[p_object->polygon[i].a].y = B.y;
p_object->binormal[p_object->polygon[i].a].z = B.z;

``````

Make sure that the tangent space basis matches the normal maps you are using, components and their signs must be consistent between the 3x3 TBN matrix, and the triplets from each texture sample. Obviously the object space vectors you are transforming to tangent space also need to be consistent.

OK, just for testing, I stopped using the normal map and started using just the normal for each face without multiplying anything by the TBN matrix, and it appears fine. So my problem is not my normals. Which leaves the tangents (I’m just gonna do the binormals in the shader) which I thought were the problem from the start. I have edited the code from the first post, so it just covers the tangents. Could someone give that a once over to see if it looks right?

Also how would I go about checking consistency between the signs? I am not sure which should have which sign.

EDIT

I found one error which was that I was going through my vertices to work everything out when I should have been going through my polygons. But now I have the problem of it seems to work for vertical objects such as walls, but not for horizontal objects. With the horizontal objects, they are bump mapped inverted. So they are lit in the parts that should be facing away from the light. My vertical objects are then constantly lit the same. They do not take into account attenuation or specular lighting correctly.