OSDN Git Service

四角面に対応 from mqo2tso fixes #22390
[tdcgexplorer/tso2mqo.git] / MqoFile.cs
1 using System;\r
2 using System.Collections.Generic;\r
3 using System.IO;\r
4 using System.Text;\r
5 using System.Text.RegularExpressions;\r
6 \r
7 namespace Tso2MqoGui\r
8 {\r
9     public class MqoFile\r
10     {\r
11         private delegate bool SectionHandler(string[] tokens);\r
12         \r
13         public static char[]        delimiters  = new char[]{' ', '\t'};\r
14         public static char[]        delimiters2 = new char[]{' ', '\t', '(', ')'};\r
15 \r
16         private string              file;\r
17         private StreamReader        sr;\r
18         private MqoScene            scene;\r
19         private List<MqoMaterial>   materials;\r
20         private List<MqoObject>     objects     = new List<MqoObject>();\r
21         private MqoObject           current;\r
22 \r
23         public MqoScene             Scene       { get { return scene;       } }\r
24         public List<MqoMaterial>    Materials   { get { return materials;   } }\r
25         public List<MqoObject>      Objects     { get { return objects;     } }\r
26 \r
27         public void Load(string file)\r
28         {\r
29             using(FileStream fs= File.OpenRead(file))\r
30             {\r
31                 this.file   = file;\r
32                 sr          = new StreamReader(fs, Encoding.Default);\r
33                 ReadAll();\r
34             }\r
35         }\r
36 \r
37         public void Dump()\r
38         {\r
39             System.Diagnostics.Debug.WriteLine(file);\r
40             System.Diagnostics.Debug.WriteLine(scene);\r
41 \r
42             foreach(MqoMaterial i in materials)\r
43                 System.Diagnostics.Debug.WriteLine(i);\r
44 \r
45             foreach(MqoObject i in objects)\r
46                 System.Diagnostics.Debug.WriteLine(i);\r
47         }\r
48 \r
49         public void ReadAll()\r
50         {\r
51             DoRead(SectionRoot);\r
52         }\r
53 \r
54         private static string[] SplitString(string s)\r
55         {\r
56             List<string>    tokens  = new List<string>();\r
57             StringBuilder   sb     = new StringBuilder(s.Length);\r
58             bool            str    = false;\r
59             bool            escape = false;\r
60             bool            bracket= false;\r
61             s                      = s.Trim(' ', '\t', '\r', '\n');\r
62 \r
63             foreach(char i in s)\r
64             {\r
65                 if(escape)\r
66                 {\r
67                     sb.Append(i);\r
68                     escape  = false;\r
69                     continue;\r
70                 }\r
71 \r
72 \r
73                 switch(i)\r
74                 {\r
75                 case '\\':\r
76                     if(str) sb.Append(i);\r
77                     else    escape  = true;\r
78                     break;\r
79                 case ' ':\r
80                 case '\t':\r
81                          if(bracket)        {sb.Append(i);                            }\r
82                     else if(str)            {sb.Append(i);                            }\r
83                     else if(sb.Length > 0)  {tokens.Add(sb.ToString()); sb.Length= 0; }\r
84                     break;\r
85                 case '(':\r
86                     sb.Append(i);\r
87                     if(!str)\r
88                         bracket= true;\r
89                     break;\r
90                 case ')':\r
91                     sb.Append(i);\r
92                     if(!str)\r
93                         bracket= false;\r
94                     break;\r
95                 case '\"':\r
96                     sb.Append(i);\r
97                     str = !str;\r
98                     break;\r
99                 default:\r
100                     sb.Append(i);\r
101                     break;\r
102                 }\r
103             }\r
104 \r
105             if(sb.Length > 0)\r
106                 tokens.Add(sb.ToString());\r
107 \r
108             return tokens.ToArray();\r
109         }\r
110 \r
111         private void DoRead(SectionHandler h)\r
112         {\r
113             for(int no= 1;; ++no)\r
114             {\r
115                 string  line= sr.ReadLine();\r
116 \r
117                 if(line == null)\r
118                     break;\r
119 \r
120                 line                = line.Trim();\r
121                 string[]    tokens  = SplitString(line);\r
122 \r
123                 try\r
124                 {\r
125                     if(tokens.Length == 0)\r
126                         continue;\r
127 \r
128                     if(!h(tokens))\r
129                         break;\r
130                 } catch(Exception e)\r
131                 {\r
132                     string  msg = string.Format("File format error: {0} \"{1}\"", no, line);\r
133                     throw new Exception(msg, e);\r
134                 }\r
135             }\r
136         }\r
137 \r
138         public void Error(string[] tokens)\r
139         {\r
140             throw new Exception("File Format Error: \"" + string.Concat(tokens) + "\"");\r
141         }\r
142 \r
143         private bool SectionRoot(string[] tokens)\r
144         {\r
145             switch(tokens[0].ToLower())\r
146             {\r
147             case "metasequoia": ParseMetasequoia(tokens);   return true;\r
148             case "format":      ParseFormat     (tokens);   return true;\r
149             case "scene":       ParseScene      (tokens);   return true;\r
150             case "material":    ParseMaterial   (tokens);   return true;\r
151             case "object":      ParseObject     (tokens);   return true;\r
152             case "eof":                                     return false;\r
153           //default:            Error(tokens);              return false;\r
154             default:                                        return true;\r
155             }\r
156         }\r
157 \r
158         private bool SectionScene(string[] tokens)\r
159         {\r
160             scene   = new MqoScene();\r
161 \r
162             switch(tokens[0].ToLower())\r
163             {\r
164             case "pos":         scene.pos           = Point3.Parse(tokens, 1);  return true;\r
165             case "lookat":      scene.lookat        = Point3.Parse(tokens, 1);  return true;\r
166             case "head":        scene.head          = float .Parse(tokens[1]);  return true;\r
167             case "pich":        scene.pich          = float .Parse(tokens[1]);  return true;\r
168             case "ortho":       scene.ortho         = float .Parse(tokens[1]);  return true;\r
169             case "zoom2":       scene.zoom2         = float .Parse(tokens[1]);  return true;\r
170             case "amb":         scene.amb           = Color3.Parse(tokens, 1);  return true;\r
171             case "}":                                                           return false;\r
172           //default:            Error(tokens);                                  return false;\r
173             default:                                                            return true;\r
174             }\r
175         }\r
176 \r
177         private static string[] SplitParam(string s)\r
178         {\r
179             return s.Split(delimiters2, StringSplitOptions.RemoveEmptyEntries);\r
180         }\r
181 \r
182         private bool SectionMaterial(string[] tokens)\r
183         {\r
184             if(tokens[0] == "}")\r
185                 return false;\r
186 \r
187             StringBuilder   sb  = new StringBuilder();\r
188 \r
189             foreach(string i in tokens)\r
190                 sb.Append(' ').Append(i);\r
191 \r
192             string      line= sb.ToString().Trim();\r
193             MqoMaterial m   = new MqoMaterial(tokens[0].Trim('"'));\r
194             tokens          = SplitString(line);\r
195             materials.Add(m);\r
196 \r
197             for(int i= 1 ; i < tokens.Length; ++i)\r
198             {\r
199                 string      t   = tokens[i];\r
200                 string      t2  = t.ToLower();\r
201 \r
202                      if(t2.StartsWith("shader("))  m.shader   = int   .Parse(SplitParam(t)[1]);\r
203                 else if(t2.StartsWith("col("))     m.col      = Color3.Parse(SplitParam(t), 1);\r
204                 else if(t2.StartsWith("dif("))     m.dif      = float .Parse(SplitParam(t)[1]);\r
205                 else if(t2.StartsWith("amb("))     m.amb      = float .Parse(SplitParam(t)[1]);\r
206                 else if(t2.StartsWith("emi("))     m.emi      = float .Parse(SplitParam(t)[1]);\r
207                 else if(t2.StartsWith("spc("))     m.spc      = float .Parse(SplitParam(t)[1]);\r
208                 else if(t2.StartsWith("power("))   m.power    = float .Parse(SplitParam(t)[1]);\r
209                 else if(t2.StartsWith("tex("))     m.tex      = t.Substring(3).Trim('(', ')', '"');\r
210             }\r
211 \r
212             return true;\r
213         }\r
214 \r
215         private bool SectionObject(string[] tokens)\r
216         {\r
217             switch(tokens[0].ToLower())\r
218             {\r
219             case "visible":     current.visible     = int   .Parse(tokens[1]);  return true;\r
220             case "locking":     current.locking     = int   .Parse(tokens[1]);  return true;\r
221             case "shading":     current.shading     = int   .Parse(tokens[1]);  return true;\r
222             case "facet":       current.facet       = float .Parse(tokens[1]);  return true;\r
223             case "color":       current.color       = Color3.Parse(tokens, 1);  return true;\r
224             case "color_type":  current.color_type  = int   .Parse(tokens[1]);  return true;\r
225             case "vertex":      ParseVertex(tokens);                            return true;\r
226             case "face":        ParseFace(tokens);                              return true;\r
227             case "}":                                                           return false;\r
228           //default:            Error(tokens);                                  return false;\r
229             default:                                                            return true;\r
230             }\r
231         }\r
232 \r
233         private bool SectionVertex(string[] tokens)\r
234         {\r
235             if (tokens[0] == "}")\r
236                 return false;\r
237 \r
238             current.vertices.Add(Point3.Parse(tokens, 0));\r
239 \r
240             return true;\r
241         }\r
242 \r
243         private bool SectionFace(string[] tokens)\r
244         {\r
245             if (tokens[0] == "}")\r
246                 return false;\r
247 \r
248             int nface = int.Parse(tokens[0]);\r
249             {\r
250                 StringBuilder sb = new StringBuilder();\r
251                 foreach (string i in tokens)\r
252                     sb.Append(' ').Append(i);\r
253                 string line = sb.ToString().Trim();\r
254                 tokens = SplitString(line);\r
255             }\r
256             switch (nface)\r
257             {\r
258                 case 3:\r
259                     {\r
260                         MqoFace f = new MqoFace();\r
261 \r
262                         for (int i = 1; i < tokens.Length; ++i)\r
263                         {\r
264                             string t = tokens[i];\r
265                             string t2 = t.ToLower();\r
266 \r
267                             if (t2.StartsWith("v("))\r
268                             {\r
269                                 string[] t3 = SplitParam(t);\r
270                                 f.a = ushort.Parse(t3[1]);\r
271                                 f.b = ushort.Parse(t3[2]);\r
272                                 f.c = ushort.Parse(t3[3]);\r
273                             }\r
274                             else\r
275                             if (t2.StartsWith("m("))\r
276                             {\r
277                                 string[] t3 = SplitParam(t);\r
278                                 f.mtl = ushort.Parse(t3[1]);\r
279                             }\r
280                             else\r
281                             if (t2.StartsWith("uv("))\r
282                             {\r
283                                 string[] t3 = SplitParam(t);\r
284                                 f.ta = Point2.Parse(t3, 1);\r
285                                 f.tb = Point2.Parse(t3, 3);\r
286                                 f.tc = Point2.Parse(t3, 5);\r
287                             }\r
288                         }\r
289                         current.faces.Add(f);\r
290                     }\r
291                     break;\r
292                 case 4:\r
293                     {\r
294                         MqoFace f = new MqoFace();\r
295                         MqoFace f2 = new MqoFace();\r
296 \r
297                         for (int i = 1; i < tokens.Length; ++i)\r
298                         {\r
299                             string t = tokens[i];\r
300                             string t2 = t.ToLower();\r
301 \r
302                             if (t2.StartsWith("v("))\r
303                             {\r
304                                 string[] t3 = SplitParam(t);\r
305                                 f.a = ushort.Parse(t3[1]);\r
306                                 f.b = ushort.Parse(t3[2]);\r
307                                 f.c = ushort.Parse(t3[3]);\r
308                                 f2.a = f.a;\r
309                                 f2.b = f.c;\r
310                                 f2.c = ushort.Parse(t3[4]);\r
311                             }\r
312                             else\r
313                             if (t2.StartsWith("m("))\r
314                             {\r
315                                 string[] t3 = SplitParam(t);\r
316                                 f.mtl = ushort.Parse(t3[1]);\r
317                                 f2.mtl = f.mtl;\r
318                             }\r
319                             else\r
320                             if (t2.StartsWith("uv("))\r
321                             {\r
322                                 string[] t3 = SplitParam(t);\r
323                                 f.ta = Point2.Parse(t3, 1);\r
324                                 f.tb = Point2.Parse(t3, 3);\r
325                                 f.tc = Point2.Parse(t3, 5);\r
326                                 f2.ta = f.ta;\r
327                                 f2.tb = f.tc;\r
328                                 f2.tc = Point2.Parse(t3, 7);\r
329                             }\r
330                         }\r
331                         current.faces.Add(f);\r
332                         current.faces.Add(f2);\r
333                     }\r
334                     break;\r
335             }\r
336             return true;\r
337         }\r
338 \r
339         //----- Root elements ----------------------------------------------\r
340         private void ParseMetasequoia(string[] tokens)\r
341         {\r
342             if(tokens[1].ToLower() != "document")   Error(tokens);\r
343         }\r
344 \r
345         private void ParseFormat(string[] tokens)\r
346         {\r
347             if(tokens[1].ToLower() != "text")       Error(tokens);\r
348             if(tokens[2].ToLower() != "ver")        Error(tokens);\r
349             if(tokens[3].ToLower() != "1.0")        Error(tokens);\r
350         }\r
351 \r
352         private void ParseScene(string[] tokens)\r
353         {\r
354             if(tokens[1].ToLower() != "{")          Error(tokens);\r
355 \r
356             DoRead(SectionScene);\r
357         }\r
358 \r
359         private void ParseMaterial(string[] tokens)\r
360         {\r
361             if(tokens[2].ToLower() != "{")          Error(tokens);\r
362 \r
363             materials   = new List<MqoMaterial>(int.Parse(tokens[1]));\r
364             DoRead(SectionMaterial);\r
365         }\r
366 \r
367         private void ParseObject(string[] tokens)\r
368         {\r
369             if(tokens[2].ToLower() != "{")          Error(tokens);\r
370 \r
371             current = new MqoObject(tokens[1].Trim('"'));\r
372             objects.Add(current);\r
373             DoRead(SectionObject);\r
374         }\r
375 \r
376         private void ParseVertex(string[] tokens)\r
377         {\r
378             if(tokens[2].ToLower() != "{")          Error(tokens);\r
379 \r
380             current.vertices    = new List<Point3>(int.Parse(tokens[1]));\r
381             DoRead(SectionVertex);\r
382         }\r
383 \r
384         private void ParseFace(string[] tokens)\r
385         {\r
386             if(tokens[2].ToLower() != "{")          Error(tokens);\r
387 \r
388             current.faces       = new List<MqoFace>(int.Parse(tokens[1]));\r
389             DoRead(SectionFace);\r
390         }\r
391     }\r
392 \r
393     public class MqoScene\r
394     {\r
395         public Point3           pos;\r
396         public Point3           lookat;\r
397         public float            head;\r
398         public float            pich;\r
399         public float            ortho;\r
400         public float            zoom2;\r
401         public Color3           amb;\r
402 \r
403         public override string ToString()\r
404         {\r
405             return (new StringBuilder(256))\r
406                 .Append(" pos: ")   .Append(pos)\r
407                 .Append(" lookat: ").Append(lookat)\r
408                 .Append(" head: ")  .Append(head)\r
409                 .Append(" pich: ")  .Append(pich)\r
410                 .Append(" ortho: ") .Append(ortho)\r
411                 .Append(" zoom2: ") .Append(zoom2)\r
412                 .Append(" amb: ")   .Append(amb)\r
413                 .ToString();\r
414         }\r
415     }\r
416 \r
417     public class MqoMaterial\r
418     {\r
419         public string           name;\r
420         public int              shader;\r
421         public Color3           col;\r
422         public float            dif;\r
423         public float            amb;\r
424         public float            emi;\r
425         public float            spc;\r
426         public float            power;\r
427         public string           tex;\r
428 \r
429         public MqoMaterial()            {           }\r
430         public MqoMaterial(string n)    { name= n;  }\r
431 \r
432         public override string ToString()\r
433         {\r
434             return (new StringBuilder(256))\r
435                 .Append(" shader: ").Append(shader)\r
436                 .Append(" col: ")   .Append(col)\r
437                 .Append(" dif: ")   .Append(dif)\r
438                 .Append(" amb: ")   .Append(amb)\r
439                 .Append(" emi: ")   .Append(emi)\r
440                 .Append(" spc: ")   .Append(spc)\r
441                 .Append(" power: ") .Append(power)\r
442                 .Append(" tex: ")   .Append(tex)\r
443                 .Append(" name: ")  .Append(name)\r
444                 .ToString();\r
445         }\r
446     }\r
447 \r
448     public class MqoObject\r
449     {\r
450         public string           name;\r
451         public int              visible;\r
452             public int              locking;\r
453             public int              shading;\r
454             public float            facet;\r
455             public Color3           color;\r
456             public int              color_type;\r
457         public List<Point3>     vertices;\r
458         public List<MqoFace>    faces;\r
459 \r
460         public MqoObject()              {           }\r
461         public MqoObject(string n)      { name= n;  }\r
462 \r
463         public override string ToString()\r
464         {\r
465             return (new StringBuilder(256))\r
466                 .Append(" visible: ")   .Append(visible)\r
467                 .Append(" locking: ")   .Append(locking)\r
468                 .Append(" shading: ")   .Append(shading)\r
469                 .Append(" facet: ")     .Append(facet)\r
470                 .Append(" color: ")     .Append(color)\r
471                 .Append(" color_type: ").Append(color_type)\r
472                 .Append(" vertices: ")  .Append(vertices.Count)\r
473                 .Append(" faces: ")     .Append(faces.Count)\r
474                 .Append(" name: ")      .Append(name)\r
475                 .ToString();\r
476         }\r
477     }\r
478 \r
479     public class  MqoFace\r
480     {\r
481         public ushort   a, b, c, mtl;\r
482         public Point2   ta, tb, tc;\r
483 \r
484         public MqoFace()\r
485         {\r
486         }\r
487 \r
488         public MqoFace(ushort a, ushort b, ushort c, ushort mtl, Point2 ta, Point2 tb, Point2 tc)\r
489         {\r
490             this.a  = a;\r
491             this.b  = b;\r
492             this.c  = c;\r
493             this.mtl= mtl;\r
494             this.ta = ta;\r
495             this.tb = tb;\r
496             this.tc = tc;\r
497         }\r
498 \r
499         public override string ToString()\r
500         {\r
501             return (new StringBuilder(256))\r
502                 .Append("v: ")   .Append(a).Append(" ").Append(b).Append(" ").Append(c)\r
503                 .Append(" mtl: ").Append(mtl)\r
504                 .Append(" uv: ") .Append(ta).Append(" ").Append(tb).Append(" ").Append(tc)\r
505                 .ToString();\r
506         }\r
507     }\r
508 }\r