Tangent Basis of Torque 3D is.....???
by Andrew Robinson · in Artist Corner · 11/05/2013 (10:45 pm) · 11 replies
Per this thread:
http://www.garagegames.com/community/forums/viewthread/99887/
It does not seem this was ever resolved?

*

What seems to be happening is the way the tangent space is calculated in Torque 3d is its own unique way that does not correlate even close to the output of most baking software. I am speaking not about the swizzle which is correct, instead Torques tangent basis. To give an example of what I mean:
www.youtube.com/watch?v=QeP-tOKryxU
Unfortunately Handplane has no support for t3d. So, I guess what do I use to get bakes with matching support for Torque's Tangent Space? If nothing currently,is there somewhere where the tangent basis information is accessible other than deep in code? Possibly to try to bug the above developer to support Torque 3d if nothing else. Though very unlikely as I have asked before, and I can see his reasoning as to why bother with such a small audience engine.
Or maybe, just maybe, someone out there would want to take on the task of making a mod for the engine to have a 1:1 tangent basis that matched Xnormal? www.xnormal.net/Developers.aspx
*The inverted Normals Double Sided was to mimic Chris Robertsons fix. Azazel even implemented the code on his side with similar results. Unfortunately all that fixed was the diamonds.
http://www.garagegames.com/community/forums/viewthread/99887/
It does not seem this was ever resolved?

