The calculation of a tangent from a normal

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


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

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


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
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 ?

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


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
VectorScale(DotProd(axis,y),axis,result); // result = (axis dot y) * axis
VectorSubtract(y,result,result); // result=y-result

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



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…


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;