Quote:Original post by Eric Lengyel
Hi Hulag --
The code at http://www.terathon.com/code/tangent.html does exactly what you need. The arrays pointed to by tan1 and tan2 contain the tangents and bitangents, respectively, after the main loop. The these are used to calculate a handedness factor, and then the bitangents are thrown out because you're expected to recalculate them in the vertex program using B = (N x T) * T.w.
Unfortunately, the example which is susceptible to division by zero has been around for a few years and copied all over the place, but it is just plain wrong. The algorithm is obviously not robust, even with that hacky epsilon test. Because you're dividing by the difference in vertex coordinates, it can't even handle an axis-aligned cube correctly.
-- Eric Lengyel
Hey Eric, I'm trying to port your code in http://www.terathon.com/code/tangent.html. I have the first loop like this:
for (int i = 0; i < CurrentMesh->meshNodes.size(); ++i) { for(int j = 0; j < CurrentMesh->meshNodes->numNodeGroups; ++j) { for(int k = 0; k < (int)(CurrentMesh->meshNodes->nodeMaterialIndices[j]->numIndices / 3); ++k) { Mesh::MeshVertexInfo *v0 = &CurrentMesh->meshNodes->nodeVertices[CurrentMesh->meshNodes->nodeMaterialIndices[j]->indices[k * 3]]; Mesh::MeshVertexInfo *v1 = &CurrentMesh->meshNodes->nodeVertices[CurrentMesh->meshNodes->nodeMaterialIndices[j]->indices[k * 3 + 1]]; Mesh::MeshVertexInfo *v2 = &CurrentMesh->meshNodes->nodeVertices[CurrentMesh->meshNodes->nodeMaterialIndices[j]->indices[k * 3 + 2]]; vec3 normal, tangent, biTangent; vec3 e0 = v1->position - v0->position; vec3 e1 = v2->position - v0->position; vec2 uve1 = vec2(v1->UV.x - v0->UV.x, v1->UV.y - v0->UV.y); vec2 uve2 = vec2(v2->UV.x - v0->UV.x, v2->UV.y - v0->UV.y); float r = 1.0f / (uve1.x * uve2.y - uve2.x * uve1.y); vec3 sdir( (uve2.y * e0.x - uve1.y * e1.x) * r, (uve2.y * e0.y - uve1.y * e1.y) * r, (uve2.y * e0.z - uve1.y * e1.z) * r ); vec3 tdir( (uve2.x * e0.x - uve1.x * e1.x) * r, (uve2.x * e0.y - uve1.x * e1.y) * r, (uve2.x * e0.z - uve1.x * e1.z) * r ); v0->tangent += sdir; v1->tangent += sdir; v2->tangent += sdir; v0->biTangent += tdir; v1->biTangent += tdir; v2->biTangent += tdir; } } }
Now, I'm having problems with your second loop mostly because my math functions library isn't the same as yours. The following line confuses me
tangent[a] = (t - n * Dot(n * t)).Normalize();
What confuses me there is the Dot(n * t) part because there is no Dot() function in your math libs that takes just one parameter. So how would that whole line be decomposed competly? (with the exception of the Normalize() function). I hope you (or anybody else) can help me.