OSDN Git Service

refactor.
[tdcgexplorer/tso2mqo.git] / MqoWriter.cs
index f106bc8..483b7e7 100644 (file)
-using System;\r
-using System.Collections.Generic;\r
-using System.IO;\r
-using System.Text;\r
-\r
-namespace Tso2MqoGui\r
-{\r
-    public enum MqoBoneMode\r
-    {\r
-        None,\r
-        RokDeBone,\r
-        Mikoto,\r
-    }\r
-\r
-    public class Pair<T, U>\r
-    {\r
-        public T    First;\r
-        public U    Second;\r
-\r
-        public Pair()\r
-        {\r
-        }\r
-\r
-        public Pair(T first, U second)\r
-        {\r
-            First   = first;\r
-            Second  = second;\r
-        }\r
-    }\r
-\r
-    public class MqoWriter : IDisposable\r
-    {\r
-        public TextWriter   tw;\r
-        public string       OutPath;\r
-        public string       OutFile;\r
-        public MqoBoneMode  BoneMode    = MqoBoneMode.None;\r
-\r
-        public MqoWriter(string file)\r
-        {\r
-            FileStream  fs  = File.OpenWrite(file);\r
-            fs.SetLength(0);\r
-            tw              = new StreamWriter(fs, Encoding.Default);\r
-            OutFile         = file;\r
-            OutPath         = Path.GetDirectoryName(file);\r
-        }\r
-\r
-        void IDisposable.Dispose()\r
-        {\r
-            Close();\r
-        }\r
-\r
-        public void Close()\r
-        {\r
-            if(tw != null)\r
-                tw.Close();\r
-            tw  = null;\r
-        }\r
-\r
-        string GetTexturePath(TSOTex tex)\r
-        {\r
-            string filename = Path.GetFileName(tex.File.Trim('"'));\r
-            if (filename == "")\r
-                filename = "none";\r
-            return Path.Combine(OutPath, filename);\r
-        }\r
-\r
-        public void CreateTextureFile(TSOTex tex)\r
-        {\r
-            string file = GetTexturePath(tex);\r
-            byte[]  data= tex.data;\r
-\r
-\r
-            using(FileStream fs= File.OpenWrite(file))\r
-            {\r
-                BinaryWriter    bw  = new BinaryWriter(fs);\r
-\r
-                switch(Path.GetExtension(file).ToUpper())\r
-                {\r
-                case ".TGA":\r
-                    bw.Write((byte)0);              // id\r
-                    bw.Write((byte)0);              // colormap\r
-                    bw.Write((byte)2);              // imagetype\r
-                    bw.Write((byte)0);              // unknown0\r
-                    bw.Write((byte)0);              // unknown1\r
-                    bw.Write((byte)0);              // unknown2\r
-                    bw.Write((byte)0);              // unknown3\r
-                    bw.Write((byte)0);              // unknown4\r
-                    bw.Write((short)0);             // width\r
-                    bw.Write((short)0);             // height\r
-                    bw.Write((short)tex.Width);     // width\r
-                    bw.Write((short)tex.Height);    // height\r
-                    bw.Write((byte)(tex.depth * 8));// depth\r
-                    bw.Write((byte)0);              // depth\r
-                    break;\r
-\r
-                case ".BMP":\r
-                    bw.Write((byte)'B');\r
-                    bw.Write((byte)'M');\r
-                    bw.Write((int)(54 + data.Length));\r
-                    bw.Write((int)0);\r
-                    bw.Write((int)54);\r
-                    bw.Write((int)40);\r
-                    bw.Write((int)tex.Width);\r
-                    bw.Write((int)tex.Height);\r
-                    bw.Write((short)1);\r
-                    bw.Write((short)(tex.Depth*8));\r
-                    bw.Write((int)0);\r
-                    bw.Write((int)data.Length);\r
-                    bw.Write((int)0);\r
-                    bw.Write((int)0);\r
-                    bw.Write((int)0);\r
-                    bw.Write((int)0);\r
-                    break;\r
-                }\r
-\r
-                bw.Write(data, 0, data.Length);\r
-                bw.Flush();\r
-            }\r
-        }\r
-\r
-        public void Write(TSOFile file)\r
-        {\r
-            tw.WriteLine("Metasequoia Document");\r
-            tw.WriteLine("Format Text Ver 1.0");\r
-            tw.WriteLine("");\r
-            tw.WriteLine("Scene {");\r
-            tw.WriteLine("\tpos -7.0446 4.1793 1541.1764");\r
-            tw.WriteLine("\tlookat 11.8726 193.8590 0.4676");\r
-            tw.WriteLine("\thead 0.8564");\r
-            tw.WriteLine("\tpich 0.1708");\r
-            tw.WriteLine("\tortho 0");\r
-            tw.WriteLine("\tzoom2 31.8925");\r
-            tw.WriteLine("\tamb 0.250 0.250 0.250");\r
-            tw.WriteLine("}");\r
-\r
-            VertexHeap<UVertex> vh  = new VertexHeap<UVertex>();\r
-            List<ushort>        face= new List<ushort>(2048*3);\r
-            List<float>         uv  = new List<float>(2048*3 * 2);\r
-            List<int>           mtl = new List<int>(2048);\r
-\r
-            foreach(TSOTex tex in file.textures)\r
-                CreateTextureFile(tex);\r
-\r
-            tw.WriteLine("Material {0} {{", file.materials.Length);\r
-\r
-            foreach(TSOMaterial mat in file.materials)\r
-            {\r
-                if(mat.ColorTex != null)\r
-                {\r
-                    TSOTex  tex = file.texturemap[mat.ColorTex];\r
-                    tw.WriteLine(\r
-                        "\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}\")",\r
-                        mat.name, GetTexturePath(tex));\r
-                } else\r
-                {\r
-                    tw.WriteLine(\r
-                        "\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))",\r
-                        mat.name);\r
-                }\r
-            }\r
-\r
-            tw.WriteLine("}");\r
-\r
-            foreach(TSOMesh i in file.meshes)\r
-            {\r
-                vh.Clear();\r
-                face.Clear();\r
-                uv.Clear();\r
-                mtl.Clear();\r
-\r
-                foreach(TSOSubMesh j in i.sub)\r
-                {\r
-                    int     cnt = 0;\r
-                    ushort  a= 0, b= 0, c= 0;\r
-                    Vertex  va= new Vertex(), vb= new Vertex(), vc= new Vertex();\r
-\r
-                    foreach(Vertex k in j.vertices)\r
-                    {\r
-                        ++cnt;\r
-                        va= vb; a= b;\r
-                        vb= vc; b= c;\r
-                        vc= k;  c= vh.Add(new UVertex(k.Pos, k.Nrm, k.Tex, j.spec));\r
-\r
-                        if(cnt < 3)                     continue;\r
-                        if(a == b || b == c || c == a)  continue;\r
-\r
-                        if((cnt & 1) == 0)\r
-                        {\r
-                            face.Add(a); uv.Add(va.Tex.x); uv.Add(1-va.Tex.y);\r
-                            face.Add(b); uv.Add(vb.Tex.x); uv.Add(1-vb.Tex.y);\r
-                            face.Add(c); uv.Add(vc.Tex.x); uv.Add(1-vc.Tex.y);\r
-                            mtl.Add(j.spec);\r
-                        } else\r
-                        {\r
-                            face.Add(a); uv.Add(va.Tex.x); uv.Add(1-va.Tex.y);\r
-                            face.Add(c); uv.Add(vc.Tex.x); uv.Add(1-vc.Tex.y);\r
-                            face.Add(b); uv.Add(vb.Tex.x); uv.Add(1-vb.Tex.y);\r
-                            mtl.Add(j.spec);\r
-                        }\r
-                    }\r
-                }\r
-\r
-                tw.WriteLine("Object \"{0}\" {{", i.Name);\r
-                tw.WriteLine("\tvisible {0}", 15);\r
-                tw.WriteLine("\tlocking {0}", 0);\r
-                tw.WriteLine("\tshading {0}", 1);\r
-                tw.WriteLine("\tfacet {0}", 59.5);\r
-                tw.WriteLine("\tcolor {0:F3} {1:F3} {2:F3}", 0.898f, 0.498f, 0.698f);\r
-                tw.WriteLine("\tcolor_type {0}", 0);\r
-\r
-                //\r
-                tw.WriteLine("\tvertex {0} {{", vh.Count);\r
-\r
-                foreach(UVertex j in vh.verts)\r
-                    WriteVertex(j.Pos.x, j.Pos.y, j.Pos.z);\r
-\r
-                tw.WriteLine("\t}");\r
-\r
-                //\r
-                tw.WriteLine("\tface {0} {{", face.Count / 3);\r
-\r
-                System.Diagnostics.Debug.Assert(face.Count*2 == uv.Count);\r
-                System.Diagnostics.Debug.Assert(face.Count == mtl.Count * 3);\r
-\r
-                for(int j= 0, n= face.Count; j < n; j+=3)\r
-                    WriteFace(face[j+0], face[j+1], face[j+2],\r
-                              uv[j*2+0], uv[j*2+1],\r
-                              uv[j*2+2], uv[j*2+3],\r
-                              uv[j*2+4], uv[j*2+5],\r
-                              mtl[j/3]);\r
-                tw.WriteLine("\t}");\r
-                tw.WriteLine("}");\r
-            }\r
-\r
-            // ボーンを出す\r
-            switch(BoneMode)\r
-            {\r
-            case MqoBoneMode.None:      break;\r
-            case MqoBoneMode.RokDeBone:\r
-                {\r
-                // マトリクス計算\r
-                foreach(TSONode i in file.nodes)\r
-                {\r
-                    if(i.parent == null)\r
-                            i.world = i.Matrix;\r
-                    else    i.world = Matrix44.Mul(i.Matrix, i.parent.World);\r
-                }\r
-                \r
-                List<Point3>                points  = new List<Point3>();\r
-                List<int>                   bones   = new List<int>();\r
-\r
-                tw.WriteLine("Object \"{0}\" {{", "Bone");\r
-                tw.WriteLine("\tvisible {0}", 15);\r
-                tw.WriteLine("\tlocking {0}", 0);\r
-                tw.WriteLine("\tshading {0}", 1);\r
-                tw.WriteLine("\tfacet {0}", 59.5);\r
-                tw.WriteLine("\tcolor {0} {1} {2}", 1, 0, 0);\r
-                tw.WriteLine("\tcolor_type {0}", 0);\r
-\r
-                foreach(TSONode i in file.nodes)\r
-                {\r
-                    if(i.children.Count == 0)\r
-                        continue;\r
-\r
-                    Point3  q   = new Point3(i.world.M41, i.world.M42, i.world.M43);\r
-                    Point3  p   = new Point3();\r
-                    \r
-                    foreach(TSONode j in i.children)\r
-                    {\r
-                        p.x     +=j.world.M41;\r
-                        p.y     +=j.world.M42;\r
-                        p.z     +=j.world.M43;\r
-                    }\r
-\r
-                    p.x         /=i.children.Count;\r
-                    p.y         /=i.children.Count;\r
-                    p.z         /=i.children.Count;\r
-\r
-                    bones.Add(points.Count); points.Add(q);\r
-                    bones.Add(points.Count); points.Add(p);\r
-                }\r
-\r
-                tw.WriteLine("\tvertex {0} {{", points.Count);\r
-\r
-                foreach(Point3 j in points)\r
-                    WriteVertex(j.x, j.y, j.z);\r
-\r
-                tw.WriteLine("\t}");\r
-\r
-                //\r
-                tw.WriteLine("\tface {0} {{", bones.Count / 2);\r
-\r
-                for(int j= 0, n= bones.Count; j < n; j+=2)\r
-                    tw.WriteLine(string.Format("\t\t2 V({0} {1})", bones[j+0], bones[j+1]));\r
-\r
-                tw.WriteLine("\t}");\r
-                tw.WriteLine("}");\r
-                }\r
-                break;\r
-\r
-            case MqoBoneMode.Mikoto:\r
-                {\r
-                }\r
-                break;\r
-            }\r
-\r
-            tw.WriteLine("Eof");\r
-        }\r
-\r
-        public void WriteFace(int a, int b, int c, float u1, float v1, float u2, float v2, float u3, float v3, int m)\r
-        {\r
-            tw.WriteLine("\t\t{0} V({1} {2} {3}) M({10}) UV({4:F5} {5:F5} {6:F5} {7:F5} {8:F5} {9:F5})",\r
-                3, a, b, c, u1, v1, u2, v2, u3, v3, m);\r
-        }\r
-\r
-        public void WriteVertex(float x, float y, float z)\r
-        {\r
-            tw.WriteLine("\t\t{0:F4} {1:F4} {2:F4}", x, y, z);\r
-        }\r
-    }\r
-\r
-    public class UVertex : IComparable<UVertex>\r
-    {\r
-        public Point3 Pos;\r
-        public Point3 Nrm;\r
-        public Point2 Tex;\r
-        public int      mtl;\r
-        \r
-        public UVertex()\r
-        {\r
-        }\r
-\r
-        public UVertex(Point3 pos, Point3 nrm, Point2 tex, int mtl)\r
-        {\r
-            Pos = pos;\r
-            Nrm = nrm;\r
-            Tex = tex;\r
-            this.mtl= mtl;\r
-        }\r
-\r
-        public int CompareTo(UVertex o)\r
-        {\r
-            int cmp;\r
-            cmp = Pos.CompareTo(o.Pos); if (cmp != 0) return cmp;\r
-            cmp = Nrm.CompareTo(o.Nrm);\r
-            return cmp;\r
-        }\r
-\r
-        public override int GetHashCode()\r
-        {\r
-            return Pos.GetHashCode() ^ Nrm.GetHashCode();\r
-        }\r
-\r
-        public override bool Equals(object obj)\r
-        {\r
-            if (obj is UVertex)\r
-            {\r
-                UVertex v = (UVertex)obj;\r
-                return Pos.Equals(v.Pos) && Nrm.Equals(v.Nrm);\r
-            }\r
-            return false;\r
-        }\r
-\r
-        public bool Equals(UVertex v)\r
-        {\r
-            if ((object)v == null)\r
-            {\r
-                return false;\r
-            }\r
-\r
-            return Pos.Equals(v.Pos) && Nrm.Equals(v.Nrm);\r
-        }\r
-    }\r
-}\r
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Xml;
+
+namespace Tso2MqoGui
+{
+    public class MqoWriter : IDisposable
+    {
+        public TextWriter tw;
+        public string OutPath;
+        public string OutFile;
+        public bool MqxEnabled;
+
+        public MqoWriter(string file)
+        {
+            FileStream fs = File.OpenWrite(file);
+            fs.SetLength(0);
+            tw = new StreamWriter(fs, Encoding.Default);
+            OutFile = file;
+            OutPath = Path.GetDirectoryName(file);
+        }
+
+        void IDisposable.Dispose()
+        {
+            Close();
+        }
+
+        public void Close()
+        {
+            if (tw != null)
+                tw.Close();
+            tw = null;
+        }
+
+        string GetTextureFileName(TSOTex tex)
+        {
+            string filename = Path.GetFileName(tex.File.Trim('"'));
+            if (filename == "")
+                filename = "none";
+            return filename;
+        }
+
+        string GetTexturePath(TSOTex tex)
+        {
+            return Path.Combine(OutPath, GetTextureFileName(tex));
+        }
+
+        public void CreateTextureFile(TSOTex tex)
+        {
+            string file = GetTexturePath(tex);
+            byte[] data = tex.data;
+
+            //TODO: .bmpのはずが.psdになってるものがある
+
+            using (FileStream fs = File.OpenWrite(file))
+            {
+                BinaryWriter bw = new BinaryWriter(fs);
+
+                switch (Path.GetExtension(file).ToUpper())
+                {
+                    case ".TGA":
+                        bw.Write((byte)0);              // id
+                        bw.Write((byte)0);              // colormap
+                        bw.Write((byte)2);              // imagetype
+                        bw.Write((byte)0);              // unknown0
+                        bw.Write((byte)0);              // unknown1
+                        bw.Write((byte)0);              // unknown2
+                        bw.Write((byte)0);              // unknown3
+                        bw.Write((byte)0);              // unknown4
+                        bw.Write((short)0);             // width
+                        bw.Write((short)0);             // height
+                        bw.Write((short)tex.Width);     // width
+                        bw.Write((short)tex.Height);    // height
+                        bw.Write((byte)(tex.depth * 8));// depth
+                        bw.Write((byte)0);              // depth
+                        break;
+
+                    default:
+                        bw.Write((byte)'B');
+                        bw.Write((byte)'M');
+                        bw.Write((int)(54 + data.Length));
+                        bw.Write((int)0);
+                        bw.Write((int)54);
+                        bw.Write((int)40);
+                        bw.Write((int)tex.Width);
+                        bw.Write((int)tex.Height);
+                        bw.Write((short)1);
+                        bw.Write((short)(tex.Depth * 8));
+                        bw.Write((int)0);
+                        bw.Write((int)data.Length);
+                        bw.Write((int)0);
+                        bw.Write((int)0);
+                        bw.Write((int)0);
+                        bw.Write((int)0);
+                        break;
+                }
+
+                bw.Write(data, 0, data.Length);
+                bw.Flush();
+            }
+        }
+
+        public void Write(TSOFile tso)
+        {
+            tw.WriteLine("Metasequoia Document");
+            tw.WriteLine("Format Text Ver 1.0");
+            tw.WriteLine("");
+            if (MqxEnabled)
+            {
+                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("\thead 0.8564");
+            tw.WriteLine("\tpich 0.1708");
+            tw.WriteLine("\tortho 0");
+            tw.WriteLine("\tzoom2 31.8925");
+            tw.WriteLine("\tamb 0.250 0.250 0.250");
+            tw.WriteLine("}");
+
+            foreach (TSOTex tex in tso.textures)
+                CreateTextureFile(tex);
+
+            tw.WriteLine("Material {0} {{", tso.materials.Length);
+
+            foreach (TSOMaterial mat in tso.materials)
+            {
+                TSOTex tex = null;
+                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}\")",
+                        mat.name, GetTextureFileName(tex));
+                }
+                else
+                {
+                    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))",
+                        mat.name);
+                }
+            }
+
+            tw.WriteLine("}");
+
+            MqoBone[] bones = null;
+
+            if (MqxEnabled)
+                bones = CreateBones(tso);
+
+            MqoObjectGen.uid_enabled = MqxEnabled;
+            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);
+
+                if (MqxEnabled)
+                    obj.AddWeits(bones);
+            }
+
+            if (MqxEnabled)
+            {
+                MqxWriter writer = new MqxWriter();
+                writer.MqoFile = OutFile;
+                writer.Write(bones, object_id /* eq numobjects */);
+            }
+
+            tw.WriteLine("Eof");
+        }
+
+        MqoBone[] CreateBones(TSOFile tso)
+        {
+            MqoBone[] bones = new MqoBone[tso.nodes.Length];
+
+            tso.UpdateNodesWorld();
+
+            foreach (TSONode node in tso.nodes)
+            {
+                MqoBone bone = new MqoBone(node.id);
+                bone.id = node.id+1;
+                bone.name = node.Name;
+                bone.tail = node.children.Count == 0;
+
+                if (node.parent == null)
+                {
+                    bone.pid = 0;
+                }
+                else
+                {
+                    bone.pid = node.parent.id+1;
+                    bones[node.parent.id].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;
+            }
+            return bones;
+        }
+    }
+
+    public class MqoObjectGen
+    {
+        public static bool uid_enabled;
+
+        public int id; //object_id
+        public string name;
+        Heap<UVertex> vh = new Heap<UVertex>();
+        public List<MqoFace> faces;
+
+        public int numvertices { get { return vh.Count; } }
+        public List<UVertex> vertices { get { return vh.ary; } }
+        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
+                    {
+                        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);
+                    }
+                }
+            }
+        }
+
+        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} {{", numvertices);
+
+            foreach (UVertex v in vertices)
+                v.Write(tw);
+
+            tw.WriteLine("\t}");
+
+            if (uid_enabled)
+            {
+                tw.WriteLine("\tvertexattr {");
+                tw.WriteLine("\t\tuid {");
+
+                ushort vertex_id = 0;
+                foreach (UVertex v in vertices)
+                    tw.WriteLine("\t\t\t{0}", ++vertex_id);
+
+                tw.WriteLine("\t\t}");
+                tw.WriteLine("\t}");
+            }
+
+            //
+            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)
+            {
+                ++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)
+                    {
+                        MqoWeit weit = new MqoWeit();
+                        weit.object_id = id;
+                        weit.vertex_id = vertex_id;
+                        weit.weit = wgt[k];
+                        bones[idx[k]].weits.Add(weit);
+                    }
+            }
+        }
+    }
+}