elaverick's picture

More tangents and bitangents

OK I've been playing with trying automatically generate tangent and bitangent vectors from the 3 vertices that form a triangle section of a quad, however this keeps returning 0,0,0 each time. Anyone see what's wrong with this?

public static void computeTangentBasis(Vector3 vertexA, Vector3 vertexB, Vector3 vertexC, Vector2 texCoordA, Vector2 texCoordB, Vector2 texCoordC, out Vector3 tangent, out Vector3 bitangent )
        {
            Vector3 Edge1 = Vector3.Subtract(vertexA, vertexB);
            Vector3 Edge2 = Vector3.Subtract(vertexA, vertexC);
            Vector2 Edge1uv = Vector2.Subtract(texCoordA, texCoordB);
            Vector2 Edge2uv = Vector2.Subtract(texCoordA, texCoordC);
 
            tangent = Vector3.Normalize(Vector3.Multiply(Edge1, Edge2uv.Y) - (Vector3.Multiply(Edge2, Edge1uv.Y)));
            bitangent = Vector3.Normalize(Vector3.Multiply(Edge2, Edge1uv.X) - (Vector3.Multiply(Edge1, Edge2uv.X)));
}

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Radar's picture

Hi!
Your code looks okay, just the calculations seem to be flipped, i don't know if that is the problem.

I post the thing i use atm.
The class TriangleVertex is just a class that holds vertex attributes like positions(vector3)and texturecoords(vector2). But you understand it anyway. Tell me if it works for you.

It also takes care of the winding of the tangent. You can experiment with that if you wanna flip the tangent or just set the info in the W value.

public static void CalculateSurfaceTangentBitangent(Vector3 surfaceNormal, TriangleVertex vertex1, TriangleVertex vertex2, TriangleVertex vertex3, out Vector4 tangent, out Vector4 biTangent)
        {
            tangent = new Vector4();
            Vector3 side_0 = vertex1.Position - vertex2.Position;
            Vector3 side_1 = vertex3.Position - vertex2.Position;
 
            float delta_U_0 = vertex1.TexCoord.X - vertex2.TexCoord.X;
            float delta_U_1 = vertex3.TexCoord.X - vertex2.TexCoord.X;
            float delta_V_0 = vertex1.TexCoord.Y - vertex2.TexCoord.Y;
            float delta_V_1 = vertex3.TexCoord.Y - vertex2.TexCoord.Y;
 
            tangent   = new Vector4(new Vector3(delta_V_1 * side_0 - delta_V_0 * side_1), 0.0f);
            biTangent = new Vector4(new Vector3(delta_U_1 * side_0 - delta_U_0 * side_1), 0.0f);
            Vector3 tangentCross = Vector3.Cross(tangent.Xyz, biTangent.Xyz);
 
            tangent.Normalize();
            biTangent.Normalize();
 
            //wind the tangent into the other direction if necassary; means: if the UVs are mirrored
            if (Vector3.Dot(surfaceNormal, tangentCross) < 0.0f)
            {
                biTangent  *= -1.0f;
                biTangent.W = -1.0f;
 
                tangent  *= -1.0f;
                tangent.W = -1.0f;
            }
            else
            {
                biTangent.W = 1.0f;
                tangent.W   = 1.0f;
            }
        }