That’s exactly what I’m unsure of. I honestly have no idea what space they are in. I think that they are in object space, but I’m not sure one bit. If they are in the correct space, therefore making this code correct, then the one other possible error would be in how I compute the tangent and binormal, which I doubt. Here is the code I use to compute T and B from the N I recieved from the modeling program (Maya) I use. The bottom section of the code sets up the vertex buffer objects if it looks strange to anyone. Also, for some reason I can’t post this with the “less than” sign in the text, so I have replace all “less than signs” in the code with the word lessthan. The parameters are a list of each objects vertices and uvs, as well as the total object count and the number of vertices in each object. Vertices are x, y, z and UVs are u, v.
void TangentMatrix::computeMatrix(float **vertices, float **uvs,
int objCount, int *vertCount)
{
float **tangents, binormals;
tangents = new float[objCount];
binormals = new float[objCount];
// compute the data
for(int i = 0 ; i lessthan objCount ; i++)
{
tangents[i] = new float[vertCount[i] * 3];
binormals[i] = new float[vertCount[i] * 3];
for(int j = 0 ; j lessthan vertCount[i] * 3; j += 9)
{
float deltaX2 = vertices[i][j + 3] - vertices[i][j];
float deltaY2 = vertices[i][j + 4] - vertices[i][j + 1];
float deltaZ2 = vertices[i][j + 5] - vertices[i][j + 2];
float deltaX3 = vertices[i][j + 6] - vertices[i][j];
float deltaY3 = vertices[i][j + 7] - vertices[i][j + 1];
float deltaZ3 = vertices[i][j + 8] - vertices[i][j + 2];
float deltaU2 = uvs[i][((j / 3) * 2) + 2] - uvs[i][(j / 3) * 2];
float deltaV2 = uvs[i][((j / 3) * 2) + 3] - uvs[i][((j / 3) * 2) + 1];
float deltaU3 = uvs[i][((j / 3) * 2) + 4] - uvs[i][(j / 3) * 2];
float deltaV3 = uvs[i][((j / 3) * 2) + 5] - uvs[i][((j / 3) * 2) + 1];
Vector3 one = Vector3(deltaX2, deltaU2, deltaV2);
one = one.cross(Vector3(deltaX3, deltaU3, deltaV3));
Vector3 two = Vector3(deltaY2, deltaU2, deltaV2);
two = two.cross(Vector3(deltaY3, deltaU3, deltaV3));
Vector3 three = Vector3(deltaZ2, deltaU2, deltaV2);
three = three.cross(Vector3(deltaZ3, deltaU3, deltaV3));
float Tx = 0.0f, Ty = 0.0f, Tz = 0.0f,
Bx = 0.0f, By = 0.0f, Bz = 0.0f;
if(one.x != 0)
{
one.normalize();
Tx = -one.y / one.x;
Bx = -one.z / one.x;
}
if(two.x != 0)
{
two.normalize();
Ty = -two.y / two.x;
By = -two.z / two.x;
}
if(three.x != 0)
{
three.normalize();
Tz = -three.y / three.x;
Bz = -three.z / three.x;
}
Vector3 T = Vector3(Tx, Ty, Tz);
Vector3 B = Vector3(Bx, By, Bz);
T.normalize();
B.normalize();
tangents[i][j] = T.x;
tangents[i][j + 1] = T.y;
tangents[i][j + 2] = T.z;
tangents[i][j + 3] = T.x;
tangents[i][j + 4] = T.y;
tangents[i][j + 5] = T.z;
tangents[i][j + 6] = T.x;
tangents[i][j + 7] = T.y;
tangents[i][j + 8] = T.z;
binormals[i][j] = B.x;
binormals[i][j + 1] = B.y;
binormals[i][j + 2] = B.z;
binormals[i][j + 3] = B.x;
binormals[i][j + 4] = B.y;
binormals[i][j + 5] = B.z;
binormals[i][j + 6] = B.x;
binormals[i][j + 7] = B.y;
binormals[i][j + 8] = B.z;
}
}
// build the vertex buffer objects
g_uiTangents = new unsigned int[objCount];
g_uiBinormals = new unsigned int[objCount];
for(int i = 0 ; i lessthan objCount ; i++)
{
glGenBuffersARB(1, &g_uiTangents[i]);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, g_uiTangents[i]);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, vertCount[i] * 3 * sizeof(float), tangents[i], GL_STATIC_DRAW_ARB);
glGenBuffersARB(1, &g_uiBinormals[i]);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, g_uiBinormals[i]);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, vertCount[i] * 3 * sizeof(float), binormals[i], GL_STATIC_DRAW_ARB);
delete[] tangents[i];
delete[] binormals[i];
}
}