Skip to content

Commit 3067abd

Browse files
committed
Cleaning up tangent math.
1 parent 4ffda56 commit 3067abd

File tree

1 file changed

+112
-14
lines changed

1 file changed

+112
-14
lines changed

xivModdingFramework/Models/Helpers/ModelModifiers.cs

Lines changed: 112 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1746,6 +1746,9 @@ public static async Task CalculateTangents(TTModel model, Action<bool, string> l
17461746
}
17471747
if (model == null) return;
17481748

1749+
// DEBUG ASDF
1750+
forceRecalculation = true;
1751+
17491752

17501753
var anyMissingData = AnyMissingTangentData(model);
17511754
if (!anyMissingData && !forceRecalculation)
@@ -1822,7 +1825,7 @@ private static bool AnyMissingTangentData(TTModel model)
18221825
return false;
18231826
}
18241827

1825-
private static (List<int> Indices, Dictionary<int, List<TTVertex>> VertexTable) GetWeldedMeshData(TTMeshGroup m)
1828+
private static (List<int> Indices, List<List<TTVertex>> VertexTable) GetWeldedMeshData(TTMeshGroup m, bool weldMirrors = false)
18261829
{
18271830
List<int> indices = new List<int>(m.Parts.Sum(x => x.TriangleIndices.Count));
18281831
List<TTVertex> vertices = new List<TTVertex>(m.Parts.Sum(x => x.Vertices.Count));
@@ -1839,10 +1842,49 @@ private static (List<int> Indices, Dictionary<int, List<TTVertex>> VertexTable)
18391842
vertices.AddRange(p.Vertices);
18401843
}
18411844

1845+
// Compile lists of connected vertices.
1846+
Dictionary<int, HashSet<int>> connectedVertices = new Dictionary<int, HashSet<int>>();
1847+
if (!weldMirrors)
1848+
{
1849+
for (int i = 0; i < indices.Count; i += 3)
1850+
{
1851+
var v0 = indices[i];
1852+
var v1 = indices[i + 1];
1853+
var v2 = indices[i + 2];
1854+
1855+
if (!connectedVertices.ContainsKey(v0))
1856+
{
1857+
connectedVertices.Add(v0, new HashSet<int>());
1858+
}
1859+
if (!connectedVertices.ContainsKey(v1))
1860+
{
1861+
connectedVertices.Add(v1, new HashSet<int>());
1862+
}
1863+
if (!connectedVertices.ContainsKey(v2))
1864+
{
1865+
connectedVertices.Add(v2, new HashSet<int>());
1866+
}
1867+
1868+
connectedVertices[v0].Add(v1);
1869+
connectedVertices[v0].Add(v2);
1870+
connectedVertices[v1].Add(v0);
1871+
connectedVertices[v1].Add(v2);
1872+
connectedVertices[v2].Add(v0);
1873+
connectedVertices[v2].Add(v1);
1874+
}
1875+
}
1876+
1877+
// Weld Hash => List of original Vertex Ids
18421878
Dictionary<int, List<int>> weldHashes = new Dictionary<int, List<int>>();
1879+
1880+
// Original Vertex Id => New (Welded) Vertex Id
18431881
Dictionary<int, int> oldToNewVertex = new Dictionary<int, int>();
1844-
List<TTVertex> newVertices = new List<TTVertex>(vertices.Count);
1845-
var vertexTable = new Dictionary<int, List<TTVertex>>();
1882+
1883+
// New Vertex Id => List of Vertex IDs welded into it.
1884+
var vertexIdTable = new List<List<int>>();
1885+
1886+
// New Vertex Id => List of Vertex Classes welded into it.
1887+
var vertexTable = new List<List<TTVertex>>();
18461888

