OSDN Git Service

renamed
[tdcgexplorer/tso2mqo.git] / TSOGenerator.cs
1 using System;\r
2 using System.Collections.Generic;\r
3 using System.Drawing.Design;\r
4 using System.IO;\r
5 using System.Text;\r
6 using System.Runtime.InteropServices;\r
7 using System.ComponentModel;\r
8 using System.Windows.Forms;\r
9 using System.Windows.Forms.Design;\r
10 \r
11 namespace Tso2MqoGui\r
12 {\r
13     public unsafe class TSOGenerator\r
14     {\r
15         private string                      dir;\r
16         private TSOGenerateConfig           config;\r
17         private PointCluster                pc;\r
18         private MqoFile                     mqo;\r
19         private TSOFile                     tsor;\r
20         private List<Vertex>                vlst;\r
21         private Dictionary<string, TSONode> nodes;\r
22         private List<TSOMesh>               meshes;\r
23         private string                      mqoin;\r
24         private string                      tsoref;\r
25         private string                      tsoex;\r
26         private ImportInfo                  ii;\r
27         private BinaryWriter                bw;\r
28         private Dictionary<string, MaterialInfo>    materials;\r
29         private Dictionary<string, TextureInfo>     textures;\r
30 \r
31         public TSOFile  LoadTSO(string file)\r
32         {\r
33             TSOFile         tso = new TSOFile(file);\r
34             tso.ReadAll();\r
35             return tso;\r
36         }\r
37 \r
38         private void CreatePointCluster(TSOFile tso)\r
39         {\r
40             vlst= new List<Vertex>();\r
41 \r
42             foreach(TSOMesh i in tso.meshes)\r
43             foreach(TSOSubMesh j in i.sub)\r
44                 vlst.AddRange(j.vertices);\r
45 \r
46             pc  = new PointCluster(vlst.Count);\r
47 \r
48             foreach(Vertex i in vlst)\r
49                 pc.Add(i.Pos.x, i.Pos.y, i.Pos.z);\r
50 \r
51             pc.Clustering();\r
52         }\r
53 \r
54         private bool Common_DoSetupDir()\r
55         {\r
56             Environment.CurrentDirectory= dir= Path.GetDirectoryName(mqoin);\r
57             return true;\r
58         }\r
59 \r
60         private bool Common_DoLoadMQO()\r
61         {\r
62             // MQO読み込み\r
63             mqo = new MqoFile();\r
64             mqo.Load(mqoin);\r
65             mqo.Dump();\r
66             return true;\r
67         }\r
68 \r
69         private bool AutoBone_DoLoadRefTSO()\r
70         {\r
71             // 参照TSOロード\r
72             tsor    = LoadTSO(tsoref);\r
73 \r
74             foreach(TSOMesh i in tsor.meshes)\r
75             foreach(TSOSubMesh j in i.sub)\r
76             {\r
77                 int[]   bones   = j.bones;\r
78 \r
79                 for(int k= 0, n= j.numvertices; k < n; ++k)\r
80                 {\r
81                     // ボーンをグローバルな番号に変換\r
82                     uint    idx0= j.vertices[k].Idx;\r
83                     byte*   idx = (byte*)(&idx0);\r
84                     idx[0]      = (byte)bones[idx[0]];\r
85                     idx[1]      = (byte)bones[idx[1]];\r
86                     idx[2]      = (byte)bones[idx[2]];\r
87                     idx[3]      = (byte)bones[idx[3]];\r
88                     j.vertices[k].Idx   = idx0;\r
89                 }\r
90             }\r
91 \r
92             CreatePointCluster(tsor);\r
93             return true;\r
94         }\r
95 \r
96         private bool OneBone_DoLoadRefTSO()\r
97         {\r
98             // 参照TSOロード\r
99             tsor    = LoadTSO(tsoref);\r
100             return true;\r
101         }\r
102 \r
103         private bool Common_DoLoadXml()\r
104         {\r
105             // XML読み込み\r
106             ii  = ImportInfo.Load(Path.ChangeExtension(mqoin, ".xml"));\r
107 \r
108             // 使用マテリアル一覧取得\r
109             materials       = new Dictionary<string, MaterialInfo>();\r
110             bool    validmap= true;\r
111 \r
112             foreach(MqoMaterial i in mqo.Materials)\r
113             {\r
114                 MaterialInfo    mi  = new MaterialInfo(dir, i, ii.GetMaterial(i.name));\r
115                 validmap            &=mi.Valid;\r
116                 materials.Add(i.name, mi);\r
117             }\r
118 \r
119             if(!validmap || config.materialconfig)\r
120             {\r
121                 if(config.cui)\r
122                     throw new Exception("マテリアルの設定が無効です");\r
123 \r
124                 FormMaterial    dlg = new FormMaterial();\r
125                 dlg.materials       = materials;\r
126 \r
127                 if(dlg.ShowDialog() != System.Windows.Forms.DialogResult.OK)\r
128                     return false;\r
129             }\r
130 \r
131             // 使用テクスチャ一覧の取得\r
132             textures        = new Dictionary<string, TextureInfo>();\r
133 \r
134             foreach(MaterialInfo i in materials.Values)\r
135             {\r
136                 string  name= Path.GetFileNameWithoutExtension(i.diffuse);\r
137 \r
138                 if(!textures.ContainsKey(name))\r
139                     textures.Add(name, new TextureInfo(name, i.diffuse));\r
140 \r
141                 name        = Path.GetFileNameWithoutExtension(i.shadow);\r
142 \r
143                 if(!textures.ContainsKey(name))\r
144                     textures.Add(name, new TextureInfo(name, i.shadow));\r
145             }\r
146 \r
147             return true;\r
148         }\r
149 \r
150         private bool Common_DoWriteHeader()\r
151         {\r
152             bw.Write(0x314F5354);\r
153             return true;\r
154         }\r
155 \r
156         private bool Common_DoWriteNodeNames()\r
157         {\r
158             bw.Write(tsor.nodes.Length);\r
159 \r
160             nodes   = new Dictionary<string,TSONode>();\r
161 \r
162             foreach(TSONode i in tsor.nodes)\r
163             {\r
164                 WriteString(bw, i.Name);\r
165                 nodes.Add(i.ShortName, i);\r
166             }\r
167 \r
168             return true;\r
169         }\r
170 \r
171         private bool Common_DoWriteNodeMatrices()\r
172         {\r
173             bw.Write(tsor.nodes.Length);\r
174 \r
175             foreach(TSONode i in tsor.nodes)\r
176                 WriteMatrix(bw, i.Matrix);\r
177 \r
178             return true;\r
179         }\r
180 \r
181         private bool Common_DoWriteTextures()\r
182         {\r
183             bw.Write(textures.Count);\r
184 \r
185             foreach(TextureInfo i in textures.Values)\r
186             {\r
187                 string  file= i.file;\r
188                 string  name= i.name;\r
189 \r
190                 WriteString(bw, name);\r
191                 WriteString(bw, "\"" + Path.GetFileName(file) + "\"");\r
192 \r
193                 // テクスチャの読み込み\r
194                 TSOTex  tex = LoadTex(file);\r
195                 tex.name    = name;\r
196                 bw.Write(tex.Width);\r
197                 bw.Write(tex.Height);\r
198                 bw.Write(tex.Depth);\r
199                 bw.Write(tex.data, 0, tex.data.Length);\r
200 \r
201                 ImportTextureInfo   iti = new ImportTextureInfo(tex);\r
202                 ii.textures.Add(iti);\r
203 \r
204                 // テクスチャが同じフォルダにない場合、コピーしておく\r
205                 if(Path.GetDirectoryName(file).ToUpper() != dir.ToUpper())\r
206                 {\r
207                     iti.File    = Path.Combine(dir, Path.GetFileName(file));\r
208                     File.Copy(file, iti.File, true);\r
209                 }\r
210             }\r
211 \r
212             return true;\r
213         }\r
214 \r
215         private bool Common_DoWriteEffects()\r
216         {\r
217             bw.Write(ii.effects.Count);\r
218 \r
219             foreach(ImportEffectInfo i in ii.effects)\r
220             {\r
221                 string      file= Path.Combine(dir, i.Name);\r
222                 string[]    code= File.ReadAllLines(file, Encoding.Default);\r
223 \r
224                 WriteString(bw, i.Name);\r
225                 bw.Write(code.Length);\r
226 \r
227                 foreach(string j in code)\r
228                     WriteString(bw, j.Trim('\r', '\n'));\r
229             }\r
230 \r
231             return true;\r
232         }\r
233 \r
234         private bool Common_DoWriteMaterials()\r
235         {\r
236             bw.Write(mqo.Materials.Count);\r
237 \r
238             foreach(MqoMaterial i in mqo.Materials)\r
239             {\r
240                 MaterialInfo    mi  = materials[i.name];\r
241                 string[]        code= mi.GetCode();\r
242 \r
243                 WriteString(bw, i.name);\r
244                 WriteString(bw, "cgfxShader");\r
245                 bw.Write(code.Length);\r
246 \r
247                 foreach(string j in code)\r
248                     WriteString(bw, j.Trim('\r', '\n'));\r
249 \r
250                 ImportMaterialInfo  imi = new ImportMaterialInfo();\r
251                 imi.Name                = i.name;\r
252                 imi.File                = "cgfxShader";\r
253                 ii.materials.Add(imi);\r
254 \r
255                 // コードを保存する\r
256                 File.WriteAllLines(Path.Combine(dir, i.name), code);\r
257             }\r
258 \r
259             return true;\r
260         }\r
261 \r
262         private bool AutoBone_DoGenerateMeshes()\r
263         {\r
264             meshes  = new List<TSOMesh>();\r
265 \r
266             foreach(MqoObject i in mqo.Objects)\r
267             {\r
268                 if(i.name.ToLower() == "bone")\r
269                     continue;\r
270 #if true\r
271                 System.Diagnostics.Debug.WriteLine("object:" + i.name);            \r
272 #endif\r
273                 // 一番近い頂点への参照\r
274                 List<int>       vref= new List<int>(i.vertices.Count);\r
275 \r
276                 foreach(Point3 j in i.vertices)\r
277                     vref.Add(pc.NearestIndex(j.x, j.y, j.z));\r
278 \r
279                 // 法線生成\r
280                 Point3[]        nrm = new Point3[i.vertices.Count];\r
281                 \r
282                 foreach(MqoFace j in i.faces)\r
283                 {\r
284                     Point3  v1  = Point3.Normalize(i.vertices[j.b] - i.vertices[j.a]);\r
285                     Point3  v2  = Point3.Normalize(i.vertices[j.c] - i.vertices[j.b]);\r
286                     Point3  n   = Point3.Normalize(Point3.Cross(v1, v2));\r
287 #if false\r
288                     nrm[j.a]    +=n;\r
289                     nrm[j.b]    +=n;\r
290                     nrm[j.c]    +=n;\r
291 #else\r
292                     nrm[j.a]    -=n;\r
293                     nrm[j.b]    -=n;\r
294                     nrm[j.c]    -=n;\r
295 #endif\r
296                 }\r
297 \r
298                 for(int j= 0; j < nrm.Length; ++j)\r
299                     nrm[j]      = Point3.Normalize(nrm[j]);\r
300 \r
301                 // フェイスの組成\r
302                 List<int>               faces1  = new List<int>();\r
303                 List<int>               faces2  = new List<int>();\r
304               //int[]                   bonecnv = new int[tsor.nodes.Length];   // ボーン変換テーブル\r
305                 VertexHeap<Vertex>      vh      = new VertexHeap<Vertex>();\r
306                 Vertex[]                v       = new Vertex[3];\r
307                 List<int>               bones   = new List<int>(16);\r
308                 List<ushort>            indices = new List<ushort>();\r
309                 Dictionary<int, int>    selected= new Dictionary<int,int>();\r
310                 Dictionary<int, int>    work    = new Dictionary<int,int>();\r
311                 List<TSOSubMesh>        subs    = new List<TSOSubMesh>();\r
312 \r
313                 for(int j= 0, n= i.faces.Count; j < n; ++j)\r
314                     faces1.Add(j);\r
315 \r
316 #region ボーンパーティション\r
317                 while(faces1.Count > 0)\r
318                 {\r
319                     int                 mtl     = i.faces[faces1[0]].mtl;\r
320                     selected.Clear();\r
321                     indices .Clear();\r
322                     vh      .Clear();\r
323                     bones   .Clear();\r
324 \r
325                     foreach(int j in faces1)\r
326                     {\r
327                         MqoFace         f       = i.faces[j];\r
328 \r
329                         if(f.mtl != mtl)\r
330                         {\r
331                             faces2.Add(j);\r
332                             continue;\r
333                         }\r
334 \r
335                         v[0]                    = vlst[vref[f.a]];\r
336                         v[1]                    = vlst[vref[f.b]];\r
337                         v[2]                    = vlst[vref[f.c]];\r
338                         bool            valid       = true;\r
339                         work.Clear();\r
340 \r
341                         for(int k= 0; k < 3; ++k)\r
342                         {\r
343                             Vertex      vv      = v[k];\r
344                             UInt32      idx0    = vv.Idx;\r
345                             Point4      wgt0    = vv.Wgt;\r
346                             byte*       idx     = (byte*)(&idx0);\r
347                             float*      wgt     = (float*)(&wgt0);\r
348 \r
349 //                              if(idx0 != 0)\r
350 //                                  idx0            = idx0;\r
351 \r
352                             for(int l= 0; l < 4; ++l)\r
353                             {\r
354                                 if(wgt[l] <= float.Epsilon)         continue;\r
355                                 if(selected.ContainsKey(idx[l]))    continue;\r
356                                 \r
357                                 if(selected.Count == 16)\r
358                                 {\r
359                                     valid   = false;\r
360                                     break;\r
361                                 }\r
362 \r
363                                 if(!work.ContainsKey(idx[l]))\r
364                                     work.Add(idx[l], 0);\r
365 \r
366                                 if(selected.Count + work.Count >= 17)\r
367                                 {\r
368                                     valid   = false;\r
369                                     break;\r
370                                 }\r
371                             }\r
372 \r
373                             if(!valid)\r
374                                 break;\r
375                         }\r
376 \r
377                         if(!valid)\r
378                         {\r
379                             faces2.Add(j);\r
380                             continue;\r
381                         }\r
382 \r
383                         // ボーンリストに足してvalid\r
384                         foreach(KeyValuePair<int, int> l in work)\r
385                         {\r
386                             System.Diagnostics.Debug.WriteLine(\r
387                                 string.Format("Add: {0} -> {1}", l.Key, selected.Count)); \r
388                             selected.Add(l.Key, selected.Count);    // ボーンテーブルに追加\r
389                             bones.Add(l.Key);\r
390                         }\r
391 \r
392                         // \todo 点の追加\r
393                         Vertex  va  = new Vertex(i.vertices[f.a], v[0].Wgt, v[0].Idx, nrm[f.a], new Point2(f.ta.x, 1-f.ta.y));\r
394                         Vertex  vb  = new Vertex(i.vertices[f.b], v[1].Wgt, v[1].Idx, nrm[f.b], new Point2(f.tb.x, 1-f.tb.y));\r
395                         Vertex  vc  = new Vertex(i.vertices[f.c], v[2].Wgt, v[2].Idx, nrm[f.c], new Point2(f.tc.x, 1-f.tc.y));\r
396 #if false\r
397                         indices.Add(vh.Add(va));\r
398                         indices.Add(vh.Add(vb));\r
399                         indices.Add(vh.Add(vc));\r
400 #else\r
401                         indices.Add(vh.Add(va));\r
402                         indices.Add(vh.Add(vc));\r
403                         indices.Add(vh.Add(vb));\r
404 #endif\r
405                     }\r
406 \r
407                     // フェイス最適化\r
408                     ushort[]    nidx    = NvTriStrip.Optimize(indices.ToArray());\r
409 \r
410                     // 頂点のボーン参照ローカルに変換\r
411                     Vertex[]    verts   = vh.verts.ToArray();\r
412 \r
413                     for(int j= 0; j < verts.Length; ++j)\r
414                     {\r
415                         uint        idx0= verts[j].Idx;\r
416                         byte*       idx = (byte*)(&idx0);\r
417                         Point4      wgt0= verts[j].Wgt;\r
418                         float*      wgt = (float*)(&wgt0);\r
419 \r
420                         for(int k= 0; k < 4; ++k)\r
421                             if(wgt[k] > float.Epsilon)\r
422                                 idx[k]  = (byte)selected[idx[k]];\r
423 \r
424                         verts[j].Idx    = idx0;\r
425                     }\r
426 \r
427                     // サブメッシュ生成\r
428                     TSOSubMesh  sub = new TSOSubMesh();\r
429                     sub.spec        = mtl;\r
430                     sub.numbones    = bones.Count;\r
431                     sub.bones       = bones.ToArray();\r
432                     sub.numvertices = nidx.Length;\r
433                     sub.vertices    = new Vertex[nidx.Length];\r
434                    \r
435                     for(int j= 0; j < nidx.Length; ++j)\r
436                         sub.vertices[j] = verts[nidx[j]];\r
437 \r
438                     subs.Add(sub);\r
439 \r
440                     // 次の周回\r
441                     List<int>   t   = faces1;\r
442                     faces1          = faces2;\r
443                     faces2          = t;\r
444                     t.Clear();\r
445                 }\r
446 #endregion\r
447                 // \todo TSOMesh生成\r
448                 TSOMesh mesh    = new TSOMesh();\r
449                 mesh.name       = i.name;\r
450                 mesh.numsubs    = subs.Count;\r
451                 mesh.sub        = subs.ToArray();\r
452                 mesh.matrix     = Matrix44.Identity;\r
453                 mesh.effect     = 0;\r
454                 meshes.Add(mesh);\r
455             }\r
456 \r
457             return true;\r
458         }\r
459 \r
460         private bool OneBone_DoGenerateMeshes()\r
461         {\r
462             meshes  = new List<TSOMesh>();\r
463 \r
464             foreach(MqoObject i in mqo.Objects)\r
465             {\r
466                 if(i.name.ToLower() == "bone")\r
467                     continue;\r
468 #if true\r
469                 System.Diagnostics.Debug.WriteLine("object:" + i.name);            \r
470 #endif\r
471                 // 法線生成\r
472                 Point3[]        nrm = new Point3[i.vertices.Count];\r
473                 \r
474                 foreach(MqoFace j in i.faces)\r
475                 {\r
476                     Point3  v1  = Point3.Normalize(i.vertices[j.b] - i.vertices[j.a]);\r
477                     Point3  v2  = Point3.Normalize(i.vertices[j.c] - i.vertices[j.b]);\r
478                     Point3  n   = Point3.Normalize(Point3.Cross(v1, v2));\r
479                     nrm[j.a]    -=n;\r
480                     nrm[j.b]    -=n;\r
481                     nrm[j.c]    -=n;\r
482                 }\r
483 \r
484                 for(int j= 0; j < nrm.Length; ++j)\r
485                     nrm[j]      = Point3.Normalize(nrm[j]);\r
486 \r
487                 // ボーン情報作成\r
488                 uint                idx     = 0x00000000;\r
489                 Point4              wgt     = new Point4(1, 0, 0, 0);\r
490                 int[]               bones   = new int[1];\r
491                 string              bone    = config.boneref[i.name];\r
492                 bones[0]                    = nodes[bone].ID;\r
493 \r
494                 // マテリアル別に処理を実行\r
495                 List<ushort>        indices = new List<ushort>();\r
496                 VertexHeap<Vertex>  vh      = new VertexHeap<Vertex>();\r
497                 List<TSOSubMesh>    subs    = new List<TSOSubMesh>();\r
498 \r
499                 for(int j= 0, n= materials.Count; j < n; ++j)\r
500                 {\r
501                     int mtl = j;\r
502                     indices.Clear();\r
503 \r
504                     foreach(MqoFace f in i.faces)\r
505                     {\r
506                         if(f.mtl != mtl)\r
507                             continue;\r
508 \r
509                         Vertex  va  = new Vertex(i.vertices[f.a], wgt, idx, nrm[f.a], new Point2(f.ta.x, 1-f.ta.y));\r
510                         Vertex  vb  = new Vertex(i.vertices[f.b], wgt, idx, nrm[f.b], new Point2(f.tb.x, 1-f.tb.y));\r
511                         Vertex  vc  = new Vertex(i.vertices[f.c], wgt, idx, nrm[f.c], new Point2(f.tc.x, 1-f.tc.y));\r
512 \r
513                         indices.Add(vh.Add(va));\r
514                         indices.Add(vh.Add(vc));\r
515                         indices.Add(vh.Add(vb));\r
516                     }\r
517 \r
518                     if(indices.Count == 0)\r
519                         continue;\r
520 \r
521                     // フェイス最適化\r
522                     ushort[]    nidx    = NvTriStrip.Optimize(indices.ToArray());\r
523 \r
524                     // サブメッシュ生成\r
525                     Vertex[]    verts= vh.verts.ToArray();\r
526                     TSOSubMesh  sub = new TSOSubMesh();\r
527                     sub.spec        = mtl;\r
528                     sub.numbones    = bones.Length;\r
529                     sub.bones       = bones;\r
530                     sub.numvertices = nidx.Length;\r
531                     sub.vertices    = new Vertex[nidx.Length];\r
532                    \r
533                     for(int k= 0; k < nidx.Length; ++k)\r
534                         sub.vertices[k] = verts[nidx[k]];\r
535 \r
536                     subs.Add(sub);\r
537                 }\r
538 \r
539                 // メッシュ生成\r
540                 TSOMesh mesh    = new TSOMesh();\r
541                 mesh.name       = i.name;\r
542                 mesh.numsubs    = subs.Count;\r
543                 mesh.sub        = subs.ToArray();\r
544                 mesh.matrix     = Matrix44.Identity;\r
545                 mesh.effect     = 0;\r
546                 meshes.Add(mesh);\r
547             }\r
548 \r
549             return true;\r
550         }\r
551 \r
552         private bool Common_DoWriteMeshes()\r
553         {\r
554             bw.Write(meshes.Count);\r
555 \r
556             foreach(TSOMesh i in meshes)\r
557             {\r
558                 WriteString(bw, i.Name);\r
559                 WriteMatrix(bw, i.Matrix);\r
560                 bw.Write(1);\r
561                 bw.Write(i.numsubs);\r
562 \r
563                 foreach(TSOSubMesh j in i.sub)\r
564                 {\r
565                     bw.Write(j.spec);\r
566                     bw.Write(j.numbones);\r
567 \r
568                     foreach(int k in j.bones)\r
569                         bw.Write(k);\r
570 \r
571                     bw.Write(j.numvertices);\r
572 \r
573                     foreach(Vertex k in j.vertices)\r
574                         WriteVertex(bw, k);\r
575                 }\r
576             }\r
577 \r
578             return true;\r
579         }\r
580 \r
581         private bool AutoBone_DoOutput()\r
582         {\r
583             //----- 出力処理 -----------------------------------------------\r
584             ii.materials.Clear();\r
585             ii.textures.Clear();\r
586 \r
587             using(FileStream fs= File.OpenWrite(tsoex))\r
588             {\r
589                 fs.SetLength(0);\r
590                 bw      = new BinaryWriter(fs);\r
591 \r
592                 Common_DoWriteHeader();\r
593                 Common_DoWriteNodeNames();\r
594                 Common_DoWriteNodeMatrices();\r
595                 Common_DoWriteTextures();\r
596                 Common_DoWriteEffects();\r
597                 Common_DoWriteMaterials();\r
598                 AutoBone_DoGenerateMeshes();\r
599                 Common_DoWriteMeshes();\r
600             }\r
601 \r
602             return true;\r
603         }\r
604 \r
605         private bool OneBone_DoOutput()\r
606         {\r
607             //----- 出力処理 -----------------------------------------------\r
608             ii.materials.Clear();\r
609             ii.textures.Clear();\r
610 \r
611             using(FileStream fs= File.OpenWrite(tsoex))\r
612             {\r
613                 fs.SetLength(0);\r
614                 bw      = new BinaryWriter(fs);\r
615 \r
616                 Common_DoWriteHeader();\r
617                 Common_DoWriteNodeNames();\r
618                 Common_DoWriteNodeMatrices();\r
619                 Common_DoWriteTextures();\r
620                 Common_DoWriteEffects();\r
621                 Common_DoWriteMaterials();\r
622                 OneBone_DoGenerateMeshes();\r
623                 Common_DoWriteMeshes();\r
624             }\r
625 \r
626             return true;\r
627         }\r
628 \r
629         private bool Common_DoSaveXml()\r
630         {\r
631             // 結果を保存しておく\r
632             ImportInfo.Save(Path.ChangeExtension(mqoin, ".xml"), ii);\r
633             return true;\r
634         }\r
635 \r
636         private bool Common_DoCleanup()\r
637         {\r
638             dir         = null;\r
639             pc          = null;\r
640             tsor        = null;\r
641             vlst        = null;\r
642             nodes       = null;\r
643             meshes      = null;\r
644             mqoin       = null;\r
645             tsoref      = null;\r
646             tsoex       = null;\r
647             config      = null;\r
648             mqo         = null;\r
649             ii          = null;\r
650             bw          = null;\r
651             materials   = null;\r
652             textures    = null;\r
653 \r
654             System.GC.Collect();\r
655             return true;\r
656         }\r
657 \r
658         public unsafe void GenerateOneBone(string mqoin, string tsoref, string tsoex, TSOGenerateConfig config)\r
659         {\r
660             this.mqoin  = mqoin;\r
661             this.tsoref = tsoref;\r
662             this.tsoex  = tsoex;\r
663             this.config = config;\r
664 \r
665             try\r
666             {\r
667                 if(!Common_DoSetupDir())        return;\r
668                 if(!Common_DoLoadMQO())         return;\r
669                 if(!OneBone_DoLoadRefTSO())     return;\r
670                 if(!Common_DoLoadXml())         return;\r
671                 if(!OneBone_DoOutput())         return;\r
672                 if(!Common_DoSaveXml())         return;\r
673             } finally\r
674             {\r
675                 Common_DoCleanup();\r
676             }\r
677         }\r
678         \r
679         public unsafe void GenerateAutoBone(string mqoin, string tsoref, string tsoex, TSOGenerateConfig config)\r
680         {\r
681             this.mqoin  = mqoin;\r
682             this.tsoref = tsoref;\r
683             this.tsoex  = tsoex;\r
684             this.config = config;\r
685 \r
686             try\r
687             {\r
688                 if(!Common_DoSetupDir())        return;\r
689                 if(!Common_DoLoadMQO())         return;\r
690                 if(!AutoBone_DoLoadRefTSO())    return;\r
691                 if(!Common_DoLoadXml())         return;\r
692                 if(!AutoBone_DoOutput())        return;\r
693                 if(!Common_DoSaveXml())         return;\r
694             } finally\r
695             {\r
696                 Common_DoCleanup();\r
697             }\r
698         }\r
699 #region ユーティリティ\r
700         public void WriteString(BinaryWriter bw, string s)\r
701         {\r
702             byte[]  b   = Encoding.ASCII.GetBytes(s);\r
703             bw.Write(b);\r
704             bw.Write((byte)0);\r
705         }\r
706 \r
707         public void WriteMatrix(BinaryWriter bw, Matrix44 m)\r
708         {\r
709             bw.Write(m.M11); bw.Write(m.M12); bw.Write(m.M13); bw.Write(m.M14);\r
710             bw.Write(m.M21); bw.Write(m.M22); bw.Write(m.M23); bw.Write(m.M24);\r
711             bw.Write(m.M31); bw.Write(m.M32); bw.Write(m.M33); bw.Write(m.M34);\r
712             bw.Write(m.M41); bw.Write(m.M42); bw.Write(m.M43); bw.Write(m.M44);\r
713         }\r
714 \r
715         public unsafe void WriteVertex(BinaryWriter bw, Vertex v)\r
716         {\r
717             uint        idx0    = v.Idx;\r
718             byte*       idx     = (byte*)(&idx0);\r
719             List<int>   idxs    = new List<int>(4);\r
720             List<float> wgts    = new List<float>(4);\r
721 \r
722             if(v.Wgt.x > 0) { idxs.Add(idx[0]); wgts.Add(v.Wgt.x); }\r
723             if(v.Wgt.y > 0) { idxs.Add(idx[1]); wgts.Add(v.Wgt.y); }\r
724             if(v.Wgt.z > 0) { idxs.Add(idx[2]); wgts.Add(v.Wgt.z); }\r
725             if(v.Wgt.w > 0) { idxs.Add(idx[3]); wgts.Add(v.Wgt.w); }\r
726 \r
727             bw.Write(v.Pos.X); bw.Write(v.Pos.Y); bw.Write(v.Pos.Z);\r
728             bw.Write(v.Nrm.X); bw.Write(v.Nrm.Y); bw.Write(v.Nrm.Z);\r
729             bw.Write(v.Tex.X); bw.Write(v.Tex.Y);\r
730 \r
731             bw.Write(wgts.Count);\r
732 \r
733             for(int i= 0, n= idxs.Count; i < n; ++i)\r
734             {\r
735                 bw.Write(idxs[i]);\r
736                 bw.Write(wgts[i]);\r
737             }\r
738         }\r
739 #endregion\r
740 #region テクスチャ処理\r
741         public TSOTex   LoadTex(string file)\r
742         {\r
743             string  ext = Path.GetExtension(file).ToUpper();\r
744             TSOTex  tex;\r
745 \r
746             switch(ext)\r
747             {\r
748             case ".TGA":    tex= LoadTarga(file);   break;\r
749             case ".BMP":    tex= LoadBitmap(file);  break;\r
750             default:        throw new Exception("Unsupported texture file: " + file);\r
751             }\r
752 \r
753             for(int i= 0, n= tex.data.Length; i < n; i+=tex.Depth)\r
754             {\r
755                 byte    b       = tex.data[i+0];\r
756                 tex.data[i+0]   = tex.data[i+2];\r
757                 tex.data[i+2]   = b;\r
758             }\r
759 \r
760             return tex;\r
761         }\r
762 \r
763         public unsafe TSOTex   LoadTarga(string file)\r
764         {\r
765             using(FileStream fs= File.OpenRead(file))\r
766             {\r
767                 BinaryReader        br      = new BinaryReader(fs);\r
768                 TARGA_HEADER        header;\r
769 \r
770                 Marshal.Copy(br.ReadBytes(sizeof(TARGA_HEADER)), 0, (IntPtr)(&header), sizeof(TARGA_HEADER));\r
771 \r
772                 if(header.imagetype != 0x02)    throw new Exception("Invalid imagetype: " + file);\r
773                 if(header.depth     != 24\r
774                 && header.depth     != 32)      throw new Exception("Invalid depth: " + file);\r
775                 \r
776                 TSOTex      tex = new TSOTex();\r
777                 tex.depth       = header.depth  / 8;\r
778                 tex.width       = header.width;\r
779                 tex.height      = header.height;\r
780                 tex.file        = file;\r
781                 tex.data        = br.ReadBytes(tex.width * tex.height * tex.depth);\r
782 \r
783                 return tex;\r
784             }\r
785         }\r
786 \r
787         public unsafe TSOTex   LoadBitmap(string file)\r
788         {\r
789             using(FileStream fs= File.OpenRead(file))\r
790             {\r
791                 BinaryReader        br      = new BinaryReader(fs);\r
792                 BITMAPFILEHEADER    bfh;\r
793                 BITMAPINFOHEADER    bih;\r
794 \r
795                 Marshal.Copy(br.ReadBytes(sizeof(BITMAPFILEHEADER)), 0, (IntPtr)(&bfh), sizeof(BITMAPFILEHEADER));\r
796                 Marshal.Copy(br.ReadBytes(sizeof(BITMAPINFOHEADER)), 0, (IntPtr)(&bih), sizeof(BITMAPINFOHEADER));\r
797 \r
798                 if(bfh.bfType != 0x4D42)        throw new Exception("Invalid imagetype: " + file);\r
799                 if(bih.biBitCount != 24\r
800                 && bih.biBitCount != 32)        throw new Exception("Invalid depth: " + file);\r
801                 \r
802                 TSOTex      tex = new TSOTex();\r
803                 tex.depth       = bih.biBitCount  / 8;\r
804                 tex.width       = bih.biWidth;\r
805                 tex.height      = bih.biHeight;\r
806                 tex.file        = file;\r
807                 tex.data        = br.ReadBytes(tex.width * tex.height * tex.depth);\r
808 \r
809                 return tex;\r
810             }\r
811         }\r
812 #endregion\r
813     }\r
814 \r
815     public class TextureInfo\r
816     {\r
817         public string name;\r
818         public string file;\r
819 \r
820         public TextureInfo(string name, string file)\r
821         {\r
822             this.name   = name;\r
823             this.file   = file;\r
824         }\r
825     }\r
826 \r
827     public class MaterialInfo\r
828     {\r
829         public string           name;\r
830         public string           shader;\r
831         public string           diffuse;\r
832         public string           shadow;\r
833       //public Dictionary<string, string>   parameters;\r
834 \r
835         public MaterialInfo(string path, MqoMaterial mqom, ImportMaterialInfo impm)\r
836         {\r
837             name    = mqom.name;\r
838             diffuse = mqom.tex;\r
839 \r
840             if(impm != null)\r
841             {\r
842                 string  file= Path.Combine(path, impm.Name);\r
843 \r
844                 if(File.Exists(file))\r
845                     shader          = file;\r
846 \r
847                 if(impm.shadow != null)\r
848                 {\r
849                     file        = Path.Combine(path, impm.shadow.File);\r
850 \r
851                     if(File.Exists(file))\r
852                         shadow  = file;\r
853                 }\r
854             }\r
855         }\r
856 \r
857         public bool   Valid\r
858         {\r
859             get\r
860             {\r
861                 return File.Exists(shader)\r
862                     && File.Exists(diffuse)\r
863                     && File.Exists(shadow);\r
864             }\r
865         }\r
866 \r
867         public string[] GetCode()\r
868         {\r
869             TSOMaterialCode code= TSOMaterialCode.GenerateFromFile(shader);\r
870             List<string>    line= new List<string>();\r
871 \r
872             code.SetValue("ColorTex", Path.GetFileNameWithoutExtension(diffuse));\r
873             code.SetValue("ShadeTex", Path.GetFileNameWithoutExtension(shadow));\r
874 \r
875             foreach(KeyValuePair<string, TSOParameter> i in code)\r
876                 line.Add(i.Value.ToString());\r
877 \r
878             return line.ToArray();\r
879         }\r
880 \r
881         public string Name           { get { return name;    } }\r
882         \r
883         [Editor(typeof(FileNameEditor), typeof(UITypeEditor))]\r
884         [DisplayNameAttribute("シェーダー設定ファイル")]\r
885         public string ShaderFile     { get { return shader;  } set { shader  = value; } }\r
886         \r
887         [Editor(typeof(FileNameEditor), typeof(UITypeEditor))]\r
888         [DisplayNameAttribute("テクスチャ:カラー")]\r
889         public string DiffuseTexture { get { return diffuse; } set { diffuse = value; } }\r
890 \r
891         [Editor(typeof(FileNameEditor), typeof(UITypeEditor))]\r
892         [DisplayNameAttribute("テクスチャ:シェーティング")]\r
893         public string ShadowTexture  { get { return shadow;  } set { shadow  = value; } }\r
894     }\r
895 }\r