• R/O
  • SSH
  • HTTPS

mmdx: Commit


Commit MetaInfo

Revision78 (tree)
Zeit2010-03-21 19:47:38
Autorwilfrem

Log Message

カメラライトモーション実装中に見つけたバグを一旦コミット
モーションの回転の補完を間違えてX軸の補完にしていたのを修正
ベイク前のモーションを再生しないようなエンバグをしていたので修正
モーションの補間計算に使用していたニュートン法にミスがあったので修正。ついでに安全装置も付加

Ändern Zusammenfassung

Diff

--- trunk/MikuMikuDanceXNA/MikuMikuDanceXNA.cs (revision 77)
+++ trunk/MikuMikuDanceXNA/MikuMikuDanceXNA.cs (revision 78)
@@ -69,7 +69,7 @@
6969 public MikuMikuDanceXNA(Game game)
7070 {
7171 Content = game.Content;
72- Camera = new MMDCamera();
72+ Camera = new MMDCamera(game);
7373 LightManager = new MMDLightManager();
7474 #if WINDOWS
7575 //論理コア数を取得して、最適スレッド数を取得
@@ -89,7 +89,7 @@
8989 public MikuMikuDanceXNA(Game game, btDiscreteDynamicsWorld physic)
9090 {
9191 Content = game.Content;
92- Camera = new MMDCamera();
92+ Camera = new MMDCamera(game);
9393 LightManager = new MMDLightManager();
9494 #if WINDOWS
9595 //論理コア数を取得して、最適スレッド数を取得
--- trunk/MikuMikuDanceXNA/Motion/MotionData/MMDLightMotion.cs (nonexistent)
+++ trunk/MikuMikuDanceXNA/Motion/MotionData/MMDLightMotion.cs (revision 78)
@@ -0,0 +1,25 @@
1+using Microsoft.Xna.Framework;
2+using DWORD = System.UInt32;
3+
4+namespace MikuMikuDance.XNA.Motion.MotionData
5+{
6+ /// <summary>
7+ /// ライトモーションデータ
8+ /// </summary>
9+ public class MMDLightMotion
10+ {
11+ /// <summary>
12+ /// フレームナンバー
13+ /// </summary>
14+ public DWORD FrameNo { get; set; }
15+ /// <summary>
16+ /// ライトの色
17+ /// </summary>
18+ public Vector3 Color { get; set; }
19+ /// <summary>
20+ /// ライトの位置
21+ /// </summary>
22+ public Vector3 Location { get; set; }
23+
24+ }
25+}
\ No newline at end of file
--- trunk/MikuMikuDanceXNA/Motion/MotionData/MMDCameraMotion.cs (nonexistent)
+++ trunk/MikuMikuDanceXNA/Motion/MotionData/MMDCameraMotion.cs (revision 78)
@@ -0,0 +1,41 @@
1+using System;
2+using System.Collections.Generic;
3+using System.Linq;
4+using System.Text;
5+using Microsoft.Xna.Framework;
6+using DWORD = System.UInt32;
7+
8+namespace MikuMikuDance.XNA.Motion.MotionData
9+{
10+ /// <summary>
11+ /// カメラモーションデータ
12+ /// </summary>
13+ public class MMDCameraMotion
14+ {
15+ /// <summary>
16+ /// フレーム番号
17+ /// </summary>
18+ public DWORD FrameNo { get; set; }
19+ /// <summary>
20+ /// 距離
21+ /// </summary>
22+ public float Length { get; set; }
23+ /// <summary>
24+ /// 位置
25+ /// </summary>
26+ public Vector3 Location { get; set; }
27+ /// <summary>
28+ /// 回転
29+ /// </summary>
30+ public Quaternion Quatanion { get; set; }
31+ /// <summary>
32+ /// 補完用曲線
33+ /// </summary>
34+ /// <remarks>順にX,Y,Z,回転,距離,視野角</remarks>
35+ public BezierCurve[] Curve { get; set; }
36+ /// <summary>
37+ /// 視野角
38+ /// </summary>
39+ public float ViewAngle { get; set; }
40+ }
41+}
--- trunk/MikuMikuDanceXNA/Motion/MotionData/MMDMotionData.cs (revision 77)
+++ trunk/MikuMikuDanceXNA/Motion/MotionData/MMDMotionData.cs (revision 78)
@@ -14,5 +14,13 @@
1414 /// フェイスモーションデータ
1515 /// </summary>
1616 public MMDFaceMotion[] FaceMotions { get; set; }
17+ /// <summary>
18+ /// カメラモーションデータ
19+ /// </summary>
20+ public MMDCameraMotion[] CameraMotions { get; set; }
21+ /// <summary>
22+ /// ライトモーションデータ
23+ /// </summary>
24+ public MMDLightMotion[] LightMotions { get; set; }
1725 }
1826 }
--- trunk/MikuMikuDanceXNA/Motion/MotionData/BezierCurve.cs (nonexistent)
+++ trunk/MikuMikuDanceXNA/Motion/MotionData/BezierCurve.cs (revision 78)
@@ -0,0 +1,62 @@
1+using System;
2+using System.Collections.Generic;
3+using System.Linq;
4+using System.Text;
5+using Microsoft.Xna.Framework;
6+
7+namespace MikuMikuDance.XNA.Motion.MotionData
8+{
9+ /// <summary>
10+ /// ベジェ曲線
11+ /// </summary>
12+ public class BezierCurve
13+ {
14+ internal const float Epsilon = 1.0e-3f;
15+ /// <summary>
16+ /// ベジェ曲線に用いる点1
17+ /// </summary>
18+ public Vector2 v1 { get; set; }
19+ /// <summary>
20+ /// ベジェ曲線に用いる点2
21+ /// </summary>
22+ public Vector2 v2 { get; set; }
23+ /// <summary>
24+ /// 進行度合から移行度合を取得
25+ /// </summary>
26+ /// <param name="Progress">進行度合</param>
27+ /// <returns>移行度合</returns>
28+ public float Evaluate(float Progress)
29+ {
30+ //ニュートン法による近似
31+ float t = MathHelper.Clamp(Progress, 0, 1);
32+ float dt;
33+ do
34+ {
35+ dt = -(fx(t) - Progress) / dfx(t);
36+ if (float.IsNaN(dt))
37+ break;
38+ t += MathHelper.Clamp(dt, -1f, 1f);//大幅に移動して別の解に到達するのを防止する用
39+ } while (Math.Abs(dt) > Epsilon);
40+ return MathHelper.Clamp(fy(t), 0f, 1f);//念のため、0-1の間に収まるようにした
41+ }
42+
43+ private float fy(float t)
44+ {
45+ //fy(t)=(1-t)^3*0+3*(1-t)^2*t*v1.y+3*(1-t)*t^2*v2.y+t^3*1
46+ return 3 * (1 - t) * (1 - t) * t * v1.Y + 3 * (1 - t) * t * t * v2.Y + t * t * t;
47+ }
48+
49+ float fx(float t)
50+ {
51+ //fx(t)=(1-t)^3*0+3*(1-t)^2*t*v1.x+3*(1-t)*t^2*v2.x+t^3*1
52+ return 3 * (1 - t) * (1 - t) * t * v1.X + 3 * (1 - t) * t * t * v2.X + t * t * t;
53+ }
54+ float dfx(float t)
55+ {
56+ //dfx(t)/dt=-6(1-t)*t*v1.x+3(1-t)^2*v1.x-3t^2*v2.x+6(1-t)*t*v2.x+3t^2
57+ return -6 * (1 - t) * t * v1.X + 3 * (1 - t) * (1 - t) * v1.X
58+ - 3 * t * t * v2.X + 6 * (1 - t) * t * v2.X + 3 * t * t;
59+ }
60+
61+ }
62+}
\ No newline at end of file
--- trunk/MikuMikuDanceXNA/Motion/MotionData/MMDBoneMotion.cs (revision 77)
+++ trunk/MikuMikuDanceXNA/Motion/MotionData/MMDBoneMotion.cs (revision 78)
@@ -3,60 +3,8 @@
33
44 namespace MikuMikuDance.XNA.Motion.MotionData
55 {
6+
67 /// <summary>
7- /// ベジェ曲線
8- /// </summary>
9- public class BezierCurve
10- {
11- internal const float Epsilon = 1.0e-3f;
12- /// <summary>
13- /// ベジェ曲線に用いる点1
14- /// </summary>
15- public Vector2 v1 { get; set; }
16- /// <summary>
17- /// ベジェ曲線に用いる点2
18- /// </summary>
19- public Vector2 v2 { get; set; }
20- /// <summary>
21- /// 進行度合から移行度合を取得
22- /// </summary>
23- /// <param name="Progress">進行度合</param>
24- /// <returns>移行度合</returns>
25- public float Evaluate(float Progress)
26- {
27- //ニュートン法による近似
28- float t = MathHelper.Clamp(Progress, 0, 1);
29- float dt;
30- do
31- {
32- dt = -(fx(t)-Progress) / dfx(t);
33- if (float.IsNaN(dt))
34- break;
35- t += dt;
36- } while (dt > Epsilon);
37- return fy(t);
38- }
39-
40- private float fy(float t)
41- {
42- //fy(t)=(1-t)^3*0+3*(1-t)^2*t*v1.y+3*(1-t)*t^2*v2.y+t^3*1
43- return 3 * (1 - t) * (1 - t) * t * v1.Y + 3 * (1 - t) * t * t * v2.Y + t * t * t;
44- }
45-
46- float fx(float t)
47- {
48- //fx(t)=(1-t)^3*0+3*(1-t)^2*t*v1.x+3*(1-t)*t^2*v2.x+t^3*1
49- return 3 * (1 - t) * (1 - t) * t * v1.X + 3 * (1 - t) * t * t * v2.X + t * t * t;
50- }
51- float dfx(float t)
52- {
53- //dfx(t)/dt=-6(1-t)*t*v1.x+3(1-t)^2*v1.x-3t^2*v2.x+6(1-t)*t*v2.x+3t^2
54- return -6 * (1 - t) * t * v1.X + 3 * (1 - t) * (1 - t) * v1.X
55- - 3 * t * t * v2.X + 6 * (1 - t) * t * v2.X + 3 * t * t;
56- }
57-
58- }
59- /// <summary>
608 /// ボーンモーションデータ
619 /// </summary>
6210 public class MMDBoneMotion
@@ -80,6 +28,7 @@
8028 /// <summary>
8129 /// 補完用曲線
8230 /// </summary>
31+ /// <remarks>順にX,Y,Z,回転</remarks>
8332 public BezierCurve[] Curve { get; set; }
8433
8534
--- trunk/MikuMikuDanceXNA/Motion/AnimationPlayer.cs (revision 77)
+++ trunk/MikuMikuDanceXNA/Motion/AnimationPlayer.cs (revision 78)
@@ -73,7 +73,8 @@
7373 mmdNMotion[index].motion = motion;
7474 mmdNMotion[index].IsEmpty = false;
7575 mmdMotion[index] = mmdNMotion[index];//オブジェクトプールから引っ張ってくる
76- Update(index);
76+ if (SetStartPos)
77+ Update(index);
7778 }
7879 /// <summary>
7980 /// モーションをストップする
@@ -114,6 +115,8 @@
114115 {
115116 for (int i = 0; i < mmdMotion.Length; i++)
116117 {
118+ if (mmdMotion[i].IsEmpty)
119+ continue;
117120 Start(i, gameTime, bLoopPlay);
118121 }
119122 }
--- trunk/MikuMikuDanceXNA/Motion/MMDMotion.cs (revision 77)
+++ trunk/MikuMikuDanceXNA/Motion/MMDMotion.cs (revision 78)
@@ -109,6 +109,7 @@
109109 {
110110 Array.Sort(i.Value, new FaceCompare());
111111 }
112+
112113 }
113114 //ソート用
114115 class BoneComparer : IComparer<MMDBoneMotion>
@@ -193,7 +194,7 @@
193194 ProgY = motions[NextPos].Curve[1].Evaluate(Progress);
194195 ProgZ = motions[NextPos].Curve[2].Evaluate(Progress);
195196
196- float ProgR = motions[NextPos].Curve[0].Evaluate(Progress);
197+ float ProgR = motions[NextPos].Curve[3].Evaluate(Progress);
197198 float x,y,z;
198199 x = MathHelper.Lerp(motions[BeforePos].Location.X, motions[NextPos].Location.X, ProgX);
199200 y = MathHelper.Lerp(motions[BeforePos].Location.Y, motions[NextPos].Location.Y, ProgY);
@@ -252,5 +253,7 @@
252253 }
253254 return rate;
254255 }
256+
257+
255258 }
256259 }
--- trunk/MikuMikuDanceXNA/Motion/NormalMotionTrack.cs (revision 77)
+++ trunk/MikuMikuDanceXNA/Motion/NormalMotionTrack.cs (revision 78)
@@ -61,7 +61,7 @@
6161
6262 public void Start()
6363 {
64- if (!timer.IsRunning)
64+ if (timer.IsRunning)
6565 return;
6666 timer.Start();
6767 beforeMS = (decimal)timer.Elapsed.TotalMilliseconds - LossTime;
--- trunk/MikuMikuDanceXNA/Stages/CameraMotionTrack.cs (nonexistent)
+++ trunk/MikuMikuDanceXNA/Stages/CameraMotionTrack.cs (revision 78)
@@ -0,0 +1,86 @@
1+using System;
2+using System.Collections.Generic;
3+using System.Linq;
4+using System.Text;
5+using MikuMikuDance.XNA.Motion;
6+using System.Diagnostics;
7+using Microsoft.Xna.Framework;
8+
9+namespace MikuMikuDance.XNA.Stages
10+{
11+ class CameraMotionTrack
12+ {
13+ public MMDStageMotion motion;
14+ Stopwatch timer = new Stopwatch();
15+ decimal frame = 0;
16+ decimal beforeMS = 0;
17+ decimal LossTime = 0;
18+ bool isEmpty = true;
19+ bool isLoopPlay;
20+
21+ public bool IsEmpty { get { return isEmpty; } set { isEmpty = value; } }
22+ public bool IsLoopPlay { get { return isLoopPlay; } set { isLoopPlay = value; } }
23+ public void Reset() { motion = null; timer.Reset(); isLoopPlay = false; isEmpty = true; }
24+ public decimal NowFrame { get; set; }
25+ public long MaxFrame { get { return motion.MaxFrame; } }
26+
27+ public void Stop()
28+ {
29+ if (!timer.IsRunning)
30+ return;
31+ timer.Stop();
32+ LossTime = (decimal)timer.Elapsed.TotalMilliseconds - beforeMS;//ロスタイムを計測
33+ }
34+
35+ public void Start()
36+ {
37+ if (!timer.IsRunning)
38+ return;
39+ timer.Start();
40+ beforeMS = (decimal)timer.Elapsed.TotalMilliseconds - LossTime;
41+ }
42+ public bool IsPlay
43+ {
44+ get
45+ {
46+ return timer.IsRunning;
47+ }
48+ }
49+ public void UpdateFrame(decimal FramePerSecond)
50+ {
51+ //現在時刻の取得
52+ decimal nowMS = (decimal)timer.Elapsed.TotalMilliseconds;
53+ //前回コール時からの経過フレーム数を取得
54+ decimal dframe = (nowMS - beforeMS) * FramePerSecond / 1000.0m;
55+ //フレーム数の更新
56+ frame += dframe;
57+ beforeMS = nowMS;
58+
59+ if (frame > motion.MaxFrame && !isLoopPlay)
60+ {
61+ Stop();
62+ NowFrame = (decimal)motion.MaxFrame;
63+ }
64+ NowFrame = frame % (decimal)(motion.MaxFrame + 1);
65+ }
66+
67+ public void ApplyMotion(MMDCamera mmdCamera)
68+ {
69+ float Length, ViewAngle;
70+ Vector3 Locate ;
71+ Quaternion Rotate;
72+ //モーションデータを計算
73+ motion.GetCameraData(NowFrame, out Length, out Locate, out Rotate, out ViewAngle);
74+ //カメラ位置を計算
75+ Vector3 CameraPos = new Vector3(0, 0, 1) * Length;
76+ CameraPos = Vector3.Transform(CameraPos, Rotate) + Locate;
77+ mmdCamera.CameraPos = CameraPos;
78+ //ターゲット位置を計算
79+ mmdCamera.CameraTarget = Locate;
80+ //Upvectorを計算
81+ mmdCamera.CameraUpVector = Vector3.Transform(Vector3.Up, Rotate);
82+ //viewAngleを適応
83+ mmdCamera.FieldOfView = ViewAngle;
84+ }
85+ }
86+}
--- trunk/MikuMikuDanceXNA/Stages/CameraAnimationPlayer.cs (nonexistent)
+++ trunk/MikuMikuDanceXNA/Stages/CameraAnimationPlayer.cs (revision 78)
@@ -0,0 +1,122 @@
1+using System;
2+using System.Collections.Generic;
3+using System.Linq;
4+using System.Text;
5+using MikuMikuDance.XNA.Motion;
6+using Microsoft.Xna.Framework;
7+
8+namespace MikuMikuDance.XNA.Stages
9+{
10+ /// <summary>
11+ /// モーションファイルからカメラモーションを再生するアニメーションプレイヤー
12+ /// </summary>
13+ public class CameraAnimationPlayer
14+ {
15+ //カメラ
16+ MMDCamera camera;
17+ //現在のモーション一覧
18+ CameraMotionTrack[] mmdMotion = new CameraMotionTrack[MikuMikuDanceXNA.MotionTrackCap];
19+
20+ /// <summary>
21+ /// 一秒あたりのフレーム数
22+ /// </summary>
23+ public int FramePerSecond { get; set; }
24+
25+
26+ internal CameraAnimationPlayer(MMDCamera camera)
27+ {
28+ this.camera = camera;
29+ FramePerSecond = 30;//MMDは30フレーム/秒が標準
30+ for (int i = 0; i < mmdMotion.Length; i++)
31+ mmdMotion[i] = new CameraMotionTrack();
32+ }
33+
34+ /// <summary>
35+ /// モーションがループプレイかどうかを調べる
36+ /// </summary>
37+ /// <param name="index">モーションインデックス番号</param>
38+ /// <returns>ループプレイならtrue</returns>
39+ public bool IsLoopPlay(int index)
40+ {
41+ return mmdMotion[index].IsLoopPlay;
42+ }
43+ /// <summary>
44+ /// モーションの再生状態を取得
45+ /// </summary>
46+ /// <param name="index">モーショントラック番号</param>
47+ /// <returns>再生中ならtrue</returns>
48+ public bool IsPlay(int index)
49+ {
50+ return (mmdMotion[index].IsPlay);
51+ }
52+
53+ /// <summary>
54+ /// 開いているトラックにモーションをセット
55+ /// </summary>
56+ /// <param name="index">トラック番号(0〜MikuMikuDanceXNA.MotionTrackCap)</param>
57+ /// <param name="motion">セットするMMDステージモーションデータ</param>
58+ /// <param name="SetStartPos">0フレームのデータでカメラを初期化する</param>
59+ /// <returns>セットしたトラックの番号。開いているトラックが無ければ-1</returns>
60+ public void SetMotion(int index, MMDStageMotion motion, bool SetStartPos)
61+ {
62+ //オブジェクトプールのモーショントラックにデータをセット
63+ mmdMotion[index].Reset();
64+ mmdMotion[index].motion = motion;
65+ mmdMotion[index].IsEmpty = false;
66+ mmdMotion[index] = mmdMotion[index];//オブジェクトプールから引っ張ってくる
67+ if (SetStartPos)
68+ Update(index);
69+ }
70+
71+ /// <summary>
72+ /// 指定したトラックにモーションをセット
73+ /// </summary>
74+ /// <param name="motion">セットするMMDモーションデータ</param>
75+ /// <param name="SetStartPos">0フレームのデータでカメラを初期化する</param>
76+ public int SetMotion(MMDStageMotion motion, bool SetStartPos)
77+ {
78+ int Index = -1;
79+ for (Index = 0; Index < MikuMikuDanceXNA.MotionTrackCap; Index++)
80+ if (mmdMotion[Index].IsEmpty)
81+ break;
82+ if (Index >= MikuMikuDanceXNA.MotionTrackCap)
83+ return -1;
84+ SetMotion(Index, motion, SetStartPos);
85+ return Index;
86+ }
87+ /// <summary>
88+ /// モーションを再生する
89+ /// </summary>
90+ /// <param name="index">モーションインデックス番号</param>
91+ /// <param name="gameTime">GameTimeオブジェクト</param>
92+ /// <param name="bLoopPlay">ループプレイ</param>
93+ public void Start(int index, GameTime gameTime, bool bLoopPlay)
94+ {
95+ if (mmdMotion[index].IsEmpty)
96+ throw new ApplicationException("モーションデータがセットされてないのにStartを実行した");
97+ mmdMotion[index].Start();
98+ mmdMotion[index].IsLoopPlay = bLoopPlay;
99+ }
100+ /// <summary>
101+ /// モーションをストップする
102+ /// </summary>
103+ public void Stop(int index)
104+ {
105+ mmdMotion[index].Stop();
106+ }
107+
108+ internal void Update(int motionIndex)
109+ {
110+ for (int i = (motionIndex < 0 ? 0 : motionIndex); i < (motionIndex < 0 ? mmdMotion.Length : motionIndex + 1); i++)
111+ {
112+ //再生中かどうかチェック
113+ if (!mmdMotion[i].IsEmpty && mmdMotion[i].IsPlay)
114+ {
115+ //現在の再生フレームを更新
116+ mmdMotion[i].UpdateFrame(camera.Player.FramePerSecond);
117+ mmdMotion[i].ApplyMotion(camera);
118+ }
119+ }
120+ }
121+ }
122+}
\ No newline at end of file
--- trunk/MikuMikuDanceXNA/Stages/MMDCamera.cs (revision 77)
+++ trunk/MikuMikuDanceXNA/Stages/MMDCamera.cs (revision 78)
@@ -8,7 +8,7 @@
88 /// 仮組み。最終的にどうするかは未定。
99 /// このままでもいい気もするけど……
1010 /// </summary>
11- public class MMDCamera
11+ public class MMDCamera : GameComponent
1212 {
1313 /// <summary>
1414 /// カメラのポジション
@@ -35,9 +35,14 @@
3535 /// </summary>
3636 public float Far { get; set; }
3737 /// <summary>
38+ /// アニメーションプレイヤー
39+ /// </summary>
40+ public CameraAnimationPlayer Player { get; set; }
41+ /// <summary>
3842 /// 既定のコンストラクタ
3943 /// </summary>
40- internal MMDCamera()
44+ internal MMDCamera(Game game)
45+ :base(game)
4146 {
4247 //CameraPos = new Vector3(-35, 10, 0);
4348 CameraPos = new Vector3(0, 10, 35);
@@ -46,6 +51,7 @@
4651 FieldOfView = MathHelper.PiOver4;
4752 Near = 1.0f;
4853 Far = 10000.0f;
54+ Player = new CameraAnimationPlayer(this);
4955 }
5056 /// <summary>
5157 /// ビューマトリックス取得
@@ -66,5 +72,13 @@
6672 float aspectRatio = (float)viewport.Width / (float)viewport.Height;
6773 return Matrix.CreatePerspectiveFieldOfView(FieldOfView, aspectRatio, Near, Far);
6874 }
75+ /// <summary>
76+ /// カメラUpdate
77+ /// </summary>
78+ /// <param name="gameTime">ゲームタイムオブジェクト</param>
79+ public override void Update(GameTime gameTime)
80+ {
81+ Player.Update(-1);
82+ }
6983 }
7084 }
--- trunk/MikuMikuDanceXNA/Stages/MMDStageMotion.cs (nonexistent)
+++ trunk/MikuMikuDanceXNA/Stages/MMDStageMotion.cs (revision 78)
@@ -0,0 +1,92 @@
1+using System;
2+using System.Collections.Generic;
3+using System.Linq;
4+using System.Text;
5+using MikuMikuDance.XNA.Motion.MotionData;
6+using Microsoft.Xna.Framework;
7+
8+namespace MikuMikuDance.XNA.Stages
9+{
10+ /// <summary>
11+ /// カメラ・ライト用のモーションクラス
12+ /// </summary>
13+ public class MMDStageMotion
14+ {
15+ //内部データ
16+ internal MMDMotionData MotionData { get; private set; }
17+ internal MikuMikuDanceXNA mmdXNA { get; private set; }
18+
19+ internal long MaxFrame { get; set; }
20+
21+ internal MMDStageMotion() { }//外から作らせない
22+ internal void Initialize(MMDMotionData motionData, MikuMikuDanceXNA mmdxna, bool ToCameraUse)
23+ {
24+ MotionData = motionData;
25+ mmdXNA = mmdxna;
26+ if (ToCameraUse)
27+ MaxFrame = motionData.CameraMotions.Last().FrameNo;
28+ else
29+ MaxFrame = motionData.LightMotions.Last().FrameNo;
30+ }
31+ internal void GetCameraData(decimal NowFrame, out float Length, out Vector3 Locate, out Quaternion Rotate, out float ViewAngle)
32+ {
33+ //前後のフレームをチェック
34+ long BeforePos = 0;
35+ long NextPos = 0;
36+ for (NextPos = 0; NextPos < MotionData.CameraMotions.Length; NextPos++)
37+ {
38+ if (MotionData.CameraMotions[NextPos].FrameNo > NowFrame)
39+ break;
40+ }
41+ BeforePos = NextPos - 1;
42+ if (NextPos >= MotionData.CameraMotions.Length)
43+ {
44+ if (BeforePos == -1)
45+ {
46+ //モーションが無い……?
47+ //仕方ないのでMMDのデフォルト値挿入
48+ Length = 35;
49+ Locate = new Vector3(0, 10, 0);
50+ Rotate = Quaternion.Identity;
51+ ViewAngle = MathHelper.PiOver4;
52+ }
53+ else
54+ {
55+ Length = MotionData.CameraMotions[BeforePos].Length;
56+ Locate = MotionData.CameraMotions[BeforePos].Location;
57+ Rotate = MotionData.CameraMotions[BeforePos].Quatanion;
58+ ViewAngle = MotionData.CameraMotions[BeforePos].ViewAngle;
59+ }
60+ }
61+ else if (BeforePos == -1)
62+ {
63+ Length = MotionData.CameraMotions[NextPos].Length;
64+ Locate = MotionData.CameraMotions[NextPos].Location;
65+ Rotate = MotionData.CameraMotions[NextPos].Quatanion;
66+ ViewAngle = MotionData.CameraMotions[NextPos].ViewAngle;
67+ }
68+ else
69+ {
70+
71+ float Progress = ((float)(NowFrame - MotionData.CameraMotions[BeforePos].FrameNo)) / ((float)(MotionData.CameraMotions[NextPos].FrameNo - MotionData.CameraMotions[BeforePos].FrameNo));
72+ float ProgX, ProgY, ProgZ;
73+ ProgX = MotionData.CameraMotions[NextPos].Curve[0].Evaluate(Progress);
74+ ProgY = MotionData.CameraMotions[NextPos].Curve[1].Evaluate(Progress);
75+ ProgZ = MotionData.CameraMotions[NextPos].Curve[2].Evaluate(Progress);
76+ float ProgR = MotionData.CameraMotions[NextPos].Curve[3].Evaluate(Progress);
77+ float ProgLen = MotionData.CameraMotions[NextPos].Curve[4].Evaluate(Progress);
78+ float ProgVA = MotionData.CameraMotions[NextPos].Curve[5].Evaluate(Progress);
79+
80+ float x, y, z;
81+ x = MathHelper.Lerp(MotionData.CameraMotions[BeforePos].Location.X, MotionData.CameraMotions[NextPos].Location.X, ProgX);
82+ y = MathHelper.Lerp(MotionData.CameraMotions[BeforePos].Location.Y, MotionData.CameraMotions[NextPos].Location.Y, ProgY);
83+ z = MathHelper.Lerp(MotionData.CameraMotions[BeforePos].Location.Z, MotionData.CameraMotions[NextPos].Location.Z, ProgZ);
84+
85+ Locate = new Vector3(x, y, z);
86+ Rotate = Quaternion.Slerp(MotionData.CameraMotions[BeforePos].Quatanion, MotionData.CameraMotions[NextPos].Quatanion, ProgR);
87+ Length = MathHelper.Lerp(MotionData.CameraMotions[BeforePos].Length, MotionData.CameraMotions[NextPos].Length, ProgLen);
88+ ViewAngle = MathHelper.Lerp(MotionData.CameraMotions[BeforePos].ViewAngle, MotionData.CameraMotions[NextPos].ViewAngle, ProgVA);
89+ }
90+ }
91+ }
92+}
--- trunk/MikuMikuDanceXNA/memo.txt (revision 77)
+++ trunk/MikuMikuDanceXNA/memo.txt (revision 78)
@@ -43,7 +43,9 @@
4343 -処理の高速化
4444 -ライティングをMMDに近づけた(スポットライトだけ未実装)
4545 -モーションのベイク機能実装。マルチスレッド化
46--
46+-モーションの回転の補完を間違えてX軸の補完にしていたのを修正
47+-ベイク前のモーションを再生しないようなエンバグをしていたので修正
48+-モーションの補完計算のニュートン法にミスがあったため、安全装置も追加して修正
4749
4850
4951 MMDX周りの技術メモ
Show on old repository browser