• R/O
  • SSH
  • HTTPS

mmdx: Commit


Commit MetaInfo

Revision87 (tree)
Zeit2010-03-22 10:25:48
Autorwilfrem

Log Message

パイプラインでビルド出来るようにビルド処理機構の切り離し作業途中

Ändern Zusammenfassung

Diff

--- trunk/MikuMikuDanceXNA/Motion/MotionData/MMDBakedMotionReader.cs (nonexistent)
+++ trunk/MikuMikuDanceXNA/Motion/MotionData/MMDBakedMotionReader.cs (revision 87)
@@ -0,0 +1,53 @@
1+using System;
2+using System.Collections.Generic;
3+using System.Linq;
4+using Microsoft.Xna.Framework;
5+using Microsoft.Xna.Framework.Content;
6+using Microsoft.Xna.Framework.Graphics;
7+
8+// TODO: replace this with the type you want to read.
9+using TRead = MikuMikuDance.XNA.Motion.MotionData.MMDBakedMotionData;
10+
11+namespace MikuMikuDance.XNA.Motion.MotionData
12+{
13+ /// <summary>
14+ /// ベイク済みモーション読み込み用タイプリーダー
15+ /// </summary>
16+ public class MMDBakedMotionReader : ContentTypeReader<TRead>
17+ {
18+ /// <summary>
19+ /// ベイク済みモーション読み込み用タイプリーダー
20+ /// </summary>
21+ /// <param name="input">コンテンツリーダー</param>
22+ /// <param name="existingInstance">既存のインスタンス</param>
23+ /// <returns>ベイク済みモーションデータ</returns>
24+ protected override TRead Read(ContentReader input, TRead existingInstance)
25+ {
26+ if (existingInstance != null)
27+ return existingInstance;
28+ TRead result = new MMDBakedMotionData();
29+ int size1, size2;
30+ size1 = input.ReadInt32();
31+ size2 = input.ReadInt32();
32+ result.Poses = new BakedBoneData[size1, size2];
33+ for (int i = 0; i < size1; i++)
34+ {
35+ for (int j = 0; j < size2; j++)
36+ {
37+ result.Poses[i, j] = input.ReadObject<BakedBoneData>();
38+ }
39+ }
40+ size1 = input.ReadInt32();
41+ size2 = input.ReadInt32();
42+ result.Faces = new BakedFaceData[size1, size2];
43+ for (int i = 0; i < size1; i++)
44+ {
45+ for (int j = 0; j < size2; j++)
46+ {
47+ result.Faces[i, j] = input.ReadObject<BakedFaceData>();
48+ }
49+ }
50+ return result;
51+ }
52+ }
53+}
--- trunk/MikuMikuDanceXNA/Motion/MotionData/MMDBakedMotionData.cs (revision 86)
+++ trunk/MikuMikuDanceXNA/Motion/MotionData/MMDBakedMotionData.cs (revision 87)
@@ -10,7 +10,16 @@
1010 /// </summary>
1111 public class MMDBakedMotionData
1212 {
13+ /// <summary>
14+ /// ベイク済みポーズ(フレーム番号,ポーズ番号)
15+ /// </summary>
16+ public BakedBoneData[,] Poses;
17+ /// <summary>
18+ /// ベイク済み表情(フレーム番号,番号)
19+ /// </summary>
20+ public BakedFaceData[,] Faces;
1321 }
1422
1523
24+
1625 }
--- trunk/MikuMikuDanceXNA/Motion/AnimationPlayer.cs (revision 86)
+++ trunk/MikuMikuDanceXNA/Motion/AnimationPlayer.cs (revision 87)
@@ -188,7 +188,9 @@
188188 return;
189189 //トラック準備
190190 NormalMotionTrack normal = mmdMotion[index] as NormalMotionTrack;
191- BakedMotionTrack result = new BakedMotionTrack();
191+
192+ //AnimationBakerに移行
193+ /*
192194 int NumFrame = (int)normal.MaxFrame + 1;//モーション数の限界はuintなのだが、.Net CFは配列が対応してない……
193195 //モーションに含まれているボーンと表情一覧取得
194196 List<string> BoneList = normal.motion.GetBoneList();
@@ -232,9 +234,10 @@
232234 }
233235 }
234236 //データ配列をセット
237+ BakedMotionTrack result = new BakedMotionTrack();
235238 result.Poses = new BakedBoneData[NumFrame, BoneList.Count];
236- result.Faces = new BakedFaceData[NumFrame, FaceList.Count];
237- //退避用の配列にボーン情報を退避
239+ result.Faces = new BakedFaceData[NumFrame, FaceList.Count];*/
240+ //退避用の配列にボーン情報と表情を退避
238241 QuatTransform[] PopedBones = new QuatTransform[mmdModel.BoneManager.Count];
239242 for (int i = 0; i < mmdModel.BoneManager.Count; i++)
240243 {
@@ -242,8 +245,20 @@
242245 }
243246 Dictionary<string, float> PopedFaces = mmdModel.FaceManager.FaceRates;
244247 mmdModel.FaceManager.FaceRates = new Dictionary<string, float>();
245-
248+
249+ //AnimationBakerに処理を投げる
246250 #if XBOX360
251+ int NumThread = MikuMikuDanceXNA.NumThread;
252+#else
253+ int NumThread = mmdModel.mmdXNA.NumThread;
254+#endif
255+ MikuMikuDance.XNA.Motion.MotionData.MMDBakedMotionData bakedData = AnimationBaker.Bake(NumThread, normal, mmdModel.BoneManager, mmdModel.FaceManager);
256+ BakedMotionTrack result = new BakedMotionTrack();
257+ result.Faces = bakedData.Faces;
258+ result.Poses = bakedData.Poses;
259+
260+ /*
261+#if XBOX360
247262 BakeTaskManager[] tasks = new BakeTaskManager[MikuMikuDanceXNA.NumThread];
248263 #else
249264 BakeTaskManager[] tasks = new BakeTaskManager[mmdModel.mmdXNA.NumThread];
@@ -268,7 +283,7 @@
268283 {
269284 tasks[thread].thread.Join();//処理終わりまで待つ
270285
271- }
286+ }*/
272287 result.IsEmpty = false;
273288 //ベイク済みモーションを再セット
274289 mmdMotion[index] = result;
@@ -280,65 +295,6 @@
280295 mmdModel.FaceManager.FaceRates = PopedFaces;
281296 mmdModel.BoneManager.Update();
282297 }
283- /// <summary>
284- /// ベイク用ワーカースレッドのためのクラス
285- /// </summary>
286- class BakeTaskManager
287- {
288- public Thread thread;
289- public int index;
290- public int NumThread;
291- public int NumFrame;
292- public bool[] BoneUpdated;
293- //readだけなので、Clone要らず
294- public Dictionary<int, int> BoneTable;
295- public List<string> FaceList;
296- //処理分けするのでClone要らず
297- public BakedMotionTrack result;
298- //要Clone
299- public NormalMotionTrack _normal;
300- public MMDBoneManager _BoneManager;
301- public MMDFaceManager _FaceManager;
302-
303- public void Work()
304- {
305-#if XBOX360
306- Thread.CurrentThread.SetProcessorAffinity(index == 3 ? 1 : 5 - index);
307-#endif
308- NormalMotionTrack normal = _normal.CloneForBake();
309- MMDBoneManager BoneManager = _BoneManager.CloneForBake();
310- MMDFaceManager FaceManager = _FaceManager.CloneForBake();
311- //ベイクのために1フレームずつ再生する
312- for (int Frame = index; Frame < NumFrame; Frame += NumThread)
313- {
314- Array.Clear(BoneUpdated, 0, BoneUpdated.Length);
315- //現在の再生フレームをセットし更新
316- normal.NowFrame = Frame;
317- normal.ApplyMotion(BoneManager, FaceManager, ref BoneUpdated);
318-
319- //IKボーンの処理前にモデルのワールド座標系更新
320- BoneManager.UpdateWorldTransforms();
321- //IKボーンの処理
322- for (int i2 = 0; i2 < BoneManager.Count; i2++)
323- {
324- if (BoneManager[i2].BoneData.IK != null && BoneUpdated[i2])
325- BoneManager.SolveIK(i2, BoneManager[i2].BoneTransform);
326- }
327- //処理済みボーン情報を抽出して保存
328- foreach(var it in BoneTable)
329- {
330- result.Poses[Frame, it.Value].BoneIndex = it.Key;
331- result.Poses[Frame, it.Value].Poses = BoneManager[it.Key].BoneTransform;
332-
333- }
334- //表情の抽出
335- for (int i = 0; i < FaceList.Count; i++)
336- {
337- result.Faces[Frame, i].Rate = normal.motion.GetFaceRate(FaceList[i], Frame);
338- result.Faces[Frame, i].FaceName = FaceList[i];
339- }
340- }
341- }
342- }
298+
343299 }
344300 }
--- trunk/MikuMikuDanceXNA/Motion/BakedMotionTrack.cs (revision 86)
+++ trunk/MikuMikuDanceXNA/Motion/BakedMotionTrack.cs (revision 87)
@@ -8,14 +8,32 @@
88
99 namespace MikuMikuDance.XNA.Motion
1010 {
11- struct BakedBoneData
11+ /// <summary>
12+ /// ベイク済みの各ボーンのデータ
13+ /// </summary>
14+ public struct BakedBoneData
1215 {
16+ /// <summary>
17+ /// ボーン番号
18+ /// </summary>
1319 public int BoneIndex;
20+ /// <summary>
21+ /// トランスフォーム
22+ /// </summary>
1423 public QuatTransform Poses;
1524 }
16- struct BakedFaceData
25+ /// <summary>
26+ /// ベイク済みの各表情データ
27+ /// </summary>
28+ public struct BakedFaceData
1729 {
30+ /// <summary>
31+ /// 表情名
32+ /// </summary>
1833 public string FaceName;
34+ /// <summary>
35+ /// 表情適応率
36+ /// </summary>
1937 public float Rate;
2038 }
2139 class BakedMotionTrack : MotionTrack
--- trunk/MikuMikuDanceXNA/Motion/MMDMotion.cs (revision 86)
+++ trunk/MikuMikuDanceXNA/Motion/MMDMotion.cs (revision 87)
@@ -26,9 +26,17 @@
2626 //表情名ごとに時系列順に並べ直したモーションデータ
2727 Dictionary<string, MMDFaceMotion[]> FaceMotions;
2828 internal long MaxFrame { get; private set; }
29- internal MMDMotion() { }//外から作らせない
3029
31- internal void Initialize(MMDMotionData motionData)
30+ /// <summary>
31+ /// コンストラクタ
32+ /// </summary>
33+ public MMDMotion() { }
34+
35+ /// <summary>
36+ /// モーションデータを元に初期化
37+ /// </summary>
38+ /// <param name="motionData">モーションデータ</param>
39+ public void Initialize(MMDMotionData motionData)
3240 {
3341 MotionData = motionData;
3442 //モーションデータ内を検索し、ボーン辞書を作っておく
--- trunk/MikuMikuDanceXNA/Motion/NormalMotionTrack.cs (revision 86)
+++ trunk/MikuMikuDanceXNA/Motion/NormalMotionTrack.cs (revision 87)
@@ -12,9 +12,11 @@
1212 /// <summary>
1313 /// 通常のモーショントラック
1414 /// </summary>
15- class NormalMotionTrack : MotionTrack
15+ public class NormalMotionTrack : MotionTrack
1616 {
17- //このモーションに関連付けられている
17+ /// <summary>
18+ /// このモーショントラックに関連付けられているモーションデータ
19+ /// </summary>
1820 public MMDMotion motion;
1921 Stopwatch timer = new Stopwatch();
2022 decimal frame = 0;
@@ -23,11 +25,29 @@
2325 bool isEmpty = true;
2426 bool isLoopPlay;
2527
28+ /// <summary>
29+ /// 未初期化フラグ
30+ /// </summary>
2631 public bool IsEmpty { get { return isEmpty; } set { isEmpty = value; } }
32+ /// <summary>
33+ /// ループプレイフラグ
34+ /// </summary>
2735 public bool IsLoopPlay { get { return isLoopPlay; } set { isLoopPlay = value; } }
36+ /// <summary>
37+ /// モーショントラック初期化
38+ /// </summary>
2839 public void Reset() { motion = null; timer.Reset(); isLoopPlay = false; isEmpty = true; }
40+ /// <summary>
41+ /// モーショントラックの現在の再生フレームを取得/設定
42+ /// </summary>
2943 public decimal NowFrame { get; set; }
44+ /// <summary>
45+ /// モーショントラックの最大フレームを取得
46+ /// </summary>
3047 public long MaxFrame { get { return motion.MaxFrame; } }
48+ /// <summary>
49+ /// モーショントラックの種別を取得
50+ /// </summary>
3151 public TrackType Type { get { return TrackType.NormalTrack; } }
3252
3353 /// <summary>
@@ -50,7 +70,9 @@
5070 newTrack.NowFrame = NowFrame;
5171 return newTrack;
5272 }
53-
73+ /// <summary>
74+ /// モーショントラックの再生停止
75+ /// </summary>
5476 public void Stop()
5577 {
5678 if (!timer.IsRunning)
@@ -58,7 +80,9 @@
5880 timer.Stop();
5981 LossTime = (decimal)timer.Elapsed.TotalMilliseconds - beforeMS;//ロスタイムを計測
6082 }
61-
83+ /// <summary>
84+ /// モーショントラックの再生
85+ /// </summary>
6286 public void Start()
6387 {
6488 if (timer.IsRunning)
@@ -66,6 +90,9 @@
6690 timer.Start();
6791 beforeMS = (decimal)timer.Elapsed.TotalMilliseconds - LossTime;
6892 }
93+ /// <summary>
94+ /// モーショントラックを再生中かどうか取得
95+ /// </summary>
6996 public bool IsPlay
7097 {
7198 get
@@ -73,6 +100,10 @@
73100 return timer.IsRunning;
74101 }
75102 }
103+ /// <summary>
104+ /// モーショントラックの再生フレームを更新
105+ /// </summary>
106+ /// <param name="FramePerSecond"></param>
76107 public void UpdateFrame(decimal FramePerSecond)
77108 {
78109 //現在時刻の取得
@@ -90,7 +121,12 @@
90121 }
91122 NowFrame = frame % (decimal)(motion.MaxFrame + 1);
92123 }
93-
124+ /// <summary>
125+ /// 現在の再生フレームにあわせてボーンと表情を設定
126+ /// </summary>
127+ /// <param name="mmdBone">ボーンマネージャ</param>
128+ /// <param name="mmdFace">フェイスマネージャ</param>
129+ /// <param name="BoneUpdated">更新されたボーンはtrueとなる</param>
94130 public void ApplyMotion(MMDBoneManager mmdBone, MMDFaceManager mmdFace, ref bool[] BoneUpdated)
95131 {
96132 //モーションのボーンリストを取得
--- trunk/MikuMikuDanceXNA/Motion/AnimationBaker.cs (nonexistent)
+++ trunk/MikuMikuDanceXNA/Motion/AnimationBaker.cs (revision 87)
@@ -0,0 +1,165 @@
1+using System;
2+using System.Collections.Generic;
3+using System.Linq;
4+using System.Text;
5+using MikuMikuDance.XNA.Model;
6+using System.Threading;
7+using MikuMikuDance.XNA.Motion.MotionData;
8+
9+namespace MikuMikuDance.XNA.Motion
10+{
11+ /// <summary>
12+ /// アニメーションベイククラス
13+ /// </summary>
14+ public static class AnimationBaker
15+ {
16+
17+ //スレッド準備系
18+ /// <summary>
19+ /// モーションをベイクする
20+ /// </summary>
21+ /// <param name="NumThread">使用するスレッド数</param>
22+ /// <param name="normal">ベイクするノーマルモーショントラック</param>
23+ /// <param name="BoneManager">ボーンマネージャ</param>
24+ /// <param name="FaceManager">フェイスマネージャー</param>
25+ /// <returns>ベイク済みモーションデータ</returns>
26+ public static MMDBakedMotionData Bake(int NumThread, NormalMotionTrack normal, MMDBoneManager BoneManager, MMDFaceManager FaceManager)
27+ {
28+
29+
30+ int NumFrame = (int)normal.MaxFrame + 1;//モーション数の限界はuintなのだが、.Net CFは配列が対応してない……
31+ //モーションに含まれているボーンと表情一覧取得
32+ List<string> BoneList = normal.motion.GetBoneList();
33+ List<string> FaceList = normal.motion.GetFaceList();
34+ //変換テーブルセット
35+ Dictionary<int, int> BoneTable = new Dictionary<int, int>();
36+ for (int i = 0; i < BoneList.Count; i++)
37+ {
38+ if (!BoneManager.ContainsBone(BoneList[i]))
39+ {//このモデルにないボーンなので、ベイクから除外
40+ BoneList.RemoveAt(i);
41+ --i;
42+ }
43+ else
44+ {//変換表作成
45+ BoneTable.Add(BoneManager.IndexOf(BoneList[i]), i);
46+
47+ }
48+ }
49+ for (int i = 0; i < BoneList.Count; i++)
50+ {
51+ //IKボーンなら影響下ボーンを登録
52+ if (BoneManager[BoneList[i]].BoneData.IK != null)
53+ {
54+ foreach (var ikchild in BoneManager[BoneList[i]].BoneData.IK.IKChildBones)
55+ {
56+ if (!BoneTable.ContainsKey(ikchild))
57+ {
58+ BoneList.Add(BoneManager[ikchild].BoneData.Name);
59+ BoneTable.Add(ikchild, BoneList.Count - 1);
60+ }
61+ }
62+ }
63+ }
64+ for (int i = 0; i < FaceList.Count; i++)
65+ {
66+ if (!FaceManager.ContainsFace(FaceList[i]))
67+ {//このモデルに無い表情なので、ベイクから除外
68+ FaceList.RemoveAt(i);
69+ --i;
70+ }
71+ }
72+ //データ配列をセット
73+ MMDBakedMotionData result = new MMDBakedMotionData();
74+ result.Poses = new BakedBoneData[NumFrame, BoneList.Count];
75+ result.Faces = new BakedFaceData[NumFrame, FaceList.Count];
76+ BakeTaskManager[] tasks = new BakeTaskManager[NumThread];
77+ for (int thread = 0; thread < tasks.Length; thread++)
78+ {
79+ tasks[thread] = new BakeTaskManager();
80+ tasks[thread].NumThread = tasks.Length;
81+ tasks[thread].index = thread;
82+ tasks[thread].NumFrame = NumFrame;
83+ tasks[thread].BoneUpdated = new bool[BoneManager.Count];
84+ tasks[thread].BoneTable = BoneTable;
85+ tasks[thread].FaceList = FaceList;
86+ tasks[thread].result = result;
87+ tasks[thread]._FaceManager = FaceManager;
88+ tasks[thread]._normal = normal;
89+ tasks[thread]._BoneManager = BoneManager;
90+ tasks[thread].thread = new Thread(new ThreadStart(tasks[thread].Work));
91+ tasks[thread].thread.Start();//処理が重いのでワーカースレッドに投げる
92+ }
93+ for (int thread = tasks.Length - 1; thread > 0; --thread)
94+ {
95+ tasks[thread].thread.Join();//処理終わりまで待つ
96+
97+ }
98+ return result;
99+ }
100+
101+
102+ //ワーカースレッド系
103+ /// <summary>
104+ /// ベイク用ワーカースレッドのためのクラス
105+ /// </summary>
106+ class BakeTaskManager
107+ {
108+ public Thread thread;
109+ public int index;
110+ public int NumThread;
111+ public int NumFrame;
112+ public bool[] BoneUpdated;
113+ //readだけなので、Clone要らず
114+ public Dictionary<int, int> BoneTable;
115+ public List<string> FaceList;
116+ //処理分けするのでClone要らず
117+ public MMDBakedMotionData result;
118+ //要Clone
119+ public NormalMotionTrack _normal;
120+ public MMDBoneManager _BoneManager;
121+ public MMDFaceManager _FaceManager;
122+
123+
124+ public void Work()
125+ {
126+#if XBOX360
127+ Thread.CurrentThread.SetProcessorAffinity(index == 3 ? 1 : 5 - index);
128+#endif
129+ NormalMotionTrack normal = _normal.CloneForBake();
130+ MMDBoneManager BoneManager = _BoneManager.CloneForBake();
131+ MMDFaceManager FaceManager = _FaceManager.CloneForBake();
132+ //ベイクのために1フレームずつ再生する
133+ for (int Frame = index; Frame < NumFrame; Frame += NumThread)
134+ {
135+ Array.Clear(BoneUpdated, 0, BoneUpdated.Length);
136+ //現在の再生フレームをセットし更新
137+ normal.NowFrame = Frame;
138+ normal.ApplyMotion(BoneManager, FaceManager, ref BoneUpdated);
139+
140+ //IKボーンの処理前にモデルのワールド座標系更新
141+ BoneManager.UpdateWorldTransforms();
142+ //IKボーンの処理
143+ for (int i2 = 0; i2 < BoneManager.Count; i2++)
144+ {
145+ if (BoneManager[i2].BoneData.IK != null && BoneUpdated[i2])
146+ BoneManager.SolveIK(i2, BoneManager[i2].BoneTransform);
147+ }
148+ //処理済みボーン情報を抽出して保存
149+ foreach (var it in BoneTable)
150+ {
151+ result.Poses[Frame, it.Value].BoneIndex = it.Key;
152+ result.Poses[Frame, it.Value].Poses = BoneManager[it.Key].BoneTransform;
153+
154+ }
155+ //表情の抽出
156+ for (int i = 0; i < FaceList.Count; i++)
157+ {
158+ result.Faces[Frame, i].Rate = normal.motion.GetFaceRate(FaceList[i], Frame);
159+ result.Faces[Frame, i].FaceName = FaceList[i];
160+ }
161+ }
162+ }
163+ }
164+ }
165+}
--- trunk/MikuMikuDanceXNA/Motion/MotionTrack.cs (revision 86)
+++ trunk/MikuMikuDanceXNA/Motion/MotionTrack.cs (revision 87)
@@ -7,9 +7,18 @@
77
88 namespace MikuMikuDance.XNA.Motion
99 {
10- enum TrackType
10+ /// <summary>
11+ /// モーショントラック種別
12+ /// </summary>
13+ public enum TrackType
1114 {
15+ /// <summary>
16+ /// 通常トラック
17+ /// </summary>
1218 NormalTrack,
19+ /// <summary>
20+ /// ベイク済みモーショントラック
21+ /// </summary>
1322 BakedTrack,
1423 }
1524 /// <summary>
Show on old repository browser