# Tangents and binormals

Hi.

Is where way to compute tangents and binormals for each pixel from height map and normal map ?

Thanks.

Hi
What’s wrong with my question ?
Thanks.

[joke]
… or maybe anyone can’t answer it? To me, it seems to be quite OK formulated
[/joke]

me, i just wait to get an answer for it, too cant help you… but perhaps matt can help you, he said he understand it, but last time he didnt wanted to explain it to me and just refered to the developer page, but this code there is not understandable in any way, so i wait till today

Why do you want to do this calculations at per pixel basis?

The problem is, for a point in a 2D surface, there are an infinite number of tangent and binormal vectors. A point on a space curve on the otherhand has unique tangent and binormal vectors. So to get the tangent and binormal vectors at a point of a surface, you need some additional constraint. Such as requiring the tangent vector to be in the direction of increasing x or y. Without the additional constraint there is no sensible way to pick a tangent vector (and hence binormal vector since it is derived by the cross product of the tangent and normal).

[This message has been edited by DFrey (edited 03-18-2001).]

ok, letz do it simple:

a simple triangle with 2 texturecoordinates and 3 spacecoordinates and 3 normal-coordinates per vertex. now you can calculate the tangent and binormal to do per pixel lighing effects like bumpmapping simple ( you can transform then your lightsource into texturespace to do this )

like it is done in the demos on nvidia/developer

now how to do this? dont understand them how they do this… and i think this is what michail wants to know too, not?

I’m not good in math, but in another NVidia presentation paper they used another way to compute the 3x3 transformation matrix which makes the light vector to be in texture space (they used the position and texture coordinates of the vertex to construct an equations system based on the plane equation formula). But this maybe the same thing, and i don’t know very well (as i said before i’m not good in math).

My question is realy bad formulated,sorry.
I want to compute two textures,one for tangent vectors and second for binormals at
preprocessing time.I have only height map and
calculated normal map,no geometry info.

Thanks.

If you have no geometry info, you can not calculate these vectors in eye space. But you can calculate these vectors in local coordinate system as:

B=normalize(1,0,df/dx);
T1=normalize(0,1,df/dy);
N=normalize(T1 cross B);
T=N cross B.

N is normal, T tangent, B - binormal, T1-aux vector.

You simply have to take some random vector V that is not the same or the opposite direction of your normal N.

Then a tangent vector is calculated by N x V. So you need no geometric info, only the normals at each point.

With a heightmap you can safely choose your x or y axis as your vector V because the normals of height maps are never in the XY-plane.

