From 66d490679f625229196538d9ba8a80e1b37d29e6 Mon Sep 17 00:00:00 2001 From: MediaMoots <81146974+MediaMoots@users.noreply.github.com> Date: Wed, 12 Jul 2023 06:04:40 +0800 Subject: [PATCH] Fix wrong UV map being used to generate tangents on TOTK (#644) * Fix wrong UV map being used to generate tangents on TOTK * use o_texture2_texcoord instead --- .../BFRES/Bfres Structs/SubFiles/FMDL.cs | 12 +++- .../BFRES/Bfres Structs/SubFiles/FMDL/FMAT.cs | 17 ++++-- .../BFRES/Bfres Structs/SubFiles/FMDL/FSHP.cs | 18 ++++-- .../FileFormats/Pokemon/GFLX/GFBMDL/GFBMDL.cs | 2 +- .../Pokemon/GFLX/GFBMDL/GFLXMesh.cs | 2 +- .../Generics/GenericObject.cs | 58 ++++++++++--------- 6 files changed, 67 insertions(+), 42 deletions(-) diff --git a/File_Format_Library/FileFormats/BFRES/Bfres Structs/SubFiles/FMDL.cs b/File_Format_Library/FileFormats/BFRES/Bfres Structs/SubFiles/FMDL.cs index 55ecbd54..e87b697d 100644 --- a/File_Format_Library/FileFormats/BFRES/Bfres Structs/SubFiles/FMDL.cs +++ b/File_Format_Library/FileFormats/BFRES/Bfres Structs/SubFiles/FMDL.cs @@ -383,7 +383,7 @@ namespace Bfres.Structs } } - bool UseUVLayer2 = false; + int UseUVIndex = 0; //for BOTW if it uses UV layer 2 for normal maps use second UV map if (shp.GetFMAT().shaderassign.options.ContainsKey("uking_texture2_texcoord")) @@ -391,10 +391,16 @@ namespace Bfres.Structs float value = float.Parse(shp.GetFMAT().shaderassign.options["uking_texture2_texcoord"]); if (value == 1) - UseUVLayer2 = true; + UseUVIndex = 1; } - shp.CalculateTangentBitangent(UseUVLayer2); + //for TOTK use o_texture2_texcoord to find required uv layer for tangents + if (shp.GetFMAT().shaderassign.options.ContainsKey("o_texture2_texcoord")) + { + UseUVIndex = int.TryParse(shp.GetFMAT().shaderassign.options["o_texture2_texcoord"], out UseUVIndex) ? UseUVIndex : 0; + } + + shp.CalculateTangentBitangent(UseUVIndex); shp.SaveVertexBuffer(GetResFileU() != null); } diff --git a/File_Format_Library/FileFormats/BFRES/Bfres Structs/SubFiles/FMDL/FMAT.cs b/File_Format_Library/FileFormats/BFRES/Bfres Structs/SubFiles/FMDL/FMAT.cs index 8ec94224..6c24c9f1 100644 --- a/File_Format_Library/FileFormats/BFRES/Bfres Structs/SubFiles/FMDL/FMAT.cs +++ b/File_Format_Library/FileFormats/BFRES/Bfres Structs/SubFiles/FMDL/FMAT.cs @@ -261,23 +261,32 @@ namespace Bfres.Structs } } - public bool IsNormalMapTexCoord2() + public int GetNormalMapUVIndex() { //for BOTW if it uses UV layer 2 for normal maps use second UV map if (shaderassign.options.ContainsKey("uking_texture2_texcoord")) { float value = float.Parse(shaderassign.options["uking_texture2_texcoord"]); - return (value == 1); + return (int)value; + } + + //for TOTK use o_texture2_texcoord to find required uv layer for tangents + if (shaderassign.options.ContainsKey("o_texture2_texcoord")) + { + return int.TryParse(shaderassign.options["o_texture2_texcoord"], out int UseUVIndex) ? UseUVIndex : 0; } //For 3D world if (shaderassign.options.ContainsKey("cIsEnableNormalMap")) { float value = float.Parse(shaderassign.options["cIsEnableNormalMap"]); - return (value == 1); + if (value == 1) + { + return 1; + } } - return false; + return 0; } public void SetActiveGame() diff --git a/File_Format_Library/FileFormats/BFRES/Bfres Structs/SubFiles/FMDL/FSHP.cs b/File_Format_Library/FileFormats/BFRES/Bfres Structs/SubFiles/FMDL/FSHP.cs index bb4e0f75..f8f882f3 100644 --- a/File_Format_Library/FileFormats/BFRES/Bfres Structs/SubFiles/FMDL/FSHP.cs +++ b/File_Format_Library/FileFormats/BFRES/Bfres Structs/SubFiles/FMDL/FSHP.cs @@ -674,14 +674,14 @@ namespace Bfres.Structs { try { - bool UseUVLayer2 = false; + int UseUVIndex = 0; //check second UV layer if (Parent != null) { - UseUVLayer2 = GetFMAT().IsNormalMapTexCoord2(); + UseUVIndex = GetFMAT().GetNormalMapUVIndex(); } - CalculateTangentBitangent(UseUVLayer2); + CalculateTangentBitangent(UseUVIndex); } catch (Exception ex) { @@ -784,7 +784,7 @@ namespace Bfres.Structs } } - bool UseUVLayer2 = false; + int UseUVIndex = 0; //for BOTW if it uses UV layer 2 for normal maps use second UV map if (GetFMAT().shaderassign.options.ContainsKey("uking_texture2_texcoord")) @@ -792,10 +792,16 @@ namespace Bfres.Structs float value = float.Parse(GetFMAT().shaderassign.options["uking_texture2_texcoord"]); if (value == 1) - UseUVLayer2 = true; + UseUVIndex = 1; } - CalculateTangentBitangent(UseUVLayer2); + //for TOTK use o_texture2_texcoord to find required uv layer for tangents + if (GetFMAT().shaderassign.options.ContainsKey("o_texture2_texcoord")) + { + UseUVIndex = int.TryParse(GetFMAT().shaderassign.options["o_texture2_texcoord"], out UseUVIndex) ? UseUVIndex : 0; + } + + CalculateTangentBitangent(UseUVIndex); SaveVertexBuffer(GetResFileU() != null); UpdateVertexData(); Cursor.Current = Cursors.Default; diff --git a/File_Format_Library/FileFormats/Pokemon/GFLX/GFBMDL/GFBMDL.cs b/File_Format_Library/FileFormats/Pokemon/GFLX/GFBMDL/GFBMDL.cs index 290d1e42..361ddde4 100644 --- a/File_Format_Library/FileFormats/Pokemon/GFLX/GFBMDL/GFBMDL.cs +++ b/File_Format_Library/FileFormats/Pokemon/GFLX/GFBMDL/GFBMDL.cs @@ -595,7 +595,7 @@ namespace FirstPlugin if (setting.HasTangents || setting.HasBitangents) { try { - mesh.CalculateTangentBitangent(false); + mesh.CalculateTangentBitangent(0); } catch { } } diff --git a/File_Format_Library/FileFormats/Pokemon/GFLX/GFBMDL/GFLXMesh.cs b/File_Format_Library/FileFormats/Pokemon/GFLX/GFBMDL/GFLXMesh.cs index 9f38cf76..36cae880 100644 --- a/File_Format_Library/FileFormats/Pokemon/GFLX/GFBMDL/GFLXMesh.cs +++ b/File_Format_Library/FileFormats/Pokemon/GFLX/GFBMDL/GFLXMesh.cs @@ -124,7 +124,7 @@ namespace FirstPlugin private void CalculateTangentBitangenAction(object sender, EventArgs args) { - this.CalculateTangentBitangent(false); + this.CalculateTangentBitangent(0); UpdateMesh(); } diff --git a/Switch_Toolbox_Library/Generics/GenericObject.cs b/Switch_Toolbox_Library/Generics/GenericObject.cs index ad4839f4..b2cc7537 100644 --- a/Switch_Toolbox_Library/Generics/GenericObject.cs +++ b/Switch_Toolbox_Library/Generics/GenericObject.cs @@ -276,7 +276,7 @@ namespace Toolbox.Library } } - public void CalculateTangentBitangent(bool UseUVLayer2) + public void CalculateTangentBitangent(int UseUVIndex) { if (vertices.Count < 3) return; @@ -286,7 +286,7 @@ namespace Toolbox.Library Vector3[] tanArray = new Vector3[vertices.Count]; Vector3[] bitanArray = new Vector3[vertices.Count]; - CalculateTanBitanArrays(f, tanArray, bitanArray, UseUVLayer2); + CalculateTanBitanArrays(f, tanArray, bitanArray, UseUVIndex); ApplyTanBitanArray(tanArray, bitanArray); } @@ -309,7 +309,7 @@ namespace Toolbox.Library } } - private void CalculateTanBitanArrays(List faces, Vector3[] tanArray, Vector3[] bitanArray, bool UseUVLayer2) + private void CalculateTanBitanArrays(List faces, Vector3[] tanArray, Vector3[] bitanArray, int UseUVIndex) { if (vertices.Count < 3 || faces.Count <= 0) return; @@ -331,22 +331,33 @@ namespace Toolbox.Library float z2 = v3.pos.Z - v1.pos.Z; float s1, s2, t1, t2; - if (UseUVLayer2) - { - s1 = v2.uv1.X - v1.uv1.X; - s2 = v3.uv1.X - v1.uv1.X; - t1 = v2.uv1.Y - v1.uv1.Y; - t2 = v3.uv1.Y - v1.uv1.Y; - } - else - { - s1 = v2.uv0.X - v1.uv0.X; - s2 = v3.uv0.X - v1.uv0.X; - t1 = v2.uv0.Y - v1.uv0.Y; - t2 = v3.uv0.Y - v1.uv0.Y; - } + List v1Uvs = new List { + v1.uv0, + v1.uv1, + v1.uv2, + v1.uv3 + }; + List v2Uvs = new List { + v2.uv0, + v2.uv1, + v2.uv2, + v2.uv3 + }; + + List v3Uvs = new List + { + v3.uv0, + v3.uv1, + v3.uv2, + v3.uv3 + }; + + s1 = v2Uvs[UseUVIndex].X - v1Uvs[UseUVIndex].X; + s2 = v3Uvs[UseUVIndex].X - v1Uvs[UseUVIndex].X; + t1 = v2Uvs[UseUVIndex].Y - v1Uvs[UseUVIndex].Y; + t2 = v3Uvs[UseUVIndex].Y - v1Uvs[UseUVIndex].Y; float div = (s1 * t2 - s2 * t1); float r = 1.0f / div; @@ -368,16 +379,9 @@ namespace Toolbox.Library // Prevents black tangents or bitangents due to having vertices with the same UV coordinates. float delta = 0.00075f; bool sameU, sameV; - if (UseUVLayer2) - { - sameU = (Math.Abs(v1.uv1.X - v2.uv1.X) < delta) && (Math.Abs(v2.uv1.X - v3.uv1.X) < delta); - sameV = (Math.Abs(v1.uv1.Y - v2.uv1.Y) < delta) && (Math.Abs(v2.uv1.Y - v3.uv1.Y) < delta); - } - else - { - sameU = (Math.Abs(v1.uv0.X - v2.uv0.X) < delta) && (Math.Abs(v2.uv0.X - v3.uv0.X) < delta); - sameV = (Math.Abs(v1.uv0.Y - v2.uv0.Y) < delta) && (Math.Abs(v2.uv0.Y - v3.uv0.Y) < delta); - } + + sameU = (Math.Abs(v1Uvs[UseUVIndex].X - v2Uvs[UseUVIndex].X) < delta) && (Math.Abs(v2Uvs[UseUVIndex].X - v3Uvs[UseUVIndex].X) < delta); + sameV = (Math.Abs(v1Uvs[UseUVIndex].Y - v2Uvs[UseUVIndex].Y) < delta) && (Math.Abs(v2Uvs[UseUVIndex].Y - v3Uvs[UseUVIndex].Y) < delta); if (sameU || sameV) {