Something's wrong with my tangents and bitangents.

Started by
32 comments, last by Eric Lengyel 18 years, 10 months ago
A couple of comments.

1) What if v[ 0 ] == zero?

2) Why are your orthonormalizing the vectors? This is not needed in general, and can produce wrong results in many cases.

3) Why are you calculating the normal from the t x b? You should just use the normal that came in or compute it directly. This helps with mirrored texture coordinates.

Have you looked at nvMeshMender?

http://developer.nvidia.com/object/NVMeshMender.html

Not as fast as it could be, but it works pretty well, IMHO.

Advertisement
Quote:Original post by ganchmaster
Yeah, the binormal isn't really normal to the surface...so what? Everyone knows what it means.


Clearly it is news to you, but terminology matters. For example, a 'line' is an entity with infinite extent. A 'line segment' is a finite section of a line. If you, for example, ask for how to find the closest points between two lines when you mean two line segments you're gonna get an answer completely irrelevant to your problem.

The same applies to 'binormal' and 'bitangent' and Eric's "crusade" is justified. FYI, most if not all game and graphics professionals I know have corrected their usage of these terms as it is obvious that Eric is right. It says a lot that they find it important to do so. It also says a lot that you don't.
Quote:Original post by Christer Ericson
Quote:Original post by ganchmaster
Yeah, the binormal isn't really normal to the surface...so what? Everyone knows what it means.


Clearly it is news to you, but terminology matters. For example, a 'line' is an entity with infinite extent. A 'line segment' is a finite section of a line. If you, for example, ask for how to find the closest points between two lines when you mean two line segments you're gonna get an answer completely irrelevant to your problem.

The same applies to 'binormal' and 'bitangent' and Eric's "crusade" is justified. FYI, most if not all game and graphics professionals I know have corrected their usage of these terms as it is obvious that Eric is right. It says a lot that they find it important to do so. It also says a lot that you don't.


Yeah, I totally agree that terminology matters. I think people should use terminology that is not confusing. Despite your comments about "most if not all" graphics professionals, "Binormal" is heavily enshrined in the literature. And it's confusing to try to introduce a new term.

it is hardcoded in D3D for instance:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/hlslreference/hlslreference.asp

ATI uses the term

http://www.ati.com/developer/sdk/RadeonSDK/Html/Tutorials/RadeonBumpMap.html

GPU Gems mentions it:

http://www.awprofessional.com/content/images/0321228324/samplechapter/fernando_ch03.pdf

Dave Eberly, who I am sure you are familiar with, uses the term:

http://www.geometrictools.com/Foundation/Effects/Wm3BumpMapEffect.cpp

The granny SDK which generates tangent space vectors uses it:

http://www.radgametools.com/grasdk.htm

A tutorial on gamedev itself uses it

http://nehe.gamedev.net/data/articles/article.asp?article=20

I could go on but I think I make my point. You are basically setting up a straw man by saying "terminology matters" and then knocking it over. I never said terminology didn't matter. I think people should use terminology that is not confusing. It's confusing when people decide to adopt a new terminology to replace a perfectly good one that is widely used. Further the term "bitangent" already means something else, so how is it an improvement to use that? And the term binormal is appropriate since for either curves or surfaces, B = T x N.

It's really kind of ironic that people are attempting to put a self-righteous smackdown on me for this, since I am actually kind of a stickler for calling things by their right name - more than most people I would say. So yes I say line when I mean line and line segment when I mean that, and so on. I think you would find your comment about how it "says a lot that I don't" humorous if you knew me. Maybe it's better to not get personal.

I don't know if I should dignify the anonymous post with a response, but the analogy is obviously flawed, since it is not harmful to anyone to call something a binormal :). Probably that post should be deleted anyway, especially since it was an Anonymous Coward (tm).

terminology is still damn irrelevant to this thread.
Ok, first an update. I had the normals of the face wrong since I was sharing them among faces that shared a vertex even if they didn't share the same normal. So now that's solved but I still have problems where the bumpiness of the faces point kinda to the other side so I will have to check out what's wrong with that but I'm not so sure. In an hour or so I will have a few screenshots.

Quote:Original post by SimmerD
A couple of comments.

1) What if v[ 0 ] == zero?

