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));
            }
        }
Exemple #5
0
        /// <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();
            }
        }