*
What seems to be happening is the way the tangent space is calculated in Torque 3d is its own unique way that does not correlate even close to the output of most baking software. I am speaking not about the swizzle which is correct, instead Torques tangent basis. To give an example of what I mean:
www.youtube.com/watch?v=QeP-tOKryxU
Unfortunately Handplane has no support for t3d. So, I guess what do I use to get bakes with matching support for Torque's Tangent Space? If nothing currently,is there somewhere where the tangent basis information is accessible other than deep in code? Possibly to try to bug the above developer to support Torque 3d if nothing else. Though very unlikely as I have asked before, and I can see his reasoning as to why bother with such a small audience engine.
Or maybe, just maybe, someone out there would want to take on the task of making a mod for the engine to have a 1:1 tangent basis that matched Xnormal? www.xnormal.net/Developers.aspx
*The inverted Normals Double Sided was to mimic Chris Robertsons fix. Azazel even implemented the code on his side with similar results. Unfortunately all that fixed was the diamonds.
#2
11/06/2013 (8:28 am)
Duion, please look at the video I provided above. Its using the source engine, but the principle is the same. This isnt a swizzle issue, its a tangent basis issue.
#3
What does this result in, practically? Do the normals get mirrored? I'm guessing that's not what you're talking about.
11/06/2013 (8:56 am)
Andrew,What does this result in, practically? Do the normals get mirrored? I'm guessing that's not what you're talking about.
#4
Azazel sent me the torque tangent basis math, and I will forward to the handplane developer. However, the most accessible way would be someone creating a xnormal plugin to bake out torque3d compliant normal maps.
11/06/2013 (7:54 pm)
Stefan, attempted to reply to you in irc. Per mirroring, actually I was having an issue, but it was a matter of hard edges/smoothing groups. I don't want to get into details and confuse this thread, but it acted inverse of everthing I know with wanting both sides of the mirror to be the same smoothing group versus having a hard edge/vertice split. That thread though showed the closest to what I am seeing otherwise with the weird shading I get with a stock xnormal map.Azazel sent me the torque tangent basis math, and I will forward to the handplane developer. However, the most accessible way would be someone creating a xnormal plugin to bake out torque3d compliant normal maps.
#5
TBN is not a ortho-transform therefore you should not cross 2 vectors to get the third one.
On the second side Autodesk use interpolation for TBN. That means when you cross or use t.w, you skip their interpolation and this results in hard seams.
I had the same problem creating an exporter and an importer for Gameloft 2 years ago using SDK 6.0. The only solution is to export the three vectors. Then change the vertex format to use the T,B and N.
In the vertex shader do not cross, but construct the space using the information from the exporter (T,B,N). For better precision move TBN to EYE space.
Hope this helps.
11/07/2013 (4:18 am)
The problem the the mirroring is because t3d is using t.w which is the cross dot of the tangent basis, that one is used to detect mirroring (well described in the book of Eric Lengyel, because dot is always right handed and dotting cross products give 1.0 or -1.0 for left or right handed systems).TBN is not a ortho-transform therefore you should not cross 2 vectors to get the third one.
On the second side Autodesk use interpolation for TBN. That means when you cross or use t.w, you skip their interpolation and this results in hard seams.
I had the same problem creating an exporter and an importer for Gameloft 2 years ago using SDK 6.0. The only solution is to export the three vectors. Then change the vertex format to use the T,B and N.
In the vertex shader do not cross, but construct the space using the information from the exporter (T,B,N). For better precision move TBN to EYE space.
Hope this helps.
#6
11/07/2013 (11:40 am)
Hrm... I had suspected it might be at least related to a handedness mismatch issue. That'd explain why //-----------------------------------------------------------------------------
// create array of tangent vectors
//-----------------------------------------------------------------------------
void TSMesh::createTangents(const Vector<Point3F> &_verts, const Vector<Point3F> &_norms)
{...
// fill out final info from accumulated basis data
for( U32 i = 0; i < numVerts; i++ )
{...
if (mDot( cp, b ) < 0.0f)
{
tangents[i].w = -1.0f;
}
else
{
tangents[i].w = 1.0f;
tangents[i].y = -tangents[i].y;
tangents[i].z = -tangents[i].z;
}
}has given us fairly close fidelity between the xNormal and in-game results (though still subtly 'off'). Happen to have any decent links laying around for the applicable concepts for further research? (I suspect as usual at this point it's been a case of asking the wrong questions.)
#7
wiki.blender.org/index.php/Dev:Shading/Tangent_Space_Normal_Maps
"The standard is used in Blender 2.57 and is also used by default in xNormal since version 3.17.5 in the form of a built-in tangent space plugin (binary and code). "
11/07/2013 (3:59 pm)
Also I heard there was better integration with Blender on the map for 4.0? If so this might be the time to change the tangent space to match. Which in fact xnormal uses as well. Here is the info.wiki.blender.org/index.php/Dev:Shading/Tangent_Space_Normal_Maps
"The standard is used in Blender 2.57 and is also used by default in xNormal since version 3.17.5 in the form of a built-in tangent space plugin (binary and code). "
#8
Guys,
this code will never work for mirrored surfaces. I hope you understand that.
and this line:
vNout = normalize( vNt.x * vT + vNt.y * vB + vNt.z * vN );
is just the tangent to world normal, a common way to transform normals, leads to bad precision. Interpolation will never fix the seam.
11/08/2013 (8:07 am)
vB = sign * cross(vN, vT);Guys,
this code will never work for mirrored surfaces. I hope you understand that.
and this line:
vNout = normalize( vNt.x * vT + vNt.y * vB + vNt.z * vN );
is just the tangent to world normal, a common way to transform normals, leads to bad precision. Interpolation will never fix the seam.
#9
I had similar issues with normal map seams and wrong shading from normal maps, tried several things, but they never matched, like with your fix, it fixed one thing, but messed up another.
I believe the issue is that when you rotate UV-islands or mirror them on the texture, the axes will no longer match in Torque, that would explain, why the normal shadowing is a little different on each part, since every UV-island is rotated in a different way.
11/08/2013 (9:47 am)
Now I see the issue, the watch in Torque3D has normal map seams and wrong shading, while the original has not.I had similar issues with normal map seams and wrong shading from normal maps, tried several things, but they never matched, like with your fix, it fixed one thing, but messed up another.
I believe the issue is that when you rotate UV-islands or mirror them on the texture, the axes will no longer match in Torque, that would explain, why the normal shadowing is a little different on each part, since every UV-island is rotated in a different way.
#10
In other words it sounds like the bake does the heavy lifting versus the shader??
Duion, what do you use to bake with? Does it have the ability to translate a object space map and a low poly to a tangent space version? Do you also work with hard edges? (The watch aboves weird shading is along its hard edge. There are no mirrors in the above images.)
All engines I know of allow the rotation of UV assets/islands as long as they are not inverted. UDK is a sticker for mirrored seams to be up/down, but the rest can be rotated. In either case Handplane allows mirrors not to follow this older rule for UDK (from what I understand) with its ability to translate the object space to tangent space specific for the engine.
Here is my workflow:
-Make a medium detail mesh from high poly and UV layout such.
-Make Cage from Medium to match High poly.
-Bake out an 32bit or 16 bit per channel object space from it with +RGB from xnormal
-Make a lower version of the medium mesh for final in game. (Keeping same UV island outlines). I.E. Just edge loop removals.
-Take this lower version and the bake from the higher version and using xnormal bake a tangent from an object space. (It corrects errors you get when you remove edgeloops from an already baked mesh).
The above may seem longer than normal but it actually saves time and allows lower tri assets as with a medium detail mesh, your cage can better follow the raycasts of the high with missing or skewing. Translating this bake then unto a lower poly version, you wont have to worry about the missed raycasts and attempting to create an exotic cage or manually paint missed rays for extremely low poly objects.
11/09/2013 (2:25 pm)
Ivan. How much precision is lost? At least from the write up, they mention " baker is designed to do the EXACT inverse of this very transformation allowing the pixel shader to remain fast and simple".In other words it sounds like the bake does the heavy lifting versus the shader??
Duion, what do you use to bake with? Does it have the ability to translate a object space map and a low poly to a tangent space version? Do you also work with hard edges? (The watch aboves weird shading is along its hard edge. There are no mirrors in the above images.)
All engines I know of allow the rotation of UV assets/islands as long as they are not inverted. UDK is a sticker for mirrored seams to be up/down, but the rest can be rotated. In either case Handplane allows mirrors not to follow this older rule for UDK (from what I understand) with its ability to translate the object space to tangent space specific for the engine.
Here is my workflow:
-Make a medium detail mesh from high poly and UV layout such.
-Make Cage from Medium to match High poly.
-Bake out an 32bit or 16 bit per channel object space from it with +RGB from xnormal
-Make a lower version of the medium mesh for final in game. (Keeping same UV island outlines). I.E. Just edge loop removals.
-Take this lower version and the bake from the higher version and using xnormal bake a tangent from an object space. (It corrects errors you get when you remove edgeloops from an already baked mesh).
The above may seem longer than normal but it actually saves time and allows lower tri assets as with a medium detail mesh, your cage can better follow the raycasts of the high with missing or skewing. Translating this bake then unto a lower poly version, you wont have to worry about the missed raycasts and attempting to create an exotic cage or manually paint missed rays for extremely low poly objects.
#11
being the culprit, and altering that to:
seems to have resolved the errors. If folks want to verify that this doesn't introduce additional errors that we're not seeing, I'll check back in a week and make a pull-request out of it.
11/10/2013 (3:44 pm)
So after a bit more digging around, I came across a sister-implementation at http://www.terathon.com/code/tangent.html . Comparative analysis pointed to:if( mFabs( denom ) < 0.0001f )
return; // handle degenerate triangles from stripsbeing the culprit, and altering that to:
if( mFabs( denom ) < 0.0001f )
if (denom<0) denom = -0.0001f;
else denom = 0.0001f;
//return; // handle degenerate triangles from stripsseems to have resolved the errors. If folks want to verify that this doesn't introduce additional errors that we're not seeing, I'll check back in a week and make a pull-request out of it.
Duion
Non-inverted normal maps look the way, that if you have a bump that looks to come out, will result in a hole in Torque.