OSDN Git Service

removed unused code
[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 \r
271                 // 一番近い頂点への参照\r
272                 List<int>       vref= new List<int>(i.vertices.Count);\r
273 \r
274                 foreach(Point3 j in i.vertices)\r
275                     vref.Add(pc.NearestIndex(j.x, j.y, j.z));\r
276 \r
277                 // 法線生成\r
278                 Point3[]        nrm = new Point3[i.vertices.Count];\r
279                 \r
280                 foreach(MqoFace j in i.faces)\r
281                 {\r
282                     Point3  v1  = Point3.Normalize(i.vertices[j.b] - i.vertices[j.a]);\r
283                     Point3  v2  = Point3.Normalize(i.vertices[j.c] - i.vertices[j.b]);\r
284                     Point3  n   = Point3.Normalize(Point3.Cross(v1, v2));\r
285 \r
286                     nrm[j.a]    -=n;\r
287                     nrm[j.b]    -=n;\r
288                     nrm[j.c]    -=n;\r
289                 }\r
290 \r
291                 for(int j= 0; j < nrm.Length; ++j)\r
292                     nrm[j]      = Point3.Normalize(nrm[j]);\r
293 \r
294                 // フェイスの組成\r
295                 List<int>               faces1  = new List<int>();\r
296                 List<int>               faces2  = new List<int>();\r
297               //int[]                   bonecnv = new int[tsor.nodes.Length];   // ボーン変換テーブル\r
298                 VertexHeap<Vertex>      vh      = new VertexHeap<Vertex>();\r
299                 Vertex[]                v       = new Vertex[3];\r
300                 List<int>               bones   = new List<int>(16);\r
301                 List<ushort>            indices = new List<ushort>();\r
302                 Dictionary<int, int>    selected= new Dictionary<int,int>();\r
303                 Dictionary<int, int>    work    = new Dictionary<int,int>();\r
304                 List<TSOSubMesh>        subs    = new List<TSOSubMesh>();\r
305 \r
306                 for(int j= 0, n= i.faces.Count; j < n; ++j)\r
307                     faces1.Add(j);\r
308 \r
309 #region ボーンパーティション\r
310                 while(faces1.Count > 0)\r
311                 {\r
312                     int                 mtl     = i.faces[faces1[0]].mtl;\r
313                     selected.Clear();\r
314                     indices .Clear();\r
315                     vh      .Clear();\r
316                     bones   .Clear();\r
317 \r
318                     foreach(int j in faces1)\r
319                     {\r
320                         MqoFace         f       = i.faces[j];\r
321 \r
322                         if(f.mtl != mtl)\r
323                         {\r
324                             faces2.Add(j);\r
325                             continue;\r
326                         }\r
327 \r
328                         v[0]                    = vlst[vref[f.a]];\r
329                         v[1]                    = vlst[vref[f.b]];\r
330                         v[2]                    = vlst[vref[f.c]];\r
331                         bool            valid       = true;\r
332                         work.Clear();\r
333 \r
334                         for(int k= 0; k < 3; ++k)\r
335                         {\r
336                             Vertex      vv      = v[k];\r
337                             UInt32      idx0    = vv.Idx;\r
338                             Point4      wgt0    = vv.Wgt;\r
339                             byte*       idx     = (byte*)(&idx0);\r
340                             float*      wgt     = (float*)(&wgt0);\r
341 \r
342 //                              if(idx0 != 0)\r
343 //                                  idx0            = idx0;\r
344 \r
345                             for(int l= 0; l < 4; ++l)\r
346                             {\r
347                                 if(wgt[l] <= float.Epsilon)         continue;\r
348                                 if(selected.ContainsKey(idx[l]))    continue;\r
349                                 \r
350                                 if(selected.Count == 16)\r
351                                 {\r
352                                     valid   = false;\r
353                                     break;\r
354                                 }\r
355 \r
356                                 if(!work.ContainsKey(idx[l]))\r
357                                     work.Add(idx[l], 0);\r
358 \r
359                                 if(selected.Count + work.Count >= 17)\r
360                                 {\r
361                                     valid   = false;\r
362                                     break;\r
363                                 }\r
364                             }\r
365 \r
366                             if(!valid)\r
367                                 break;\r
368                         }\r
369 \r
370                         if(!valid)\r
371                         {\r
372                             faces2.Add(j);\r
373                             continue;\r
374                         }\r
375 \r
376                         // ボーンリストに足してvalid\r
377                         foreach(KeyValuePair<int, int> l in work)\r
378                         {\r
379                             System.Diagnostics.Debug.WriteLine(\r
380                                 string.Format("Add: {0} -> {1}", l.Key, selected.Count)); \r
381                             selected.Add(l.Key, selected.Count);    // ボーンテーブルに追加\r
382                             bones.Add(l.Key);\r
383                         }\r
384 \r
385                         // \todo 点の追加\r
386                         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
387                         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
388                         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
389 \r
390                         indices.Add(vh.Add(va));\r
391                         indices.Add(vh.Add(vc));\r
392                         indices.Add(vh.Add(vb));\r
393                     }\r
394 \r
395                     // フェイス最適化\r
396                     ushort[]    nidx    = NvTriStrip.Optimize(indices.ToArray());\r
397 \r
398                     // 頂点のボーン参照ローカルに変換\r
399                     Vertex[]    verts   = vh.verts.ToArray();\r
400 \r
401                     for(int j= 0; j < verts.Length; ++j)\r
402                     {\r
403                         uint        idx0= verts[j].Idx;\r
404                         byte*       idx = (byte*)(&idx0);\r
405                         Point4      wgt0= verts[j].Wgt;\r
406                         float*      wgt = (float*)(&wgt0);\r
407 \r
408                         for(int k= 0; k < 4; ++k)\r
409                             if(wgt[k] > float.Epsilon)\r
410                                 idx[k]  = (byte)selected[idx[k]];\r
411 \r
412                         verts[j].Idx    = idx0;\r
413                     }\r
414 \r
415                     // サブメッシュ生成\r
416                     TSOSubMesh  sub = new TSOSubMesh();\r
417                     sub.spec        = mtl;\r
418                     sub.numbones    = bones.Count;\r
419                     sub.bones       = bones.ToArray();\r
420                     sub.numvertices = nidx.Length;\r
421                     sub.vertices    = new Vertex[nidx.Length];\r
422                    \r
423                     for(int j= 0; j < nidx.Length; ++j)\r
424                         sub.vertices[j] = verts[nidx[j]];\r
425 \r
426                     subs.Add(sub);\r
427 \r
428                     // 次の周回\r
429                     List<int>   t   = faces1;\r
430                     faces1          = faces2;\r
431                     faces2          = t;\r
432                     t.Clear();\r
433                 }\r
434 #endregion\r
435                 // \todo TSOMesh生成\r
436                 TSOMesh mesh    = new TSOMesh();\r
437                 mesh.name       = i.name;\r
438                 mesh.numsubs    = subs.Count;\r
439                 mesh.sub        = subs.ToArray();\r
440                 mesh.matrix     = Matrix44.Identity;\r
441                 mesh.effect     = 0;\r
442                 meshes.Add(mesh);\r
443             }\r
444 \r
445             return true;\r
446         }\r
447 \r
448         private bool OneBone_DoGenerateMeshes()\r
449         {\r
450             meshes  = new List<TSOMesh>();\r
451 \r
452             foreach(MqoObject i in mqo.Objects)\r
453             {\r
454                 if(i.name.ToLower() == "bone")\r
455                     continue;\r
456 \r
457                 // 法線生成\r
458                 Point3[]        nrm = new Point3[i.vertices.Count];\r
459                 \r
460                 foreach(MqoFace j in i.faces)\r
461                 {\r
462                     Point3  v1  = Point3.Normalize(i.vertices[j.b] - i.vertices[j.a]);\r
463                     Point3  v2  = Point3.Normalize(i.vertices[j.c] - i.vertices[j.b]);\r
464                     Point3  n   = Point3.Normalize(Point3.Cross(v1, v2));\r
465                     nrm[j.a]    -=n;\r
466                     nrm[j.b]    -=n;\r
467                     nrm[j.c]    -=n;\r
468                 }\r
469 \r
470                 for(int j= 0; j < nrm.Length; ++j)\r
471                     nrm[j]      = Point3.Normalize(nrm[j]);\r
472 \r
473                 // ボーン情報作成\r
474                 uint                idx     = 0x00000000;\r
475                 Point4              wgt     = new Point4(1, 0, 0, 0);\r
476                 int[]               bones   = new int[1];\r
477                 string              bone    = config.boneref[i.name];\r
478                 bones[0]                    = nodes[bone].ID;\r
479 \r
480                 // マテリアル別に処理を実行\r
481                 List<ushort>        indices = new List<ushort>();\r
482                 VertexHeap<Vertex>  vh      = new VertexHeap<Vertex>();\r
483                 List<TSOSubMesh>    subs    = new List<TSOSubMesh>();\r
484 \r
485                 for(int j= 0, n= materials.Count; j < n; ++j)\r
486                 {\r
487                     int mtl = j;\r
488                     indices.Clear();\r
489 \r
490                     foreach(MqoFace f in i.faces)\r
491                     {\r
492                         if(f.mtl != mtl)\r
493                             continue;\r
494 \r
495                         Vertex  va  = new Vertex(i.vertices[f.a], wgt, idx, nrm[f.a], new Point2(f.ta.x, 1-f.ta.y));\r
496                         Vertex  vb  = new Vertex(i.vertices[f.b], wgt, idx, nrm[f.b], new Point2(f.tb.x, 1-f.tb.y));\r
497                         Vertex  vc  = new Vertex(i.vertices[f.c], wgt, idx, nrm[f.c], new Point2(f.tc.x, 1-f.tc.y));\r
498 \r
499                         indices.Add(vh.Add(va));\r
500                         indices.Add(vh.Add(vc));\r
501                         indices.Add(vh.Add(vb));\r
502                     }\r
503 \r
504                     if(indices.Count == 0)\r
505                         continue;\r
506 \r
507                     // フェイス最適化\r
508                     ushort[]    nidx    = NvTriStrip.Optimize(indices.ToArray());\r
509 \r
510                     // サブメッシュ生成\r
511                     Vertex[]    verts= vh.verts.ToArray();\r
512                     TSOSubMesh  sub = new TSOSubMesh();\r
513                     sub.spec        = mtl;\r
514                     sub.numbones    = bones.Length;\r
515                     sub.bones       = bones;\r
516                     sub.numvertices = nidx.Length;\r
517                     sub.vertices    = new Vertex[nidx.Length];\r
518                    \r
519                     for(int k= 0; k < nidx.Length; ++k)\r
520                         sub.vertices[k] = verts[nidx[k]];\r
521 \r
522                     subs.Add(sub);\r
523                 }\r
524 \r
525                 // メッシュ生成\r
526                 TSOMesh mesh    = new TSOMesh();\r
527                 mesh.name       = i.name;\r
528                 mesh.numsubs    = subs.Count;\r
529                 mesh.sub        = subs.ToArray();\r
530                 mesh.matrix     = Matrix44.Identity;\r
531                 mesh.effect     = 0;\r
532                 meshes.Add(mesh);\r
533             }\r
534 \r
535             return true;\r
536         }\r
537 \r
538         private bool Common_DoWriteMeshes()\r
539         {\r
540             bw.Write(meshes.Count);\r
541 \r
542             foreach(TSOMesh i in meshes)\r
543             {\r
544                 WriteString(bw, i.Name);\r
545                 WriteMatrix(bw, i.Matrix);\r
546                 bw.Write(1);\r
547                 bw.Write(i.numsubs);\r
548 \r
549                 foreach(TSOSubMesh j in i.sub)\r
550                 {\r
551                     bw.Write(j.spec);\r
552                     bw.Write(j.numbones);\r
553 \r
554                     foreach(int k in j.bones)\r
555                         bw.Write(k);\r
556 \r
557                     bw.Write(j.numvertices);\r
558 \r
559                     foreach(Vertex k in j.vertices)\r
560                         WriteVertex(bw, k);\r
561                 }\r
562             }\r
563 \r
564             return true;\r
565         }\r
566 \r
567         private bool AutoBone_DoOutput()\r
568         {\r
569             //----- 出力処理 -----------------------------------------------\r
570             ii.materials.Clear();\r
571             ii.textures.Clear();\r
572 \r
573             using(FileStream fs= File.OpenWrite(tsoex))\r
574             {\r
575                 fs.SetLength(0);\r
576                 bw      = new BinaryWriter(fs);\r
577 \r
578                 Common_DoWriteHeader();\r
579                 Common_DoWriteNodeNames();\r
580                 Common_DoWriteNodeMatrices();\r
581                 Common_DoWriteTextures();\r
582                 Common_DoWriteEffects();\r
583                 Common_DoWriteMaterials();\r
584                 AutoBone_DoGenerateMeshes();\r
585                 Common_DoWriteMeshes();\r
586             }\r
587 \r
588             return true;\r
589         }\r
590 \r
591         private bool OneBone_DoOutput()\r
592         {\r
593             //----- 出力処理 -----------------------------------------------\r
594             ii.materials.Clear();\r
595             ii.textures.Clear();\r
596 \r
597             using(FileStream fs= File.OpenWrite(tsoex))\r
598             {\r
599                 fs.SetLength(0);\r
600                 bw      = new BinaryWriter(fs);\r
601 \r
602                 Common_DoWriteHeader();\r
603                 Common_DoWriteNodeNames();\r
604                 Common_DoWriteNodeMatrices();\r
605                 Common_DoWriteTextures();\r
606                 Common_DoWriteEffects();\r
607                 Common_DoWriteMaterials();\r
608                 OneBone_DoGenerateMeshes();\r
609                 Common_DoWriteMeshes();\r
610             }\r
611 \r
612             return true;\r
613         }\r
614 \r
615         private bool Common_DoSaveXml()\r
616         {\r
617             // 結果を保存しておく\r
618             ImportInfo.Save(Path.ChangeExtension(mqoin, ".xml"), ii);\r
619             return true;\r
620         }\r
621 \r
622         private bool Common_DoCleanup()\r
623         {\r
624             dir         = null;\r
625             pc          = null;\r
626             tsor        = null;\r
627             vlst        = null;\r
628             nodes       = null;\r
629             meshes      = null;\r
630             mqoin       = null;\r
631             tsoref      = null;\r
632             tsoex       = null;\r
633             config      = null;\r
634             mqo         = null;\r
635             ii          = null;\r
636             bw          = null;\r
637             materials   = null;\r
638             textures    = null;\r
639 \r
640             System.GC.Collect();\r
641             return true;\r
642         }\r
643 \r
644         public unsafe void GenerateOneBone(string mqoin, string tsoref, string tsoex, TSOGenerateConfig config)\r
645         {\r
646             this.mqoin  = mqoin;\r
647             this.tsoref = tsoref;\r
648             this.tsoex  = tsoex;\r
649             this.config = config;\r
650 \r
651             try\r
652             {\r
653                 if(!Common_DoSetupDir())        return;\r
654                 if(!Common_DoLoadMQO())         return;\r
655                 if(!OneBone_DoLoadRefTSO())     return;\r
656                 if(!Common_DoLoadXml())         return;\r
657                 if(!OneBone_DoOutput())         return;\r
658                 if(!Common_DoSaveXml())         return;\r
659             } finally\r
660             {\r
661                 Common_DoCleanup();\r
662             }\r
663         }\r
664         \r
665         public unsafe void GenerateAutoBone(string mqoin, string tsoref, string tsoex, TSOGenerateConfig config)\r
666         {\r
667             this.mqoin  = mqoin;\r
668             this.tsoref = tsoref;\r
669             this.tsoex  = tsoex;\r
670             this.config = config;\r
671 \r
672             try\r
673             {\r
674                 if(!Common_DoSetupDir())        return;\r
675                 if(!Common_DoLoadMQO())         return;\r
676                 if(!AutoBone_DoLoadRefTSO())    return;\r
677                 if(!Common_DoLoadXml())         return;\r
678                 if(!AutoBone_DoOutput())        return;\r
679                 if(!Common_DoSaveXml())         return;\r
680             } finally\r
681             {\r
682                 Common_DoCleanup();\r
683             }\r
684         }\r
685 #region ユーティリティ\r
686         public void WriteString(BinaryWriter bw, string s)\r
687         {\r
688             byte[]  b   = Encoding.Default.GetBytes(s);\r
689             bw.Write(b);\r
690             bw.Write((byte)0);\r
691         }\r
692 \r
693         public void WriteMatrix(BinaryWriter bw, Matrix44 m)\r
694         {\r
695             bw.Write(m.M11); bw.Write(m.M12); bw.Write(m.M13); bw.Write(m.M14);\r
696             bw.Write(m.M21); bw.Write(m.M22); bw.Write(m.M23); bw.Write(m.M24);\r
697             bw.Write(m.M31); bw.Write(m.M32); bw.Write(m.M33); bw.Write(m.M34);\r
698             bw.Write(m.M41); bw.Write(m.M42); bw.Write(m.M43); bw.Write(m.M44);\r
699         }\r
700 \r
701         public unsafe void WriteVertex(BinaryWriter bw, Vertex v)\r
702         {\r
703             uint        idx0    = v.Idx;\r
704             byte*       idx     = (byte*)(&idx0);\r
705             List<int>   idxs    = new List<int>(4);\r
706             List<float> wgts    = new List<float>(4);\r
707 \r
708             if(v.Wgt.x > 0) { idxs.Add(idx[0]); wgts.Add(v.Wgt.x); }\r
709             if(v.Wgt.y > 0) { idxs.Add(idx[1]); wgts.Add(v.Wgt.y); }\r
710             if(v.Wgt.z > 0) { idxs.Add(idx[2]); wgts.Add(v.Wgt.z); }\r
711             if(v.Wgt.w > 0) { idxs.Add(idx[3]); wgts.Add(v.Wgt.w); }\r
712 \r
713             bw.Write(v.Pos.X); bw.Write(v.Pos.Y); bw.Write(v.Pos.Z);\r
714             bw.Write(v.Nrm.X); bw.Write(v.Nrm.Y); bw.Write(v.Nrm.Z);\r
715             bw.Write(v.Tex.X); bw.Write(v.Tex.Y);\r
716 \r
717             bw.Write(wgts.Count);\r
718 \r
719             for(int i= 0, n= idxs.Count; i < n; ++i)\r
720             {\r
721                 bw.Write(idxs[i]);\r
722                 bw.Write(wgts[i]);\r
723             }\r
724         }\r
725 #endregion\r
726 #region テクスチャ処理\r
727         public TSOTex   LoadTex(string file)\r
728         {\r
729             string  ext = Path.GetExtension(file).ToUpper();\r
730             TSOTex  tex;\r
731 \r
732             switch(ext)\r
733             {\r
734             case ".TGA":    tex= LoadTarga(file);   break;\r
735             case ".BMP":    tex= LoadBitmap(file);  break;\r
736             default:        throw new Exception("Unsupported texture file: " + file);\r
737             }\r
738 \r
739             for(int i= 0, n= tex.data.Length; i < n; i+=tex.Depth)\r
740             {\r
741                 byte    b       = tex.data[i+0];\r
742                 tex.data[i+0]   = tex.data[i+2];\r
743                 tex.data[i+2]   = b;\r
744             }\r
745 \r
746             return tex;\r
747         }\r
748 \r
749         public unsafe TSOTex   LoadTarga(string file)\r
750         {\r
751             using(FileStream fs= File.OpenRead(file))\r
752             {\r
753                 BinaryReader        br      = new BinaryReader(fs);\r
754                 TARGA_HEADER        header;\r
755 \r
756                 Marshal.Copy(br.ReadBytes(sizeof(TARGA_HEADER)), 0, (IntPtr)(&header), sizeof(TARGA_HEADER));\r
757 \r
758                 if(header.imagetype != 0x02)    throw new Exception("Invalid imagetype: " + file);\r
759                 if(header.depth     != 24\r
760                 && header.depth     != 32)      throw new Exception("Invalid depth: " + file);\r
761                 \r
762                 TSOTex      tex = new TSOTex();\r
763                 tex.depth       = header.depth  / 8;\r
764                 tex.width       = header.width;\r
765                 tex.height      = header.height;\r
766                 tex.file        = file;\r
767                 tex.data        = br.ReadBytes(tex.width * tex.height * tex.depth);\r
768 \r
769                 return tex;\r
770             }\r
771         }\r
772 \r
773         public unsafe TSOTex   LoadBitmap(string file)\r
774         {\r
775             using(FileStream fs= File.OpenRead(file))\r
776             {\r
777                 BinaryReader        br      = new BinaryReader(fs);\r
778                 BITMAPFILEHEADER    bfh;\r
779                 BITMAPINFOHEADER    bih;\r
780 \r
781                 Marshal.Copy(br.ReadBytes(sizeof(BITMAPFILEHEADER)), 0, (IntPtr)(&bfh), sizeof(BITMAPFILEHEADER));\r
782                 Marshal.Copy(br.ReadBytes(sizeof(BITMAPINFOHEADER)), 0, (IntPtr)(&bih), sizeof(BITMAPINFOHEADER));\r
783 \r
784                 if(bfh.bfType != 0x4D42)        throw new Exception("Invalid imagetype: " + file);\r
785                 if(bih.biBitCount != 24\r
786                 && bih.biBitCount != 32)        throw new Exception("Invalid depth: " + file);\r
787                 \r
788                 TSOTex      tex = new TSOTex();\r
789                 tex.depth       = bih.biBitCount  / 8;\r
790                 tex.width       = bih.biWidth;\r
791                 tex.height      = bih.biHeight;\r
792                 tex.file        = file;\r
793                 tex.data        = br.ReadBytes(tex.width * tex.height * tex.depth);\r
794 \r
795                 return tex;\r
796             }\r
797         }\r
798 #endregion\r
799     }\r
800 \r
801     public class TextureInfo\r
802     {\r
803         public string name;\r
804         public string file;\r
805 \r
806         public TextureInfo(string name, string file)\r
807         {\r
808             this.name   = name;\r
809             this.file   = file;\r
810         }\r
811     }\r
812 \r
813     public class MaterialInfo\r
814     {\r
815         public string           name;\r
816         public string           shader;\r
817         public string           diffuse;\r
818         public string           shadow;\r
819       //public Dictionary<string, string>   parameters;\r
820 \r
821         public MaterialInfo(string path, MqoMaterial mqom, ImportMaterialInfo impm)\r
822         {\r
823             name    = mqom.name;\r
824             diffuse = mqom.tex;\r
825 \r
826             if(impm != null)\r
827             {\r
828                 string  file= Path.Combine(path, impm.Name);\r
829 \r
830                 if(File.Exists(file))\r
831                     shader          = file;\r
832 \r
833                 if(impm.shadow != null)\r
834                 {\r
835                     file        = Path.Combine(path, impm.shadow.File);\r
836 \r
837                     if(File.Exists(file))\r
838                         shadow  = file;\r
839                 }\r
840             }\r
841         }\r
842 \r
843         public bool   Valid\r
844         {\r
845             get\r
846             {\r
847                 return File.Exists(shader)\r
848                     && File.Exists(diffuse)\r
849                     && File.Exists(shadow);\r
850             }\r
851         }\r
852 \r
853         public string[] GetCode()\r
854         {\r
855             TSOMaterialCode code= TSOMaterialCode.GenerateFromFile(shader);\r
856             List<string>    line= new List<string>();\r
857 \r
858             code.SetValue("ColorTex", Path.GetFileNameWithoutExtension(diffuse));\r
859             code.SetValue("ShadeTex", Path.GetFileNameWithoutExtension(shadow));\r
860 \r
861             foreach(KeyValuePair<string, TSOParameter> i in code)\r
862                 line.Add(i.Value.ToString());\r
863 \r
864             return line.ToArray();\r
865         }\r
866 \r
867         public string Name           { get { return name;    } }\r
868         \r
869         [Editor(typeof(FileNameEditor), typeof(UITypeEditor))]\r
870         [DisplayNameAttribute("シェーダー設定ファイル")]\r
871         public string ShaderFile     { get { return shader;  } set { shader  = value; } }\r
872         \r
873         [Editor(typeof(FileNameEditor), typeof(UITypeEditor))]\r
874         [DisplayNameAttribute("テクスチャ:カラー")]\r
875         public string DiffuseTexture { get { return diffuse; } set { diffuse = value; } }\r
876 \r
877         [Editor(typeof(FileNameEditor), typeof(UITypeEditor))]\r
878         [DisplayNameAttribute("テクスチャ:シェーティング")]\r
879         public string ShadowTexture  { get { return shadow;  } set { shadow  = value; } }\r
880     }\r
881 }\r