Skip to content

Commit 88aa944

Browse files
committed
Max Vertex Buffer Handling
1 parent 16f04d8 commit 88aa944

File tree

3 files changed

+97
-22
lines changed

3 files changed

+97
-22
lines changed

xivModdingFramework/Items/Categories/Gear.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ await Task.Run(() => Parallel.ForEach(itemDictionary, (item) =>
165165

166166
primaryMi.PrimaryID = primaryQuad.Values[0];
167167
secondaryMi.PrimaryID = secondaryQuad.Values[0];
168+
168169
if (hasBodyId)
169170
{
170171
primaryMi.SecondaryID = primaryQuad.Values[1];

xivModdingFramework/Models/DataContainers/TTModel.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,7 @@ public class TTModel : ICloneable
673673
/// </summary>
674674
public ushort MdlVersion;
675675

676+
676677
/// <summary>
677678
/// The Mesh groups and parts of this mesh.
678679
/// </summary>
@@ -1239,7 +1240,10 @@ public int GetMeshGroupCount(EMeshType type)
12391240

12401241
if (!usesVcolor2)
12411242
{
1242-
if(v.VertexColor2.Any(x => x != 0))
1243+
if (v.VertexColor2[0] != 0
1244+
|| v.VertexColor2[1] != 0
1245+
|| v.VertexColor2[2] != 0
1246+
|| v.VertexColor2[3] != 255)
12431247
{
12441248
usesVcolor2 = true;
12451249
}
@@ -2579,10 +2583,6 @@ public static TTModel FromRaw(XivMdl rawMdl, Action<bool, string> loggingFunctio
25792583

25802584
ModelModifiers.FixUpSkinReferences(ttModel, rawMdl.MdlPath);
25812585

2582-
var sum = ttModel.MeshGroups.Sum(m => m.Parts.Sum(p => p.Vertices.Count + p.ShapeParts.Sum(z => z.Value.Vertices.Count)));
2583-
var indices = ttModel.MeshGroups.Sum(m => m.Parts.Sum(p => p.TriangleIndices.Count));
2584-
Trace.WriteLine("Vertex Count: " + sum);
2585-
Trace.WriteLine("Index Count: " + indices);
25862586
return ttModel;
25872587
}
25882588

xivModdingFramework/Models/FileTypes/Mdl.cs

Lines changed: 91 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2372,6 +2372,11 @@ public static async Task<byte[]> MakeUncompressedMdlFile(TTModel model, string t
23722372

23732373
}
23742374

2375+
// I do not know where in FFXIV's model pipeline this limit comes from,
2376+
// but vertex buffers larger than 2^23 will overflow and wrap around in game.
2377+
public const int _MaxVertexBufferSize = 8388608;
2378+
2379+
23752380
/// <summary>
23762381
/// Creates a new Uncompressed MDL file from the given information.
23772382
/// OGMdl is used to fill in gaps in data types we do not know about.
@@ -2383,6 +2388,7 @@ public static byte[] MakeUncompressedMdlFile(TTModel ttModel, XivMdl ogMdl, Acti
23832388
{
23842389
var mdlVersion = ttModel.MdlVersion > 0 ? ttModel.MdlVersion : ogMdl.MdlVersion;
23852390

2391+
23862392
// Debug Code
23872393
/*
23882394
var root = XivCache.GetFilePathRoot(ogMdl.MdlPath);
@@ -2410,6 +2416,31 @@ public static byte[] MakeUncompressedMdlFile(TTModel ttModel, XivMdl ogMdl, Acti
24102416
{
24112417
var usageInfo = ttModel.GetUsageInfo();
24122418

2419+
var vertexSize = 48;
2420+
if (usageInfo.NeedsEightWeights)
2421+
{
2422+
vertexSize += 8;
2423+
}
2424+
if (usageInfo.UsesUv2)
2425+
{
2426+
vertexSize += 8;
2427+
}
2428+
if (usageInfo.UsesVColor2)
2429+
{
2430+
vertexSize += 4;
2431+
}
2432+
var shapeVertCount = ttModel.MeshGroups.Sum(m => m.Parts.Sum(p => p.ShapeParts.Sum(s => s.Value.Vertices.Count)));
2433+
var totalVertexCount = shapeVertCount + ttModel.VertexCount;
2434+
var estimatedVertexBufferSize = (vertexSize * totalVertexCount);
2435+
2436+
if(estimatedVertexBufferSize >= _MaxVertexBufferSize)
2437+
{
2438+
upgradePrecision = false;
2439+
}
2440+
2441+
2442+
2443+
24132444
ttModel.OrderMeshGroupsForImport();
24142445
var rawShapeData = ttModel.GetRawShapeParts();
24152446

@@ -2491,8 +2522,7 @@ public static byte[] MakeUncompressedMdlFile(TTModel ttModel, XivMdl ogMdl, Acti
24912522
source.OrderBy(x => (x.DataBlock * -1000) + x.DataOffset);
24922523
vertexStreamCounts.Add(source.Max(x => x.DataBlock) + 1);
24932524

2494-
// If we're upgrading precision on a v6 mdl, might as well add all the bells and whistles.
2495-
if(mdlVersion >= 6 && upgradePrecision)
2525+
if(upgradePrecision)
24962526
{
24972527
// Add precomputed tangent data.
24982528
var tangentCount = source.Count(x => x.DataUsage == VertexUsageType.Tangent);
@@ -2508,23 +2538,61 @@ public static byte[] MakeUncompressedMdlFile(TTModel ttModel, XivMdl ogMdl, Acti
25082538
DataUsage = VertexUsageType.Tangent
25092539
});
25102540
}
2541+
} else
2542+
{
2543+
source.RemoveAll(x => x.DataUsage == VertexUsageType.Tangent);
2544+
}
25112545

2512-
if (usageInfo.UsesVColor2)
2546+
if (usageInfo.UsesVColor2)
2547+
{
2548+
// Add 2nd color channel for faux-wind simulation.
2549+
var colorCounts = source.Count(x => x.DataUsage == VertexUsageType.Color);
2550+
var colorIdx = source.FindIndex(x => x.DataUsage == VertexUsageType.Color);
2551+
if (colorCounts == 1)
25132552
{
2514-
// Add 2nd color channel for faux-wind simulation.
2515-
var colorCounts = source.Count(x => x.DataUsage == VertexUsageType.Color);
2516-
var colorIdx = source.FindIndex(x => x.DataUsage == VertexUsageType.Color);
2517-
if (colorCounts == 1)
2553+
source.Insert(colorIdx + 1, new VertexDataStruct()
25182554
{
2519-
source.Insert(colorIdx + 1, new VertexDataStruct()
2520-
{
2521-
DataBlock = 1,
2522-
DataOffset = 0, // Offset doesn't matter since we recalculate it anyways.
2523-
DataType = VertexDataType.Ubyte4n,
2524-
DataUsage = VertexUsageType.Color
2525-
});
2526-
}
2555+
DataBlock = 1,
2556+
DataOffset = 0, // Offset doesn't matter since we recalculate it anyways.
2557+
DataType = VertexDataType.Ubyte4n,
2558+
DataUsage = VertexUsageType.Color
2559+
});
2560+
}
2561+
} else
2562+
{
2563+
source.RemoveAll(x => x.DataUsage == VertexUsageType.Color && x.Count == 1);
2564+
}
2565+
2566+
if (ttModel.HasWeights)
2567+
{
2568+
// Ensure we have bone vertex structs if we need them.
2569+
var bone = source.FirstOrDefault(x => x.DataUsage == VertexUsageType.BoneWeight);
2570+
if (bone == null)
2571+
{
2572+
source.Add(new VertexDataStruct()
2573+
{
2574+
DataBlock = 0,
2575+
DataOffset = 0,
2576+
DataType = VertexDataType.Ubyte4,
2577+
DataUsage = VertexUsageType.BoneWeight
2578+
});
2579+
}
2580+
bone = source.FirstOrDefault(x => x.DataUsage == VertexUsageType.BoneIndex);
2581+
if (bone == null)
2582+
{
2583+
source.Add(new VertexDataStruct()
2584+
{
2585+
DataBlock = 0,
2586+
DataOffset = 0,
2587+
DataType = VertexDataType.Ubyte4,
2588+
DataUsage = VertexUsageType.BoneIndex
2589+
});
25272590
}
2591+
} else
2592+
{
2593+
// Remove bone vertex structs if they're not used.
2594+
source.RemoveAll(x => x.DataUsage == VertexUsageType.BoneWeight);
2595+
source.RemoveAll(x => x.DataUsage == VertexUsageType.BoneIndex);
25282596
}
25292597

25302598
foreach (var vds in source)
@@ -2555,7 +2623,7 @@ public static byte[] MakeUncompressedMdlFile(TTModel ttModel, XivMdl ogMdl, Acti
25552623

25562624
if (dataUsage == VertexUsageType.BoneWeight)
25572625
{
2558-
if (mdlVersion >= 6 && upgradePrecision)
2626+
if (usageInfo.NeedsEightWeights)
25592627
{
25602628
dataType = VertexDataType.UByte8;
25612629
}
@@ -2567,7 +2635,7 @@ public static byte[] MakeUncompressedMdlFile(TTModel ttModel, XivMdl ogMdl, Acti
25672635

25682636
if (dataUsage == VertexUsageType.BoneIndex)
25692637
{
2570-
if (mdlVersion >= 6 && upgradePrecision)
2638+
if (usageInfo.NeedsEightWeights)
25712639
{
25722640
dataType = VertexDataType.UByte8;
25732641
}
@@ -2711,6 +2779,12 @@ public static byte[] MakeUncompressedMdlFile(TTModel ttModel, XivMdl ogMdl, Acti
27112779

27122780
Dat.Pad(indexDataBlock, 16);
27132781
}
2782+
2783+
if (vertexDataBlock.Count > _MaxVertexBufferSize)
2784+
{
2785+
throw new InvalidDataException($"Total Vertex buffer data size is too large, even after compression attempts:\nTotal Size: {vertexDataBlock.Count}\nMax Size: {_MaxVertexBufferSize}\n\nPlease reduce the total number of Vertices in the model:\nVertices (After Unwelding): {totalVertexCount}");
2786+
}
2787+
27142788
#endregion
27152789

27162790
// Path Data

0 commit comments

Comments
 (0)