{
public class MqoFile
{
- private delegate bool SectionHandler(string[] tokens);
+ delegate bool SectionHandler(string[] tokens);
- private static char[] delimiters2 = new char[] { ' ', '\t', '(', ')' };
+ static char[] param_delimiters = new char[] { ' ', '\t', '(', ')' };
- private string file;
- private StreamReader sr;
- private MqoScene scene;
- private List<MqoMaterial> materials;
- private List<MqoObject> objects = new List<MqoObject>();
- private MqoObject current;
+ string file;
+ StreamReader sr;
+ MqoScene scene;
+ List<MqoMaterial> materials;
+ List<MqoObject> objects = new List<MqoObject>();
+ MqoObject current;
public MqoScene Scene { get { return scene; } }
public List<MqoMaterial> Materials { get { return materials; } }
DoRead(SectionRoot);
}
- private static string[] SplitString(string s)
+ static string[] SplitString(string s)
{
List<string> tokens = new List<string>();
StringBuilder sb = new StringBuilder(s.Length);
return tokens.ToArray();
}
- private void DoRead(SectionHandler h)
+ void DoRead(SectionHandler h)
{
- for (int no = 1; ; ++no)
+ for (int lineno = 1; ; ++lineno)
{
string line = sr.ReadLine();
}
catch (Exception exception)
{
- string msg = string.Format("File format error: {0} \"{1}\"", no, line);
- throw new Exception(msg, exception);
+ throw new Exception(string.Format("File format error: {0} \"{1}\"", lineno, line), exception);
}
}
}
public void Error(string[] tokens)
{
- throw new Exception("File Format Error: \"" + string.Concat(tokens) + "\"");
+ throw new Exception(string.Format("File Format Error: \"{0}\"", string.Concat(tokens)));
}
- private bool SectionRoot(string[] tokens)
+ bool SectionRoot(string[] tokens)
{
switch (tokens[0])
{
- case "Metasequoia": ParseMetasequoia(tokens); return true;
- case "Format": ParseFormat(tokens); return true;
- case "Thumbnail": ParseThumbnail(tokens); return true;
- case "Scene": ParseScene(tokens); return true;
- case "Material": ParseMaterial(tokens); return true;
- case "Object": ParseObject(tokens); return true;
+ case "Metasequoia":
+ {
+ // Metasequoia Document
+ if (tokens[1] != "Document")
+ Error(tokens);
+ }
+ return true;
+ case "Format":
+ {
+ // @since v2.2
+ // Format Text Ver 1.0
+ // @since v4.0
+ // Format Text Ver 1.1
+ if (tokens[1] != "Text")
+ Error(tokens);
+ if (tokens[2] != "Ver")
+ Error(tokens);
+ if (tokens[3] != "1.0" && tokens[3] != "1.1")
+ Error(tokens);
+ }
+ return true;
+ case "Thumbnail":
+ {
+ // Thumbnail 128 128 24 rgb raw {
+ // ...
+ // }
+ if (tokens[6] != "{")
+ Error(tokens);
+
+ DoRead(SectionThumbnail);
+ }
+ return true;
+ case "Scene":
+ {
+ if (tokens[1] != "{")
+ Error(tokens);
+
+ DoRead(SectionScene);
+ }
+ return true;
+ case "Material":
+ {
+ if (tokens[2] != "{")
+ Error(tokens);
+
+ materials = new List<MqoMaterial>(int.Parse(tokens[1]));
+ DoRead(SectionMaterial);
+ }
+ return true;
+ case "Object":
+ {
+ if (tokens[2] != "{")
+ Error(tokens);
+
+ current = new MqoObject(tokens[1].Trim('"'));
+ objects.Add(current);
+ DoRead(SectionObject);
+ }
+ return true;
case "Eof":
return false;
default:
}
}
- private bool SectionThumbnail(string[] tokens)
+ bool SectionThumbnail(string[] tokens)
{
switch (tokens[0])
{
}
}
- private bool SectionScene(string[] tokens)
+ bool SectionScene(string[] tokens)
{
scene = new MqoScene();
case "ortho": scene.ortho = float.Parse(tokens[1]); return true;
case "zoom2": scene.zoom2 = float.Parse(tokens[1]); return true;
case "amb": scene.amb = Color3.Parse(tokens, 1); return true;
- case "dirlights": ParseDirlights(tokens); return true;
+ case "dirlights":
+ {
+ // dirlights 1 {
+ // ...
+ // }
+ if (tokens[2] != "{")
+ Error(tokens);
+
+ DoRead(SectionDirlights);
+ }
+ return true;
case "}":
return false;
default:
}
}
- private bool SectionDirlights(string[] tokens)
+ bool SectionDirlights(string[] tokens)
{
switch (tokens[0])
{
- case "light": ParseLight(tokens); return true;
+ case "light":
+ {
+ // light {
+ // ...
+ // }
+ if (tokens[1] != "{")
+ Error(tokens);
+
+ DoRead(SectionLight);
+ }
+ break;
case "}":
return false;
- default:
- return true;
}
+ return true;
}
- private bool SectionLight(string[] tokens)
+ bool SectionLight(string[] tokens)
{
switch (tokens[0])
{
case "}":
return false;
- default:
- return true;
}
+ return true;
}
- private static string[] SplitParam(string s)
+ static string[] SplitParam(string s)
{
- return s.Split(delimiters2, StringSplitOptions.RemoveEmptyEntries);
+ return s.Split(param_delimiters, StringSplitOptions.RemoveEmptyEntries);
}
- private bool SectionMaterial(string[] tokens)
+ bool SectionMaterial(string[] tokens)
{
if (tokens[0] == "}")
return false;
return true;
}
- private bool SectionObject(string[] tokens)
+ bool SectionObject(string[] tokens)
{
switch (tokens[0])
{
- case "visible": current.visible = int.Parse(tokens[1]); return true;
- case "locking": current.locking = int.Parse(tokens[1]); return true;
- case "shading": current.shading = int.Parse(tokens[1]); return true;
- case "facet": current.facet = float.Parse(tokens[1]); return true;
- case "color": current.color = Color3.Parse(tokens, 1); return true;
- case "color_type": current.color_type = int.Parse(tokens[1]); return true;
- case "vertex": ParseVertex(tokens); return true;
- case "face": ParseFace(tokens); return true;
+ case "visible": current.visible = int.Parse(tokens[1]); break;
+ case "locking": current.locking = int.Parse(tokens[1]); break;
+ case "shading": current.shading = int.Parse(tokens[1]); break;
+ case "facet": current.facet = float.Parse(tokens[1]); break;
+ case "color": current.color = Color3.Parse(tokens, 1); break;
+ case "color_type": current.color_type = int.Parse(tokens[1]); break;
+ case "vertex":
+ {
+ if (tokens[2] != "{")
+ Error(tokens);
+
+ current.vertices = new List<Point3>(int.Parse(tokens[1]));
+ DoRead(SectionVertex);
+ }
+ break;
+ case "vertexattr":
+ DoRead(SectionVertexAttr);
+ break;
+ case "face":
+ {
+ if (tokens[2] != "{")
+ Error(tokens);
+
+ current.faces = new List<MqoFace>(int.Parse(tokens[1]));
+ DoRead(SectionFace);
+ }
+ break;
case "}":
return false;
- default:
- return true;
}
+ return true;
}
- private bool SectionVertex(string[] tokens)
+ bool SectionVertex(string[] tokens)
{
if (tokens[0] == "}")
return false;
return true;
}
- private bool SectionFace(string[] tokens)
+ bool SectionVertexAttr(string[] tokens)
+ {
+ switch (tokens[0])
+ {
+ case "uid":
+ {
+ // uid {
+ // ...
+ // }
+ if (tokens[1] != "{")
+ Error(tokens);
+
+ DoRead(SectionUid);
+ }
+ break;
+ case "}":
+ return false;
+ }
+ return true;
+ }
+
+ bool SectionUid(string[] tokens)
+ {
+ switch (tokens[0])
+ {
+ case "}":
+ return false;
+ }
+ return true;
+ }
+
+ bool SectionFace(string[] tokens)
{
if (tokens[0] == "}")
return false;
f.b = ushort.Parse(t3[2]);
f.c = ushort.Parse(t3[3]);
}
- else
- if (t2.StartsWith("m("))
- {
- string[] t3 = SplitParam(t);
- f.mtl = ushort.Parse(t3[1]);
- }
- else
- if (t2.StartsWith("uv("))
- {
- string[] t3 = SplitParam(t);
- f.ta = Point2.Parse(t3, 1);
- f.tb = Point2.Parse(t3, 3);
- f.tc = Point2.Parse(t3, 5);
- }
+ else if (t2.StartsWith("m("))
+ {
+ string[] t3 = SplitParam(t);
+ f.mtl = ushort.Parse(t3[1]);
+ }
+ else if (t2.StartsWith("uv("))
+ {
+ string[] t3 = SplitParam(t);
+ f.ta = Point2.Parse(t3, 1);
+ f.tb = Point2.Parse(t3, 3);
+ f.tc = Point2.Parse(t3, 5);
+ }
}
current.faces.Add(f);
}
f2.b = f.c;
f2.c = ushort.Parse(t3[4]);
}
- else
- if (t2.StartsWith("m("))
- {
- string[] t3 = SplitParam(t);
- f.mtl = ushort.Parse(t3[1]);
- f2.mtl = f.mtl;
- }
- else
- if (t2.StartsWith("uv("))
- {
- string[] t3 = SplitParam(t);
- f.ta = Point2.Parse(t3, 1);
- f.tb = Point2.Parse(t3, 3);
- f.tc = Point2.Parse(t3, 5);
- f2.ta = f.ta;
- f2.tb = f.tc;
- f2.tc = Point2.Parse(t3, 7);
- }
+ else if (t2.StartsWith("m("))
+ {
+ string[] t3 = SplitParam(t);
+ f.mtl = ushort.Parse(t3[1]);
+ f2.mtl = f.mtl;
+ }
+ else if (t2.StartsWith("uv("))
+ {
+ string[] t3 = SplitParam(t);
+ f.ta = Point2.Parse(t3, 1);
+ f.tb = Point2.Parse(t3, 3);
+ f.tc = Point2.Parse(t3, 5);
+ f2.ta = f.ta;
+ f2.tb = f.tc;
+ f2.tc = Point2.Parse(t3, 7);
+ }
}
current.faces.Add(f);
current.faces.Add(f2);
}
return true;
}
-
- //----- Root elements ----------------------------------------------
- private void ParseMetasequoia(string[] tokens)
- {
- // Metasequoia Document
- if (tokens[1] != "Document")
- Error(tokens);
- }
-
- private void ParseFormat(string[] tokens)
- {
- // @since v2.2
- // Format Text Ver 1.0
- // @since v4.0
- // Format Text Ver 1.1
- if (tokens[1] != "Text")
- Error(tokens);
- if (tokens[2] != "Ver")
- Error(tokens);
- if (tokens[3] != "1.0" && tokens[3] != "1.1")
- Error(tokens);
- }
-
- private void ParseThumbnail(string[] tokens)
- {
- // Thumbnail 128 128 24 rgb raw {
- // ...
- // }
- if (tokens[6] != "{") Error(tokens);
-
- DoRead(SectionThumbnail);
- }
-
- private void ParseScene(string[] tokens)
- {
- if (tokens[1].ToLower() != "{") Error(tokens);
-
- DoRead(SectionScene);
- }
-
- private void ParseDirlights(string[] tokens)
- {
- // dirlights 1 {
- // ...
- // }
- if (tokens[2].ToLower() != "{") Error(tokens);
-
- DoRead(SectionDirlights);
- }
-
- private void ParseLight(string[] tokens)
- {
- // light {
- // ...
- // }
- if (tokens[1].ToLower() != "{") Error(tokens);
-
- DoRead(SectionLight);
- }
-
- private void ParseMaterial(string[] tokens)
- {
- if (tokens[2].ToLower() != "{") Error(tokens);
-
- materials = new List<MqoMaterial>(int.Parse(tokens[1]));
- DoRead(SectionMaterial);
- }
-
- private void ParseObject(string[] tokens)
- {
- if (tokens[2].ToLower() != "{") Error(tokens);
-
- current = new MqoObject(tokens[1].Trim('"'));
- objects.Add(current);
- DoRead(SectionObject);
- }
-
- private void ParseVertex(string[] tokens)
- {
- if (tokens[2].ToLower() != "{") Error(tokens);
-
- current.vertices = new List<Point3>(int.Parse(tokens[1]));
- DoRead(SectionVertex);
- }
-
- private void ParseFace(string[] tokens)
- {
- if (tokens[2].ToLower() != "{") Error(tokens);
-
- current.faces = new List<MqoFace>(int.Parse(tokens[1]));
- DoRead(SectionFace);
- }
}
public class MqoScene
this.tb = tb;
this.tc = tc;
}
+
+ public void Write(TextWriter tw)
+ {
+ tw.WriteLine("\t\t{0} V({1} {2} {3}) M({10}) UV({4:F5} {5:F5} {6:F5} {7:F5} {8:F5} {9:F5})",
+ 3, a, b, c, ta.x, ta.y, tb.x, tb.y, tc.x, tc.y, mtl);
+ }
}
}
using System.Collections.Generic;
using System.IO;
using System.Text;
+using System.Xml;
namespace Tso2MqoGui
{
}
}
- public void Write(TSOFile file)
+ public void Write(TSOFile tso)
{
+ // ボーンを出す
+ bool mqx_enabled = BoneMode == MqoBoneMode.RokDeBone;
+
tw.WriteLine("Metasequoia Document");
tw.WriteLine("Format Text Ver 1.0");
tw.WriteLine("");
+ if (mqx_enabled)
+ {
+ tw.WriteLine("IncludeXml \"{0}\"", Path.GetFileName(Path.ChangeExtension(OutFile, ".mqx")));
+ tw.WriteLine("");
+ }
tw.WriteLine("Scene {");
tw.WriteLine("\tpos -7.0446 4.1793 1541.1764");
tw.WriteLine("\tlookat 11.8726 193.8590 0.4676");
tw.WriteLine("\tamb 0.250 0.250 0.250");
tw.WriteLine("}");
- VertexHeap<UVertex> vh = new VertexHeap<UVertex>();
- List<MqoFace> faces = new List<MqoFace>(2048);
-
- foreach (TSOTex tex in file.textures)
+ foreach (TSOTex tex in tso.textures)
CreateTextureFile(tex);
- tw.WriteLine("Material {0} {{", file.materials.Length);
+ tw.WriteLine("Material {0} {{", tso.materials.Length);
- foreach (TSOMaterial mat in file.materials)
+ foreach (TSOMaterial mat in tso.materials)
{
TSOTex tex = null;
- if (file.texturemap.TryGetValue(mat.ColorTex, out tex))
+ if (tso.texturemap.TryGetValue(mat.ColorTex, out tex))
{
tw.WriteLine(
"\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}\")",
tw.WriteLine("}");
- foreach (TSOMesh mesh in file.meshes)
+ tso.UpdateNodesWorld();
+
+ MqoBone[] bones = new MqoBone[tso.nodes.Length];
+
+ foreach (TSONode node in tso.nodes)
{
- vh.Clear();
- faces.Clear();
+ MqoBone bone = new MqoBone();
+ bone.id = node.id;
+ bone.name = node.ShortName;
+ bone.tail = node.children.Count == 0;
- foreach (TSOSubMesh sub_mesh in mesh.sub_meshes)
+ if (node.parent == null)
{
- int cnt = 0;
- ushort a = 0, b = 0, c = 0;
- Vertex va = new Vertex(), vb = new Vertex(), vc = new Vertex();
+ bone.pid = -1;
+ }
+ else
+ {
+ bone.pid = node.parent.id;
+ bones[bone.pid].cids.Add(bone.id);
+ }
+
+ //根本
+ bone.q = node.world.Translation;
+ //先端
+ if (! bone.tail)
+ bone.p = node.children[0].world.Translation;
+ else
+ bone.p = node.world.Translation;
+
+ bones[node.id] = bone;
+ }
+
+ MqoObjectGen.uid_enabled = mqx_enabled;
+ MqoObjectGen obj = new MqoObjectGen();
+
+ ushort object_id = 0;
+ foreach (TSOMesh mesh in tso.meshes)
+ {
+ obj.id = ++object_id;
+ obj.name = mesh.Name;
+ obj.Update(mesh);
+ obj.Write(tw);
+ obj.AddWeits(bones);
+ }
+
+ if (mqx_enabled)
+ WriteMqxDeBone(bones, object_id /* eq numobjects */);
+
+ tw.WriteLine("Eof");
+ }
+
+ void WriteMqxDeBone(MqoBone[] bones, int numobjects)
+ {
+ XmlWriterSettings settings = new XmlWriterSettings();
+ settings.Indent = true;
+ settings.IndentChars = new String(' ', 4);
+ XmlWriter writer = XmlWriter.Create(Path.ChangeExtension(OutFile, ".mqx"), settings);
+ writer.WriteStartElement("MetasequoiaDocument");
+ writer.WriteElementString("IncludedBy", Path.GetFileName(OutFile));
+
+ writer.WriteStartElement("Plugin.56A31D20.71F282AB");
+ writer.WriteAttributeString("name", "Bone");
+ writer.WriteStartElement("BoneSet");
+
+ foreach (MqoBone bone in bones)
+ bone.Write(writer);
+
+ writer.WriteEndElement();//BoneSet
- foreach (Vertex v in sub_mesh.vertices)
+ for (int i = 0; i < numobjects; i++)
+ {
+ writer.WriteStartElement("Obj");
+ writer.WriteAttributeString("id", (i+1).ToString());
+ writer.WriteEndElement();
+ }
+ writer.WriteEndElement();//Plugin.56A31D20.71F282AB
+
+ writer.WriteEndElement();//MetasequoiaDocument
+ writer.Close();
+ }
+
+ void WriteRokDeBone(MqoBone[] bones)
+ {
+ tw.WriteLine("Object \"{0}\" {{", "Bone");
+ tw.WriteLine("\tvisible {0}", 15);
+ tw.WriteLine("\tlocking {0}", 0);
+ tw.WriteLine("\tshading {0}", 1);
+ tw.WriteLine("\tfacet {0}", 59.5);
+ tw.WriteLine("\tcolor {0} {1} {2}", 1, 0, 0);
+ tw.WriteLine("\tcolor_type {0}", 0);
+
+ tw.WriteLine("\tvertex {0} {{", bones.Length);
+
+ foreach (MqoBone bone in bones)
+ tw.WriteLine("\t\t{0:F4} {1:F4} {2:F4}", bone.q.x, bone.q.y, bone.q.z);
+
+ tw.WriteLine("\t}");
+
+ //
+ tw.WriteLine("\tface {0} {{", bones.Length);
+
+ foreach (MqoBone bone in bones)
+ {
+ if (bone.pid == -1)
+ continue;
+
+ //根元と先端を接続するedge
+ if (! bone.tail)
+ tw.WriteLine(string.Format("\t\t2 V({0} {1})", bone.pid, bone.id));
+ }
+
+ tw.WriteLine("\t}");
+ tw.WriteLine("}");
+ }
+ }
+
+ public class MqoObjectGen
+ {
+ public static bool uid_enabled;
+
+ public int id; //object_id
+ public string name;
+ VertexHeap<UVertex> vh = new VertexHeap<UVertex>();
+ public List<MqoFace> faces;
+
+ public int numvertices { get { return vh.Count; } }
+ public List<UVertex> vertices { get { return vh.verts; } }
+ public int numfaces { get { return faces.Count; } }
+
+ public MqoObjectGen()
+ {
+ faces = new List<MqoFace>(2048);
+ }
+
+ public void Update(TSOMesh mesh)
+ {
+ vh.Clear();
+ faces.Clear();
+
+ foreach (TSOSubMesh sub_mesh in mesh.sub_meshes)
+ {
+ int cnt = 0;
+ ushort a = 0, b = 0, c = 0;
+ Vertex va = new Vertex(), vb = new Vertex(), vc = new Vertex();
+
+ foreach (Vertex v in sub_mesh.vertices)
+ {
+ ++cnt;
+ va = vb; a = b;
+ vb = vc; b = c;
+ vc = v; c = vh.Add(new UVertex(v.Pos, v.Wgt, v.Idx, v.Nrm));
+
+ if (cnt < 3) continue;
+ if (a == b || b == c || c == a) continue;
+
+ if ((cnt & 1) == 0)
+ {
+ MqoFace f = new MqoFace(a, b, c, (ushort)sub_mesh.spec,
+ new Point2(va.Tex.x, 1 - va.Tex.y),
+ new Point2(vb.Tex.x, 1 - vb.Tex.y),
+ new Point2(vc.Tex.x, 1 - vc.Tex.y));
+ faces.Add(f);
+ }
+ else
{
- ++cnt;
- va = vb; a = b;
- vb = vc; b = c;
- vc = v; c = vh.Add(new UVertex(v.Pos, v.Nrm));
-
- if (cnt < 3) continue;
- if (a == b || b == c || c == a) continue;
-
- if ((cnt & 1) == 0)
- {
- MqoFace f = new MqoFace(a, b, c, (ushort)sub_mesh.spec,
- new Point2(va.Tex.x, 1 - va.Tex.y),
- new Point2(vb.Tex.x, 1 - vb.Tex.y),
- new Point2(vc.Tex.x, 1 - vc.Tex.y));
- faces.Add(f);
- }
- else
- {
- MqoFace f = new MqoFace(a, c, b, (ushort)sub_mesh.spec,
- new Point2(va.Tex.x, 1 - va.Tex.y),
- new Point2(vc.Tex.x, 1 - vc.Tex.y),
- new Point2(vb.Tex.x, 1 - vb.Tex.y));
- faces.Add(f);
- }
+ MqoFace f = new MqoFace(a, c, b, (ushort)sub_mesh.spec,
+ new Point2(va.Tex.x, 1 - va.Tex.y),
+ new Point2(vc.Tex.x, 1 - vc.Tex.y),
+ new Point2(vb.Tex.x, 1 - vb.Tex.y));
+ faces.Add(f);
}
}
+ }
+ }
- tw.WriteLine("Object \"{0}\" {{", mesh.Name);
- tw.WriteLine("\tvisible {0}", 15);
- tw.WriteLine("\tlocking {0}", 0);
- tw.WriteLine("\tshading {0}", 1);
- tw.WriteLine("\tfacet {0}", 59.5);
- tw.WriteLine("\tcolor {0:F3} {1:F3} {2:F3}", 0.898f, 0.498f, 0.698f);
- tw.WriteLine("\tcolor_type {0}", 0);
+ public void Write(TextWriter tw)
+ {
+ tw.WriteLine("Object \"{0}\" {{", name);
+ if (uid_enabled)
+ tw.WriteLine("\tuid {0}", id);
+ tw.WriteLine("\tvisible {0}", 15);
+ tw.WriteLine("\tlocking {0}", 0);
+ tw.WriteLine("\tshading {0}", 1);
+ tw.WriteLine("\tfacet {0}", 59.5);
+ tw.WriteLine("\tcolor {0:F3} {1:F3} {2:F3}", 0.898f, 0.498f, 0.698f);
+ tw.WriteLine("\tcolor_type {0}", 0);
- //
- tw.WriteLine("\tvertex {0} {{", vh.Count);
+ //
+ tw.WriteLine("\tvertex {0} {{", numvertices);
- foreach (UVertex v in vh.verts)
- WriteVertex(v.Pos.x, v.Pos.y, v.Pos.z);
+ foreach (UVertex v in vertices)
+ v.Write(tw);
- tw.WriteLine("\t}");
+ tw.WriteLine("\t}");
+
+ if (uid_enabled)
+ {
+ tw.WriteLine("\tvertexattr {");
+ tw.WriteLine("\t\tuid {");
- //
- tw.WriteLine("\tface {0} {{", faces.Count);
+ ushort vertex_id = 0;
+ foreach (UVertex v in vertices)
+ tw.WriteLine("\t\t\t{0}", ++vertex_id);
- for (int i = 0, n = faces.Count; i < n; i++)
- WriteFace(faces[i]);
+ tw.WriteLine("\t\t}");
tw.WriteLine("\t}");
- tw.WriteLine("}");
}
- // ボーンを出す
- switch (BoneMode)
+ //
+ tw.WriteLine("\tface {0} {{", numfaces);
+
+ for (int i = 0, n = numfaces; i < n; i++)
+ faces[i].Write(tw);
+ tw.WriteLine("\t}");
+ tw.WriteLine("}");
+ }
+
+ public unsafe void AddWeits(MqoBone[] bones)
+ {
+ ushort vertex_id = 0;
+ foreach (UVertex v in vertices)
{
- case MqoBoneMode.None:
- break;
- case MqoBoneMode.RokDeBone:
+ ++vertex_id;
+
+ uint idx0 = v.Idx;
+ byte* idx = (byte*)(&idx0);
+ Point4 wgt0 = v.Wgt;
+ float* wgt = (float*)(&wgt0);
+
+ for (int k = 0; k < 4; ++k)
+ if (wgt[k] > float.Epsilon)
{
- // マトリクス計算
- foreach (TSONode i in file.nodes)
- {
- if (i.parent == null)
- i.world = i.Matrix;
- else i.world = Matrix44.Mul(i.Matrix, i.parent.World);
- }
-
- List<Point3> points = new List<Point3>();
- List<int> bones = new List<int>();
-
- tw.WriteLine("Object \"{0}\" {{", "Bone");
- tw.WriteLine("\tvisible {0}", 15);
- tw.WriteLine("\tlocking {0}", 0);
- tw.WriteLine("\tshading {0}", 1);
- tw.WriteLine("\tfacet {0}", 59.5);
- tw.WriteLine("\tcolor {0} {1} {2}", 1, 0, 0);
- tw.WriteLine("\tcolor_type {0}", 0);
-
- foreach (TSONode i in file.nodes)
- {
- if (i.children.Count == 0)
- continue;
-
- Point3 q = new Point3(i.world.M41, i.world.M42, i.world.M43);
- Point3 p = new Point3();
-
- foreach (TSONode j in i.children)
- {
- p.x += j.world.M41;
- p.y += j.world.M42;
- p.z += j.world.M43;
- }
-
- p.x /= i.children.Count;
- p.y /= i.children.Count;
- p.z /= i.children.Count;
-
- bones.Add(points.Count); points.Add(q);
- bones.Add(points.Count); points.Add(p);
- }
-
- tw.WriteLine("\tvertex {0} {{", points.Count);
-
- foreach (Point3 j in points)
- WriteVertex(j.x, j.y, j.z);
-
- tw.WriteLine("\t}");
-
- //
- tw.WriteLine("\tface {0} {{", bones.Count / 2);
-
- for (int j = 0, n = bones.Count; j < n; j += 2)
- tw.WriteLine(string.Format("\t\t2 V({0} {1})", bones[j + 0], bones[j + 1]));
-
- tw.WriteLine("\t}");
- tw.WriteLine("}");
+ MqoWeit weit = new MqoWeit();
+ weit.object_id = id;
+ weit.vertex_id = vertex_id;
+ weit.weit = wgt[k];
+ bones[idx[k]].weits.Add(weit);
}
- break;
-
- case MqoBoneMode.Mikoto:
- break;
}
+ }
+ }
- tw.WriteLine("Eof");
+ public class MqoBone
+ {
+ public int id;
+ public string name;
+ public bool tail;
+ //なければ-1
+ public int pid;
+ public List<int> cids = new List<int>();
+
+ //根本position
+ public Point3 q;
+
+ //先端position
+ public Point3 p;
+
+ public List<MqoWeit> weits;
+
+ public MqoBone()
+ {
+ weits = new List<MqoWeit>(2048*3*4);
}
- public void WriteFace(MqoFace f)
+ public void Write(XmlWriter writer)
{
- tw.WriteLine("\t\t{0} V({1} {2} {3}) M({10}) UV({4:F5} {5:F5} {6:F5} {7:F5} {8:F5} {9:F5})",
- 3, f.a, f.b, f.c, f.ta.x, f.ta.y, f.tb.x, f.tb.y, f.tc.x, f.tc.y, f.mtl);
+ writer.WriteStartElement("Bone");
+ writer.WriteAttributeString("id", (id+1).ToString());
+
+ writer.WriteAttributeString("rtX", q.X.ToString());
+ writer.WriteAttributeString("rtY", q.Y.ToString());
+ writer.WriteAttributeString("rtZ", q.Z.ToString());
+
+ writer.WriteAttributeString("tpX", p.X.ToString());
+ writer.WriteAttributeString("tpY", p.Y.ToString());
+ writer.WriteAttributeString("tpZ", p.Z.ToString());
+
+ writer.WriteAttributeString("rotB", "0.0");
+ writer.WriteAttributeString("rotH", "0.0");
+ writer.WriteAttributeString("rotP", "0.0");
+
+ writer.WriteAttributeString("mvX", "0.0");
+ writer.WriteAttributeString("mvY", "0.0");
+ writer.WriteAttributeString("mvZ", "0.0");
+
+ writer.WriteAttributeString("sc", "1.0");
+
+ writer.WriteAttributeString("maxAngB", "90.0");
+ writer.WriteAttributeString("maxAngH", "180.0");
+ writer.WriteAttributeString("maxAngP", "180.0");
+
+ writer.WriteAttributeString("minAngB", "-90.0");
+ writer.WriteAttributeString("minAngH", "-180.0");
+ writer.WriteAttributeString("minAngP", "-180.0");
+
+ writer.WriteAttributeString("isDummy", tail ? "1" : "0");
+ writer.WriteAttributeString("name", name);
+
+ writer.WriteStartElement("P");
+ writer.WriteAttributeString("id", (pid+1).ToString());
+ writer.WriteEndElement();
+
+ foreach (int cid in cids)
+ {
+ writer.WriteStartElement("C");
+ writer.WriteAttributeString("id", (cid+1).ToString());
+ writer.WriteEndElement();
+ }
+ foreach (MqoWeit weit in weits)
+ {
+ weit.Write(writer);
+ }
+
+ writer.WriteEndElement();
}
+ }
- public void WriteVertex(float x, float y, float z)
+ public class MqoWeit
+ {
+ public int object_id;
+ public int vertex_id;
+ //public int bone_id;
+ public float weit;
+
+ public void Write(XmlWriter writer)
{
- tw.WriteLine("\t\t{0:F4} {1:F4} {2:F4}", x, y, z);
+ float weit_percent = weit * 100.0f;
+
+ writer.WriteStartElement("W");
+ writer.WriteAttributeString("oi", object_id.ToString());
+ writer.WriteAttributeString("vi", vertex_id.ToString());
+ writer.WriteAttributeString("w", weit_percent.ToString());
+ writer.WriteEndElement();
}
}
public class UVertex : IComparable<UVertex>
{
+ //public int id; //vertex_id
public Point3 Pos;
+ public Point4 Wgt;
+ public UInt32 Idx;
public Point3 Nrm;
public UVertex()
{
}
- public UVertex(Point3 pos, Point3 nrm)
+ public UVertex(Point3 pos, Point4 wgt, UInt32 idx, Point3 nrm)
{
Pos = pos;
+ Wgt = wgt;
+ Idx = idx;
Nrm = nrm;
}
return Pos.Equals(o.Pos) && Nrm.Equals(o.Nrm);
}
+
+ public void Write(TextWriter tw)
+ {
+ tw.WriteLine("\t\t{0:F4} {1:F4} {2:F4}", Pos.x, Pos.y, Pos.z);
+ }
}
}