2 using System.Collections.Generic;
9 public enum MqoBoneMode
16 public class Pair<T, U>
25 public Pair(T first, U second)
32 public class MqoWriter : IDisposable
35 public string OutPath;
36 public string OutFile;
37 public MqoBoneMode BoneMode = MqoBoneMode.None;
39 public MqoWriter(string file)
41 FileStream fs = File.OpenWrite(file);
43 tw = new StreamWriter(fs, Encoding.Default);
45 OutPath = Path.GetDirectoryName(file);
48 void IDisposable.Dispose()
60 string GetTextureFileName(TSOTex tex)
62 string filename = Path.GetFileName(tex.File.Trim('"'));
68 string GetTexturePath(TSOTex tex)
70 return Path.Combine(OutPath, GetTextureFileName(tex));
73 public void CreateTextureFile(TSOTex tex)
75 string file = GetTexturePath(tex);
76 byte[] data = tex.data;
78 //TODO: .bmpのはずが.psdになってるものがある
80 using (FileStream fs = File.OpenWrite(file))
82 BinaryWriter bw = new BinaryWriter(fs);
84 switch (Path.GetExtension(file).ToUpper())
87 bw.Write((byte)0); // id
88 bw.Write((byte)0); // colormap
89 bw.Write((byte)2); // imagetype
90 bw.Write((byte)0); // unknown0
91 bw.Write((byte)0); // unknown1
92 bw.Write((byte)0); // unknown2
93 bw.Write((byte)0); // unknown3
94 bw.Write((byte)0); // unknown4
95 bw.Write((short)0); // width
96 bw.Write((short)0); // height
97 bw.Write((short)tex.Width); // width
98 bw.Write((short)tex.Height); // height
99 bw.Write((byte)(tex.depth * 8));// depth
100 bw.Write((byte)0); // depth
106 bw.Write((int)(54 + data.Length));
110 bw.Write((int)tex.Width);
111 bw.Write((int)tex.Height);
113 bw.Write((short)(tex.Depth * 8));
115 bw.Write((int)data.Length);
123 bw.Write(data, 0, data.Length);
128 public void Write(TSOFile tso)
131 bool mqx_enabled = BoneMode == MqoBoneMode.RokDeBone;
133 tw.WriteLine("Metasequoia Document");
134 tw.WriteLine("Format Text Ver 1.0");
138 tw.WriteLine("IncludeXml \"{0}\"", Path.GetFileName(Path.ChangeExtension(OutFile, ".mqx")));
141 tw.WriteLine("Scene {");
142 tw.WriteLine("\tpos -7.0446 4.1793 1541.1764");
143 tw.WriteLine("\tlookat 11.8726 193.8590 0.4676");
144 tw.WriteLine("\thead 0.8564");
145 tw.WriteLine("\tpich 0.1708");
146 tw.WriteLine("\tortho 0");
147 tw.WriteLine("\tzoom2 31.8925");
148 tw.WriteLine("\tamb 0.250 0.250 0.250");
151 foreach (TSOTex tex in tso.textures)
152 CreateTextureFile(tex);
154 tw.WriteLine("Material {0} {{", tso.materials.Length);
156 foreach (TSOMaterial mat in tso.materials)
159 if (tso.texturemap.TryGetValue(mat.ColorTex, out tex))
162 "\t\"{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}\")",
163 mat.name, GetTextureFileName(tex));
168 "\t\"{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))",
175 tso.UpdateNodesWorld();
177 MqoBone[] bones = new MqoBone[tso.nodes.Length];
179 foreach (TSONode node in tso.nodes)
181 MqoBone bone = new MqoBone();
183 bone.name = node.ShortName;
184 bone.tail = node.children.Count == 0;
186 if (node.parent == null)
192 bone.pid = node.parent.id;
193 bones[bone.pid].cids.Add(bone.id);
197 bone.q = node.world.Translation;
200 bone.p = node.children[0].world.Translation;
202 bone.p = node.world.Translation;
204 bones[node.id] = bone;
207 MqoObjectGen.uid_enabled = mqx_enabled;
208 MqoObjectGen obj = new MqoObjectGen();
210 ushort object_id = 0;
211 foreach (TSOMesh mesh in tso.meshes)
213 obj.id = ++object_id;
214 obj.name = mesh.Name;
221 WriteMqxDeBone(bones, object_id /* eq numobjects */);
226 void WriteMqxDeBone(MqoBone[] bones, int numobjects)
228 XmlWriterSettings settings = new XmlWriterSettings();
229 settings.Indent = true;
230 settings.IndentChars = new String(' ', 4);
231 XmlWriter writer = XmlWriter.Create(Path.ChangeExtension(OutFile, ".mqx"), settings);
232 writer.WriteStartElement("MetasequoiaDocument");
233 writer.WriteElementString("IncludedBy", Path.GetFileName(OutFile));
235 writer.WriteStartElement("Plugin.56A31D20.71F282AB");
236 writer.WriteAttributeString("name", "Bone");
237 writer.WriteStartElement("BoneSet");
239 foreach (MqoBone bone in bones)
242 writer.WriteEndElement();//BoneSet
244 for (int i = 0; i < numobjects; i++)
246 writer.WriteStartElement("Obj");
247 writer.WriteAttributeString("id", (i+1).ToString());
248 writer.WriteEndElement();
250 writer.WriteEndElement();//Plugin.56A31D20.71F282AB
252 writer.WriteEndElement();//MetasequoiaDocument
256 void WriteRokDeBone(MqoBone[] bones)
258 tw.WriteLine("Object \"{0}\" {{", "Bone");
259 tw.WriteLine("\tvisible {0}", 15);
260 tw.WriteLine("\tlocking {0}", 0);
261 tw.WriteLine("\tshading {0}", 1);
262 tw.WriteLine("\tfacet {0}", 59.5);
263 tw.WriteLine("\tcolor {0} {1} {2}", 1, 0, 0);
264 tw.WriteLine("\tcolor_type {0}", 0);
266 tw.WriteLine("\tvertex {0} {{", bones.Length);
268 foreach (MqoBone bone in bones)
269 tw.WriteLine("\t\t{0:F4} {1:F4} {2:F4}", bone.q.x, bone.q.y, bone.q.z);
274 tw.WriteLine("\tface {0} {{", bones.Length);
276 foreach (MqoBone bone in bones)
283 tw.WriteLine(string.Format("\t\t2 V({0} {1})", bone.pid, bone.id));
291 public class MqoObjectGen
293 public static bool uid_enabled;
295 public int id; //object_id
297 VertexHeap<UVertex> vh = new VertexHeap<UVertex>();
298 public List<MqoFace> faces;
300 public int numvertices { get { return vh.Count; } }
301 public List<UVertex> vertices { get { return vh.verts; } }
302 public int numfaces { get { return faces.Count; } }
304 public MqoObjectGen()
306 faces = new List<MqoFace>(2048);
309 public void Update(TSOMesh mesh)
314 foreach (TSOSubMesh sub_mesh in mesh.sub_meshes)
317 ushort a = 0, b = 0, c = 0;
318 Vertex va = new Vertex(), vb = new Vertex(), vc = new Vertex();
320 foreach (Vertex v in sub_mesh.vertices)
325 vc = v; c = vh.Add(new UVertex(v.Pos, v.Wgt, v.Idx, v.Nrm));
327 if (cnt < 3) continue;
328 if (a == b || b == c || c == a) continue;
332 MqoFace f = new MqoFace(a, b, c, (ushort)sub_mesh.spec,
333 new Point2(va.Tex.x, 1 - va.Tex.y),
334 new Point2(vb.Tex.x, 1 - vb.Tex.y),
335 new Point2(vc.Tex.x, 1 - vc.Tex.y));
340 MqoFace f = new MqoFace(a, c, b, (ushort)sub_mesh.spec,
341 new Point2(va.Tex.x, 1 - va.Tex.y),
342 new Point2(vc.Tex.x, 1 - vc.Tex.y),
343 new Point2(vb.Tex.x, 1 - vb.Tex.y));
350 public void Write(TextWriter tw)
352 tw.WriteLine("Object \"{0}\" {{", name);
354 tw.WriteLine("\tuid {0}", id);
355 tw.WriteLine("\tvisible {0}", 15);
356 tw.WriteLine("\tlocking {0}", 0);
357 tw.WriteLine("\tshading {0}", 1);
358 tw.WriteLine("\tfacet {0}", 59.5);
359 tw.WriteLine("\tcolor {0:F3} {1:F3} {2:F3}", 0.898f, 0.498f, 0.698f);
360 tw.WriteLine("\tcolor_type {0}", 0);
363 tw.WriteLine("\tvertex {0} {{", numvertices);
365 foreach (UVertex v in vertices)
372 tw.WriteLine("\tvertexattr {");
373 tw.WriteLine("\t\tuid {");
375 ushort vertex_id = 0;
376 foreach (UVertex v in vertices)
377 tw.WriteLine("\t\t\t{0}", ++vertex_id);
379 tw.WriteLine("\t\t}");
384 tw.WriteLine("\tface {0} {{", numfaces);
386 for (int i = 0, n = numfaces; i < n; i++)
392 public unsafe void AddWeits(MqoBone[] bones)
394 ushort vertex_id = 0;
395 foreach (UVertex v in vertices)
400 byte* idx = (byte*)(&idx0);
402 float* wgt = (float*)(&wgt0);
404 for (int k = 0; k < 4; ++k)
405 if (wgt[k] > float.Epsilon)
407 MqoWeit weit = new MqoWeit();
409 weit.vertex_id = vertex_id;
411 bones[idx[k]].weits.Add(weit);
424 public List<int> cids = new List<int>();
432 public List<MqoWeit> weits;
436 weits = new List<MqoWeit>(2048*3*4);
439 public void Write(XmlWriter writer)
441 writer.WriteStartElement("Bone");
442 writer.WriteAttributeString("id", (id+1).ToString());
444 writer.WriteAttributeString("rtX", q.X.ToString());
445 writer.WriteAttributeString("rtY", q.Y.ToString());
446 writer.WriteAttributeString("rtZ", q.Z.ToString());
448 writer.WriteAttributeString("tpX", p.X.ToString());
449 writer.WriteAttributeString("tpY", p.Y.ToString());
450 writer.WriteAttributeString("tpZ", p.Z.ToString());
452 writer.WriteAttributeString("rotB", "0.0");
453 writer.WriteAttributeString("rotH", "0.0");
454 writer.WriteAttributeString("rotP", "0.0");
456 writer.WriteAttributeString("mvX", "0.0");
457 writer.WriteAttributeString("mvY", "0.0");
458 writer.WriteAttributeString("mvZ", "0.0");
460 writer.WriteAttributeString("sc", "1.0");
462 writer.WriteAttributeString("maxAngB", "90.0");
463 writer.WriteAttributeString("maxAngH", "180.0");
464 writer.WriteAttributeString("maxAngP", "180.0");
466 writer.WriteAttributeString("minAngB", "-90.0");
467 writer.WriteAttributeString("minAngH", "-180.0");
468 writer.WriteAttributeString("minAngP", "-180.0");
470 writer.WriteAttributeString("isDummy", tail ? "1" : "0");
471 writer.WriteAttributeString("name", name);
473 writer.WriteStartElement("P");
474 writer.WriteAttributeString("id", (pid+1).ToString());
475 writer.WriteEndElement();
477 foreach (int cid in cids)
479 writer.WriteStartElement("C");
480 writer.WriteAttributeString("id", (cid+1).ToString());
481 writer.WriteEndElement();
483 foreach (MqoWeit weit in weits)
488 writer.WriteEndElement();
494 public int object_id;
495 public int vertex_id;
496 //public int bone_id;
499 public void Write(XmlWriter writer)
501 float weit_percent = weit * 100.0f;
503 writer.WriteStartElement("W");
504 writer.WriteAttributeString("oi", object_id.ToString());
505 writer.WriteAttributeString("vi", vertex_id.ToString());
506 writer.WriteAttributeString("w", weit_percent.ToString());
507 writer.WriteEndElement();
511 public class UVertex : IComparable<UVertex>
513 //public int id; //vertex_id
523 public UVertex(Point3 pos, Point4 wgt, UInt32 idx, Point3 nrm)
531 public int CompareTo(UVertex o)
534 cmp = Pos.CompareTo(o.Pos); if (cmp != 0) return cmp;
535 cmp = Nrm.CompareTo(o.Nrm);
539 public override int GetHashCode()
541 return Pos.GetHashCode() ^ Nrm.GetHashCode();
544 public override bool Equals(object obj)
548 UVertex o = (UVertex)obj;
549 return Pos.Equals(o.Pos) && Nrm.Equals(o.Nrm);
554 public bool Equals(UVertex o)
556 if ((object)o == null)
561 return Pos.Equals(o.Pos) && Nrm.Equals(o.Nrm);
564 public void Write(TextWriter tw)
566 tw.WriteLine("\t\t{0:F4} {1:F4} {2:F4}", Pos.x, Pos.y, Pos.z);