Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions OpenKh.Command.AnbMaker/Commands/AnbCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,16 @@ internal class AnbCommand : IFbxSourceItemSelector, IMsetInjector
[Required]
[FileExists]
[Argument(0, Description = "fbx input")]
public string InputModel { get; set; }
public string InputModel { get; set; } = null!;

[Argument(1, Description = "anb output")]
public string Output { get; set; }
public string? Output { get; set; }

[Option(Description = "specify root armature node name", ShortName = "r")]
public string RootName { get; set; }
public string? RootName { get; set; }

[Option(Description = "specify mesh name to read bone data", ShortName = "m")]
public string MeshName { get; set; }
public string? MeshName { get; set; }

[Option(Description = "apply scaling to each source node", ShortName = "x", LongName = "node-scaling")]
public float NodeScaling { get; set; } = 1;
Expand All @@ -39,10 +39,10 @@ internal class AnbCommand : IFbxSourceItemSelector, IMsetInjector
public float PositionScaling { get; set; } = 1;

[Option(Description = "specify animation name to read bone data", ShortName = "a")]
public string AnimationName { get; set; }
public string? AnimationName { get; set; }

[Option(Description = "optionally inject new motion into mset directly", ShortName = "w")]
public string MsetFile { get; set; }
public string? MsetFile { get; set; }

[Option(Description = "zero based target index of bar entry in mset file", ShortName = "i")]
public int MsetIndex { get; set; }
Expand Down Expand Up @@ -107,9 +107,9 @@ internal class UseAssimpForRaw

public UseAssimpForRaw(
string inputModel,
string meshName,
string rootName,
string animationName,
string? meshName,
string? rootName,
string? animationName,
float nodeScaling,
float positionScaling
)
Expand Down
96 changes: 78 additions & 18 deletions OpenKh.Command.AnbMaker/Commands/AnbExCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using OpenKh.Command.AnbMaker.Utils.AssimpAnimSource;
using OpenKh.Command.AnbMaker.Utils.Builder;
using OpenKh.Command.AnbMaker.Utils.Builder.Models;
using OpenKh.Command.AnbMaker.Utils.GltfAnimSource;
using OpenKh.Command.AnbMaker.Utils.JsonAnimSource;
using OpenKh.Kh2;
using System.ComponentModel.DataAnnotations;
Expand All @@ -18,20 +19,19 @@ internal class AnbExCommand : IFbxSourceItemSelector, IMsetInjector
[Required]
[FileExists]
[Argument(0, Description = "fbx input")]
public string InputModel { get; set; }
public string InputModel { get; set; } = null!;

[Argument(1, Description = "anb output")]
public string Output { get; set; }
public string OutputMset { get; set; }
public string? OutputMset { get; set; }

[Option(Description = "specify root armature node name", ShortName = "r")]
public string RootName { get; set; }
public string? RootName { get; set; }

[Option(Description = "specify mesh name to read bone data", ShortName = "m")]
public string MeshName { get; set; }
public string? MeshName { get; set; }

[Option(Description = "specify animation name to read bone data", ShortName = "a")]
public string AnimationName { get; set; }
public string? AnimationName { get; set; }

[Option(Description = "apply scaling to each source node", ShortName = "x", LongName = "node-scaling")]
public float NodeScaling { get; set; } = 1;
Expand All @@ -40,23 +40,30 @@ internal class AnbExCommand : IFbxSourceItemSelector, IMsetInjector
public float PositionScaling { get; set; } = 1;

[Option(Description = "optionally inject new motion into mset directly", ShortName = "w")]
public string MsetFile { get; set; }
public string? MsetFile { get; set; }

[Option(Description = "zero based target index of bar entry in mset file", ShortName = "i")]
public int MsetIndex { get; set; }

[Option(Description = "prefer UseJson as BasicSourceMotion", LongName = "use-json", ShortName = "j")]
public bool UseJson { get; set; }

[Option(Description = "prefer UseGltf as BasicSourceMotion", LongName = "use-gltf", ShortName = "g")]
public bool UseGltf { get; set; }

[Option(Description = "prefer UseAssimp as BasicSourceMotion", LongName = "use-assimp", ShortName = "s")]
public bool UseAssimp { get; set; }

