2025-06-08 00:55:10 +09:00

63 lines
2.4 KiB
C#

using System;
using System.Collections.Generic;
using System.Text;
using MMDIKBakerLibrary.Model;
using MMDIKBakerLibrary.Motion;
using MMDMotion2 = MikuMikuDance.Motion.Motion2.MMDMotion2;
using MMDModel1 = MikuMikuDance.Model.Ver1.MMDModel1;
namespace MMDIKBakerLibrary
{
public class IKBaker
{
public static MMDMotion2 bake(MMDMotion2 motion, MMDModel1 model)
{
//ボーン取得
MMDBoneManager boneManager = ModelConverter.BuildBoneManager(model);
//ベイク前のモーションとベイク後のモーションを準備
MMDMotion beforeMotion = MotionConverter.Convert(motion);
MMDMotion afterMotion = CreateAfterMotionPrototype(beforeMotion, boneManager);
//アニメーションプレイヤーを作成
AnimationPlayer player = new AnimationPlayer(boneManager);
player.SetMotion(beforeMotion);
//ベイクしていく
uint frameNo = 0;
bool ExitFlag = false;
while (!ExitFlag)
{
ExitFlag = !player.Update();
//ボーンのグローバル行列更新
boneManager.CalcGlobalTransform();
//IK更新
boneManager.CalcIK();
//ベイク
boneManager.bake(frameNo, afterMotion);
++frameNo;
}
//元のMMDMotion2に直して返却
return MotionConverter.Convert(afterMotion, motion.ModelName);
}
private static MMDMotion CreateAfterMotionPrototype(MMDMotion beforeMotion, MMDBoneManager boneManager)
{
//ベイク対象外の情報をコピー
MMDMotion result = new MMDMotion();
//表情は参照をコピーしておく
result.FaceFrames = beforeMotion.FaceFrames;
//ボーンは必要分だけ参照をコピー
result.BoneFrames = new Dictionary<string, List<MMDBoneKeyFrame>>();
foreach (KeyValuePair<string, List<MMDBoneKeyFrame>> boneSet in beforeMotion.BoneFrames)
{
if (!boneManager.IsUnderIK(boneSet.Key))
{
result.BoneFrames.Add(boneSet.Key, boneSet.Value);
}
else
{
result.BoneFrames.Add(boneSet.Key, new List<MMDBoneKeyFrame>());
}
}
return result;
}
}
}