add v5 and v6 model reading capabilities

This commit is contained in:
Stanley Dimant
2024-09-13 00:15:42 +02:00
parent 953ff065b1
commit 863105e897
3 changed files with 280 additions and 21 deletions

View File

@@ -1,12 +1,10 @@
using Dalamud.Plugin.Services;
using FFXIVClientStructs.FFXIV.Client.Game.Character;
using FFXIVClientStructs.FFXIV.Client.Game.Character;
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
using FFXIVClientStructs.Havok.Animation;
using FFXIVClientStructs.Havok.Common.Base.Types;
using FFXIVClientStructs.Havok.Common.Serialize.Util;
using Lumina;
using Lumina.Data.Files;
using MareSynchronos.FileCache;
using MareSynchronos.Interop.GameModel;
using MareSynchronos.MareConfiguration;
using MareSynchronos.PlayerData.Handlers;
using Microsoft.Extensions.Logging;
@@ -19,16 +17,14 @@ public sealed class XivDataAnalyzer
private readonly ILogger<XivDataAnalyzer> _logger;
private readonly FileCacheManager _fileCacheManager;
private readonly XivDataStorageService _configService;
private readonly GameData _luminaGameData;
private readonly List<string> _failedCalculatedTris = [];
public XivDataAnalyzer(ILogger<XivDataAnalyzer> logger, FileCacheManager fileCacheManager,
XivDataStorageService configService, IDataManager gameData)
XivDataStorageService configService)
{
_logger = logger;
_fileCacheManager = fileCacheManager;
_configService = configService;
_luminaGameData = new GameData(gameData.GameData.DataPath.FullName);
}
public unsafe Dictionary<string, List<ushort>>? GetSkeletonBoneIndices(GameObjectHandler handler)
@@ -154,28 +150,34 @@ public sealed class XivDataAnalyzer
return output;
}
public Task<long> GetTrianglesByHash(string hash)
public async Task<long> GetTrianglesByHash(string hash)
{
if (_configService.Current.TriangleDictionary.TryGetValue(hash, out var cachedTris) && cachedTris > 0)
return Task.FromResult(cachedTris);
return cachedTris;
if (_failedCalculatedTris.Contains(hash, StringComparer.Ordinal))
return Task.FromResult((long)0);
return 0;
var path = _fileCacheManager.GetFileCacheByHash(hash);
if (path == null || !path.ResolvedFilepath.EndsWith(".mdl", StringComparison.OrdinalIgnoreCase))
return Task.FromResult((long)0);
return 0;
var filePath = path.ResolvedFilepath;
try
{
_logger.LogDebug("Detected Model File {path}, calculating Tris", filePath);
var file = _luminaGameData.GetFileFromDisk<MdlFile>(filePath);
if (file.FileHeader.LodCount <= 0)
return Task.FromResult((long)0);
var file = new MdlFile(filePath);
if (file.LodCount <= 0)
{
_failedCalculatedTris.Add(hash);
_configService.Current.TriangleDictionary[hash] = 0;
_configService.Save();
return 0;
}
long tris = 0;
for (int i = 0; i < file.FileHeader.LodCount; i++)
for (int i = 0; i < file.LodCount; i++)
{
try
{
@@ -185,19 +187,20 @@ public sealed class XivDataAnalyzer
}
catch (Exception ex)
{
_logger.LogDebug(ex, "Could not load lod mesh {mesh} from {path}", i, filePath);
_logger.LogDebug(ex, "Could not load lod mesh {mesh} from path {path}", i, filePath);
continue;
}
if (tris > 0)
{
_logger.LogDebug("{filePath} => {tris} triangles", filePath, tris);
_logger.LogDebug("TriAnalysis: {filePath} => {tris} triangles", filePath, tris);
_configService.Current.TriangleDictionary[hash] = tris;
_configService.Save();
break;
}
}
return Task.FromResult(tris);
return tris;
}
catch (Exception e)
{
@@ -205,7 +208,7 @@ public sealed class XivDataAnalyzer
_configService.Current.TriangleDictionary[hash] = 0;
_configService.Save();
_logger.LogWarning(e, "Could not parse file {file}", filePath);
return Task.FromResult((long)0);
return 0;
}
}
}