Skip to content

Commit 0056a71

Browse files
authored
Merge pull request #79 from senko-forks/pr-zoomies
Speed up model loading (Zoomies)
2 parents 1090b81 + 213b76b commit 0056a71

File tree

3 files changed

+25
-42
lines changed

3 files changed

+25
-42
lines changed

xivModdingFramework/Models/FileTypes/Mdl.cs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,6 @@ public static async Task<XivMdl> GetXivMdl(string mdlPath, bool getOriginal = fa
348348

349349
public static XivMdl GetXivMdl(byte[] mdlData, string mdlPath = "")
350350
{
351-
352351
var xivMdl = new XivMdl { MdlPath = mdlPath };
353352
int totalNonNullMaterials = 0;
354353
var getShapeData = true;
@@ -1019,7 +1018,7 @@ public static XivMdl GetXivMdl(byte[] mdlData, string mdlPath = "")
10191018
}
10201019

10211020

1022-
var lodNum = 0;
1021+
var lodNum = 0;
10231022
var totalMeshNum = 0;
10241023
foreach (var lod in xivMdl.LoDList)
10251024
{
@@ -1031,16 +1030,12 @@ public static XivMdl GetXivMdl(byte[] mdlData, string mdlPath = "")
10311030
{
10321031
throw new Exception("Failed to parse some meshes in previous LoD level.");
10331032
}
1034-
1035-
// Seek to the start of the LoD.
1036-
br.BaseStream.Seek(lod.VertexDataOffset, SeekOrigin.Begin);
1037-
var LoDStart = br.BaseStream.Position;
10381033

10391034
var mIdx = 0;
10401035

10411036
foreach (var meshData in meshDataList)
10421037
{
1043-
MdlVertexReader.ReadVertexData(br, meshData, lod.VertexDataOffset, lod.IndexDataOffset);
1038+
MdlVertexReader.ReadVertexData(mdlData, meshData, lod.VertexDataOffset, lod.IndexDataOffset);
10441039

10451040
mIdx++;
10461041
totalMeshNum++;

xivModdingFramework/Models/FileTypes/MdlVertexReader.cs

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ namespace xivModdingFramework.Models.FileTypes
1313
{
1414
internal static class MdlVertexReader
1515
{
16-
public static void ReadVertexData(BinaryReader br, MeshData meshData, int lodVertexOffset, int lodIndexOffset)
16+
public static void ReadVertexData(byte[] mdlData, MeshData meshData, int lodVertexOffset, int lodIndexOffset)
1717
{
1818
var vertexData = new VertexData();
1919

@@ -24,45 +24,37 @@ public static void ReadVertexData(BinaryReader br, MeshData meshData, int lodVer
2424
var block1Offset = meshData.MeshInfo.VertexDataOffset1 + lodVertexOffset;
2525
var indexOffset = (meshData.MeshInfo.IndexDataOffset * 2) + lodIndexOffset;
2626

27-
br.BaseStream.Seek(block0Offset, SeekOrigin.Begin);
28-
var block0Sorted = info.Where(x => x.DataBlock == 0).OrderBy(x => x.DataOffset);
29-
for(int i = 0; i < vertexCount; i++)
27+
var block0Sorted = info.Where(x => x.DataBlock == 0).OrderBy(x => x.DataOffset).ToList();
28+
var block1Sorted = info.Where(x => x.DataBlock == 1).OrderBy(x => x.DataOffset).ToList();
29+
30+
var block0Reader = new BinaryReader(new MemoryStream(mdlData, block0Offset, vertexCount * meshData.MeshInfo.VertexDataEntrySize0));
31+
for (int i = 0; i < vertexCount; i++)
3032
{
31-
foreach(var entry in block0Sorted)
33+
foreach (var entry in block0Sorted)
3234
{
33-
ReadData(vertexData, br, entry.DataUsage, entry.DataType, entry.Count);
35+
ReadData(vertexData, block0Reader, entry.DataUsage, entry.DataType, entry.Count);
3436
}
3537
}
3638

37-
if(br.BaseStream.Position != block0Offset + (vertexCount * meshData.MeshInfo.VertexDataEntrySize0))
38-
{
39+
if (block0Reader.BaseStream.Position != block0Reader.BaseStream.Length)
3940
throw new InvalidDataException("Vertex Data Size Mismatch. Some part(s) of the vertex data in stream 0 were not read properly.");
40-
}
4141

42-
br.BaseStream.Seek(block1Offset, SeekOrigin.Begin);
43-
var block1Sorted = info.Where(x => x.DataBlock == 1).OrderBy(x => x.DataOffset);
42+
var block1Reader = new BinaryReader(new MemoryStream(mdlData, block1Offset, vertexCount * meshData.MeshInfo.VertexDataEntrySize1));
4443
for (int i = 0; i < vertexCount; i++)
4544
{
4645
foreach (var entry in block1Sorted)
4746
{
48-
ReadData(vertexData, br, entry.DataUsage, entry.DataType, entry.Count);
47+
ReadData(vertexData, block1Reader, entry.DataUsage, entry.DataType, entry.Count);
4948
}
5049
}
5150

52-
if (br.BaseStream.Position != block1Offset + (vertexCount * meshData.MeshInfo.VertexDataEntrySize1))
53-
{
51+
if (block1Reader.BaseStream.Position != block1Reader.BaseStream.Length)
5452
throw new InvalidDataException("Vertex Data Size Mismatch. Some part(s) of the vertex data in stream 1 were not read properly.");
55-
}
5653

57-
br.BaseStream.Seek(indexOffset, SeekOrigin.Begin);
54+
var indexReader = new BinaryReader(new MemoryStream(mdlData, indexOffset, indexCount * 2));
5855
for (var i = 0; i < indexCount; i++)
5956
{
60-
vertexData.Indices.Add(br.ReadUInt16());
61-
}
62-
63-
if (br.BaseStream.Position != indexOffset + (indexCount * 2))
64-
{
65-
throw new InvalidDataException("Index Size Mismatch. Some part(s) of the index data were not read properly.");
57+
vertexData.Indices.Add(indexReader.ReadUInt16());
6658
}
6759

6860
meshData.VertexData = vertexData;

xivModdingFramework/Models/Helpers/ModelModifiers.cs

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,6 @@ public static void MergeGeometryData(TTModel ttModel, XivMdl rawMdl, Action<bool
421421

422422
for (var pi = 0; pi < totalParts; pi++)
423423
{
424-
425424
var ttPart = new TTMeshPart();
426425
ttMesh.Parts.Add(ttPart);
427426
ttPart.Name = "Part " + partIdx;
@@ -431,24 +430,21 @@ public static void MergeGeometryData(TTModel ttModel, XivMdl rawMdl, Action<bool
431430
var indexStart = fakePart == false ? basePart.IndexOffset - baseMesh.MeshInfo.IndexDataOffset : 0;
432431
var indexCount = fakePart == false ? basePart.IndexCount : baseMesh.MeshInfo.IndexCount;
433432

434-
var indices = baseMesh.VertexData.Indices.GetRange(indexStart, indexCount);
433+
var indices = baseMesh.VertexData.Indices.Skip(indexStart).Take(indexCount);
435434

436435
// Get the Vertices unique to this part.
437-
var uniqueVertexIdSet = new SortedSet<int>(indices); // Maximum possible amount is # of indices, though likely it is less.
438-
439-
foreach (var ind in indices)
440-
{
441-
uniqueVertexIdSet.Add(ind);
442-
}
436+
var uniqueVertexIdSet = new HashSet<int>(indices);
443437

444438
// Need it as a list to have index access to it.
445-
var uniqueVertexIds = uniqueVertexIdSet.ToList();
439+
var uniqueVertexIds = new List<int>(uniqueVertexIdSet);
440+
uniqueVertexIds.Sort();
446441

447442
// Maps old vertex ID to new vertex ID.
448-
var vertDict = new Dictionary<int, int>(uniqueVertexIds.Count);
443+
var vertMap = new int[uniqueVertexIds.Max() + 1];
449444

450445
// Now we need to loop through, copy over the vertex data, keeping track of the new vertex IDs.
451446
ttPart.Vertices = new List<TTVertex>(uniqueVertexIds.Count);
447+
452448
for (var i = 0; i < uniqueVertexIds.Count; i++)
453449
{
454450
var oldVertexId = uniqueVertexIds[i];
@@ -556,14 +552,14 @@ public static void MergeGeometryData(TTModel ttModel, XivMdl rawMdl, Action<bool
556552
}
557553

558554
ttPart.Vertices.Add(ttVert);
559-
vertDict.Add(oldVertexId, ttPart.Vertices.Count - 1);
555+
vertMap[oldVertexId] = ttPart.Vertices.Count - 1;
560556
}
561557

562558
// Now we need to copy in the triangle indices, pointing to the new, part-level vertex IDs.
563-
ttPart.TriangleIndices = new List<int>(indices.Count);
559+
ttPart.TriangleIndices = new List<int>(indexCount);
564560
foreach (var oldVertexId in indices)
565561
{
566-
ttPart.TriangleIndices.Add(vertDict[oldVertexId]);
562+
ttPart.TriangleIndices.Add(vertMap[oldVertexId]);
567563
}
568564

569565
// Ok, gucci now.

0 commit comments

Comments
 (0)