2 using System.Collections.Generic;
\r
8 public enum MqoBoneMode
\r
15 public class Pair<T, U>
\r
24 public Pair(T first, U second)
\r
31 public class MqoWriter : IDisposable
\r
33 public TextWriter tw;
\r
34 public string OutPath;
\r
35 public string OutFile;
\r
36 public MqoBoneMode BoneMode = MqoBoneMode.None;
\r
38 public MqoWriter(string file)
\r
40 FileStream fs = File.OpenWrite(file);
\r
42 tw = new StreamWriter(fs, Encoding.Default);
\r
44 OutPath = Path.GetDirectoryName(file);
\r
47 void IDisposable.Dispose()
\r
59 public void CreateTextureFile(TSOTex tex)
\r
61 string file= Path.Combine(OutPath, Path.GetFileName(tex.file.Trim('"')));
\r
62 byte[] data= tex.data;
\r
64 using(FileStream fs= File.OpenWrite(file))
\r
66 BinaryWriter bw = new BinaryWriter(fs);
\r
68 switch(Path.GetExtension(file).ToUpper())
\r
71 bw.Write((byte)0); // id
\r
72 bw.Write((byte)0); // colormap
\r
73 bw.Write((byte)2); // imagetype
\r
74 bw.Write((byte)0); // unknown0
\r
75 bw.Write((byte)0); // unknown1
\r
76 bw.Write((byte)0); // unknown2
\r
77 bw.Write((byte)0); // unknown3
\r
78 bw.Write((byte)0); // unknown4
\r
79 bw.Write((short)0); // width
\r
80 bw.Write((short)0); // height
\r
81 bw.Write((short)tex.Width); // width
\r
82 bw.Write((short)tex.Height); // height
\r
83 bw.Write((byte)(tex.depth * 8));// depth
\r
84 bw.Write((byte)0); // depth
\r
88 bw.Write((byte)'B');
\r
89 bw.Write((byte)'M');
\r
90 bw.Write((int)(54 + data.Length));
\r
94 bw.Write((int)tex.Width);
\r
95 bw.Write((int)tex.Height);
\r
97 bw.Write((short)(tex.Depth*8));
\r
99 bw.Write((int)data.Length);
\r
107 bw.Write(data, 0, data.Length);
\r
112 public void Write(TSOFile file)
\r
114 tw.WriteLine("Metasequoia Document");
\r
115 tw.WriteLine("Format Text Ver 1.0");
\r
117 tw.WriteLine("Scene {");
\r
118 tw.WriteLine(" pos -7.0446 4.1793 1541.1764");
\r
119 tw.WriteLine(" lookat 11.8726 193.8590 0.4676");
\r
120 tw.WriteLine(" head 0.8564");
\r
121 tw.WriteLine(" pich 0.1708");
\r
122 tw.WriteLine(" ortho 0");
\r
123 tw.WriteLine(" zoom2 31.8925");
\r
124 tw.WriteLine(" amb 0.250 0.250 0.250");
\r
127 //VertexHeap<UVertex> vh = new VertexHeap<UVertex>();
\r
128 VertexHeap vh = new VertexHeap();
\r
129 List<ushort> face= new List<ushort>(2048*3);
\r
130 List<float> uv = new List<float>(2048*3 * 2);
\r
131 List<int> mtl = new List<int>(2048);
\r
133 foreach(TSOTex i in file.textures)
\r
134 CreateTextureFile(i);
\r
136 tw.WriteLine("Material {0} {{", file.materials.Length);
\r
138 foreach(TSOMaterial i in file.materials)
\r
140 if(i.ColorTex != null)
\r
142 TSOTex tex = file.texturemap[i.ColorTex];
\r
144 " \"{0}\" col(1.000 1.000 1.000 1.000) dif(0.800) amb(0.600) emi(0.000) spc(0.000) power(5.00) tex(\"{1}\")",
\r
145 i.name, Path.Combine(OutPath, tex.File.Trim('"')));
\r
149 " \"{0}\" col(1.000 1.000 1.000 1.000) dif(0.800) amb(0.600) emi(0.000) spc(0.000) power(5.00))",
\r
156 foreach(TSOMesh i in file.meshes)
\r
163 foreach(TSOSubMesh j in i.sub)
\r
166 ushort a= 0, b= 0, c= 0;
\r
167 Vertex va= new Vertex(), vb= new Vertex(), vc= new Vertex();
\r
169 foreach(Vertex k in j.vertices)
\r
174 vc= k; c= vh.Add(new UVertex(k.Pos, k.Nrm, k.Tex, j.spec));
\r
176 if(cnt < 3) continue;
\r
177 if(a == b || b == c || c == a) continue;
\r
181 face.Add(a); uv.Add(va.Tex.x); uv.Add(1-va.Tex.y);
\r
182 face.Add(b); uv.Add(vb.Tex.x); uv.Add(1-vb.Tex.y);
\r
183 face.Add(c); uv.Add(vc.Tex.x); uv.Add(1-vc.Tex.y);
\r
187 face.Add(a); uv.Add(va.Tex.x); uv.Add(1-va.Tex.y);
\r
188 face.Add(c); uv.Add(vc.Tex.x); uv.Add(1-vc.Tex.y);
\r
189 face.Add(b); uv.Add(vb.Tex.x); uv.Add(1-vb.Tex.y);
\r
195 tw.WriteLine("Object \"{0}\" {{", i.Name);
\r
196 tw.WriteLine(" visible {0}", 15);
\r
197 tw.WriteLine(" locking {0}", 0);
\r
198 tw.WriteLine(" shading {0}", 1);
\r
199 tw.WriteLine(" facet {0}", 59.5);
\r
200 tw.WriteLine(" color {0:F3} {1:F3} {2:F3}", 0.898f, 0.498f, 0.698f);
\r
201 tw.WriteLine(" color_type {0}", 0);
\r
204 tw.WriteLine(" vertex {0} {{", vh.Count);
\r
206 foreach(UVertex j in vh.verts)
\r
207 WriteVertex(j.Pos.x, j.Pos.y, j.Pos.z);
\r
209 tw.WriteLine(" }");
\r
212 tw.WriteLine(" face {0} {{", face.Count);
\r
214 System.Diagnostics.Debug.Assert(face.Count*2 == uv.Count);
\r
215 System.Diagnostics.Debug.Assert(face.Count == mtl.Count * 3);
\r
217 for(int j= 0, n= face.Count; j < n; j+=3)
\r
218 WriteFace(face[j+0], face[j+1], face[j+2],
\r
219 uv[j*2+0], uv[j*2+1],
\r
220 uv[j*2+2], uv[j*2+3],
\r
221 uv[j*2+4], uv[j*2+5],
\r
223 tw.WriteLine(" }");
\r
230 case MqoBoneMode.None: break;
\r
231 case MqoBoneMode.RokDeBone:
\r
234 foreach(TSONode i in file.nodes)
\r
236 if(i.parent == null)
\r
237 i.world = i.Matrix;
\r
238 else i.world = Matrix44.Mul(i.Matrix, i.parent.World);
\r
241 List<Point3> points = new List<Point3>();
\r
242 List<int> bones = new List<int>();
\r
244 tw.WriteLine("Object \"{0}\" {{", "Bone");
\r
245 tw.WriteLine(" visible {0}", 15);
\r
246 tw.WriteLine(" locking {0}", 0);
\r
247 tw.WriteLine(" shading {0}", 1);
\r
248 tw.WriteLine(" facet {0}", 59.5);
\r
249 tw.WriteLine(" color {0} {1} {2}", 1, 0, 0);
\r
250 tw.WriteLine(" color_type {0}", 0);
\r
252 foreach(TSONode i in file.nodes)
\r
254 if(i.children.Count == 0)
\r
257 Point3 q = new Point3(i.world.M41, i.world.M42, i.world.M43);
\r
258 Point3 p = new Point3();
\r
260 foreach(TSONode j in i.children)
\r
267 p.x /=i.children.Count;
\r
268 p.y /=i.children.Count;
\r
269 p.z /=i.children.Count;
\r
271 bones.Add(points.Count); points.Add(q);
\r
272 bones.Add(points.Count); points.Add(p);
\r
275 tw.WriteLine(" vertex {0} {{", points.Count);
\r
277 foreach(Point3 j in points)
\r
278 WriteVertex(j.x, j.y, j.z);
\r
280 tw.WriteLine(" }");
\r
283 tw.WriteLine(" face {0} {{", bones.Count / 2);
\r
285 for(int j= 0, n= bones.Count; j < n; j+=2)
\r
286 tw.WriteLine(string.Format(" 2 V({0} {1})", bones[j+0], bones[j+1]));
\r
288 tw.WriteLine(" }");
\r
293 case MqoBoneMode.Mikoto:
\r
299 tw.WriteLine("Eof");
\r
302 public void WriteFace(int a, int b, int c, float u1, float v1, float u2, float v2, float u3, float v3, int m)
\r
304 tw.WriteLine(" {0} V({1} {2} {3}) M({10}) UV({4:F5} {5:F5} {6:F5} {7:F5} {8:F5} {9:F5})",
\r
305 3, a, b, c, u1, v1, u2, v2, u3, v3, m);
\r
308 public void WriteVertex(float x, float y, float z)
\r
310 tw.WriteLine(" {0:F4} {1:F4} {2:F4}", x, y, z);
\r
314 public class UVertex : IComparable<UVertex>
\r
325 public UVertex(Point3 pos, Point3 nrm, Point2 tex, int mtl)
\r
333 public int CompareTo(UVertex o)
\r
335 if(Pos.x < o.Pos.x) return -1; if(Pos.x > o.Pos.x) return 1;
\r
336 if(Pos.y < o.Pos.y) return -1; if(Pos.y > o.Pos.y) return 1;
\r
337 if(Pos.z < o.Pos.z) return -1; if(Pos.z > o.Pos.z) return 1;
\r
338 if(Nrm.x < o.Nrm.x) return -1; if(Nrm.x > o.Nrm.x) return 1;
\r
339 if(Nrm.y < o.Nrm.y) return -1; if(Nrm.y > o.Nrm.y) return 1;
\r
340 if(Nrm.z < o.Nrm.z) return -1; if(Nrm.z > o.Nrm.z) return 1;
\r
341 if(Tex.x < o.Tex.x) return -1; if(Tex.x > o.Tex.x) return 1;
\r
342 if(Tex.y < o.Tex.y) return -1; if(Tex.y > o.Tex.y) return 1;
\r
343 return mtl - o.mtl;
\r
346 public override int GetHashCode()
\r
348 return Pos.x.GetHashCode() ^ Pos.y.GetHashCode() ^ Pos.z.GetHashCode()
\r
349 ^ Nrm.x.GetHashCode() ^ Nrm.y.GetHashCode() ^ Nrm.z.GetHashCode();
\r
352 public override bool Equals(object obj)
\r
354 UVertex o = obj as UVertex;
\r
359 return Pos.x==o.Pos.x && Pos.y==o.Pos.y && Pos.z==o.Pos.z
\r
360 && Nrm.x==o.Nrm.x && Nrm.y==o.Nrm.y && Nrm.z==o.Nrm.z;
\r