Code for Tangent Space

Hi,
I found this code somewhere and I don’t understand all thoery behind it. It’s calculating the tangent to use when creating a tangent space for one vertices in a model. It works good for me but could someone explain why? Why is for example that crossproduct needed?

void tangent_basis(float v0[3], float v1[3], float v2[3], float t0[2], float t1[2], float t2[2], float tangent_out[3])
{
float crossproduct[3];
float edge0[3]={ v1[0]-v0[0], t1[0]-t0[0], t1[1]-t0[1] };
float edge1[3]={ v2[0]-v0[0], t2[0]-t0[0], t2[1]-t0[1] };

crossproduct[0]=edge0[1]*edge1[2]-edge0[2]*edge1[1];
crossproduct[1]=edge0[2]*edge1[0]-edge0[0]*edge1[2];
crossproduct[2]=edge0[0]*edge1[1]-edge0[1]*edge1[0];

tangent_out[0]=-crossproduct[1]*(1/crossproduct[0]);

edge0[0]=v1[1]-v0[1];
edge1[0]=v2[1]-v0[1];

crossproduct[0]=edge0[1]*edge1[2]-edge0[2]*edge1[1];
crossproduct[1]=edge0[2]*edge1[0]-edge0[0]*edge1[2];
crossproduct[2]=edge0[0]*edge1[1]-edge0[1]*edge1[0];

tangent_out[1]=-crossproduct[1]*(1/crossproduct[0]);

edge0[0]=v1[2]-v0[2];
edge1[0]=v2[2]-v0[2];

crossproduct[0]=edge0[1]*edge1[2]-edge0[2]*edge1[1];
crossproduct[1]=edge0[2]*edge1[0]-edge0[0]*edge1[2];
crossproduct[2]=edge0[0]*edge1[1]-edge0[1]*edge1[0];

tangent_out[2]=-crossproduct[1]*(1/crossproduct[0]);

}

//Regards, Ninja

There are per-pixel bumpmapping presentations by nvidia that shows the math behind it. All that code is doing is computing partial derivatives from three plane equations to form a matrix to transform something into surface-local space, or tangent space if you will. The three plane equations look like this:

Ax + Bu + Cv + D = 0
Ay + Bu + Cv + D = 0
Az + Bu + Cv + D = 0

Where the u and v are texture coords of course. Then they compute the following partials:

<dudx, dudy, dudz> = U-axis
<dvdx, dvdy, dvdz> = V-axis

Then those two vectors are crossed thus giving the matrix:

[dudx dvdx UxVx]
[dudy dvdy UxVy]
[dudz dvdz UxVz]

And that’s what that code does. This is done for each triangle.

-SirKnight

Ok, so you use the same tangent for all the vertices in the triangel?

//Ninja

Once you have the tangent space vectors for each triangle then to get the tangent space for each vertex you would do something similar to computing vertex normals. For each vertex, average the tangent space vectors for each triangle that shares that vertex.

-SirKnight

I just remembered there is a paper that describes all of this in good detail. Here is the link: http://members.rogers.com/deseric/tangentspace.htm

-SirKnight

Originally posted by Ninja:
[b]Ok, so you use the same tangent for all the vertices in the triangel?

//Ninja[/b]

There is a one to one ratio between tangents and normals. If you have face normals then it would be one tangent per triangle. One thing you have to be aware of with that algorithm (I think thats the same code that I looked at a while back, I could be wrong) for generating tangents is that they will be based around the direction of your texture coordinates which can cause seams if your texture coordinates use mirroring.