Skip to content

Commit 68a02e8

Browse files
committed
Update v2.3.4.20
2 parents 30bf12a + 304818d commit 68a02e8

File tree

2 files changed

+158
-19
lines changed

2 files changed

+158
-19
lines changed

xivModdingFramework/Items/Categories/Housing.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,7 @@ private async Task GetAdditionalAssets(HousingAssets assets)
523523
var index = new Index(_gameDirectory);
524524
var dat = new Dat(_gameDirectory);
525525

526-
foreach (var additionalAsset in assets.AdditionalAssetList)
526+
foreach (var additionalAsset in assets.AdditionalAssetList.ToList())
527527
{
528528
var assetFolder = Path.GetDirectoryName(additionalAsset).Replace("\\", "/");
529529
var assetFile = Path.GetFileName(additionalAsset);

xivModdingFramework/Models/Helpers/ModelModifiers.cs

Lines changed: 157 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1423,25 +1423,158 @@ public static void CalculateTangents(TTModel model, Action<bool, string> logging
14231423
continue;
14241424
}
14251425

1426+
1427+
// Compile lists of connected vertices.
1428+
Dictionary<int, HashSet<int>> connectedVertices = new Dictionary<int, HashSet<int>>();
1429+
for (int i = 0; i < p.TriangleIndices.Count; i+=3)
1430+
{
1431+
var t0 = p.TriangleIndices[i];
1432+
var t1 = p.TriangleIndices[i+1];
1433+
var t2 = p.TriangleIndices[i+2];
1434+
1435+
if(!connectedVertices.ContainsKey(t0))
1436+
{
1437+
connectedVertices.Add(t0, new HashSet<int>());
1438+
}
1439+
if (!connectedVertices.ContainsKey(t1))
1440+
{
1441+
connectedVertices.Add(t1, new HashSet<int>());
1442+
}
1443+
if (!connectedVertices.ContainsKey(t2))
1444+
{
1445+
connectedVertices.Add(t2, new HashSet<int>());
1446+
}
1447+
1448+
connectedVertices[t0].Add(t1);
1449+
connectedVertices[t0].Add(t2);
1450+
connectedVertices[t1].Add(t0);
1451+
connectedVertices[t1].Add(t2);
1452+
connectedVertices[t2].Add(t0);
1453+
connectedVertices[t2].Add(t1);
1454+
}
1455+
1456+
1457+
// Compute the welded vertices list and the translation table.
1458+
List<TTVertex> tempVertices = new List<TTVertex>();
1459+
1460+
// Original Vertex ID => Temp Vertex ID
1461+
Dictionary<int, int> vertTranslation = new Dictionary<int, int>();
1462+
1463+
// Welded Groups
1464+
Dictionary<int, List<int>> weldedVerts = new Dictionary<int, List<int>>();
1465+
1466+
1467+
for (int oIdx = 0; oIdx < p.Vertices.Count; oIdx++)
1468+
{
1469+
var oVertex = p.Vertices[oIdx];
1470+
var idx = -1;
1471+
for(int nIdx = 0; nIdx < tempVertices.Count; nIdx++) {
1472+
var nVertex = tempVertices[nIdx];
1473+
1474+
1475+
// The only things that matter in tangent calculation are the
1476+
// UV1, Pos, Normal
1477+
// So if the point was only split due to a UV2 or vColor difference, we want to re-weld them (unless they are a mirror-seam).
1478+
if(nVertex.Position == oVertex.Position
1479+
&& nVertex.UV1 == oVertex.UV1
1480+
&& nVertex.Normal == oVertex.Normal
1481+
&& (nVertex.UV2 != oVertex.UV2
1482+
|| nVertex.VertexColor != oVertex.VertexColor))
1483+
{
1484+
1485+
// Calculate the set of already connected vertices.
1486+
var alreadyMergedVerts = weldedVerts[nIdx];
1487+
HashSet<int> alreadyConnectedOldVerts = new HashSet<int>();
1488+
foreach(var amIdx in alreadyMergedVerts)
1489+
{
1490+
foreach(var cv in connectedVertices[amIdx])
1491+
{
1492+
alreadyConnectedOldVerts.Add(cv);
1493+
}
1494+
}
1495+
1496+
// Get my connected vertices.
1497+
var myConnectedVerts = connectedVertices[oIdx];
1498+
1499+
// If this vertex is a mirror point along a UV seam we can't merge them.
1500+
// Mirror-point check involves looking at the connected vertices of the two
1501+
// points to be welded, and investigating if any point has an identical UV, but differing position.
1502+
1503+
// Note - Under certain circumstances where you have n-poles in the model at the same point where you have
1504+
// a mirror seam and a UV2 or VColor mirror seam, it's possible this could still fail depending on the exact order
1505+
// of the indices/vertices, however, this case should be exceedingly rare, and easily fixable from a modeling standpoint.
1506+
1507+
// Further addendum - Should Tangents be calculated with the entire mesh group welded together, as that is most likely
1508+
// how SE Handles it?
1509+
1510+
bool isMirror = false;
1511+
foreach(var weldedConnection in alreadyConnectedOldVerts)
1512+
{
1513+
var wcVert = p.Vertices[weldedConnection];
1514+
foreach(var newConnection in myConnectedVerts)
1515+
{
1516+
var ncVert = p.Vertices[newConnection];
1517+
1518+
if(ncVert.UV1 == wcVert.UV1 &&
1519+
ncVert.Position != wcVert.Position)
1520+
{
1521+
isMirror = true;
1522+
break;
1523+
}
1524+
}
1525+
if (isMirror)
1526+
{
1527+
break;
1528+
}
1529+
}
1530+
1531+
if (!isMirror)
1532+
{
1533+
idx = nIdx;
1534+
break;
1535+
}
1536+
}
1537+
}
1538+
1539+
if(idx == -1)
1540+
{
1541+
tempVertices.Add(oVertex);
1542+
idx = tempVertices.Count - 1;
1543+
weldedVerts.Add(idx, new List<int>());
1544+
}
1545+
1546+
weldedVerts[idx].Add(oIdx);
1547+
vertTranslation.Add(oIdx, idx);
1548+
}
1549+
1550+
// Compute the new triangle indices using the translation table
1551+
List<int> tempIndices = new List<int>();
1552+
for(int i = 0; i < p.TriangleIndices.Count; i++)
1553+
{
1554+
var oldVert = p.TriangleIndices[i];
1555+
var newVert = vertTranslation[oldVert];
1556+
tempIndices.Add(newVert);
1557+
}
1558+
14261559
// Interim arrays for calculations
1427-
var tangents = new List<Vector3>(p.Vertices.Count);
1428-
tangents.AddRange(Enumerable.Repeat(Vector3.Zero, p.Vertices.Count));
1429-
var bitangents = new List<Vector3>(p.Vertices.Count);
1430-
bitangents.AddRange(Enumerable.Repeat(Vector3.Zero, p.Vertices.Count));
1560+
var tangents = new List<Vector3>(tempVertices.Count);
1561+
tangents.AddRange(Enumerable.Repeat(Vector3.Zero, tempVertices.Count));
1562+
var bitangents = new List<Vector3>(tempVertices.Count);
1563+
bitangents.AddRange(Enumerable.Repeat(Vector3.Zero, tempVertices.Count));
14311564

14321565
// Calculate Tangent, Bitangent/Binormal and Handedness.
14331566

14341567
// This loops for each TRI, building up the sum
14351568
// tangent/bitangent angles at each VERTEX.
1436-
for (var a = 0; a < p.TriangleIndices.Count; a += 3)
1569+
for (var a = 0; a < tempIndices.Count; a += 3)
14371570
{
1438-
var vertexId1 = p.TriangleIndices[a];
1439-
var vertexId2 = p.TriangleIndices[a + 1];
1440-
var vertexId3 = p.TriangleIndices[a + 2];
1571+
var vertexId1 = tempIndices[a];
1572+
var vertexId2 = tempIndices[a + 1];
1573+
var vertexId3 = tempIndices[a + 2];
14411574

1442-
var vertex1 = p.Vertices[vertexId1];
1443-
var vertex2 = p.Vertices[vertexId2];
1444-
var vertex3 = p.Vertices[vertexId3];
1575+
var vertex1 = tempVertices[vertexId1];
1576+
var vertex2 = tempVertices[vertexId2];
1577+
var vertex3 = tempVertices[vertexId3];
14451578

14461579
var deltaX1 = vertex2.Position.X - vertex1.Position.X;
14471580
var deltaX2 = vertex3.Position.X - vertex1.Position.X;
@@ -1472,15 +1605,17 @@ public static void CalculateTangents(TTModel model, Action<bool, string> logging
14721605
}
14731606

14741607
// Loop the VERTEXES now to calculate the end tangent/bitangents based on the summed data for each VERTEX
1475-
for (var vertexId = 0; vertexId < p.Vertices.Count; ++vertexId)
1608+
for (var vertexId = 0; vertexId < tempVertices.Count; ++vertexId)
14761609
{
14771610
// Reference: https://marti.works/posts/post-calculating-tangents-for-your-mesh/post/
14781611
// We were already doing these calculations to establish handedness, but we weren't actually
14791612
// using the other results before. Better to kill the previous computations and use these numbers
14801613
// for everything to avoid minor differences causing errors.
14811614

14821615
//var posIdx = vDict[a];
1483-
var vertex = p.Vertices[vertexId];
1616+
var vertex = tempVertices[vertexId];
1617+
//List<TTVertex> oVertices = new List<TTVertex>();
1618+
var oVertices = vertTranslation.Where(x => x.Value == vertexId).Select(x => x.Key).ToList();
14841619

14851620
var n = vertex.Normal;
14861621

@@ -1500,13 +1635,17 @@ public static void CalculateTangents(TTModel model, Action<bool, string> logging
15001635

15011636
// Apply handedness
15021637
binormal *= handedness;
1638+
// FFXIV actually tracks BINORMAL handedness, not TANGENT handeness, so we have to reverse this.
1639+
var boolHandedness = !(handedness < 0 ? true : false);
15031640

1504-
vertex.Tangent = tangent;
1505-
vertex.Binormal = binormal;
1506-
vertex.Handedness = handedness < 0 ? true : false;
1641+
foreach (var vIdx in oVertices)
1642+
{
1643+
var v = p.Vertices[vIdx];
1644+
v.Tangent = tangent;
1645+
v.Binormal = binormal;
1646+
v.Handedness = boolHandedness;
1647+
}
15071648

1508-
// FFXIV actually tracks BINORMAL handedness, not TANGENT handeness, so we have to reverse this.
1509-
vertex.Handedness = !vertex.Handedness;
15101649
}
15111650
}
15121651
}

0 commit comments

Comments
 (0)