protected int OnExecute(CommandLineApplication app)
{
var logger = LogManager.GetLogger("InterpolatedMotionMaker");

Output = Path.GetFullPath(Output ?? Path.GetFileNameWithoutExtension(InputModel) + ".anb");
OutputMset = Path.GetFullPath(OutputMset ?? Path.GetFileNameWithoutExtension(InputModel) + ".mset");
Console.WriteLine($"Writing to: {Output}");

IEnumerable<BasicSourceMotion> parms;
if (Path.GetExtension(InputModel).ToLowerInvariant() == ".json")
OutputMset = Path.GetFullPath(OutputMset ?? Path.GetFileNameWithoutExtension(InputModel) + ".mset");
IEnumerable<BasicSourceMotion> LoadByUseJson()
{
parms = new UseJson(
logger.Debug("UseJson as BasicSourceMotion");
return new UseJson(
inputModel: InputModel,
meshName: MeshName,
rootName: RootName,
Expand All @@ -65,9 +72,11 @@ protected int OnExecute(CommandLineApplication app)
)
.Parameters;
}
else

IEnumerable<BasicSourceMotion> LoadByUseAssimp()
{
parms = new UseAssimp(
logger.Debug("UseAssimp as BasicSourceMotion");
return new UseAssimp(
inputModel: InputModel,
meshName: MeshName,
rootName: RootName,
Expand All @@ -78,8 +87,59 @@ protected int OnExecute(CommandLineApplication app)
.Parameters;
}

IEnumerable<BasicSourceMotion> LoadByUseGltf()
{
logger.Debug("UseGltf as BasicSourceMotion");
return new UseGltf().Load(
inputModel: InputModel,
meshName: MeshName,
rootName: RootName,
animationName: AnimationName,
nodeScaling: 1
);
}

var fileExtension = Path.GetExtension(InputModel).ToLowerInvariant();

if (false)
{ }
else if (UseAssimp)
{
parms = LoadByUseAssimp();
}
else if (UseJson)
{
parms = LoadByUseJson();
}
else if (UseGltf)
{
parms = LoadByUseGltf();
}
else if (fileExtension == ".json")
{
parms = LoadByUseJson();
}
else
{
parms = LoadByUseAssimp();
}

OutputMset = Path.GetFullPath(OutputMset ?? Path.GetFileNameWithoutExtension(InputModel) + ".anb");

logger.Info($"Writing to: {0}", OutputMset);

foreach (var parm in parms.Take(1))
{
logger.Debug("Printing summary of BasicSourceMotion");

logger.Debug($"DurationInTicks = {parm.DurationInTicks}");
logger.Debug($"TicksPerSecond = {parm.TicksPerSecond}");
logger.Debug($"BoneCount = {parm.BoneCount}");
logger.Debug($"NodeScaling = {parm.NodeScaling}");
logger.Debug($"PositionScaling = {parm.PositionScaling}");

logger.Debug("Invoking InterpolatedMotionBuilder");

var builder = new InterpolatedMotionBuilder(parm);

var ipm = builder.Ipm;
Expand Down Expand Up @@ -135,11 +195,11 @@ protected int OnExecute(CommandLineApplication app)
}
);

File.WriteAllBytes(Output, anbBarStream.ToArray());
File.WriteAllBytes(Output + ".raw", motionStream.ToArray());
File.WriteAllBytes(OutputMset, anbBarStream.ToArray());
File.WriteAllBytes(OutputMset + ".raw", motionStream.ToArray());
File.WriteAllBytes(OutputMset, msetBarStream.ToArray());

logger.Debug($"Motion data generation successful");
logger.Info($"Motion data generation successful");

new MsetInjector().InjectMotionTo(this, motionStream.ToArray());
}
Expand Down
97 changes: 97 additions & 0 deletions OpenKh.Command.AnbMaker/Commands/DumpMdlxSrtCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
using libcsv;
using McMaster.Extensions.CommandLineUtils;
using OpenKh.Kh2;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace OpenKh.Command.AnbMaker.Commands
{
[HelpOption]
[Command(Description = "mdlx file: dump scale rotation translation to csv")]
internal class DumpMdlxSrtCommand
{
[Required]
[FileExists]
[Argument(0, Description = "mdlx input")]
public string InputModel { get; set; } = null!;

[Argument(1, Description = "csv output")]
public string? OutputCsv { get; set; }

[Option(Description = "use radians instead of degrees", ShortName = "r", LongName = "use-radians")]
public bool UseRadians { get; set; }

protected int OnExecute(CommandLineApplication app)
{
OutputCsv = Path.GetFullPath(OutputCsv ?? Path.GetFileNameWithoutExtension(InputModel) + ".csv");

Console.WriteLine($"Writing to: {OutputCsv}");

using Stream mdlxFile = File.OpenRead(InputModel);

var bar = Bar.Read(mdlxFile);

var modelEntry = bar.SingleOrDefault(it => it.Type == Bar.EntryType.Model)
?? throw new Exception("Model entry not found");

var mdlx = Mdlx.Read(modelEntry.Stream);
if (mdlx.Model is ModelSkeleton modelSkeleton)
{
var subModel = mdlx.SubModels.SingleOrDefault(it => it.Type == 3)
?? throw new Exception("SubModel entry not found");

using var writer = new StreamWriter(OutputCsv, false, new UTF8Encoding(true));
var csv = new Csvw(writer, ',', '"');

string FormatScale(float value) => value.ToString();

string FormatRotation(float value) =>
UseRadians
? value.ToString()
: (value * 180 / MathF.PI).ToString();

string FormatTranslation(float value) => value.ToString();

{
csv.Write("BoneIndex");
csv.Write("BoneParent");
csv.Write("Scale X");
csv.Write("Scale Y");
csv.Write("Scale Z");
csv.Write("Rotation X");
csv.Write("Rotation Y");
csv.Write("Rotation Z");
csv.Write("Translation X");
csv.Write("Translation Y");
csv.Write("Translation Z");
}

foreach (var bone in subModel.Bones)
{
csv.NextRow();
csv.Write(bone.Index.ToString());
csv.Write(bone.Parent.ToString());
csv.Write(FormatScale(bone.ScaleX));
csv.Write(FormatScale(bone.ScaleY));
csv.Write(FormatScale(bone.ScaleZ));
csv.Write(FormatRotation(bone.RotationX));
csv.Write(FormatRotation(bone.RotationY));
csv.Write(FormatRotation(bone.RotationZ));
csv.Write(FormatTranslation(bone.TranslationX));
csv.Write(FormatTranslation(bone.TranslationY));
csv.Write(FormatTranslation(bone.TranslationZ));
}
}
else
{
throw new Exception($"Model type {mdlx.Model?.GetType()?.FullName} is not a skeleton");
}

return 0;
}
}
}
Loading
Loading