internal static Dictionary<string, List<MMDBoneKeyFrame>> SplitBoneMotion(MMDBoneKeyFrame[] keyframes) { Dictionary<string, List<MMDBoneKeyFrame>> result = new Dictionary<string, List<MMDBoneKeyFrame>>(); foreach (var keyframe in keyframes) { if (!result.ContainsKey(keyframe.BoneName)) result.Add(keyframe.BoneName, new List<MMDBoneKeyFrame>()); result[keyframe.BoneName].Add(keyframe); } foreach (var boneframes in result) { boneframes.Value.Sort((x, y) => (int)((long)x.FrameNo - (long)y.FrameNo)); } return result; }
/// <summary> /// 補完 /// </summary> /// <param name="frame1">フレーム1</param> /// <param name="frame2">フレーム2</param> /// <param name="Progress">進行度合い</param> /// <param name="result">補完結果</param> public static void Lerp(MMDBoneKeyFrame frame1, MMDBoneKeyFrame frame2, decimal Progress, out SQTTransform result) { decimal ProgX, ProgY, ProgZ, ProgR; ProgX = (decimal)frame2.Curve[0].Evaluate((float)Progress); ProgY = (decimal)frame2.Curve[1].Evaluate((float)Progress); ProgZ = (decimal)frame2.Curve[2].Evaluate((float)Progress); ProgR = (decimal)frame2.Curve[3].Evaluate((float)Progress); decimal x, y, z; Quaternion q; Vector3 scales; x = MathHelper.Lerp(frame1.Location.X, frame2.Location.X, ProgX); y = MathHelper.Lerp(frame1.Location.Y, frame2.Location.Y, ProgY); z = MathHelper.Lerp(frame1.Location.Z, frame2.Location.Z, ProgZ); Quaternion.Slerp(ref frame1.Quatanion, ref frame2.Quatanion, ProgR, out q); //MMDはスケールのアニメーションを含まないので、スケールのベジェ曲線計算は行わない Vector3.Lerp(ref frame1.Scales, ref frame2.Scales, Progress, out scales); Vector3 t = new Vector3(x, y, z); SQTTransform.Create(ref scales, ref q, ref t, out result); }
internal static MMDMotion Convert(MikuMikuDance.Motion.Motion2.MMDMotion2 input) { MMDMotion result = new MMDMotion(); //ボーンモーションデータの変換 MMDBoneKeyFrame[] BoneFrames = new MMDBoneKeyFrame[input.Motions.LongLength]; for (long i = 0; i < input.Motions.LongLength; i++) { BoneFrames[i] = new MMDBoneKeyFrame(); BoneFrames[i].BoneName = input.Motions[i].BoneName; BoneFrames[i].FrameNo = input.Motions[i].FrameNo; BoneFrames[i].Curve = new BezierCurve[4]; for (int j = 0; j < BoneFrames[i].Curve.Length; j++) { BezierCurve curve = new BezierCurve(); curve.v1 = new Vector2((float)input.Motions[i].Interpolation[0][0][j] / 128f, (float)input.Motions[i].Interpolation[0][1][j] / 128f); curve.v2 = new Vector2((float)input.Motions[i].Interpolation[0][2][j] / 128f, (float)input.Motions[i].Interpolation[0][3][j] / 128f); BoneFrames[i].Curve[j] = curve; } BoneFrames[i].Scales = new Vector3(1, 1, 1); BoneFrames[i].Location = new Vector3((decimal)input.Motions[i].Location[0], (decimal)input.Motions[i].Location[1], (decimal)input.Motions[i].Location[2]); BoneFrames[i].Quatanion = new Quaternion((decimal)input.Motions[i].Quatanion[0], (decimal)input.Motions[i].Quatanion[1], (decimal)input.Motions[i].Quatanion[2], (decimal)input.Motions[i].Quatanion[3]); BoneFrames[i].Quatanion.Normalize(); } result.BoneFrames = MotionHelper.SplitBoneMotion(BoneFrames); //表情モーションの変換 MMDFaceKeyFrame[] FaceFrames = new MMDFaceKeyFrame[input.FaceMotions.LongLength]; for (long i = 0; i < input.FaceMotions.Length; i++) { FaceFrames[i] = new MMDFaceKeyFrame(); FaceFrames[i].Rate = input.FaceMotions[i].Rate; FaceFrames[i].FaceName = input.FaceMotions[i].FaceName; FaceFrames[i].FrameNo = input.FaceMotions[i].FrameNo; float temp = input.FaceMotions[i].FrameNo; } result.FaceFrames = MotionHelper.SplitFaceMotion(FaceFrames); //カメラモーションは無視(使わんので) //ライトモーションは無視(使わんので) //変換したデータを返却 return(result); }
internal static MMDMotion Convert(MikuMikuDance.Motion.Motion2.MMDMotion2 input) { MMDMotion result = new MMDMotion(); //ボーンモーションデータの変換 MMDBoneKeyFrame[] BoneFrames = new MMDBoneKeyFrame[input.Motions.LongLength]; for (long i = 0; i < input.Motions.LongLength; i++) { BoneFrames[i] = new MMDBoneKeyFrame(); BoneFrames[i].BoneName = input.Motions[i].BoneName; BoneFrames[i].FrameNo = input.Motions[i].FrameNo; BoneFrames[i].Curve = new BezierCurve[4]; for (int j = 0; j < BoneFrames[i].Curve.Length; j++) { BezierCurve curve = new BezierCurve(); curve.v1 = new Vector2((float)input.Motions[i].Interpolation[0][0][j] / 128f, (float)input.Motions[i].Interpolation[0][1][j] / 128f); curve.v2 = new Vector2((float)input.Motions[i].Interpolation[0][2][j] / 128f, (float)input.Motions[i].Interpolation[0][3][j] / 128f); BoneFrames[i].Curve[j] = curve; } BoneFrames[i].Scales = new Vector3(1, 1, 1); BoneFrames[i].Location = new Vector3((decimal)input.Motions[i].Location[0], (decimal)input.Motions[i].Location[1], (decimal)input.Motions[i].Location[2]); BoneFrames[i].Quatanion = new Quaternion((decimal)input.Motions[i].Quatanion[0], (decimal)input.Motions[i].Quatanion[1], (decimal)input.Motions[i].Quatanion[2], (decimal)input.Motions[i].Quatanion[3]); BoneFrames[i].Quatanion.Normalize(); } result.BoneFrames = MotionHelper.SplitBoneMotion(BoneFrames); //表情モーションの変換 MMDFaceKeyFrame[] FaceFrames = new MMDFaceKeyFrame[input.FaceMotions.LongLength]; for (long i = 0; i < input.FaceMotions.Length; i++) { FaceFrames[i] = new MMDFaceKeyFrame(); FaceFrames[i].Rate = input.FaceMotions[i].Rate; FaceFrames[i].FaceName = input.FaceMotions[i].FaceName; FaceFrames[i].FrameNo = input.FaceMotions[i].FrameNo; float temp = input.FaceMotions[i].FrameNo; } result.FaceFrames = MotionHelper.SplitFaceMotion(FaceFrames); //カメラモーションは無視(使わんので) //ライトモーションは無視(使わんので) //変換したデータを返却 return result; }
/// <summary> /// 補完 /// </summary> /// <param name="frame1">フレーム1</param> /// <param name="frame2">フレーム2</param> /// <param name="Progress">進行度合い</param> /// <param name="result">補完結果</param> public static void Lerp(MMDBoneKeyFrame frame1, MMDBoneKeyFrame frame2, decimal Progress, out SQTTransform result) { decimal ProgX, ProgY, ProgZ, ProgR; ProgX = (decimal)frame2.Curve[0].Evaluate((float)Progress); ProgY = (decimal)frame2.Curve[1].Evaluate((float)Progress); ProgZ = (decimal)frame2.Curve[2].Evaluate((float)Progress); ProgR = (decimal)frame2.Curve[3].Evaluate((float)Progress); decimal x, y, z; Quaternion q; Vector3 scales; x = MathHelper.Lerp(frame1.Location.X, frame2.Location.X, ProgX); y = MathHelper.Lerp(frame1.Location.Y, frame2.Location.Y, ProgY); z = MathHelper.Lerp(frame1.Location.Z, frame2.Location.Z, ProgZ); Quaternion.Slerp(ref frame1.Quatanion, ref frame2.Quatanion, ProgR, out q); //MMDはスケールのアニメーションを含まないので、スケールのベジェ曲線計算は行わない Vector3.Lerp(ref frame1.Scales, ref frame2.Scales, Progress, out scales); Vector3 t = new Vector3(x, y, z); SQTTransform.Create(ref scales, ref q, ref t, out result); }
//終了したらfalseを返す public bool Update() { bool result = !TimeUpdate(); SubPoses.Clear(); //ボーンの更新 foreach (KeyValuePair <string, List <MMDBoneKeyFrame> > frameList in boneFrames) { //カーソル位置の更新 int CursorPos = bonePos[frameList.Key]; for (; CursorPos < frameList.Value.Count && frameList.Value[CursorPos].FrameNo < m_NowFrame; ++CursorPos) { ; } for (; CursorPos > 0 && frameList.Value[CursorPos - 1].FrameNo > m_NowFrame; --CursorPos) { ; } bonePos[frameList.Key] = CursorPos; if (CursorPos == frameList.Value.Count) {//通常再生時の最終フレーム SQTTransform subPose; frameList.Value[CursorPos - 1].GetSQTTransform(out subPose); SubPoses.Add(frameList.Key, subPose); } else { //時間経過取得 decimal Progress = (m_NowFrame - frameList.Value[CursorPos - 1].FrameNo) / (frameList.Value[CursorPos].FrameNo - frameList.Value[CursorPos - 1].FrameNo); SQTTransform subPose; MMDBoneKeyFrame pose1 = frameList.Value[CursorPos - 1], pose2 = frameList.Value[CursorPos]; MMDBoneKeyFrame.Lerp(pose1, pose2, Progress, out subPose); SubPoses.Add(frameList.Key, subPose); } } return(result); }
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); } } }