mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 18:27:24 +01:00
Add lenient model export mode
This commit is contained in:
parent
6689e326ee
commit
1166c9e297
5 changed files with 42 additions and 6 deletions
|
|
@ -3,4 +3,5 @@ namespace Penumbra.Import.Models.Export;
|
||||||
public struct ExportConfig
|
public struct ExportConfig
|
||||||
{
|
{
|
||||||
public bool GenerateMissingBones;
|
public bool GenerateMissingBones;
|
||||||
|
public bool LenientMode;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -445,7 +445,7 @@ public class MeshExporter
|
||||||
return new VertexTexture2ColorFfxiv(
|
return new VertexTexture2ColorFfxiv(
|
||||||
new Vector2(uv.X, uv.Y),
|
new Vector2(uv.X, uv.Y),
|
||||||
new Vector2(uv.Z, uv.W),
|
new Vector2(uv.Z, uv.W),
|
||||||
ToVector4(GetFirstSafe(attributes, MdlFile.VertexUsage.Color))
|
ToVector4(_config.LenientMode ? GetFirstUnsafe(attributes, MdlFile.VertexUsage.Color) : GetFirstSafe(attributes, MdlFile.VertexUsage.Color))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (_materialType == typeof(VertexTexture3))
|
if (_materialType == typeof(VertexTexture3))
|
||||||
|
|
@ -468,7 +468,7 @@ public class MeshExporter
|
||||||
new Vector2(uv0.X, uv0.Y),
|
new Vector2(uv0.X, uv0.Y),
|
||||||
new Vector2(uv0.Z, uv0.W),
|
new Vector2(uv0.Z, uv0.W),
|
||||||
new Vector2(uv1.X, uv1.Y),
|
new Vector2(uv1.X, uv1.Y),
|
||||||
ToVector4(GetFirstSafe(attributes, MdlFile.VertexUsage.Color))
|
ToVector4(_config.LenientMode ? GetFirstUnsafe(attributes, MdlFile.VertexUsage.Color) : GetFirstSafe(attributes, MdlFile.VertexUsage.Color))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -538,6 +538,23 @@ public class MeshExporter
|
||||||
return list[0];
|
return list[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary> Check that the list has length 1 for any case where this is expected and return the one entry. Otherwise, report a warning. </summary>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
|
private T GetFirstUnsafe<T>(IReadOnlyDictionary<MdlFile.VertexUsage, List<T>> attributes, MdlFile.VertexUsage usage)
|
||||||
|
{
|
||||||
|
var list = attributes[usage];
|
||||||
|
switch (list.Count)
|
||||||
|
{
|
||||||
|
case > 1:
|
||||||
|
_notifier.Warning($"Multiple usage indices encountered for {usage}.", true);
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
throw _notifier.Exception($"No usage indices encountered for {usage}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return list[0];
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary> Convert a vertex attribute value to a Vector2. Supported inputs are Vector2, Vector3, and Vector4. </summary>
|
/// <summary> Convert a vertex attribute value to a Vector2. Supported inputs are Vector2, Vector3, and Vector4. </summary>
|
||||||
private static Vector2 ToVector2(object data)
|
private static Vector2 ToVector2(object data)
|
||||||
=> data switch
|
=> data switch
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,8 @@ public record class IoNotifier
|
||||||
=> this with { _context = $"{_context}{context}: "};
|
=> this with { _context = $"{_context}{context}: "};
|
||||||
|
|
||||||
/// <summary> Send a warning with any current context to notification channels. </summary>
|
/// <summary> Send a warning with any current context to notification channels. </summary>
|
||||||
public void Warning(string content)
|
public void Warning(string content, bool ignoreDuplicates = false)
|
||||||
=> SendMessage(content, Logger.LogLevel.Warning);
|
=> SendMessage(content, Logger.LogLevel.Warning, ignoreDuplicates);
|
||||||
|
|
||||||
/// <summary> Get the current warnings for this notifier. </summary>
|
/// <summary> Get the current warnings for this notifier. </summary>
|
||||||
/// <remarks> This does not currently filter to notifications with the current notifier's context - it will return all IO notifications from all notifiers. </remarks>
|
/// <remarks> This does not currently filter to notifications with the current notifier's context - it will return all IO notifications from all notifiers. </remarks>
|
||||||
|
|
@ -31,9 +31,15 @@ public record class IoNotifier
|
||||||
where TException : Exception, new()
|
where TException : Exception, new()
|
||||||
=> (TException)Activator.CreateInstance(typeof(TException), $"{_context}{message}")!;
|
=> (TException)Activator.CreateInstance(typeof(TException), $"{_context}{message}")!;
|
||||||
|
|
||||||
private void SendMessage(string message, Logger.LogLevel type)
|
private void SendMessage(string message, Logger.LogLevel type, bool ignoreDuplicates = false)
|
||||||
{
|
{
|
||||||
var fullText = $"{_context}{message}";
|
var fullText = $"{_context}{message}";
|
||||||
|
|
||||||
|
if (ignoreDuplicates && _messages.Contains(fullText))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Penumbra.Log.Message(type, fullText);
|
Penumbra.Log.Message(type, fullText);
|
||||||
_messages.Add(fullText);
|
_messages.Add(fullText);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ using Penumbra.Meta;
|
||||||
using Penumbra.Meta.Files;
|
using Penumbra.Meta.Files;
|
||||||
using Penumbra.Meta.Manipulations;
|
using Penumbra.Meta.Manipulations;
|
||||||
using SharpGLTF.Scenes;
|
using SharpGLTF.Scenes;
|
||||||
|
using SharpGLTF.Validation;
|
||||||
using SixLabors.ImageSharp;
|
using SixLabors.ImageSharp;
|
||||||
using SixLabors.ImageSharp.PixelFormats;
|
using SixLabors.ImageSharp.PixelFormats;
|
||||||
|
|
||||||
|
|
@ -216,7 +217,10 @@ public sealed class ModelManager(IFramework framework, MetaFileManager metaFileM
|
||||||
|
|
||||||
Penumbra.Log.Debug("[GLTF Export] Saving...");
|
Penumbra.Log.Debug("[GLTF Export] Saving...");
|
||||||
var gltfModel = scene.ToGltf2();
|
var gltfModel = scene.ToGltf2();
|
||||||
gltfModel.Save(outputPath);
|
gltfModel.Save(outputPath, new Schema2.WriteSettings()
|
||||||
|
{
|
||||||
|
Validation = config.LenientMode ? ValidationMode.TryFix : ValidationMode.Strict,
|
||||||
|
});
|
||||||
Penumbra.Log.Debug("[GLTF Export] Done.");
|
Penumbra.Log.Debug("[GLTF Export] Done.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -168,6 +168,14 @@ public partial class ModEditWindow
|
||||||
+ "It is primarily intended to allow exporting models weighted to bones that do not exist.\n"
|
+ "It is primarily intended to allow exporting models weighted to bones that do not exist.\n"
|
||||||
+ "Before enabling, ensure dependencies are enabled in the current collection, and EST metadata is correctly configured.");
|
+ "Before enabling, ensure dependencies are enabled in the current collection, and EST metadata is correctly configured.");
|
||||||
|
|
||||||
|
ImGui.SameLine(200 * UiHelpers.Scale + ImGui.GetStyle().ItemSpacing.X + ImGui.GetStyle().WindowPadding.X);
|
||||||
|
|
||||||
|
ImGui.Checkbox("##tryFixValidation", ref tab.ExportConfig.LenientMode);
|
||||||
|
ImGui.SameLine();
|
||||||
|
ImGuiUtil.LabeledHelpMarker("Lenient mode",
|
||||||
|
"Try fixing potential errors during model validation and ignore superfluous color information.\n"
|
||||||
|
+ "This may result in a broken model, or one missing information, so use with care!");
|
||||||
|
|
||||||
var gamePath = tab.GamePathIndex >= 0 && tab.GamePathIndex < tab.GamePaths.Count
|
var gamePath = tab.GamePathIndex >= 0 && tab.GamePathIndex < tab.GamePaths.Count
|
||||||
? tab.GamePaths[tab.GamePathIndex]
|
? tab.GamePaths[tab.GamePathIndex]
|
||||||
: _customGamePath;
|
: _customGamePath;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue