PDA

View Full Version : The calculation of a tangent from a normal



cix>foo
06-28-2001, 12:07 PM
Given a unit normal (x,y,z), how would one calculate a useful tangent from it?

Cas http://www.opengl.org/discussion_boards/ubb/smile.gif

DFrey
06-28-2001, 12:10 PM
Do you mean if given the normal vector, how can you get another vector perpendicular to it?

cix>foo
06-28-2001, 12:32 PM
Yep.
Basically another point on the plane, but in a particular direction, and unit distance from the origin.

Cas http://www.opengl.org/discussion_boards/ubb/smile.gif

DFrey
06-28-2001, 12:52 PM
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).]

cix>foo
06-28-2001, 01:06 PM
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 http://www.opengl.org/discussion_boards/ubb/smile.gif

DFrey
06-28-2001, 01:07 PM
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[0]=2*(axis[0]+1);
y[1]=3*(axis[1]+2);
y[2]=4*(axis[2]+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).]

DFrey
06-28-2001, 01:13 PM
Tx=Ny
Ty=-Nx
Tz=Nz

That will not work if Nz!=0.



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

cix>foo
06-28-2001, 01:29 PM
I just discovered that when I tried to bump map a completely flat surface just now http://www.opengl.org/discussion_boards/ubb/smile.gif

I'll try the more complicated way...

Cas http://www.opengl.org/discussion_boards/ubb/smile.gif

grady
06-28-2001, 02:33 PM
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.

grady
06-28-2001, 07:41 PM
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 http://www.opengl.org/discussion_boards/ubb/rolleyes.gif http://www.opengl.org/discussion_boards/ubb/smile.gif ), 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).]

grady
06-28-2001, 08:01 PM
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;