|
6 | 6 | using System.Linq; |
7 | 7 | using Newtonsoft.Json.Linq; |
8 | 8 | using System.Globalization; |
| 9 | +using Utilities; |
9 | 10 |
|
10 | 11 | namespace Max2Babylon |
11 | 12 | { |
@@ -1097,12 +1098,16 @@ int CreateGlobalVertex(IIGameMesh mesh, BabylonAbstractMesh babylonAbstractMesh, |
1097 | 1098 | // tangent |
1098 | 1099 | if (exportParameters.exportTangents) |
1099 | 1100 | { |
1100 | | - int indexTangentBinormal = mesh.GetFaceVertexTangentBinormal(face.MeshFaceIndex, facePart, 1); |
1101 | | - IPoint3 normal = vertex.Normal.Normalize; |
1102 | | - IPoint3 tangent = mesh.GetTangent(indexTangentBinormal, 1).Normalize; |
1103 | | - IPoint3 bitangent = mesh.GetBinormal(indexTangentBinormal, 1).Normalize; |
1104 | | - int w = GetW(normal, tangent, bitangent); |
1105 | | - vertex.Tangent = new float[] { tangent.X, tangent.Y, tangent.Z, w }; |
| 1101 | + int mapChannel = 1; // Texture Coordinates |
| 1102 | + if (mesh.GetNumberOfTangents(mapChannel) != 0) |
| 1103 | + { |
| 1104 | + int indexTangentBinormal = mesh.GetFaceVertexTangentBinormal(face.MeshFaceIndex, facePart, mapChannel); |
| 1105 | + IPoint3 normal = vertex.Normal.Normalize; |
| 1106 | + IPoint3 tangent = mesh.GetTangent(indexTangentBinormal, mapChannel).Normalize; |
| 1107 | + IPoint3 bitangent = mesh.GetBinormal(indexTangentBinormal, mapChannel).Normalize; |
| 1108 | + float w = GetW(normal, tangent, bitangent); |
| 1109 | + vertex.Tangent = new float[] { tangent.X, tangent.Y, tangent.Z, w }; |
| 1110 | + } |
1106 | 1111 | } |
1107 | 1112 |
|
1108 | 1113 | if (hasUV) |
@@ -1336,33 +1341,45 @@ public void GenerateCoordinatesAnimations(IIGameNode meshNode, List<BabylonAnima |
1336 | 1341 | } |
1337 | 1342 |
|
1338 | 1343 | /// <summary> |
1339 | | - /// get the w of the tangent |
| 1344 | + /// get the w of the UV tangent |
1340 | 1345 | /// </summary> |
1341 | 1346 | /// <param name="normal"></param> |
1342 | 1347 | /// <param name="tangent"></param> |
1343 | 1348 | /// <param name="bitangent"></param> |
1344 | 1349 | /// <returns> |
1345 | | - /// -1 when the normal is not flipped |
1346 | | - /// 1 when the normal is flipped |
| 1350 | + /// 1 when the bitangent is nearly 0,0,0 or is not flipped |
| 1351 | + /// -1 when the bitangent is flipped (oposite direction of the cross product of normal ^ tangent) |
1347 | 1352 | /// </returns> |
1348 | | - private int GetW(IPoint3 normal, IPoint3 tangent, IPoint3 bitangent) |
| 1353 | + private float GetW(IPoint3 normal, IPoint3 tangent, IPoint3 bitangent) |
1349 | 1354 | { |
1350 | | - //Cross product bitangent = w * normal ^ tangent |
1351 | | - float x = normal.Y * tangent.Z - normal.Z * tangent.Y; |
1352 | | - float y = normal.Z * tangent.X - normal.X * tangent.Z; |
1353 | | - float z = normal.X * tangent.Y - normal.Y * tangent.X; |
| 1355 | + float btx = MathUtilities.RoundToIfAlmostEqualTo(bitangent.X, 0, Tools.Epsilon); |
| 1356 | + float bty = MathUtilities.RoundToIfAlmostEqualTo(bitangent.Y, 0, Tools.Epsilon); |
| 1357 | + float btz = MathUtilities.RoundToIfAlmostEqualTo(bitangent.Z, 0, Tools.Epsilon); |
1354 | 1358 |
|
1355 | | - int w = Math.Sign(bitangent.X * x); |
1356 | | - if (w == 0) |
| 1359 | + if( btx == 0 && bty == 0 && btz == 0) |
1357 | 1360 | { |
1358 | | - w = Math.Sign(bitangent.Y * y); |
| 1361 | + return 1; |
1359 | 1362 | } |
1360 | | - if (w == 0) |
1361 | | - { |
1362 | | - w = Math.Sign(bitangent.Z * z); |
1363 | | - } |
1364 | | - |
1365 | | - return w; |
| 1363 | + |
| 1364 | + float nx = MathUtilities.RoundToIfAlmostEqualTo(normal.X, 0, Tools.Epsilon); |
| 1365 | + float ny = MathUtilities.RoundToIfAlmostEqualTo(normal.Y, 0, Tools.Epsilon); |
| 1366 | + float nz = MathUtilities.RoundToIfAlmostEqualTo(normal.Z, 0, Tools.Epsilon); |
| 1367 | + |
| 1368 | + float tx = MathUtilities.RoundToIfAlmostEqualTo(tangent.X, 0, Tools.Epsilon); |
| 1369 | + float ty = MathUtilities.RoundToIfAlmostEqualTo(tangent.Y, 0, Tools.Epsilon); |
| 1370 | + float tz = MathUtilities.RoundToIfAlmostEqualTo(tangent.Z, 0, Tools.Epsilon); |
| 1371 | + |
| 1372 | + // Cross product bitangent = w * normal ^ tangent |
| 1373 | + |
| 1374 | + // theorical bittangent |
| 1375 | + MathUtilities.CrossProduct(nx, ny, nz, tx, ty, tz, out float x, out float y, out float z); |
| 1376 | + |
| 1377 | + // Speaking in broadest terms, if the dot product of two non-zero vectors is positive, |
| 1378 | + // then the two vectors point in the same general direction, meaning less than 90 degrees. |
| 1379 | + // If the dot product is negative, then the two vectors point in opposite directions, |
| 1380 | + // or above 90 and less than or equal to 180 degrees. |
| 1381 | + var dot = MathUtilities.DotProduct(btx, bty,btz, x,y,z); |
| 1382 | + return dot < 0 ? -1 : 1; |
1366 | 1383 | } |
1367 | 1384 |
|
1368 | 1385 | } |
|
0 commit comments