- Home /

# Calculating Tangents (Vector4)

Hello!

I'm writing an importer and I would like to know if there's a way to generate tangents from my vertex,uvs and normals. Because mesh.RecalculateNormals isn't giving me the result I want.

thx!

sanryoga

**Answer** by Aras
·
Nov 16, 2009 at 05:28 PM

I assume you know what tangent space is then (in short: it's a surface-relative coordinate system, and consists of tangent, bitangent and normal; mostly used for normal mapped shaders).

Tangents in Unity are Vector4. Three components (xyz) of it store the tangent vector itself, and w component is used to determine "handedness" of the bitangent. Bitangent (sometimes called binormal) is always computed from tangent and normal. In Cg shader code:

```
float3 binormal = cross (normal, tangent.xyz) * tangent.w;
```

Now, computing tangents needs a texture coordinate set (UVs). There's actually tons of resources for that, e.g. Lengyel's approach is a good starting point. NVIDIA also has a NVMeshMender library that does it. Calculating tangents *can* get quite nasty when you want to make it fully robust.

**Answer** by N1nja
·
May 29, 2010 at 03:47 PM

and the same script in C#..

```
class TangentSolver
{
public static void Solve(Mesh mesh)
{
int triangleCount = mesh.triangles.Length / 3;
int vertexCount = mesh.vertices.Length;
```

```
```

```
Vector3[] tan1 = new Vector3[vertexCount];
Vector3[] tan2 = new Vector3[vertexCount];
Vector4[] tangents = new Vector4[vertexCount];
for(long a = 0; a < triangleCount; a+=3)
{
long i1 = mesh.triangles[a+0];
long i2 = mesh.triangles[a+1];
long i3 = mesh.triangles[a+2];
Vector3 v1 = mesh.vertices[i1];
Vector3 v2 = mesh.vertices[i2];
Vector3 v3 = mesh.vertices[i3];
Vector2 w1 = mesh.uv[i1];
Vector2 w2 = mesh.uv[i2];
Vector2 w3 = mesh.uv[i3];
float x1 = v2.x - v1.x;
float x2 = v3.x - v1.x;
float y1 = v2.y - v1.y;
float y2 = v3.y - v1.y;
float z1 = v2.z - v1.z;
float z2 = v3.z - v1.z;
float s1 = w2.x - w1.x;
float s2 = w3.x - w1.x;
float t1 = w2.y - w1.y;
float t2 = w3.y - w1.y;
float r = 1.0f / (s1 * t2 - s2 * t1);
Vector3 sdir = new Vector3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
Vector3 tdir = new Vector3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);
tan1[i1] += sdir;
tan1[i2] += sdir;
tan1[i3] += sdir;
tan2[i1] += tdir;
tan2[i2] += tdir;
tan2[i3] += tdir;
}
for (long a = 0; a < vertexCount; ++a)
{
Vector3 n = mesh.normals[a];
Vector3 t = tan1[a];
Vector3 tmp = (t - n * Vector3.Dot(n, t)).normalized;
tangents[a] = new Vector4(tmp.x, tmp.y, tmp.z);
tangents[a].w = (Vector3.Dot(Vector3.Cross(n, t), tan2[a]) < 0.0f) ? -1.0f : 1.0f;
}
mesh.tangents = tangents;
}
```

}

**Answer** by noontz
·
Mar 30, 2010 at 06:00 PM

Here is the javascript derived from the link above & developed with help from this thread http://forum.unity3d.com/viewtopic.php?t=41476

`/* Derived from Lengyel, Eric. Computing Tangent Space Basis Vectors for an Arbitrary Mesh. Terathon Software 3D Graphics Library, 2001. http://www.terathon.com/code/tangent.html */`

` `

class TangentSolver { function TangentSolver(theMesh : Mesh) { vertexCount = theMesh.vertexCount; vertices = theMesh.vertices; normals = theMesh.normals; texcoords = theMesh.uv; triangles = theMesh.triangles; triangleCount = triangles.length/3; tangents = new Vector4[vertexCount]; tan1 = new Vector3[vertexCount]; tan2 = new Vector3[vertexCount]; tri = 0; for ( i = 0; i < (triangleCount); i++) { i1 = triangles[tri]; i2 = triangles[tri+1]; i3 = triangles[tri+2];

```
v1 = vertices[i1];
v2 = vertices[i2];
v3 = vertices[i3];
w1 = texcoords[i1];
w2 = texcoords[i2];
w3 = texcoords[i3];
x1 = v2.x - v1.x;
x2 = v3.x - v1.x;
y1 = v2.y - v1.y;
y2 = v3.y - v1.y;
z1 = v2.z - v1.z;
z2 = v3.z - v1.z;
s1 = w2.x - w1.x;
s2 = w3.x - w1.x;
t1 = w2.y - w1.y;
t2 = w3.y - w1.y;
r = 1.0 / (s1 * t2 - s2 * t1);
sdir = new Vector3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
tdir = new Vector3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);
tan1[i1] += sdir;
tan1[i2] += sdir;
tan1[i3] += sdir;
tan2[i1] += tdir;
tan2[i2] += tdir;
tan2[i3] += tdir;
tri += 3;
}
for (i = 0; i < (vertexCount); i++)
{
n = normals[i];
t = tan1[i];
// Gram-Schmidt orthogonalize
Vector3.OrthoNormalize( n, t );
tangents[i].x = t.x;
tangents[i].y = t.y;
tangents[i].z = t.z;
// Calculate handedness
tangents[i].w = ( Vector3.Dot(Vector3.Cross(n, t), tan2[i]) < 0.0 ) ? -1.0 : 1.0;
}
theMesh.tangents = tangents;
}
```

`} `

**Answer** by cyble
·
Jul 07, 2012 at 01:50 PM

In the C# version: to prevent corrupt tangents, make sure you catch the division by zero as it will result in a NaN. You can do this by replacing the calculation of r with something like this:

```
float div = s1 * t2 - s2 * t1;
float r = div == 0.0f ? 0.0f : 1.0f / div;
```

**Answer** by dvorm
·
Jul 09, 2019 at 06:45 AM

Thank you for this one. It works fine even today.

Both triangleCount vertexCount and are int while a is long. That seems inconsistent. Can anyone explain?

### Your answer

### Welcome to Unity Answers

If you’re new to Unity Answers, please check our User Guide to help you navigate through our website and refer to our FAQ for more information.

Before posting, make sure to check out our Knowledge Base for commonly asked Unity questions.

Check our Moderator Guidelines if you’re a new moderator and want to work together in an effort to improve Unity Answers and support our users.

### Follow this Question

### Related Questions

Normal mapping mirrored UVs? 2 Answers

How do I modify a keyframe/curve's tangent in code? 2 Answers

Imported 2D sprites don't look good 1 Answer

Unity2D vector sprite sheet is blurry compared to single image with the same resolution. 1 Answer

Tangent Space Normal Map to World Space Normal Vector in C# Script 0 Answers