Calculating mesh tangent space vectors
#1
Posted 08 January 2006 - 05:22 PM
Can someone give me a hint what to do exactly?
#2
Posted 08 January 2006 - 07:46 PM
-si
Edit: In the text above I'm reffering to the first sentence in the last sentence..
#3
Posted 09 January 2006 - 01:24 AM
Quote
PS: I deliberately do not call the bitangent "binormal", because thats just wrong.
#4
Posted 09 January 2006 - 03:58 AM
That aside, in fact the tangent space does not need to be orthogonally related to the world space. The u and v axes of the tangent space are defined by the texture coordinates, and if the texture mapping is not orthogonal, then the tangent space mapping will not be either. Similiarly, if the texture is scaled so that texel areas are greater or smaller than 1 in world space, then the tangent space basis vectors will not be of unit length either.
Averaging the tangent bases at each vertex is completely correct and results in an approximation to the continuous parameterization of the curved surface that is represented by the triangle mesh, in just the same way that averaging normals at vertices approximates the continuous normal map of a curved surface. This is of course assuming that the texture mapping is consistent with some kind of continuous parameterization of a curved surface. Whenever you have a seam in the texture mapping there will also be a seam in the tangent bases (i.e. at edges of smoothing groups).
#5
Posted 09 January 2006 - 09:44 AM
The tangent basis should define a transformation to 'texture space'. The non-unit tangent and bitangent vectors correspond to 'stretch' in the texture mapping.
To Reedbeta:
Are you sure? I've read quite a bit differential geometry/topology and I've never seen a definition for the binormal that would give sense to anything except curves in R^3. I do somewhat agree that bitangent is even worse, since a bitangent is a line that tangents twice. The standard mathematical way to treat this is to call the two vectors a tangent basis and it it usally reffered to as an ordered pair {u_x, u_y} or {u,v}, never seen anything but this actually.
Reffering to the main subjcet, I was unsure if this is the 'correct' way to do it, since it is not enough that the texture mapping is consistent with a contionous parameterization, but it just struck me that it should be C^1. I'm sure that 99% of the texture mappings out there are just piecewise C^1...
-si
#6
Posted 09 January 2006 - 09:13 PM
Reedbeta said:
In the book "Mathematics for 3D Game Programming & Computer Graphics" there is a passage that you should orthonormalize the tangent space vectors :|
#7
Posted 09 January 2006 - 10:28 PM
Axel said:
In the book "Mathematics for 3D Game Programming & Computer Graphics" there is a passage that you should orthonormalize the tangent space vectors :|
Well, the truth is that you should not orthogonalize or normalize. The tangent basis should define a transformation to 'texture space' dependent on the texture mapping coordinates. You will almost certainly have some stretch, and you will get non-orthogonal basis when you have textures that is 'skew' (like if you have a square with texture coordinates (0,0), (1,0), (0.5,1),(0.75,1)).
-si
#8
Posted 12 January 2006 - 08:46 PM
The reasoning is similar to why we need special matrices to transform normals.
We use the TBN matrix to transform a _direction_ vector (the light vector)into the tangentspace! Matrices that contain non-uniform scaling (as non-normalized T and B would introduce) are supposed to transform direction vectors this way (transposed inverse of M):
n' = (M^-1)^t)*n
(this is kind of removing the non-uniformity in scaling, leaving us with a vector that has the right direction, but may not have the right length, thus a renormalization of n' is needed, too)
Eric Lengyel´s derivation in fact produces a matrix that would transform a vector from tangentspace to objectspace (lets call it matrix 'A'). But the lightingcode needs the inverted matrix of that ('B'). But instead of doing a real inversion of the matrix, Lengyel makes the assumption that A is nearly-orthogonal (or even forces orthogonality using that schmidth-gram step) and by normalizing T,B, N. This way he gets an orthonormalized (rotation-)matrix that is perfectly suited for transforming the light vector.
Lets see, what my "real" solution would yield:
B=A^-1
l'= ((B^-1)^t) * l
l'= ((A^-1)^-1)^t) * l
l'= A^t * l
Doh! This is the same thing that Lengyel is using, except there´s no normalization and orthogonalization is taking place. But why doesn´t this work?
I forgot that I created the per-vertex-TB vectors by summing up the face-TB-vectors this vertex is belonging to! This creates vectors that are way too long. So, I would have to either a) normalize the vectors again or b) divide by the number of vertices we summed up (in order to get some kind of "average").
Actually I did not test, if averaging instead of normalization results in a different look.
But then it hit me. What is the basic reason, why we do that TBN stuff at all? We want to transform l into the space where the normalmap-vectors live, so we can "safely" calculate dot(n, l). They (usually?) live in "unstretched" texture space.
Here´s the thing that people arguing with "stretched texture space" seem to miss: Stretching the normalmap only changes the positions where the normal-texel get fetched. But it DOES NOT stretch the direction of the fetched normals. They still live in unstretched space. And this is why the incoming l vector must not get stretched too, thus TBN should be orthonormal. Otherwise we would combine a stretched l-vector with an unstretched n which would result in weird lighting.
Of course, if my assumption is wrong and the normalmap-vectors are kind of "pre-stretched", the reasoning above does not hold. But it would drastically reduce the re-usability of normalmaps (since the normalmap normals would be only right for triangles with a specific texture stretching) and we could switch to objectspace normalmaps anyway :-)
#9
Posted 12 January 2006 - 10:31 PM
You make a good point about dot products in a stretched tangent space. The inner product is not preserved by non-orthogonal transformations, so to be completely correct we need to evaluate a different inner product in the tangent space. In differential geometry this is called the first fundamental form.
On the whole, it is probably easier to use object space normal maps, or just transform the normals into world space at each pixel, rather than transforming the light and view vectors into tangent space.
#10
Posted 13 January 2006 - 11:55 AM
The TBN transformation should not preserve inner-product or angles since stretch in the texture mapping does not preserve angles or inner product. This is easy to see if you f.ex. have a slope at 45 deg. in texture space, and when 'stretched' upon the surface the angle will ofcourse be less han 45 deg.(or more than 45 deg. if we have some 'shrink'). So the thought is that by having non-normalized tangent basis we want to preserve the angle and inner-product from object-space when transforming to texture-space.
So, if p is your local diffeomorphism to texture space, and n is a normal in texture space, and v is any curve or ray. Then to get correct angle you should calculate the angle between p´(v)*v´ and n (In our case p'(v) is simply the interpolated non-normalized TBN, and v' is the light/eye vector whatever).
You have to consider this anytime you pass to/from texture space, so using object space normal maps or world space lighting doesn't fix this magicly.
Using a normalized tangent basis will ofcourse give you some sort of bumpmapping, however if you use it with parallax mapping I'm sure you will be able to create examples where this give wierd results.
-si
Edited for an error in the diff. geom part at the beginning of the message.
Editing again, now everything should be correct...
#11
Posted 13 January 2006 - 01:15 PM
However, to orthogonalize and normalize the TBN is incorrect.
-si
#12
Posted 13 January 2006 - 04:37 PM
I wonder, if anyone has ever implemented it "the right way". Do you know, if there´s any demo showing the differences of the various techniques? I´m really interested to see how much difference it would make...
#13
Posted 14 January 2006 - 08:12 PM
skynet said:
I wonder, if anyone has ever implemented it "the right way". Do you know, if there´s any demo showing the differences of the various techniques? I´m really interested to see how much difference it would make...
To simply scale it by the x and y components is not enough, if the basis is orthogonal you should use the inverse-transpose, however I'm not sure this applies to non-orthogonal basises too (should be OK to check, but it's kind of an ackward calculation, I might do this sunday).
I've googled for derivations of the tangent basis but can't find any satisfactory reasoning (some try, but the details are similar to ancient egyptian mathmaticians (which would reason certain things with something like 'because this is the truth')). I can't find anyone doing it 'the right way'. This is not strange at all since trying to do it the right way obviously opens a can of worms. The best thing to do is probably to make sure your artists doesn't do anything funny the normal maps or generate them accuratly from high-detail models (in the latter case you can probably use orthonormal tangent basis and get away with it).
-si
#14
Posted 14 January 2006 - 09:05 PM
#15
Posted 14 January 2006 - 11:58 PM
#16
Posted 15 January 2006 - 12:42 AM
#17
Posted 15 January 2006 - 03:47 AM
#18
Posted 15 January 2006 - 11:23 AM
I average face-normals by adding the non-normalized cross product to the vertices (by that the face area is considered in the calculation as you likely know) and after that I will renormalize all vertex-normals.
I thought I can do something similar with binormal and tangent...
#19
Posted 15 January 2006 - 11:41 AM
#20
Posted 15 January 2006 - 12:55 PM
Could I keep track how many faces affected a vertex and dividing the vectors by that value?
Reedbeta said:
1 user(s) are reading this topic
0 members, 1 guests, 0 anonymous users












