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)
133 switch (tokens[0].ToLower())
135 case "metasequoia": ParseMetasequoia(tokens); return true;
136 case "format": ParseFormat(tokens); return true;
137 case "scene": ParseScene(tokens); return true;
138 case "material": ParseMaterial(tokens); return true;
139 case "object": ParseObject(tokens); return true;
140 case "eof": return false;
141 default: return true;
145 private bool SectionScene(string[] tokens)
147 scene = new MqoScene();
149 switch (tokens[0].ToLower())
151 case "pos": scene.pos = Point3.Parse(tokens, 1); return true;
152 case "lookat": scene.lookat = Point3.Parse(tokens, 1); return true;
153 case "head": scene.head = float.Parse(tokens[1]); return true;
154 case "pich": scene.pich = float.Parse(tokens[1]); return true;
155 case "ortho": scene.ortho = float.Parse(tokens[1]); return true;
156 case "zoom2": scene.zoom2 = float.Parse(tokens[1]); return true;
157 case "amb": scene.amb = Color3.Parse(tokens, 1); return true;
158 case "}": return false;
159 default: return true;
163 private static string[] SplitParam(string s)
165 return s.Split(delimiters2, StringSplitOptions.RemoveEmptyEntries);
168 private bool SectionMaterial(string[] tokens)
170 if (tokens[0] == "}")
173 StringBuilder sb = new StringBuilder();
175 foreach (string i in tokens)
176 sb.Append(' ').Append(i);
178 string line = sb.ToString().Trim();
179 MqoMaterial m = new MqoMaterial(tokens[0].Trim('"'));
180 tokens = SplitString(line);
183 for (int i = 1; i < tokens.Length; ++i)
185 string t = tokens[i];
186 string t2 = t.ToLower();
188 if (t2.StartsWith("shader(")) m.shader = int.Parse(SplitParam(t)[1]);
189 else if (t2.StartsWith("col(")) m.col = Color3.Parse(SplitParam(t), 1);
190 else if (t2.StartsWith("dif(")) m.dif = float.Parse(SplitParam(t)[1]);
191 else if (t2.StartsWith("amb(")) m.amb = float.Parse(SplitParam(t)[1]);
192 else if (t2.StartsWith("emi(")) m.emi = float.Parse(SplitParam(t)[1]);
193 else if (t2.StartsWith("spc(")) m.spc = float.Parse(SplitParam(t)[1]);
194 else if (t2.StartsWith("power(")) m.power = float.Parse(SplitParam(t)[1]);
195 else if (t2.StartsWith("tex(")) m.tex = t.Substring(3).Trim('(', ')', '"');
201 private bool SectionObject(string[] tokens)
203 switch (tokens[0].ToLower())
205 case "visible": current.visible = int.Parse(tokens[1]); return true;
206 case "locking": current.locking = int.Parse(tokens[1]); return true;
207 case "shading": current.shading = int.Parse(tokens[1]); return true;
208 case "facet": current.facet = float.Parse(tokens[1]); return true;
209 case "color": current.color = Color3.Parse(tokens, 1); return true;
210 case "color_type": current.color_type = int.Parse(tokens[1]); return true;
211 case "vertex": ParseVertex(tokens); return true;
212 case "face": ParseFace(tokens); return true;
213 case "}": return false;
214 default: return true;
218 private bool SectionVertex(string[] tokens)
220 if (tokens[0] == "}")
223 current.vertices.Add(Point3.Parse(tokens, 0));
228 private bool SectionFace(string[] tokens)
230 if (tokens[0] == "}")
233 int nface = int.Parse(tokens[0]);
235 StringBuilder sb = new StringBuilder();
236 foreach (string i in tokens)
237 sb.Append(' ').Append(i);
238 string line = sb.ToString().Trim();
239 tokens = SplitString(line);
245 MqoFace f = new MqoFace();
247 for (int i = 1; i < tokens.Length; ++i)
249 string t = tokens[i];
250 string t2 = t.ToLower();
252 if (t2.StartsWith("v("))
254 string[] t3 = SplitParam(t);
255 f.a = ushort.Parse(t3[1]);
256 f.b = ushort.Parse(t3[2]);
257 f.c = ushort.Parse(t3[3]);
260 if (t2.StartsWith("m("))
262 string[] t3 = SplitParam(t);
263 f.mtl = ushort.Parse(t3[1]);
266 if (t2.StartsWith("uv("))
268 string[] t3 = SplitParam(t);
269 f.ta = Point2.Parse(t3, 1);
270 f.tb = Point2.Parse(t3, 3);
271 f.tc = Point2.Parse(t3, 5);
274 current.faces.Add(f);
279 MqoFace f = new MqoFace();
280 MqoFace f2 = new MqoFace();
282 for (int i = 1; i < tokens.Length; ++i)
284 string t = tokens[i];
285 string t2 = t.ToLower();
287 if (t2.StartsWith("v("))
289 string[] t3 = SplitParam(t);
290 f.a = ushort.Parse(t3[1]);
291 f.b = ushort.Parse(t3[2]);
292 f.c = ushort.Parse(t3[3]);
295 f2.c = ushort.Parse(t3[4]);
298 if (t2.StartsWith("m("))
300 string[] t3 = SplitParam(t);
301 f.mtl = ushort.Parse(t3[1]);
305 if (t2.StartsWith("uv("))
307 string[] t3 = SplitParam(t);
308 f.ta = Point2.Parse(t3, 1);
309 f.tb = Point2.Parse(t3, 3);
310 f.tc = Point2.Parse(t3, 5);
313 f2.tc = Point2.Parse(t3, 7);
316 current.faces.Add(f);
317 current.faces.Add(f2);
324 //----- Root elements ----------------------------------------------
325 private void ParseMetasequoia(string[] tokens)
327 if (tokens[1].ToLower() != "document") Error(tokens);
330 private void ParseFormat(string[] tokens)
332 if (tokens[1].ToLower() != "text") Error(tokens);
333 if (tokens[2].ToLower() != "ver") Error(tokens);
334 if (tokens[3].ToLower() != "1.0") Error(tokens);
337 private void ParseScene(string[] tokens)
339 if (tokens[1].ToLower() != "{") Error(tokens);
341 DoRead(SectionScene);
344 private void ParseMaterial(string[] tokens)
346 if (tokens[2].ToLower() != "{") Error(tokens);
348 materials = new List<MqoMaterial>(int.Parse(tokens[1]));
349 DoRead(SectionMaterial);
352 private void ParseObject(string[] tokens)
354 if (tokens[2].ToLower() != "{") Error(tokens);
356 current = new MqoObject(tokens[1].Trim('"'));
357 objects.Add(current);
358 DoRead(SectionObject);
361 private void ParseVertex(string[] tokens)
363 if (tokens[2].ToLower() != "{") Error(tokens);
365 current.vertices = new List<Point3>(int.Parse(tokens[1]));
366 DoRead(SectionVertex);
369 private void ParseFace(string[] tokens)
371 if (tokens[2].ToLower() != "{") Error(tokens);
373 current.faces = new List<MqoFace>(int.Parse(tokens[1]));
378 public class MqoScene
381 public Point3 lookat;
389 public class MqoMaterial
401 public MqoMaterial() { }
402 public MqoMaterial(string n) { name = n; }
405 public class MqoObject
413 public int color_type;
414 public List<Point3> vertices;
415 public List<MqoFace> faces;
417 public MqoObject() { }
418 public MqoObject(string n) { name = n; }
423 public ushort a, b, c, mtl;
424 public Point2 ta, tb, tc;
430 public MqoFace(ushort a, ushort b, ushort c, ushort mtl, Point2 ta, Point2 tb, Point2 tc)