Skip to content

Commit

Permalink
Havok stuff (zzz)
Browse files Browse the repository at this point in the history
  • Loading branch information
PassiveModding committed Jul 17, 2024
1 parent 90249cd commit 9a11225
Show file tree
Hide file tree
Showing 15 changed files with 451 additions and 232 deletions.
7 changes: 4 additions & 3 deletions Meddle/Meddle.Plugin/Utils/ParseUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using Meddle.Utils.Files.Structs.Material;
using Meddle.Utils.Models;
using Meddle.Utils.Skeletons.Havok;
using Meddle.Utils.Skeletons.Havok.Models;
using Attach = Meddle.Plugin.Skeleton.Attach;
using Texture = FFXIVClientStructs.FFXIV.Client.Graphics.Kernel.Texture;

Expand Down Expand Up @@ -186,12 +187,12 @@ public unsafe ExportUtil.AttachedModelGroup HandleAttachGroup(CharacterBase* att
return attachGroup;
}

private unsafe List<HavokXml> ParseSkeletons(Human* human)
private unsafe List<HavokSkeleton> ParseSkeletons(Human* human)
{
var skeletonResourceHandles =
new Span<Pointer<SkeletonResourceHandle>>(human->Skeleton->SkeletonResourceHandles,
human->Skeleton->PartialSkeletonCount);
var skeletons = new List<HavokXml>();
var skeletons = new List<HavokSkeleton>();
foreach (var skeletonPtr in skeletonResourceHandles)
{
var skeletonResourceHandle = skeletonPtr.Value;
Expand All @@ -217,7 +218,7 @@ private unsafe List<HavokXml> ParseSkeletons(Human* human)
var xml = HkUtil.HkxToXml(tempFile);
return xml;
}).GetAwaiter().GetResult();
var havokXml = new HavokXml(hkXml);
var havokXml = HavokUtils.ParseHavokXml(hkXml);

skeletons.Add(havokXml);
} finally
Expand Down
4 changes: 3 additions & 1 deletion Meddle/Meddle.UI/Configuration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public class Configuration
public int WindowHeight { get; set; }
public int DisplayScale { get; set; }
public int FpsLimit { get; set; }
public bool AssetCcResolve { get; set; }

public static Configuration Load()
{
Expand All @@ -25,7 +26,8 @@ public static Configuration Load()
WindowHeight = 720,
DisplayScale = 1,
FpsLimit = 60,
InteropPort = 5000
InteropPort = 5000,
AssetCcResolve = false
};
}

Expand Down
2 changes: 1 addition & 1 deletion Meddle/Meddle.UI/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public class Program
private readonly ILoggerFactory logFactory = LoggerFactory.Create(builder => builder.AddConsole());
private readonly ILogger<Program> logger;

public Configuration Configuration;
public static Configuration Configuration;
public Sdl2Window Window;
public GraphicsDevice GraphicsDevice;
public ImGuiHandler ImGuiHandler;
Expand Down
44 changes: 44 additions & 0 deletions Meddle/Meddle.UI/Util/SkeletonUtil.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,59 @@
using System.Diagnostics;
using Meddle.Utils.Skeletons.Havok;
using Meddle.Utils.Skeletons.Havok.Models;

namespace Meddle.UI.Util;

public class SkeletonUtil
{
public static string ParseHavokInput(byte[] data)
{
if (Program.Configuration.AssetCcResolve)
{
return ParseHavokInputCc(data);
}
else
{
return ParseHavokInputInterop(data);
}
}

public static (string, HavokSkeleton) ProcessHavokInput(byte[] data)
{
if (Program.Configuration.AssetCcResolve)
{
var str = ParseHavokInputCc(data);
var skeleton = HavokCCUtils.ParseHavokXml(str);
return (str, skeleton);
}
else
{
var str = ParseHavokInputInterop(data);
var skeleton = HavokUtils.ParseHavokXml(str);
return (str, skeleton);
}
}

public static string ParseHavokInputCc(byte[] data)
{
File.WriteAllBytes("./data/input.pap", data);
var program = Process.Start("./data/NotAssetCc.exe", new[] {"./data/input.pap", "./data/output.pap"});
program.WaitForExit();
var parseResult = File.ReadAllText("./data/output.pap");
return parseResult;
}

public static string ParseHavokInputInterop(byte[] data)
{
var tempPath = Path.GetTempFileName();
File.WriteAllBytes(tempPath, data);

using var message = new HttpRequestMessage(HttpMethod.Post, $"http://localhost:{Program.Configuration.InteropPort}/parsesklb");
using var content = new StringContent(tempPath);
message.Content = content;
using var client = new HttpClient();
var response = client.SendAsync(message).GetAwaiter().GetResult();
var result = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
return result;
}
}
30 changes: 6 additions & 24 deletions Meddle/Meddle.UI/Windows/Views/ExportView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using Meddle.Utils.Materials;
using Meddle.Utils.Models;
using Meddle.Utils.Skeletons.Havok;
using Meddle.Utils.Skeletons.Havok.Models;
using Meddle.Utils.Skeletons.HavokAnim;
using SharpGLTF.Materials;
using SharpGLTF.Scenes;
Expand All @@ -24,7 +25,6 @@ private record SklbGroup(SklbFile File, string Path);

