Skip to content

Commit 3df03db

Browse files
committed
Update v3.0.6.1
2 parents bbd213b + 88aa944 commit 3df03db

File tree

7 files changed

+237
-63
lines changed

7 files changed

+237
-63
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: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System;
88
using System.Collections.Generic;
99
using System.Data.SQLite;
10+
using System.Diagnostics;
1011
using System.IO;
1112
using System.Linq;
1213
using System.Text.RegularExpressions;
@@ -672,6 +673,7 @@ public class TTModel : ICloneable
672673
/// </summary>
673674
public ushort MdlVersion;
674675

676+
675677
/// <summary>
676678
/// The Mesh groups and parts of this mesh.
677679
/// </summary>
@@ -1201,6 +1203,59 @@ public int GetMeshGroupCount(EMeshType type)
12011203
return MeshGroups.Count(x => x.MeshType == type);
12021204
}
12031205

1206+
public (bool UsesVColor2, bool UsesUv2, bool NeedsEightWeights) GetUsageInfo()
1207+
{
1208+
bool usesVcolor2 = false;
1209+
bool usesUv2 = false;
1210+
bool needs8Weight = false;
1211+
1212+
foreach (var m in MeshGroups)
1213+
{
1214+
foreach(var p in m.Parts)
1215+
{
1216+
foreach(var v in p.Vertices)
1217+
{
1218+
if (!needs8Weight)
1219+
{
1220+
if(v.Weights.Length > 4)
1221+
{
1222+
for(int i = 4; i < v.Weights.Length; i++)
1223+
{
1224+
if (v.Weights[i] > 0 || v.BoneIds[i] > 0)
1225+
{
1226+
needs8Weight = true;
1227+
break;
1228+
}
1229+
}
1230+
}
1231+
}
1232+
1233+
if (!usesUv2)
1234+
{
1235+
if (v.UV2 != Vector2.Zero)
1236+
{
1237+
usesUv2 = true;
1238+
}
1239+
}
1240+
1241+
if (!usesVcolor2)
1242+
{
1243+
if (v.VertexColor2[0] != 0
1244+
|| v.VertexColor2[1] != 0
1245+
|| v.VertexColor2[2] != 0
1246+
|| v.VertexColor2[3] != 255)
1247+
{
1248+
usesVcolor2 = true;
1249+
}
1250+
}
1251+
1252+
}
1253+
}
1254+
}
1255+
1256+
return (usesVcolor2, usesUv2, needs8Weight);
1257+
}
1258+
12041259
/// <summary>
12051260
/// Creates a bone set from the model and group information.
12061261
/// </summary>
@@ -1311,6 +1366,10 @@ public static TTModel LoadFromFile(string filePath, Action<bool, string> logging
13111366
{
13121367
loggingFunction = ModelModifiers.NoOp;
13131368
}
1369+
if(settings == null)
1370+
{
1371+
settings = new ModelImportOptions();
1372+
}
13141373

13151374
var connectionString = "Data Source=" + filePath + ";Pooling=True;";
13161375
TTModel model = new TTModel();

xivModdingFramework/Models/FileTypes/Mdl.cs

Lines changed: 99 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2042,9 +2042,9 @@ public static async Task<TTModel> LoadExternalModel(string externalPath, ModelIm
20422042
/// <param name="ogMdl"></param>
20432043
/// <param name="loggingFunction"></param>
20442044
/// <returns></returns>
2045-
public static async Task<byte[]> MakeCompressedMdlFile(TTModel ttModel, XivMdl ogMdl, Action<bool, string> loggingFunction = null)
2045+
public static async Task<byte[]> MakeCompressedMdlFile(TTModel ttModel, XivMdl ogMdl, Action<bool, string> loggingFunction = null, bool upgradePrecision = true)
20462046
{
2047-
var mdl = MakeUncompressedMdlFile(ttModel, ogMdl, loggingFunction);
2047+
var mdl = MakeUncompressedMdlFile(ttModel, ogMdl, loggingFunction, upgradePrecision);
20482048
var compressed = await CompressMdlFile(mdl);
20492049
return compressed;
20502050
}
@@ -2371,17 +2371,24 @@ public static async Task<byte[]> MakeUncompressedMdlFile(TTModel model, string t
23712371
return MakeUncompressedMdlFile(model, xivMdl, loggingFunction);
23722372

23732373
}
2374+
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+
23742380
/// <summary>
23752381
/// Creates a new Uncompressed MDL file from the given information.
23762382
/// OGMdl is used to fill in gaps in data types we do not know about.
23772383
/// TODO: It should be possible at this point to adjust this function to accomodate [null] ogMDLs.
23782384
/// </summary>
23792385
/// <param name="ttModel">The ttModel to import</param>
23802386
/// <param name="ogMdl">The currently modified Mdl file.</param>
2381-
public static byte[] MakeUncompressedMdlFile(TTModel ttModel, XivMdl ogMdl, Action<bool, string> loggingFunction = null)
2387+
public static byte[] MakeUncompressedMdlFile(TTModel ttModel, XivMdl ogMdl, Action<bool, string> loggingFunction = null, bool upgradePrecision = true)
23822388
{
23832389
var mdlVersion = ttModel.MdlVersion > 0 ? ttModel.MdlVersion : ogMdl.MdlVersion;
23842390

2391+
23852392
// Debug Code
23862393
/*
23872394
var root = XivCache.GetFilePathRoot(ogMdl.MdlPath);
@@ -2393,10 +2400,6 @@ public static byte[] MakeUncompressedMdlFile(TTModel ttModel, XivMdl ogMdl, Acti
23932400

23942401
byte _LoDCount = 1;
23952402

2396-
// Pipe some user var down here and we could ship this toggle.
2397-
// Not really much reason to ever use lower precision other than file size/perf though.
2398-
bool _UpgradePrecision = true;
2399-
24002403
// Distance used for model LoD settings. 0 is infinite.
24012404
float _ModelLoDDistance = 0.0f;
24022405

@@ -2411,6 +2414,33 @@ public static byte[] MakeUncompressedMdlFile(TTModel ttModel, XivMdl ogMdl, Acti
24112414

24122415
try
24132416
{
2417+
var usageInfo = ttModel.GetUsageInfo();
2418+
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+
24142444
ttModel.OrderMeshGroupsForImport();
24152445
var rawShapeData = ttModel.GetRawShapeParts();
24162446

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

2495-
// If we're upgrading precision on a v6 mdl, might as well add all the bells and whistles.
2496-
if(mdlVersion >= 6 && _UpgradePrecision)
2525+
if(upgradePrecision)
24972526
{
24982527
// Add precomputed tangent data.
24992528
var tangentCount = source.Count(x => x.DataUsage == VertexUsageType.Tangent);
@@ -2508,9 +2537,14 @@ public static byte[] MakeUncompressedMdlFile(TTModel ttModel, XivMdl ogMdl, Acti
25082537
DataType = VertexDataType.Ubyte4n,
25092538
DataUsage = VertexUsageType.Tangent
25102539
});
2511-
25122540
}
2513-
2541+
} else
2542+
{
2543+
source.RemoveAll(x => x.DataUsage == VertexUsageType.Tangent);
2544+
}
2545+
2546+
if (usageInfo.UsesVColor2)
2547+
{
25142548
// Add 2nd color channel for faux-wind simulation.
25152549
var colorCounts = source.Count(x => x.DataUsage == VertexUsageType.Color);
25162550
var colorIdx = source.FindIndex(x => x.DataUsage == VertexUsageType.Color);
@@ -2524,6 +2558,41 @@ public static byte[] MakeUncompressedMdlFile(TTModel ttModel, XivMdl ogMdl, Acti
25242558
DataUsage = VertexUsageType.Color
25252559
});
25262560
}
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+
});
2590+
}
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);
25272596
}
25282597

25292598
foreach (var vds in source)
@@ -2542,7 +2611,7 @@ public static byte[] MakeUncompressedMdlFile(TTModel ttModel, XivMdl ogMdl, Acti
25422611
// Perform precision updates if requested, and adjustments for MDL version.
25432612
if (dataUsage == VertexUsageType.Position)
25442613
{
2545-
if (_UpgradePrecision)
2614+
if (upgradePrecision)
25462615
{
25472616
dataType = VertexDataType.Float3;
25482617
}
@@ -2554,7 +2623,7 @@ public static byte[] MakeUncompressedMdlFile(TTModel ttModel, XivMdl ogMdl, Acti
25542623

25552624
if (dataUsage == VertexUsageType.BoneWeight)
25562625
{
2557-
if (mdlVersion >= 6 && _UpgradePrecision)
2626+
if (usageInfo.NeedsEightWeights)
25582627
{
25592628
dataType = VertexDataType.UByte8;
25602629
}
@@ -2566,7 +2635,7 @@ public static byte[] MakeUncompressedMdlFile(TTModel ttModel, XivMdl ogMdl, Acti
25662635

25672636
if (dataUsage == VertexUsageType.BoneIndex)
25682637
{
2569-
if (mdlVersion >= 6 && _UpgradePrecision)
2638+
if (usageInfo.NeedsEightWeights)
25702639
{
25712640
dataType = VertexDataType.UByte8;
25722641
}
@@ -2578,7 +2647,7 @@ public static byte[] MakeUncompressedMdlFile(TTModel ttModel, XivMdl ogMdl, Acti
25782647

25792648
if (dataUsage == VertexUsageType.Normal)
25802649
{
2581-
if (_UpgradePrecision)
2650+
if (upgradePrecision)
25822651
{
25832652
dataType = VertexDataType.Float3;
25842653
}
@@ -2590,26 +2659,25 @@ public static byte[] MakeUncompressedMdlFile(TTModel ttModel, XivMdl ogMdl, Acti
25902659

25912660
if (dataUsage == VertexUsageType.TextureCoordinate)
25922661
{
2593-
if (_UpgradePrecision)
2662+
if (upgradePrecision)
25942663
{
2595-
if (dataType == VertexDataType.Half2)
2664+
if (usageInfo.UsesUv2)
25962665
{
2597-
dataType = VertexDataType.Float2;
2666+
dataType = VertexDataType.Float4;
25982667
}
2599-
else if (dataType == VertexDataType.Half4)
2668+
else
26002669
{
2601-
dataType = VertexDataType.Float4;
2670+
dataType = VertexDataType.Float2;
26022671
}
26032672
}
26042673
else
26052674
{
2606-
if (dataType == VertexDataType.Float2)
2607-
{
2608-
dataType = VertexDataType.Half2;
2609-
}
2610-
else if (dataType == VertexDataType.Float4)
2675+
if (usageInfo.UsesUv2)
26112676
{
26122677
dataType = VertexDataType.Half4;
2678+
} else
2679+
{
2680+
dataType = VertexDataType.Half2;
26132681
}
26142682
}
26152683
}
@@ -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)