OSDN Git Service

update v0.37 for mqx BoneDeformer.
authornomeu <nomeu@nomeu.org>
Thu, 22 Jan 2015 08:51:36 +0000 (17:51 +0900)
committernomeu <nomeu@nomeu.org>
Sat, 24 Jan 2015 15:28:14 +0000 (00:28 +0900)
Form1.Designer.cs
MqoFile.cs
MqoGenerator.cs
MqoWriter.cs
TSOFile.cs
TSOGenerator.cs

index e3e4b91..8dfbe03 100644 (file)
             this.rbBoneRokDeBone.Size = new System.Drawing.Size(170, 16);\r
             this.rbBoneRokDeBone.TabIndex = 7;\r
             this.rbBoneRokDeBone.TabStop = true;\r
-            this.rbBoneRokDeBone.Text = "RokDeBone形式のボーン作成";\r
+            this.rbBoneRokDeBone.Text = "Mqx形式のボーン作成";\r
             this.rbBoneRokDeBone.UseVisualStyleBackColor = true;\r
             // \r
             // rbBoneNone\r
             this.Controls.Add(this.tabControl1);\r
             this.MinimumSize = new System.Drawing.Size(528, 200);\r
             this.Name = "Form1";\r
-            this.Text = "Tso2MqoGui v0.36";\r
+            this.Text = "Tso2MqoGui v0.37";\r
             this.Load += new System.EventHandler(this.Form1_Load);\r
             this.DragDrop += new System.Windows.Forms.DragEventHandler(this.Form1_DragDrop);\r
             this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.Form1_FormClosed);\r
index 9112b52..c08e474 100644 (file)
@@ -8,16 +8,16 @@ namespace Tso2MqoGui
 {
     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; } }
@@ -38,7 +38,7 @@ namespace Tso2MqoGui
             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);
@@ -95,9 +95,9 @@ namespace Tso2MqoGui
             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();
 
@@ -117,27 +117,79 @@ namespace Tso2MqoGui
                 }
                 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:
@@ -145,7 +197,7 @@ namespace Tso2MqoGui
             }
         }
 
-        private bool SectionThumbnail(string[] tokens)
+        bool SectionThumbnail(string[] tokens)
         {
             switch (tokens[0])
             {
@@ -156,7 +208,7 @@ namespace Tso2MqoGui
             }
         }
 
-        private bool SectionScene(string[] tokens)
+        bool SectionScene(string[] tokens)
         {
             scene = new MqoScene();
 
@@ -169,7 +221,17 @@ namespace Tso2MqoGui
                 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:
@@ -177,35 +239,43 @@ namespace Tso2MqoGui
             }
         }
 
-        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;
@@ -238,26 +308,44 @@ namespace Tso2MqoGui
             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;
@@ -267,7 +355,38 @@ namespace Tso2MqoGui
             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;
@@ -298,20 +417,18 @@ namespace Tso2MqoGui
                                 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);
                     }
@@ -336,24 +453,22 @@ namespace Tso2MqoGui
                                 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);
@@ -362,98 +477,6 @@ namespace Tso2MqoGui
             }
             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
@@ -518,5 +541,11 @@ namespace Tso2MqoGui
             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);
+        }
     }
 }
index 6723e9f..b856001 100644 (file)
@@ -7,6 +7,13 @@ namespace Tso2MqoGui
 {\r
     public class MqoGenerator\r
     {\r
+        public TSOFile LoadTSO(string file)\r
+        {\r
+            TSOFile tso = new TSOFile(file);\r
+            tso.ReadAll();\r
+            return tso;\r
+        }\r
+\r
         public void Generate(string tso_file, string out_path, MqoBoneMode bone_mode)\r
         {\r
             string tso_filename = Path.GetFileName(tso_file);\r
@@ -16,8 +23,8 @@ namespace Tso2MqoGui
             // モデル、テクスチャの作成\r
             using (MqoWriter mqo = new MqoWriter(mqo_file))\r
             {\r
-                TSOFile tso = new TSOFile(tso_file);\r
-                tso.ReadAll();\r
+                TSOFile tso = LoadTSO(tso_file);\r
+                tso.SwitchBoneIndicesOnMesh();\r
 \r
                 mqo.BoneMode = bone_mode;\r
 \r
index 9c8bbcf..44c2fcd 100644 (file)
@@ -2,6 +2,7 @@ using System;
 using System.Collections.Generic;
 using System.IO;
 using System.Text;
+using System.Xml;
 
 namespace Tso2MqoGui
 {
@@ -124,11 +125,19 @@ 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");
@@ -139,18 +148,15 @@ namespace Tso2MqoGui
             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}\")",
@@ -166,169 +172,359 @@ namespace Tso2MqoGui
 
             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;
         }
 
@@ -364,5 +560,10 @@ namespace Tso2MqoGui
 
             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);
+        }
     }
 }
index 6039730..eb956c3 100644 (file)
@@ -198,6 +198,38 @@ namespace Tso2MqoGui
 
             r.BaseStream.Dispose();
         }
+
+        // ボーンをグローバルな番号に変換
+        public unsafe void SwitchBoneIndicesOnMesh()
+        {
+            foreach (TSOMesh mesh in this.meshes)
+                foreach (TSOSubMesh sub in mesh.sub_meshes)
+                {
+                    int[] bones = sub.bones;
+
+                    for (int k = 0, n = sub.numvertices; k < n; ++k)
+                    {
+                        uint idx0 = sub.vertices[k].Idx;
+                        byte* idx = (byte*)(&idx0);
+                        idx[0] = (byte)bones[idx[0]];
+                        idx[1] = (byte)bones[idx[1]];
+                        idx[2] = (byte)bones[idx[2]];
+                        idx[3] = (byte)bones[idx[3]];
+                        sub.vertices[k].Idx = idx0;
+                    }
+                }
+        }
+
+        public void UpdateNodesWorld()
+        {
+            foreach (TSONode node in this.nodes)
+            {
+                if (node.parent == null)
+                    node.world = node.Matrix;
+                else
+                    node.world = Matrix44.Mul(node.matrix, node.parent.world);
+            }
+        }
     }
 
     public class TSONode
index 4f510f0..5f2bf47 100644 (file)
@@ -579,25 +579,7 @@ namespace Tso2MqoGui
         {\r
             // 参照TSOロード\r
             tsoref = LoadTSO(tsoref_file);\r
-\r
-            foreach (TSOMesh mesh in tsoref.meshes)\r
-                foreach (TSOSubMesh sub in mesh.sub_meshes)\r
-                {\r
-                    int[] bones = sub.bones;\r
-\r
-                    for (int k = 0, n = sub.numvertices; k < n; ++k)\r
-                    {\r
-                        // ボーンをグローバルな番号に変換\r
-                        uint idx0 = sub.vertices[k].Idx;\r
-                        byte* idx = (byte*)(&idx0);\r
-                        idx[0] = (byte)bones[idx[0]];\r
-                        idx[1] = (byte)bones[idx[1]];\r
-                        idx[2] = (byte)bones[idx[2]];\r
-                        idx[3] = (byte)bones[idx[3]];\r
-                        sub.vertices[k].Idx = idx0;\r
-                    }\r
-                }\r
-\r
+            tsoref.SwitchBoneIndicesOnMesh();\r
             CreatePointCluster(tsoref);\r
             return true;\r
         }\r
@@ -862,4 +844,4 @@ namespace Tso2MqoGui
         [DisplayNameAttribute("テクスチャ:シェーティング")]\r
         public string ShadeTexture { get { return shade_tex; } set { shade_tex = value; } }\r
     }\r
-}
\ No newline at end of file
+}\r