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)); }
public void bake(uint frameNo, MMDMotion afterMotion) { foreach (KeyValuePair <string, bool> it in ik_dict) { if (it.Value && afterMotion.BoneFrames.ContainsKey(it.Key)) { Matrix globalTrans = this[it.Key].GlobalTransform; Matrix parentTrans, invParentTrans; if (this[it.Key].SkeletonHierarchy >= bones.Count) { parentTrans = Matrix.Identity; } else { parentTrans = this[this[it.Key].SkeletonHierarchy].GlobalTransform; } Matrix.Invert(ref parentTrans, out invParentTrans); Matrix LocalTrans; Matrix.Multiply(ref globalTrans, ref invParentTrans, out LocalTrans); Matrix BindPose = this[it.Key].BindPose.CreateMatrix(); Matrix invBindPose; Matrix.Invert(ref BindPose, out invBindPose); Matrix subPose; Vector3 scale, Location; Quaternion quaternion; Matrix.Multiply(ref LocalTrans, ref invBindPose, out subPose); subPose.Decompose(out scale, out quaternion, out Location); MMDBoneKeyFrame keyframe = new MMDBoneKeyFrame(); if (afterMotion.BoneFrames[it.Key].Count == 0 && frameNo > 0) { keyframe.FrameNo = 0; keyframe.BoneName = it.Key; keyframe.Curve = MathHelper.CreateIdentityCurve(); keyframe.Location = Location; keyframe.Quatanion = quaternion; keyframe.Scales = scale; afterMotion.BoneFrames[it.Key].Add(keyframe); keyframe = new MMDBoneKeyFrame(); } keyframe.FrameNo = frameNo; keyframe.BoneName = it.Key; keyframe.Curve = MathHelper.CreateIdentityCurve(); keyframe.Location = Location; keyframe.Quatanion = quaternion; keyframe.Scales = scale; afterMotion.BoneFrames[it.Key].Add(keyframe); } } }
/// <summary> /// ファイルからMMDモーションを読み込む /// </summary> /// <param name="filename">MMDモーションファイル</param> /// <param name="coordinate">変換先座標系</param> /// <returns>MMDモーションオブジェクト</returns> /// <param name="scale">スケーリング値</param> public static MMDMotion Read(string filename, CoordinateType coordinate, float scale = 1.0f) { //フルパス取得 filename = Path.GetFullPath(filename); //ファイルチェック if (!File.Exists(filename)) { throw new FileNotFoundException("MMDモーションファイル:" + filename + "が見つかりません"); } //戻り値用変数 MMDMotion result = null; //ファイルリーダー using (FileStream fs = new FileStream(filename, FileMode.Open)) { BinaryReader reader = new BinaryReader(fs); //マジック文字列 string magic = MMDMotion2.GetString(reader.ReadBytes(30)); if (magic.Substring(0, 20) != "Vocaloid Motion Data") { throw new FileLoadException("MMDモーションファイルではありません"); } //バージョン int version = Convert.ToInt32(magic.Substring(21)); if (version == 2) { result = new MMDMotion2(); } else { throw new FileLoadException("version=" + version.ToString() + "モデルは対応していません"); } result.Read(reader, coordinate, scale); if (fs.Length != fs.Position) { Console.WriteLine("警告:ファイル末尾以降に不明データ?"); } fs.Close(); } return(result); }
public static void Load(this MMDMotion motion, VMDFormat vmd) { motion.BoneKeyFrameSet.Clear(); motion.MorphKeyFrameSet.Clear(); foreach (var pair in vmd.BoneKeyFrameSet) { var keyFrames = new List <BoneKeyFrame>(pair.Value); motion.BoneKeyFrameSet.Add(pair.Key, keyFrames); for (int i = 0; i < keyFrames.Count; i++) { BoneKeyFrame keyFrame = keyFrames[i]; keyFrame.Translation *= 0.1f; keyFrames[i] = keyFrame; } } foreach (var pair in vmd.MorphKeyFrameSet) { motion.MorphKeyFrameSet.Add(pair.Key, new List <MorphKeyFrame>(pair.Value)); } }
/// <summary> /// ファイルへの書き出し /// </summary> /// <param name="filename">ファイル名</param> /// <param name="motion">モーション</param> /// <param name="scale">スケーリング値</param> public static void Write(string filename, MMDMotion motion, float scale=1f) { //フルパス取得 filename = Path.GetFullPath(filename); //ファイルリーダー using (FileStream fs = new FileStream(filename, FileMode.Create)) { BinaryWriter writer = new BinaryWriter(fs); //マジック文字列 if (motion is MMDMotion2) { writer.Write(MMDMotion2.GetBytes("Vocaloid Motion Data 0002", 25)); writer.Write((byte)0); writer.Write(MMDMotion2.GetBytes("JKLM", 4)); } else new NotImplementedException("その他のバーションは未作成"); motion.Write(writer, scale); fs.Close(); } }
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); }
/// <summary> /// ファイルへの書き出し /// </summary> /// <param name="filename">ファイル名</param> /// <param name="motion">モーション</param> /// <param name="scale">スケーリング値</param> public static void Write(string filename, MMDMotion motion, float scale = 1f) { //フルパス取得 filename = Path.GetFullPath(filename); //ファイルリーダー using (FileStream fs = new FileStream(filename, FileMode.Create)) { BinaryWriter writer = new BinaryWriter(fs); //マジック文字列 if (motion is MMDMotion2) { writer.Write(MMDMotion2.GetBytes("Vocaloid Motion Data 0002", 25)); writer.Write((byte)0); writer.Write(MMDMotion2.GetBytes("JKLM", 4)); } else { new NotImplementedException("その他のバーションは未作成"); } motion.Write(writer, scale); fs.Close(); } }