2 using System.Collections.Generic;
5 using System.Text.RegularExpressions;
11 private delegate bool SectionHandler(string[] tokens);
13 private static char[] delimiters2 = new char[] { ' ', '\t', '(', ')' };
16 private StreamReader sr;
17 private MqoScene scene;
18 private List<MqoMaterial> materials;
19 private List<MqoObject> objects = new List<MqoObject>();
20 private MqoObject current;
22 public MqoScene Scene { get { return scene; } }
23 public List<MqoMaterial> Materials { get { return materials; } }
24 public List<MqoObject> Objects { get { return objects; } }
26 public void Load(string file)
28 using (FileStream fs = File.OpenRead(file))
31 sr = new StreamReader(fs, Encoding.Default);
41 private static string[] SplitString(string s)
43 List<string> tokens = new List<string>();
44 StringBuilder sb = new StringBuilder(s.Length);
48 s = s.Trim(' ', '\t', '\r', '\n');
63 if (str) sb.Append(i);
68 if (bracket) { sb.Append(i); }
69 else if (str) { sb.Append(i); }
70 else if (sb.Length > 0) { tokens.Add(sb.ToString()); sb.Length = 0; }
93 tokens.Add(sb.ToString());
95 return tokens.ToArray();
98 private void DoRead(SectionHandler h)
100 for (int no = 1; ; ++no)
102 string line = sr.ReadLine();
108 string[] tokens = SplitString(line);
112 if (tokens.Length == 0)
118 catch (Exception exception)
120 string msg = string.Format("File format error: {0} \"{1}\"", no, line);
121 throw new Exception(msg, exception);
126 public void Error(string[] tokens)
128 throw new Exception("File Format Error: \"" + string.Concat(tokens) + "\"");
131 private bool SectionRoot(string[] tokens)
135 case "Metasequoia": ParseMetasequoia(tokens); return true;
136 case "Format": ParseFormat(tokens); return true;
137 case "Thumbnail": ParseThumbnail(tokens); return true;
138 case "Scene": ParseScene(tokens); return true;
139 case "Material": ParseMaterial(tokens); return true;
140 case "Object": ParseObject(tokens); return true;
148 private bool SectionThumbnail(string[] tokens)
159 private bool SectionScene(string[] tokens)
161 scene = new MqoScene();
165 case "pos": scene.pos = Point3.Parse(tokens, 1); return true;
166 case "lookat": scene.lookat = Point3.Parse(tokens, 1); return true;
167 case "head": scene.head = float.Parse(tokens[1]); return true;
168 case "pich": scene.pich = float.Parse(tokens[1]); return true;
169 case "ortho": scene.ortho = float.Parse(tokens[1]); return true;
170 case "zoom2": scene.zoom2 = float.Parse(tokens[1]); return true;
171 case "amb": scene.amb = Color3.Parse(tokens, 1); return true;
172 case "dirlights": ParseDirlights(tokens); return true;
180 private bool SectionDirlights(string[] tokens)
184 case "light": ParseLight(tokens); return true;
192 private bool SectionLight(string[] tokens)
203 private static string[] SplitParam(string s)
205 return s.Split(delimiters2, StringSplitOptions.RemoveEmptyEntries);
208 private bool SectionMaterial(string[] tokens)
210 if (tokens[0] == "}")
213 StringBuilder sb = new StringBuilder();
215 foreach (string i in tokens)
216 sb.Append(' ').Append(i);
218 string line = sb.ToString().Trim();
219 MqoMaterial m = new MqoMaterial(tokens[0].Trim('"'));
220 tokens = SplitString(line);
223 for (int i = 1; i < tokens.Length; ++i)
225 string t = tokens[i];
226 string t2 = t.ToLower();
228 if (t2.StartsWith("shader(")) m.shader = int.Parse(SplitParam(t)[1]);
229 else if (t2.StartsWith("col(")) m.col = Color3.Parse(SplitParam(t), 1);
230 else if (t2.StartsWith("dif(")) m.dif = float.Parse(SplitParam(t)[1]);
231 else if (t2.StartsWith("amb(")) m.amb = float.Parse(SplitParam(t)[1]);
232 else if (t2.StartsWith("emi(")) m.emi = float.Parse(SplitParam(t)[1]);
233 else if (t2.StartsWith("spc(")) m.spc = float.Parse(SplitParam(t)[1]);
234 else if (t2.StartsWith("power(")) m.power = float.Parse(SplitParam(t)[1]);
235 else if (t2.StartsWith("tex(")) m.tex = t.Substring(3).Trim('(', ')', '"');
241 private bool SectionObject(string[] tokens)
245 case "visible": current.visible = int.Parse(tokens[1]); return true;
246 case "locking": current.locking = int.Parse(tokens[1]); return true;
247 case "shading": current.shading = int.Parse(tokens[1]); return true;
248 case "facet": current.facet = float.Parse(tokens[1]); return true;
249 case "color": current.color = Color3.Parse(tokens, 1); return true;
250 case "color_type": current.color_type = int.Parse(tokens[1]); return true;
251 case "vertex": ParseVertex(tokens); return true;
252 case "face": ParseFace(tokens); return true;
260 private bool SectionVertex(string[] tokens)
262 if (tokens[0] == "}")
265 current.vertices.Add(Point3.Parse(tokens, 0));
270 private bool SectionFace(string[] tokens)
272 if (tokens[0] == "}")
275 int nface = int.Parse(tokens[0]);
277 StringBuilder sb = new StringBuilder();
278 foreach (string i in tokens)
279 sb.Append(' ').Append(i);
280 string line = sb.ToString().Trim();
281 tokens = SplitString(line);
287 MqoFace f = new MqoFace();
289 for (int i = 1; i < tokens.Length; ++i)
291 string t = tokens[i];
292 string t2 = t.ToLower();
294 if (t2.StartsWith("v("))
296 string[] t3 = SplitParam(t);
297 f.a = ushort.Parse(t3[1]);
298 f.b = ushort.Parse(t3[2]);
299 f.c = ushort.Parse(t3[3]);
302 if (t2.StartsWith("m("))
304 string[] t3 = SplitParam(t);
305 f.mtl = ushort.Parse(t3[1]);
308 if (t2.StartsWith("uv("))
310 string[] t3 = SplitParam(t);
311 f.ta = Point2.Parse(t3, 1);
312 f.tb = Point2.Parse(t3, 3);
313 f.tc = Point2.Parse(t3, 5);
316 current.faces.Add(f);
321 MqoFace f = new MqoFace();
322 MqoFace f2 = new MqoFace();
324 for (int i = 1; i < tokens.Length; ++i)
326 string t = tokens[i];
327 string t2 = t.ToLower();
329 if (t2.StartsWith("v("))
331 string[] t3 = SplitParam(t);
332 f.a = ushort.Parse(t3[1]);
333 f.b = ushort.Parse(t3[2]);
334 f.c = ushort.Parse(t3[3]);
337 f2.c = ushort.Parse(t3[4]);
340 if (t2.StartsWith("m("))
342 string[] t3 = SplitParam(t);
343 f.mtl = ushort.Parse(t3[1]);
347 if (t2.StartsWith("uv("))
349 string[] t3 = SplitParam(t);
350 f.ta = Point2.Parse(t3, 1);
351 f.tb = Point2.Parse(t3, 3);
352 f.tc = Point2.Parse(t3, 5);
355 f2.tc = Point2.Parse(t3, 7);
358 current.faces.Add(f);
359 current.faces.Add(f2);
366 //----- Root elements ----------------------------------------------
367 private void ParseMetasequoia(string[] tokens)
369 // Metasequoia Document
370 if (tokens[1] != "Document")
374 private void ParseFormat(string[] tokens)
377 // Format Text Ver 1.0
379 // Format Text Ver 1.1
380 if (tokens[1] != "Text")
382 if (tokens[2] != "Ver")
384 if (tokens[3] != "1.0" && tokens[3] != "1.1")
388 private void ParseThumbnail(string[] tokens)
390 // Thumbnail 128 128 24 rgb raw {
393 if (tokens[6] != "{") Error(tokens);
395 DoRead(SectionThumbnail);
398 private void ParseScene(string[] tokens)
400 if (tokens[1].ToLower() != "{") Error(tokens);
402 DoRead(SectionScene);
405 private void ParseDirlights(string[] tokens)
410 if (tokens[2].ToLower() != "{") Error(tokens);
412 DoRead(SectionDirlights);
415 private void ParseLight(string[] tokens)
420 if (tokens[1].ToLower() != "{") Error(tokens);
422 DoRead(SectionLight);
425 private void ParseMaterial(string[] tokens)
427 if (tokens[2].ToLower() != "{") Error(tokens);
429 materials = new List<MqoMaterial>(int.Parse(tokens[1]));
430 DoRead(SectionMaterial);
433 private void ParseObject(string[] tokens)
435 if (tokens[2].ToLower() != "{") Error(tokens);
437 current = new MqoObject(tokens[1].Trim('"'));
438 objects.Add(current);
439 DoRead(SectionObject);
442 private void ParseVertex(string[] tokens)
444 if (tokens[2].ToLower() != "{") Error(tokens);
446 current.vertices = new List<Point3>(int.Parse(tokens[1]));
447 DoRead(SectionVertex);
450 private void ParseFace(string[] tokens)
452 if (tokens[2].ToLower() != "{") Error(tokens);
454 current.faces = new List<MqoFace>(int.Parse(tokens[1]));
459 public class MqoScene
462 public Point3 lookat;
470 public class MqoMaterial
482 public MqoMaterial() { }
483 public MqoMaterial(string n) { name = n; }
486 public class MqoObject
494 public int color_type;
495 public List<Point3> vertices;
496 public List<MqoFace> faces;
498 public MqoObject() { }
499 public MqoObject(string n) { name = n; }
504 public ushort a, b, c, mtl;
505 public Point2 ta, tb, tc;
511 public MqoFace(ushort a, ushort b, ushort c, ushort mtl, Point2 ta, Point2 tb, Point2 tc)