private readonly Dictionary<string, Model.MdlGroup> models = new();
private readonly Dictionary<string, SklbGroup> skeletons = new();
private string? animation;
private Dictionary<string, IView> views = new();
private Task loadTask = Task.CompletedTask;
private CancellationTokenSource cts = new();
Expand Down Expand Up @@ -230,7 +230,6 @@ public void Draw()
{
models.Clear();
skeletons.Clear();
animation = null;
var newModels = HandleMdls(input.Split("\n"));
foreach (var (key, value) in newModels)
{
Expand All @@ -242,17 +241,6 @@ public void Draw()
{
skeletons[key] = value;
}

var animLines = input.Split("\n").Select(x => x.Trim()).Where(x => x.EndsWith(".pap")).ToList();
if (animLines.Count > 0)
{
var lookupResult = pack.GetFile(animLines[0]);
if (lookupResult != null)
{
var papFile = new PapFile(lookupResult.Value.file.RawData);
animation = SkeletonUtil.ParseHavokInput(papFile.HavokData.ToArray());
}
}
});
}

Expand All @@ -277,18 +265,12 @@ public void Draw()
if (ImGui.Button("Export as GLTF"))
{
var sklbs = this.skeletons
.Select(x => (x.Key, SkeletonUtil.ParseHavokInput(x.Value.File.Skeleton.ToArray())))
.ToDictionary(x => x.Key, y => new HavokXml(y.Item2));

HavokAnimation.BindingContainer? anim = null;
if (animation != null)
{
anim = HavokAnimation.ParseDocument(this.animation)[0];
}
.Select(x => (x.Key, SkeletonUtil.ProcessHavokInput(x.Value.File.Skeleton.ToArray())))
.ToDictionary(x => x.Key, y => y.Item2.Item2);

cts?.Cancel();
cts = new CancellationTokenSource();
exportTask = Task.Run(() => RunExport(models, sklbs, anim, cts.Token), cts.Token);
exportTask = Task.Run(() => RunExport(models, sklbs, cts.Token), cts.Token);
}

if (exportTask.IsFaulted)
Expand Down Expand Up @@ -321,11 +303,11 @@ private void DrawParameters()
ImGui.Checkbox("Lip Stick", ref customizeData.LipStick);
}

private void RunExport(Dictionary<string, Model.MdlGroup> modelDict, Dictionary<string, HavokXml> sklbDict, HavokAnimation.BindingContainer? animation, CancellationToken token = default)
private void RunExport(Dictionary<string, Model.MdlGroup> modelDict, Dictionary<string, HavokSkeleton> sklbDict, CancellationToken token = default)
{
var scene = new SceneBuilder();
var havokXmls = sklbDict.Values.ToArray();
var bones = XmlUtils.GetBoneMap(havokXmls, animation, out var root).ToArray();
var bones = XmlUtils.GetBoneMap(havokXmls, out var root).ToArray();
var boneNodes = bones.Cast<NodeBuilder>().ToArray();
var catchlightTexture = pack.GetFile("chara/common/texture/sphere_d_array.tex");
if (catchlightTexture == null)
Expand Down
19 changes: 9 additions & 10 deletions Meddle/Meddle.UI/Windows/Views/SklbView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Meddle.UI.Util;
using Meddle.Utils.Files;
using Meddle.Utils.Skeletons.Havok;
using Meddle.Utils.Skeletons.Havok.Models;

namespace Meddle.UI.Windows.Views;

Expand All @@ -20,30 +21,28 @@ public SklbView(SklbFile file, Configuration configuration)
this.configuration = configuration;
}

private string? parseResult;
private HavokXml? havokXml;
private (string, HavokSkeleton)? parseResult;
public void Draw()
{
ImGui.Text($"Version: {file.Header.Version} [{(uint)file.Header.Version:X8}]");
ImGui.Text($"Old Header: {file.Header.OldHeader}");

if (ImGui.Button("Parse"))
{
parseResult = SkeletonUtil.ParseHavokInput(file.Skeleton.ToArray());
havokXml = new HavokXml(parseResult);
parseResult = SkeletonUtil.ProcessHavokInput(file.Skeleton.ToArray());
}

if (ImGui.CollapsingHeader("Havok XML") && parseResult != null)
{
ImGui.TextUnformatted(parseResult);
ImGui.TextUnformatted(parseResult.Value.Item1);
}

if (ImGui.CollapsingHeader("Parsed XML") && havokXml != null)
if (ImGui.CollapsingHeader("Parsed XML") && parseResult != null)
{
ImGui.SeparatorText("Skeletons");
for (var i = 0; i < havokXml.Skeletons.Length; i++)
for (var i = 0; i < parseResult.Value.Item2.Skeletons.Length; i++)
{
var skeleton = havokXml.Skeletons[i];
var skeleton = parseResult.Value.Item2.Skeletons[i];
ImGui.BulletText($"Bone Count: {skeleton.BoneNames.Length}");
// scroll box
ImGui.BeginChild($"Skeleton {i}", new Vector2(0, 200), ImGuiChildFlags.Border);
Expand All @@ -59,9 +58,9 @@ public void Draw()
}

ImGui.SeparatorText("Mappings");
for (var i = 0; i < havokXml.Mappings.Length; i++)
for (var i = 0; i < parseResult.Value.Item2.Mappings.Length; i++)
{
var mapping = havokXml.Mappings[i];
var mapping = parseResult.Value.Item2.Mappings[i];
ImGui.Text($"Mapping {i}");
ImGui.BulletText($"Id: {mapping.Id}");
ImGui.BulletText($"Bone Mappings: {mapping.BoneMappings.Length}");
Expand Down
Loading

0 comments on commit 9a11225

Please sign in to comment.