True, I added the following check if(fabs(v[0]) > EPSILON) to handle that situation.

Quote:Original post by SimmerD
2)Why are your orthonormalizing the vectors? This is not needed in general, and can produce wrong results in many cases.

I didn't know that, nn which case would that be wrong?

Quote:Original post by SimmerD
3) Why are you calculating the normal from the t x b? You should just use the normal that came in or compute it directly. This helps with mirrored texture coordinates.

The normals used were actually from the mesh that I loaded. The normal defined with t x b was just for for the final check fo the values but I got rid of it since it did no good.

Quote:Original post by SimmerD
Have you looked at nvMeshMender?

http://developer.nvidia.com/object/NVMeshMender.html

Not as fast as it could be, but it works pretty well, IMHO.

I checked it out but it does way too much, I just need to get correct bitangents and tangents.

Thanks for the help SimmerD.
In most cases orthonormalizing is the ok to do. In the case of a non-square texture, or one mapped in a non-square manner, you don't necessarily want your tangents & binormals to be the same scale, for instance.

Doug Rogers has shown mathematically that for proper local lighting, the tangent space basis is not a rotation matrix, and should deform per-pixel in order to get the right thing. So, you shold not normalize these vectors per-pixel, for instance. Sorry, I don't have a link.
Quote:Original post by SimmerD
In most cases orthonormalizing is the ok to do. In the case of a non-square texture, or one mapped in a non-square manner, you don't necessarily want your tangents & binormals to be the same scale, for instance.

Doug Rogers has shown mathematically that for proper local lighting, the tangent space basis is not a rotation matrix, and should deform per-pixel in order to get the right thing. So, you shold not normalize these vectors per-pixel, for instance. Sorry, I don't have a link.

Cool, thanks for letting me know. And don't worry, I know how to use Google :)
Hi Hulag --

The code at http://www.terathon.com/code/tangent.html does exactly what you need. The arrays pointed to by tan1 and tan2 contain the tangents and bitangents, respectively, after the main loop. The these are used to calculate a handedness factor, and then the bitangents are thrown out because you're expected to recalculate them in the vertex program using B = (N x T) * T.w.

Unfortunately, the example which is susceptible to division by zero has been around for a few years and copied all over the place, but it is just plain wrong. The algorithm is obviously not robust, even with that hacky epsilon test. Because you're dividing by the difference in vertex coordinates, it can't even handle an axis-aligned cube correctly.

-- Eric Lengyel
Quote:Original post by ganchmaster
Binormal is still a better name than bitangent. It means about the same thing for surfaces as it does for curves - B = T x N.


That's not true. For a curve, yes, it's always the case that B = T x N. The vectors are ordered so that the local Frenet frame's x, y, and z axes are aligned to the directions given by T, N, and B, in that order. In tangent space, however, the order is different: the x, y, and z axes correspond to T, B, and N. If your texture coordinates are right-handed (so that your texture isn't flipped), then B = N x T, which is different than that for curves. If your texture is flipped, then you do get B = -N x T = T x N. The bitangent vector is defined in a completely different way and has a completely different meaning for surfaces than does the binormal vector for curves.

The confusion arises when people new to the subject encounter the term binormal. Sure, for curves it makes perfect sense since there is one tangent direction and two orthogonal normal directions whose names both contain the word "normal". For surfaces, there's one normal direction and two orthogonal tangent directions, and it's appropriate for the two tangent directions to both contain the word "tangent". Just because a less-than-optimal term has been used for a while doesn't mean that we should keep it that way. I think the best thing that authors can do now is explain that binormal and bitangent are used interchangeably, but also explain that the usage of binormal is not technically correct.

BTW, the entry for bitangent on MathWorld does state that it's incomplete. Many mathematical terms have multiple meanings (just look at "normal"), and using the term "bitangent vector" would not be hijacking anything from the term "bitangent", which is a line that is tangent to a curve at two points. Myself and others have recently contacted Wolfram about updating MathWorld with the meaning of "bitangent vector" in the context of bump mapping, so hopefully we'll see it there soon.
Oh yeah, don't call me delusional. You might make me angry. And you wouldn't like me angry.

This topic is closed to new replies.

Advertisement