カメラライトモーション実装中に見つけたバグを一旦コミット
モーションの回転の補完を間違えてX軸の補完にしていたのを修正
ベイク前のモーションを再生しないようなエンバグをしていたので修正
モーションの補間計算に使用していたニュートン法にミスがあったので修正。ついでに安全装置も付加
@@ -69,7 +69,7 @@ | ||
69 | 69 | public MikuMikuDanceXNA(Game game) |
70 | 70 | { |
71 | 71 | Content = game.Content; |
72 | - Camera = new MMDCamera(); | |
72 | + Camera = new MMDCamera(game); | |
73 | 73 | LightManager = new MMDLightManager(); |
74 | 74 | #if WINDOWS |
75 | 75 | //論理コア数を取得して、最適スレッド数を取得 |
@@ -89,7 +89,7 @@ | ||
89 | 89 | public MikuMikuDanceXNA(Game game, btDiscreteDynamicsWorld physic) |
90 | 90 | { |
91 | 91 | Content = game.Content; |
92 | - Camera = new MMDCamera(); | |
92 | + Camera = new MMDCamera(game); | |
93 | 93 | LightManager = new MMDLightManager(); |
94 | 94 | #if WINDOWS |
95 | 95 | //論理コア数を取得して、最適スレッド数を取得 |
@@ -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 |
@@ -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 | +} |
@@ -14,5 +14,13 @@ | ||
14 | 14 | /// フェイスモーションデータ |
15 | 15 | /// </summary> |
16 | 16 | 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; } | |
17 | 25 | } |
18 | 26 | } |
@@ -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 |
@@ -3,60 +3,8 @@ | ||
3 | 3 | |
4 | 4 | namespace MikuMikuDance.XNA.Motion.MotionData |
5 | 5 | { |
6 | + | |
6 | 7 | /// <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> | |
60 | 8 | /// ボーンモーションデータ |
61 | 9 | /// </summary> |
62 | 10 | public class MMDBoneMotion |
@@ -80,6 +28,7 @@ | ||
80 | 28 | /// <summary> |
81 | 29 | /// 補完用曲線 |
82 | 30 | /// </summary> |
31 | + /// <remarks>順にX,Y,Z,回転</remarks> | |
83 | 32 | public BezierCurve[] Curve { get; set; } |
84 | 33 | |
85 | 34 |
@@ -73,7 +73,8 @@ | ||
73 | 73 | mmdNMotion[index].motion = motion; |
74 | 74 | mmdNMotion[index].IsEmpty = false; |
75 | 75 | mmdMotion[index] = mmdNMotion[index];//オブジェクトプールから引っ張ってくる |
76 | - Update(index); | |
76 | + if (SetStartPos) | |
77 | + Update(index); | |
77 | 78 | } |
78 | 79 | /// <summary> |
79 | 80 | /// モーションをストップする |
@@ -114,6 +115,8 @@ | ||
114 | 115 | { |
115 | 116 | for (int i = 0; i < mmdMotion.Length; i++) |
116 | 117 | { |
118 | + if (mmdMotion[i].IsEmpty) | |
119 | + continue; | |
117 | 120 | Start(i, gameTime, bLoopPlay); |
118 | 121 | } |
119 | 122 | } |
@@ -109,6 +109,7 @@ | ||
109 | 109 | { |
110 | 110 | Array.Sort(i.Value, new FaceCompare()); |
111 | 111 | } |
112 | + | |
112 | 113 | } |
113 | 114 | //ソート用 |
114 | 115 | class BoneComparer : IComparer<MMDBoneMotion> |
@@ -193,7 +194,7 @@ | ||
193 | 194 | ProgY = motions[NextPos].Curve[1].Evaluate(Progress); |
194 | 195 | ProgZ = motions[NextPos].Curve[2].Evaluate(Progress); |
195 | 196 | |
196 | - float ProgR = motions[NextPos].Curve[0].Evaluate(Progress); | |
197 | + float ProgR = motions[NextPos].Curve[3].Evaluate(Progress); | |
197 | 198 | float x,y,z; |
198 | 199 | x = MathHelper.Lerp(motions[BeforePos].Location.X, motions[NextPos].Location.X, ProgX); |
199 | 200 | y = MathHelper.Lerp(motions[BeforePos].Location.Y, motions[NextPos].Location.Y, ProgY); |
@@ -252,5 +253,7 @@ | ||
252 | 253 | } |
253 | 254 | return rate; |
254 | 255 | } |
256 | + | |
257 | + | |
255 | 258 | } |
256 | 259 | } |
@@ -61,7 +61,7 @@ | ||
61 | 61 | |
62 | 62 | public void Start() |
63 | 63 | { |
64 | - if (!timer.IsRunning) | |
64 | + if (timer.IsRunning) | |
65 | 65 | return; |
66 | 66 | timer.Start(); |
67 | 67 | beforeMS = (decimal)timer.Elapsed.TotalMilliseconds - LossTime; |
@@ -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 | +} |
@@ -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 |
@@ -8,7 +8,7 @@ | ||
8 | 8 | /// 仮組み。最終的にどうするかは未定。 |
9 | 9 | /// このままでもいい気もするけど…… |
10 | 10 | /// </summary> |
11 | - public class MMDCamera | |
11 | + public class MMDCamera : GameComponent | |
12 | 12 | { |
13 | 13 | /// <summary> |
14 | 14 | /// カメラのポジション |
@@ -35,9 +35,14 @@ | ||
35 | 35 | /// </summary> |
36 | 36 | public float Far { get; set; } |
37 | 37 | /// <summary> |
38 | + /// アニメーションプレイヤー | |
39 | + /// </summary> | |
40 | + public CameraAnimationPlayer Player { get; set; } | |
41 | + /// <summary> | |
38 | 42 | /// 既定のコンストラクタ |
39 | 43 | /// </summary> |
40 | - internal MMDCamera() | |
44 | + internal MMDCamera(Game game) | |
45 | + :base(game) | |
41 | 46 | { |
42 | 47 | //CameraPos = new Vector3(-35, 10, 0); |
43 | 48 | CameraPos = new Vector3(0, 10, 35); |
@@ -46,6 +51,7 @@ | ||
46 | 51 | FieldOfView = MathHelper.PiOver4; |
47 | 52 | Near = 1.0f; |
48 | 53 | Far = 10000.0f; |
54 | + Player = new CameraAnimationPlayer(this); | |
49 | 55 | } |
50 | 56 | /// <summary> |
51 | 57 | /// ビューマトリックス取得 |
@@ -66,5 +72,13 @@ | ||
66 | 72 | float aspectRatio = (float)viewport.Width / (float)viewport.Height; |
67 | 73 | return Matrix.CreatePerspectiveFieldOfView(FieldOfView, aspectRatio, Near, Far); |
68 | 74 | } |
75 | + /// <summary> | |
76 | + /// カメラUpdate | |
77 | + /// </summary> | |
78 | + /// <param name="gameTime">ゲームタイムオブジェクト</param> | |
79 | + public override void Update(GameTime gameTime) | |
80 | + { | |
81 | + Player.Update(-1); | |
82 | + } | |
69 | 83 | } |
70 | 84 | } |
@@ -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 | +} |
@@ -43,7 +43,9 @@ | ||
43 | 43 | -処理の高速化 |
44 | 44 | -ライティングをMMDに近づけた(スポットライトだけ未実装) |
45 | 45 | -モーションのベイク機能実装。マルチスレッド化 |
46 | -- | |
46 | +-モーションの回転の補完を間違えてX軸の補完にしていたのを修正 | |
47 | +-ベイク前のモーションを再生しないようなエンバグをしていたので修正 | |
48 | +-モーションの補完計算のニュートン法にミスがあったため、安全装置も追加して修正 | |
47 | 49 | |
48 | 50 | |
49 | 51 | MMDX周りの技術メモ |