Tangent Calculation 'NaN'

I’m having problems calculating tangents from plane information generated from position and texture coordinate information.

Here’s the code I have for generating tangent information from 3 given positions, and 3 texture coordinates.

/**
 * Calculates a per-triangle tangent from given triangle texture UV and position data (normalized)
 * @param v0 The triangle's 1st vertex
 * @param v1 The triangle's 2nd vertex
 * @param v2 The triangle's 3rd vertex
 * @param st0 The triangle's 1st texture UV
 * @param st1 The triangle's 2st texture UV
 * @param st2 The triangle's 3st texture UV
 * @return A per-triangle tangent from given triangle texture UV and position data
 */
public static Vector3f getTangent(Vector4f v0, Vector4f v1, Vector4f v2,
							      Vector2f st0, Vector2f st1, Vector2f st2){
	float x1 = v1.x - v0.x;
	float x2 = v2.x - v0.x;
	float y1 = v1.y - v0.y;
	float y2 = v2.y - v0.y;
	float z1 = v1.z - v0.z;
	float z2 = v2.z - v0.z;

	float s1 = st1.x - st0.x;
	float s2 = st2.x - st0.x;
	float t1 = st1.y - st0.y;
	float t2 = st2.y - st0.y;
	
	float r = 1.0f / (s1 * t2 - s2 * t1); // POSSIBLE CAUSE 1
	
	Vector3f out = new Vector3f(( t2 * x1 - t1 * x2 ) * r, ( t2 * y1 - t1 * y2 ) * r, ( t2 * z1 - t1 * z2 ) * r);
	out.normalize(); // POSSIBLE CAUSE 2
	
	return out;
}

Printing face information gave me this:

Face information for a not-working triangle.

positions p1: (-0.688189, -0.525736, 0.499997, 1.0) p2: (-0.894426, -0.447216, 0.0, 1.0) p3: (-0.52573, -0.850652, 0.0, 1.0)
texcoords t1: (0.573431, 0.856142) t2: (0.713285, 0.856142) t3: (0.856142, 0.856142)
normal:   (0.4089, 0.6617, -0.6284)
tangent:  (NaN, NaN, NaN)

And the face information for a triangle that’s working…

positions p1: (-0.52573, -0.850652, 0.0, 1.0) p2: (-0.688189, -0.525736, 0.499997, 1.0) p3: (-0.894426, -0.447216, 0.0, 1.0)
texcoords t1: (0.713285, 0.716288) t2: (0.573431, 0.856142) t3: (0.713285, 0.856142)
normal:   (0.4911, 0.7947, -0.3568)
tangent:  (-0.37735644, 0.14366975, -0.9148557)

[quote]“NaN” stands for “not a number”. “Nan” is produced if a floating point operation has some input parameters that cause the operation to produce some undefined result. For example, 0.0 divided by 0.0 is arithmetically undefined. Taking the square root of a negative number is also undefined.
[/quote]
The only division being done there is the [icode]1.0f / (s1 * t2 - s2 * t1);[/icode] and the normalization. So either the vector was (0.0, 0.0, 0.0) and divided by the length of itself for normalization would equal (NaN, NaN, NaN), or the [icode]r[/icode] value is being calculated incorrectly or encountered (1.0 / 0.0).

So many headaches… Thanks in advance.

EDIT:
So with the tangent-normal-binormal matrix being this: [icode][T, B, N][/icode], and multiplying it by a vector remapped from a texture (common normal mapping practice) I got this:

The texture of the sphere is pure black, the black triangles are because the normal * TBN for that face is (0.0, 0.0, 0.0, 0.0)

The texture of the box is showing through, because the normal * TBN for that face is (0.0, 0.0, 0.0, 0.0)

As you can see, when the normals become (0, 0, 0, 0) (RED GREEN BLUE ALPHA) they show the ambient texture that’s drawn before it. So on certain parts of the mesh, the tangent row of the matrix is (0, 0, 0, 0), which multiplied by any vector returns (0, 0, 0, 0). But the normals themselfs are perfectly fine, and I’ve tested them before. So is the bitangent. So the code block at the top is to blame…

Keep in mind that any calculation that involves NaN comes out to be NaN.

So now it’s time to debug your program to figure out which variable is NaN, then you can work backwards to figure out why.

I suggest stepping through this with a debugger, or at least adding a ton of print statements showing the value of every variable. Which one is NaN first?

If you still can’t figure it out, then post an MCVE with hard-coded values and we’ll go from there.

Thanks for the reply. I’ve printed the values with calculating the ‘r’ value, and got this:

Calculating Tangent... Values:
s1 = 0.13985401
t2 = 0.0
s2 = 0.28271097
t1 = 0.0
r  = Infinity

positions p1: (-0.688189, -0.525736, 0.499997, 1.0) p2: (-0.894426, -0.447216, 0.0, 1.0) p3: (-0.52573, -0.850652, 0.0, 1.0)
texcoords t1: (0.573431, 0.856142) t2: (0.713285, 0.856142) t3: (0.856142, 0.856142)
normal:   (0.4089, 0.6617, -0.6284)
tangent:  (NaN, NaN, NaN)

BTW. I got the code from brazil so he’s probably to blame for this :persecutioncomplex:
I’ll see if I can recode the method myself, and if that helps.

Well, there’s your answer. Both t1 and t2 are zero, so this line:

float r = 1.0f / (s1 * t2 - s2 * t1);

Is really this:

float r = 1.0 / 0.0;

Dividing by zero is generally not a great idea. Since you’re working with floats, r becomes infinity. And then when you use that infinity in other calculations, you get NaN.

I’m not sure what your algorithm is supposed to be doing, but something definitely seems off with your logic if you’re dividing by zero.

FYI, it looks like he’s trying to get proper face normals, for “correct” results in normal mapping.

There should be a divide by zero check, and then I think you set the “r” to 1.

Don’t have enough time to read the complete post. But I think the answer is in here.