# The calculation of a tangent from a normal

Given a unit normal (x,y,z), how would one calculate a useful tangent from it?

Cas Do you mean if given the normal vector, how can you get another vector perpendicular to it?

Yep.
Basically another point on the plane, but in a particular direction, and unit distance from the origin.

Cas You basically have to first find a point that is not on the line parallel to the tangent vector, and use this point to form a new vector that has a length of sqrt(2). It will be the hypotenuse of a right triangle, and the normalized tangent is one of the other sides. Then you can just use vector subtraction to find the other side which will lie in the plane.

[This message has been edited by DFrey (edited 06-28-2001).]

I was thinking along those lines (arf!) but unable to come up with a bit of code… must be too late.

Hm, is there a simple hack I can do along the lines of
Tx=Ny
Ty=-Nx
Tz=Nz
Which will give me the tangent along the x axis or thereabouts?

And can I then get the binormal by doing NxT?
In which case should my tangent space transformation matrix be as described in http://www.sgi.com/software/opengl/advanced98/notes/node108.html ?

In which case… why doesn’t my ratbag bump mapping produce the right results!! Curses.

Cas Here is what I have used in the past. I’m sure there are bound to be better ways. I’m not even certain this code works for all unit vectors, but I haven’t had any problems with it.

// axis is the normal vector
y=2*(axis+1);
y=3*(axis+2);
y=4*(axis+3);
VectorScale(DotProd(axis,y),axis,result); // result = (axis dot y) * axis
VectorSubtract(y,result,result); // result=y-result
Normalize(result);

[This message has been edited by DFrey (edited 06-28-2001).]

[b]

Tx=Ny
Ty=-Nx
Tz=Nz

[/b]
That will not work if Nz!=0.

[This message has been edited by DFrey (edited 06-28-2001).]

I just discovered that when I tried to bump map a completely flat surface just now I’ll try the more complicated way…

Cas If you have the normal <a,b,c> and the vertex where that normal should be assigned <r,s,t> then you can use the equation for a plane a(x-r) + b(y-s) + c(z-t) = 0 choose an arbitrary x and y then solve for z and you’ll have a tangent (non-normalized) vector.

In fact I think if you use the equation of plane way, you can always pick x and y to be sqrt(1/2) that way when you’re normalizing you only have to scale x y and z by 1/sqrt(1 + z^2) because you can replace sqrt(1/2)^2 + sqrt(1/2)^2 with 1 for the part of the scaling factor in the normalization that goes x^2+y^2. That saves 2 multiplications and an addition (as if it matters  ), and i guess you could set sqrt(1/2) as a constant too, so you don’t have to calculate it each time.

[This message has been edited by grady (edited 06-28-2001).]

Ok, i’m stupid, the equation for the plane reduces to the dot product equals zero for normals because you can always choose r s and t to be zero (ax + by + cz = 0)so you can simply do

z = -sqrt(1/2) * (a+b) * 1/c;

scale_factor = 1 / sqrt(1+pow(z, 2);

x*= scale_factor;
y*= scale_factor;
z*= scale_factor;