and how bout textured triangles where you want the tangent and binormal to get texture space? its simple, i know, but i dont get it, sorry…( for landscapes, i got it, too… there it is some parametric logic, but how to do this for textured things, where i want that for example tangent is in the u, and then the binormal into v direction, and the normal is normal to them how to get this? some simple pseudoccode i would like…

How to Generate Texture Space?
• For each triangle in the model :
• Use the x, y, z position and the s, t bump map
texture coordinates
• Create plane equations of the form :
• Ax + Bs + Ct + D = 0
• Ay + Bs + Ct + D = 0
• Az + Bs + Ct + D = 0
• Solve for the texture gradients dsdx, dsdy, dsdz,
etc.

Generating Texture Space
• Now treat the dsdx, dsdy, and dsdz as a 3D vector
representing the S axis < dsdx, dsdy, dsdz >
• Do the same to generate the T axis
• Now cross the two to generate the SxT axis – this
is the ‘Z’ or up axis of Texture Space, and is
typically close to parallel with the triangle’s
normal
• If your SxT and the triangle normal point in
opposite directions, the artist applied the texture
backwards – have the artist fix this, or negate the
SxT axis

These 3 Axes together make up a 3x3
rotation/ scale matrix
dsdx dtdx SxTx
dsdy dtdy SxTy
dsdz dtdz SxTz
Putting an XYZ model- space vector through this 3x3
matrix produces a vector expressed in local
Texture Space

thats what i dont get completely… anyone?

Originally posted by davepermen:
[b]How to Generate Texture Space?
• For each triangle in the model :
• Use the x, y, z position and the s, t bump map
texture coordinates
• Create plane equations of the form :
• Ax + Bs + Ct + D = 0
• Ay + Bs + Ct + D = 0
• Az + Bs + Ct + D = 0
• Solve for the texture gradients dsdx, dsdy, dsdz,
etc.

Generating Texture Space
• Now treat the dsdx, dsdy, and dsdz as a 3D vector
representing the S axis < dsdx, dsdy, dsdz >
• Do the same to generate the T axis
• Now cross the two to generate the SxT axis – this
is the ‘Z’ or up axis of Texture Space, and is
typically close to parallel with the triangle’s
normal
• If your SxT and the triangle normal point in
opposite directions, the artist applied the texture
backwards – have the artist fix this, or negate the
SxT axis

These 3 Axes together make up a 3x3
rotation/ scale matrix
dsdx dtdx SxTx
dsdy dtdy SxTy
dsdz dtdz SxTz
Putting an XYZ model- space vector through this 3x3
matrix produces a vector expressed in local
Texture Space

thats what i dont get completely… anyone?[/b]

Because i skipped some high-school classes the only thing i don’t know is how to solve those texture gradients, but the rest is easy. If you have any ideas please tell me. BTW, which other part didn’t you get it?

It took me quite a while but I think thats the way to calculate tangent space per !plane! polygon
(BTW the bumpmaping created with this tangenspace looks ok to me)

What you look for basically are three vectors Pv Pu and N. Were Pv points in the 3D (x,y,z) direction of changing v and
Pu in the direction of changing u. Finally N is just the normal of the polygon which is orthogonal to 2D texture space
(the u and v directions).

You start off with a triangle i.e 3 Points with coordinates:
Pi = (xi, yi, zi), (ui, vi) with ui,vi the texture and xi, yi, zi the spatial coordinates of the vertex.

Now start by calculating a bunch of direction vectors namely calculate:
T1 = (v0,u0)-(v1,u1)
T2 = (v0,u0)-(v2,u2)
V1 = P0 - P1
V2 = P0 - P2

Now the Vi Vectors can be represented in terms of Pv and Pu as:
V1 = PvT1v + PuT1u
V2 = PvT2v + PuT2u

For instance the x terms are

V1.x = Pv.xT1v + Pu.xT1u
V2.x = Pv.xT2v + Pu.xT2u

This a simple linear equation system with two equations for two unknowns namely Pv.x and Pu.x.
The Equations for y and z are analogous.

Solve all these for Pv(.xyz) and Pu(.xyz) together with the polygons normal you have
tangent space for your planar polygon.

Hope that helped

Ax + Bs + Ct + D = 0
Ay + Bs + Ct + D = 0
Az + Bs + Ct + D = 0
how do i get those equations? isn’t D always zero?

or are here the A, B, C, and D always the same values? ( looks like )

then i have 3 equations and 4 variables, sounds like fun

ok, when i got them, what are the texture gradients?
what does dsdx means? the vector is [ dsdx, dsdy, dsdz ] in S direction, what is then T? [ dtdx, dtdy, dtdz ]

thats what i want to know… answer in two steps would be best, first the equation part, then the gradients…

(btw, please use pseudoccode or pseudovertexprogram code, thats what i most understand , cause then i do know what you mean ( like dot( v0, v1 ) or cross( v0, v1 ) ), else i’m sitting here with (v0,v1) and, hm… yeah, is this perhaps a dotproduct? or a cross… depending on the math book it could be both )

# As noted by Peercy [21], transforming an object-space vector into tangent space is done by transforming the vector by the 3x3 matrix formed by the three vectors Tn, Nn, and Bn. So if LOS is the object space light vector, the light vector in tangent space LTS computed as ú ú ú û ù ê ê ê ë

n(z) n(z) n(z)
y) n( y) n( y) n(
n(x) n(x) n(x)
OS TS
N B T
N B T
N B éT
L L

dont think it can copies that

ok, for clearity:

//V0 = Point in Object Space
//V1 = Point in Texture Space
//T = Tangent
//B = Binormal
//N = Normal
V1.x = T.x * V0.x + B.x * V0.y + N.x * V0.z
V1.y = T.y * V0.x + B.y * V0.y + N.y * V0.z
V1.z = T.z * V0.x + B.z * V0.y + N.z * V0.z

//so all i need is the tangent ( binormal = T x N )

[This message has been edited by davepermen (edited 03-20-2001).]

[This message has been edited by davepermen (edited 03-20-2001).]

no one knows how to get the vector in object space, wich is in texture space [1,0] and the one wich is in texture space [0,1], these are the two i need, i think ( normalized, of course ), and the noormal

means i have to get ( in u,v,w coordinates )

[1,0,0]
[0,1,0]
[0,0,1] => this i get, its the normal

how bout the others?

I found the code to get the s and t vectors in one of the Nvidia examples (I think from the Dot3 Bumpmapping Vertex Shader Example from their effects browser). The following is the part to get the s and t vectors.

I do not really understand how it works, but maybe some of you can figure this out.

v0, v1 and v2 are the points of the current triangle, punkt is just german for point.
uTex and vTex are the u and v Texture coordinates from each point.

Lars

``````  // x, s, t Kanten berechnen
edge01 = D3DXVECTOR3( v1.punkt.x - v0.punkt.x, v1.uTex - v0.uTex, v1.vTex - v0.vTex );
edge02 = D3DXVECTOR3( v2.punkt.x - v0.punkt.x, v2.uTex - v0.uTex, v2.vTex - v0.vTex );

D3DXVec3Cross(&cp, &edge01, &edge02);
if ( fabs(cp.x) > SMALL_FLOAT )
{
v0.s.x += -cp.y / cp.x;
v0.t.x += -cp.z / cp.x;

v1.s.x += -cp.y / cp.x;
v1.t.x += -cp.z / cp.x;

v2.s.x += -cp.y / cp.x;
v2.t.x += -cp.z / cp.x;
}

// y, s, t
edge01 = D3DXVECTOR3( v1.punkt.y - v0.punkt.y, v1.uTex - v0.uTex, v1.vTex - v0.vTex );
edge02 = D3DXVECTOR3( v2.punkt.y - v0.punkt.y, v2.uTex - v0.uTex, v2.vTex - v0.vTex );

D3DXVec3Cross(&cp, &edge01, &edge02);
if ( fabs(cp.x) > SMALL_FLOAT )
{
v0.s.y += -cp.y / cp.x;
v0.t.y += -cp.z / cp.x;

v1.s.y += -cp.y / cp.x;
v1.t.y += -cp.z / cp.x;

v2.s.y += -cp.y / cp.x;
v2.t.y += -cp.z / cp.x;
}

// z, s, t
edge01 = D3DXVECTOR3( v1.punkt.z - v0.punkt.z, v1.uTex - v0.uTex, v1.vTex - v0.vTex );
edge02 = D3DXVECTOR3( v2.punkt.z - v0.punkt.z, v2.uTex - v0.uTex, v2.vTex - v0.vTex );

D3DXVec3Cross(&cp, &edge01, &edge02);
if ( fabs(cp.x) > SMALL_FLOAT )
{
v0.s.z += -cp.y / cp.x;
v0.t.z += -cp.z / cp.x;

v1.s.z += -cp.y / cp.x;
v1.t.z += -cp.z / cp.x;

v2.s.z += -cp.y / cp.x;
v2.t.z += -cp.z / cp.x;
}
}
``````

ok, i have done some calculations today in school ( while history, i’m a bad boy! ), and i got this:

struct vec
{
float x,y,z,u,v; //x,y,z modelspace, u,v texturecoordinates
};

vec calcTangentS( vec p0, vec p1, vec p2 )
{
vec v0 = p1 - p0;
vec v1 = p2 - p0;

float t0 = v1.v / ( v0.u * v1.v - v0.v * v1.u );
float t1 = v0.v / ( v0.v * v1.u - v0.u * v1.v );

return t0 * v0 + t1 * v1;
}

and

vec calcTangentS( vec p0, vec p1, vec p2 )
{
vec v0 = p1 - p0;
vec v1 = p2 - p0;

float t0 = v1.u / ( v0.v * v1.u - v0.u * v1.v );
float t1 = v0.u / ( v0.u * v1.v - v0.v * v1.u );

return t0 * v0 + t1 * v1;
}

can someone test if this is true? i dont have my visual c++ yet, so i cant ( and i have no time… working afternoon, theatre evening, school morning peng

btw, a little crieout:

[[–whas zensured after 5 minutes!–]]

[This message has been edited by davepermen (edited 03-21-2001).]