OSDN Git Service

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