18471889
// Perform vertex welding.
18481890
for (int i = 0; i < vertices.Count; i++)
@@ -1853,29 +1895,80 @@ private static (List<int> Indices, Dictionary<int, List<TTVertex>> VertexTable)
18531895
if (weldHashes.ContainsKey(hash))
18541896
{
18551897
var entries = weldHashes[hash];
1856-
for (var ni = 0; ni < entries.Count; ni++)
1898+
for (var ti = 0; ti < entries.Count; ti++)
18571899
{
1858-
var nv = vertices[entries[ni]];
1900+
var oi = entries[ti];
1901+
var ni = oldToNewVertex[oi];
1902+
var nv = vertices[oi];
18591903

18601904
if (nv.UV1 == ov.UV1
18611905
&& nv.Position == ov.Position
18621906
&& nv.Normal == ov.Normal)
18631907
{
1864-
oldToNewVertex.Add(i, ni);
1865-
vertexTable[ni].Add(ov);
1866-
found = true;
1867-
break;
1908+
bool isMirror = false;
1909+
if (!weldMirrors)
1910+
{
1911+
var alreadyConnectedVertices = new HashSet<int>();
1912+
foreach (var vi in vertexIdTable[ni])
1913+
{
1914+
alreadyConnectedVertices.UnionWith(connectedVertices[vi]);
1915+
}
1916+
1917+
// We need to determine if we are a weld point.
1918+
// Get my connected vertices.
1919+
var myConnectedVerts = connectedVertices[i];
1920+
1921+
// If this vertex is a mirror point along a UV seam we can't merge them.
1922+
// Mirror-point check involves looking at the connected vertices of the two
1923+
// points to be welded, and investigating if any point has an identical UV, but differing position.
1924+
1925+
// Note - Under certain circumstances where you have n-poles in the model at the same point where you have
1926+
// a mirror seam and a UV2 or VColor mirror seam, it's possible this could still fail depending on the exact order
1927+
// of the indices/vertices, however, this case should be exceedingly rare, and easily fixable from a modeling standpoint.
1928+
1929+
foreach (var weldedConnection in alreadyConnectedVertices)
1930+
{
1931+
var wcVert = vertices[weldedConnection];
1932+
foreach (var newConnection in myConnectedVerts)
1933+
{
1934+
var ncVert = vertices[newConnection];
1935+
1936+
if (ncVert.UV1 == wcVert.UV1 &&
1937+
ncVert.Position != wcVert.Position)
1938+
{
1939+
isMirror = true;
1940+
break;
1941+
}
1942+
}
1943+
if (isMirror)
1944+
{
1945+
break;
1946+
}
1947+
}
1948+
}
1949+
1950+
if (!isMirror)
1951+
{
1952+
oldToNewVertex.Add(i, ni);
1953+
vertexTable[ni].Add(ov);
1954+
vertexIdTable[ni].Add(i);
1955+
found = true;
1956+
break;
1957+
}
18681958
}
18691959
}
18701960
}
18711961

18721962
if (!found)
18731963
{
1874-
var ni = newVertices.Count;
1964+
var ni = vertexTable.Count;
1965+
vertexTable.Add(new List<TTVertex>());
1966+
vertexIdTable.Add(new List<int>());
1967+
18751968
oldToNewVertex.Add(i, ni);
1876-
vertexTable.Add(ni, new List<TTVertex>());
18771969
vertexTable[ni].Add(ov);
1878-
newVertices.Add(ov);
1970+
vertexIdTable[ni].Add(i);
1971+
18791972
if (weldHashes.ContainsKey(hash))
18801973
{
18811974
weldHashes[hash].Add(i);
@@ -1997,7 +2090,7 @@ private static void CalculateTangentsForMesh(TTMeshGroup m, bool force = false)
19972090
bitangents[vertexId1] += tdir;
19982091
bitangents[vertexId2] += tdir;
19992092
bitangents[vertexId3] += tdir;
2000-
}
2093+
}
20012094

20022095

20032096

@@ -2020,14 +2113,19 @@ private static void CalculateTangentsForMesh(TTMeshGroup m, bool force = false)
20202113
var binormal = Vector3.Cross(n, Vector3.Normalize(t)).Normalized();
20212114
var tangent = Vector3.Cross(n, binormal).Normalized();
20222115

2116+
20232117
// Compute handedness
20242118
int bHandedness = Vector3.Dot(Vector3.Normalize(binormal), b) >= 0 ? 1 : -1;
20252119

20262120
// Apply handedness
2027-
binormal *= bHandedness;
20282121

20292122
var boolHandedness = !(bHandedness < 0 ? true : false);
20302123

2124+
binormal *= bHandedness;
2125+
tangent *= -1;
2126+
2127+
var verts = vertices[vertexId];
2128+
20312129
// Assign results.
20322130
foreach (var v in vertices[vertexId])
20332131
{

0 commit comments

Comments
 (0)