パイプラインでビルド出来るようにビルド処理機構の切り離し作業途中
@@ -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 | +} |
@@ -10,7 +10,16 @@ | ||
10 | 10 | /// </summary> |
11 | 11 | public class MMDBakedMotionData |
12 | 12 | { |
13 | + /// <summary> | |
14 | + /// ベイク済みポーズ(フレーム番号,ポーズ番号) | |
15 | + /// </summary> | |
16 | + public BakedBoneData[,] Poses; | |
17 | + /// <summary> | |
18 | + /// ベイク済み表情(フレーム番号,番号) | |
19 | + /// </summary> | |
20 | + public BakedFaceData[,] Faces; | |
13 | 21 | } |
14 | 22 | |
15 | 23 | |
24 | + | |
16 | 25 | } |
@@ -188,7 +188,9 @@ | ||
188 | 188 | return; |
189 | 189 | //トラック準備 |
190 | 190 | NormalMotionTrack normal = mmdMotion[index] as NormalMotionTrack; |
191 | - BakedMotionTrack result = new BakedMotionTrack(); | |
191 | + | |
192 | + //AnimationBakerに移行 | |
193 | + /* | |
192 | 194 | int NumFrame = (int)normal.MaxFrame + 1;//モーション数の限界はuintなのだが、.Net CFは配列が対応してない…… |
193 | 195 | //モーションに含まれているボーンと表情一覧取得 |
194 | 196 | List<string> BoneList = normal.motion.GetBoneList(); |
@@ -232,9 +234,10 @@ | ||
232 | 234 | } |
233 | 235 | } |
234 | 236 | //データ配列をセット |
237 | + BakedMotionTrack result = new BakedMotionTrack(); | |
235 | 238 | 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 | + //退避用の配列にボーン情報と表情を退避 | |
238 | 241 | QuatTransform[] PopedBones = new QuatTransform[mmdModel.BoneManager.Count]; |
239 | 242 | for (int i = 0; i < mmdModel.BoneManager.Count; i++) |
240 | 243 | { |
@@ -242,8 +245,20 @@ | ||
242 | 245 | } |
243 | 246 | Dictionary<string, float> PopedFaces = mmdModel.FaceManager.FaceRates; |
244 | 247 | mmdModel.FaceManager.FaceRates = new Dictionary<string, float>(); |
245 | - | |
248 | + | |
249 | + //AnimationBakerに処理を投げる | |
246 | 250 | #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 | |
247 | 262 | BakeTaskManager[] tasks = new BakeTaskManager[MikuMikuDanceXNA.NumThread]; |
248 | 263 | #else |
249 | 264 | BakeTaskManager[] tasks = new BakeTaskManager[mmdModel.mmdXNA.NumThread]; |
@@ -268,7 +283,7 @@ | ||
268 | 283 | { |
269 | 284 | tasks[thread].thread.Join();//処理終わりまで待つ |
270 | 285 | |
271 | - } | |
286 | + }*/ | |
272 | 287 | result.IsEmpty = false; |
273 | 288 | //ベイク済みモーションを再セット |
274 | 289 | mmdMotion[index] = result; |
@@ -280,65 +295,6 @@ | ||
280 | 295 | mmdModel.FaceManager.FaceRates = PopedFaces; |
281 | 296 | mmdModel.BoneManager.Update(); |
282 | 297 | } |
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 | + | |
343 | 299 | } |
344 | 300 | } |
@@ -8,14 +8,32 @@ | ||
8 | 8 | |
9 | 9 | namespace MikuMikuDance.XNA.Motion |
10 | 10 | { |
11 | - struct BakedBoneData | |
11 | + /// <summary> | |
12 | + /// ベイク済みの各ボーンのデータ | |
13 | + /// </summary> | |
14 | + public struct BakedBoneData | |
12 | 15 | { |
16 | + /// <summary> | |
17 | + /// ボーン番号 | |
18 | + /// </summary> | |
13 | 19 | public int BoneIndex; |
20 | + /// <summary> | |
21 | + /// トランスフォーム | |
22 | + /// </summary> | |
14 | 23 | public QuatTransform Poses; |
15 | 24 | } |
16 | - struct BakedFaceData | |
25 | + /// <summary> | |
26 | + /// ベイク済みの各表情データ | |
27 | + /// </summary> | |
28 | + public struct BakedFaceData | |
17 | 29 | { |
30 | + /// <summary> | |
31 | + /// 表情名 | |
32 | + /// </summary> | |
18 | 33 | public string FaceName; |
34 | + /// <summary> | |
35 | + /// 表情適応率 | |
36 | + /// </summary> | |
19 | 37 | public float Rate; |
20 | 38 | } |
21 | 39 | class BakedMotionTrack : MotionTrack |
@@ -26,9 +26,17 @@ | ||
26 | 26 | //表情名ごとに時系列順に並べ直したモーションデータ |
27 | 27 | Dictionary<string, MMDFaceMotion[]> FaceMotions; |
28 | 28 | internal long MaxFrame { get; private set; } |
29 | - internal MMDMotion() { }//外から作らせない | |
30 | 29 | |
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) | |
32 | 40 | { |
33 | 41 | MotionData = motionData; |
34 | 42 | //モーションデータ内を検索し、ボーン辞書を作っておく |
@@ -12,9 +12,11 @@ | ||
12 | 12 | /// <summary> |
13 | 13 | /// 通常のモーショントラック |
14 | 14 | /// </summary> |
15 | - class NormalMotionTrack : MotionTrack | |
15 | + public class NormalMotionTrack : MotionTrack | |
16 | 16 | { |
17 | - //このモーションに関連付けられている | |
17 | + /// <summary> | |
18 | + /// このモーショントラックに関連付けられているモーションデータ | |
19 | + /// </summary> | |
18 | 20 | public MMDMotion motion; |
19 | 21 | Stopwatch timer = new Stopwatch(); |
20 | 22 | decimal frame = 0; |
@@ -23,11 +25,29 @@ | ||
23 | 25 | bool isEmpty = true; |
24 | 26 | bool isLoopPlay; |
25 | 27 | |
28 | + /// <summary> | |
29 | + /// 未初期化フラグ | |
30 | + /// </summary> | |
26 | 31 | public bool IsEmpty { get { return isEmpty; } set { isEmpty = value; } } |
32 | + /// <summary> | |
33 | + /// ループプレイフラグ | |
34 | + /// </summary> | |
27 | 35 | public bool IsLoopPlay { get { return isLoopPlay; } set { isLoopPlay = value; } } |
36 | + /// <summary> | |
37 | + /// モーショントラック初期化 | |
38 | + /// </summary> | |
28 | 39 | public void Reset() { motion = null; timer.Reset(); isLoopPlay = false; isEmpty = true; } |
40 | + /// <summary> | |
41 | + /// モーショントラックの現在の再生フレームを取得/設定 | |
42 | + /// </summary> | |
29 | 43 | public decimal NowFrame { get; set; } |
44 | + /// <summary> | |
45 | + /// モーショントラックの最大フレームを取得 | |
46 | + /// </summary> | |
30 | 47 | public long MaxFrame { get { return motion.MaxFrame; } } |
48 | + /// <summary> | |
49 | + /// モーショントラックの種別を取得 | |
50 | + /// </summary> | |
31 | 51 | public TrackType Type { get { return TrackType.NormalTrack; } } |
32 | 52 | |
33 | 53 | /// <summary> |
@@ -50,7 +70,9 @@ | ||
50 | 70 | newTrack.NowFrame = NowFrame; |
51 | 71 | return newTrack; |
52 | 72 | } |
53 | - | |
73 | + /// <summary> | |
74 | + /// モーショントラックの再生停止 | |
75 | + /// </summary> | |
54 | 76 | public void Stop() |
55 | 77 | { |
56 | 78 | if (!timer.IsRunning) |
@@ -58,7 +80,9 @@ | ||
58 | 80 | timer.Stop(); |
59 | 81 | LossTime = (decimal)timer.Elapsed.TotalMilliseconds - beforeMS;//ロスタイムを計測 |
60 | 82 | } |
61 | - | |
83 | + /// <summary> | |
84 | + /// モーショントラックの再生 | |
85 | + /// </summary> | |
62 | 86 | public void Start() |
63 | 87 | { |
64 | 88 | if (timer.IsRunning) |
@@ -66,6 +90,9 @@ | ||
66 | 90 | timer.Start(); |
67 | 91 | beforeMS = (decimal)timer.Elapsed.TotalMilliseconds - LossTime; |
68 | 92 | } |
93 | + /// <summary> | |
94 | + /// モーショントラックを再生中かどうか取得 | |
95 | + /// </summary> | |
69 | 96 | public bool IsPlay |
70 | 97 | { |
71 | 98 | get |
@@ -73,6 +100,10 @@ | ||
73 | 100 | return timer.IsRunning; |
74 | 101 | } |
75 | 102 | } |
103 | + /// <summary> | |
104 | + /// モーショントラックの再生フレームを更新 | |
105 | + /// </summary> | |
106 | + /// <param name="FramePerSecond"></param> | |
76 | 107 | public void UpdateFrame(decimal FramePerSecond) |
77 | 108 | { |
78 | 109 | //現在時刻の取得 |
@@ -90,7 +121,12 @@ | ||
90 | 121 | } |
91 | 122 | NowFrame = frame % (decimal)(motion.MaxFrame + 1); |
92 | 123 | } |
93 | - | |
124 | + /// <summary> | |
125 | + /// 現在の再生フレームにあわせてボーンと表情を設定 | |
126 | + /// </summary> | |
127 | + /// <param name="mmdBone">ボーンマネージャ</param> | |
128 | + /// <param name="mmdFace">フェイスマネージャ</param> | |
129 | + /// <param name="BoneUpdated">更新されたボーンはtrueとなる</param> | |
94 | 130 | public void ApplyMotion(MMDBoneManager mmdBone, MMDFaceManager mmdFace, ref bool[] BoneUpdated) |
95 | 131 | { |
96 | 132 | //モーションのボーンリストを取得 |
@@ -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 | +} |
@@ -7,9 +7,18 @@ | ||
7 | 7 | |
8 | 8 | namespace MikuMikuDance.XNA.Motion |
9 | 9 | { |
10 | - enum TrackType | |
10 | + /// <summary> | |
11 | + /// モーショントラック種別 | |
12 | + /// </summary> | |
13 | + public enum TrackType | |
11 | 14 | { |
15 | + /// <summary> | |
16 | + /// 通常トラック | |
17 | + /// </summary> | |
12 | 18 | NormalTrack, |
19 | + /// <summary> | |
20 | + /// ベイク済みモーショントラック | |
21 | + /// </summary> | |
13 | 22 | BakedTrack, |
14 | 23 | } |
15 | 24 | /// <summary> |