- Home /
How do you find the tangent from a given normal?
Normals in Unity are Vector3s, Meaning they represent a point in space. To my understanding, the way normals are given in unity is basically a Vector3 in relation to (0,0,0). For example: (0.5, 0.2, 0) from (0,0,0) How would you go about calculating the tangent from a normal, or any Vector3 (with normal bounds) in this case?
You're talking about a plane that's normal to your vector, right? Because, technically, there are an infinite number lines that are 90 degrees from any given vector.
Actually, the normal that Unity returns is a normalized direction vector and not a point. I know that doesn't answer your question, but a better insight into how things work never hurt anyone either.
A Vector3 doesn't necessarily represent a point in space. With regards to normals, the Vector3 represents a direction. (0, 0, 1) means "1 unit along the z axis".
Unity uses Vector3 to store both, points and vectors, what sometimes is very confusing. Vectors are universally (not only in Unity) represented as a point relative to 0,0,0 , as @Tonzie suspected.
For what do you want to know the tangent to a normal? In 2D space, a tangent is a line perpendicular to the normal at a given point of a curve. In 3D, however, its equivalent is a plane, as @ChrisD said.
Answer by Oliver Eberlei · Jun 23, 2011 at 01:45 AM
To get a tangent from a normal (out of the possible infinite number of tangents) you can use the cross product with a union vector
Vector3 normal = new Vector3( 1, 1, 0 );
Vector3 tangent;
Vector3 t1 = Vector3.Cross( normal, Vector3.forward );
Vector3 t2 = Vector3.Cross( normal, Vector3.up );
if( t1.magnitude > t2.magnitude )
{
tangent = t1;
}
else
{
tangent = t2;
}
You need to create two cross products in case the normal is pointing in the same direction as one of the test vectors.
A shorter alternative and probably better one, since it only calculates the second cross product when needed (though I have not checked if it produces correct results)
Vector3 tangent = Vector3.Cross( normal, Vector3.forward );
if( tangent.magnitude == 0 )
{
tangent = Vector3.Cross( normal, Vector3.up );
}
This second solution produces incorrect results, ins$$anonymous$$d your first one works fine.
Answer by robm123 · Jul 25, 2020 at 11:13 PM
If you want a random tangent you can try the following ie. one that is tangent but in a random orientation to the normal: private Vector3 CreateRandomTangentVector(Vector3 normal) {
//Creates a vector tangental to the one passed to this function. Note that the angle of the tangent is random.
float x = UnityEngine.Random.Range(-100, 100);
float y = UnityEngine.Random.Range(-100, 100);
float z = UnityEngine.Random.Range(-100, 100);
Vector3 randomVector = new Vector3(x, y, z);
randomVector = randomVector / randomVector.magnitude;
Vector3 t1 = Vector3.Cross(normal, randomVector);
Vector3 t2 = Vector3.Cross(normal, Vector3.up);
Vector3 tangent; //= new Vector3(0, 0, 0);
if (t1.magnitude > t2.magnitude)
{
tangent = t1;
}
else
{
tangent = t2;
}
return tangent;
}