normal mapping--tangents

Started by
0 comments, last by bootstrap 17 years, 4 months ago
Hi, I am trying to compute the tangent basis at each vertex for an arbitrary triangle mesh. I coded up the algorithm described in Eric Lengyel's game math book. Basically this is the problem: for some reason, in my meshes there will be some degenerate triangle texture, that is, the vertices lie on a line in texture space. This messes up the tangent calculation and makes the determinant, used in the formula, zero, which then causes a divide by zero... In particular, I tried my code with the Dwarf.x mesh that ships with the DX SDK. Does anyone know if this mesh is fouled up? As another example, I made a cylinder and generated cylindrical coordinates for it. This too failed. Here I found the problem was at the cylinder caps--cylindrical texturing doesn't work for the caps. So as a test I removed the end caps, then the code worked correctly and the output was correct. I also tested my code with a box and it worked correctly. My tangents for the cylinder (without the caps) matched that of D3DXComputeTangentFrame, so I am pretty confident my code is correct, but I am just not handling some problematic cases. I think D3DX must either repair the mesh or do something to handle these certain situations. Does my problem sound familiar to anyone?
-----Quat
Advertisement
Yes, this is familiar. When code computes an east-vector (AKA "tangent-vector") or north-vector (AKA "bitangent-vector" or "binormal-vector"), the code must average ALL triangles on the smooth-continuous-surface-in-question that include the vertex, but must average NO triangles that include the vertex but lie on other surfaces (not part of the same smooth-continuous surface).
For sure, the caps on the end of a cylinder are not part of the outside or inside surfaces of the cylinder.

But that alone is not enough, however. To illustrate, consider a rather crude cylinder with only 4 rectangular sides that are divided into triangles in the common way (each rectangle is divided into two triangles by connecting the lower-left vertex on that side to the upper-right vertex. Now consider the code that computes the tangent-vector and bitangent-vector of any vertex along the bottom of the cylinder. See the problem? That vertex is part of THREE triangles --- two triangles on the face to its right, and one triangle on the face to its left. In conventional averaging schemes, the computed vectors are
influenced twice as much by the two triangles to the right of the vertex as the one triangle to the left of the vertex. The answer generated is very wrong.

But this example makes the best solution (that I found anyway) obvious too. The code must weight the influence of each triangle in proportion to the angle in the triangle at the vertex, which is easily computed with a dot product (once the triangle-side vectors are normalized, as they must be). In my tests, these two modifications of my original "off-the-top-of-my-head" routine created tangent-vectors and bitangent-vectors that look very, very nice. So nice that I modified my normal-vector computation function similarly, which cleaned up some minor-to-modest roughness on some surfaces of objects with certian shapes.

So yeah, what you say does sound very familiar!

However, you do have at least one problem remaining. If you import objects generated by other people and software, you may have a very difficult time writing code that can figure out which triangles must be excluded from the tangent/bitangent computations. This is just one of ten-trillion problems that arise when you try to adopt the work of others --- the problems never end. :-(

This topic is closed to new replies.

Advertisement