예제 #1
0
        void AssignSkinWeights(MqoVert vertex)
        {
            if (vertex == null)
            {
                return;
            }

            lvSkinWeights.BeginUpdate();
            lvSkinWeights.Items.Clear();
            foreach (MqoSkinWeight skin_weight in vertex.skin_weights)
            {
                TSONode bone   = skin_weight.bone;
                float   weight = skin_weight.weight;
                if (weight == 0.0f)
                {
                    continue;
                }
                ListViewItem li = new ListViewItem(bone.Name);
                li.SubItems.Add(weight.ToString("F3"));
                li.Tag = skin_weight;
                lvSkinWeights.Items.Add(li);
            }
            lvSkinWeights.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
            lvSkinWeights.EndUpdate();
        }
예제 #2
0
        private void btnPosUpdate_Click(object sender, EventArgs e)
        {
            TSONode node = viewer.SelectedNode;

            if (node == null)
            {
                return;
            }

            float x1 = float.Parse(edNodePosX.Text);
            float y1 = float.Parse(edNodePosY.Text);
            float z1 = float.Parse(edNodePosZ.Text);

            Vector3 p1 = new Vector3(x1, y1, z1);

            viewer.BeginNodeCommand();

            Matrix m = Matrix.Identity;

            if (node.parent != null)
            {
                m = Matrix.Invert(node.parent.GetWorldCoordinate());
            }
            Vector3 local = Vector3.TransformCoordinate(p1, m);

            node.Translation = local;

            viewer.EndNodeCommand();

            UpdateSelectedNodeLocalPos();
            UpdateSelectedNodeSub();
            Invalidate(false);
        }
예제 #3
0
        private void btnLocalPosUpdate_Click(object sender, EventArgs e)
        {
            TSONode node = viewer.SelectedNode;

            if (node == null)
            {
                return;
            }

            float x1 = float.Parse(edNodeLocalPosX.Text);
            float y1 = float.Parse(edNodeLocalPosY.Text);
            float z1 = float.Parse(edNodeLocalPosZ.Text);

            Vector3 p1 = new Vector3(x1, y1, z1);

            viewer.BeginNodeCommand();

            node.Translation = p1;

            viewer.EndNodeCommand();

            UpdateSelectedNodePos();
            UpdateSelectedNodeSub();
            Invalidate(false);
        }
예제 #4
0
        public void UpdateSelectedNodeLocalPos()
        {
            TSONode node = viewer.SelectedNode;

            Vector3 local = node.Translation;

            UpdateNodeLocalPos(local);
        }
예제 #5
0
        public void UpdateSelectedNodePos()
        {
            TSONode node = viewer.SelectedNode;

            Vector3 world = node.GetWorldPosition();

            UpdateNodePos(world);
        }
예제 #6
0
        public void UpdateSelectedNodeSub()
        {
            TSONode node = viewer.SelectedNode;

            Vector3 world = node.GetWorldPosition();

            Vector3 local = Vector3.TransformCoordinate(world, node.offset_matrix);

            UpdateNodeSub(local);
        }
예제 #7
0
 private Matrix[] ClipBoneMatrices(TSOSubMesh sub_mesh, TMOFile tmo)
 {
     Matrix[] clipped_boneMatrices = new Matrix[sub_mesh.maxPalettes];
     for (int numPalettes = 0; numPalettes < sub_mesh.maxPalettes; numPalettes++)
     {
         TSONode tso_node = sub_mesh.GetBone(numPalettes);
         TMONode tmo_node = tmo.FindNodeByName(tso_node.Name);
         clipped_boneMatrices[numPalettes] = tso_node.OffsetMatrix * tmo_node.combined_matrix;
     }
     return(clipped_boneMatrices);
 }
예제 #8
0
        private void lvNodes_SelectedIndexChanged(object sender, EventArgs e)
        {
            TSONode node = GetSelectedNode();

            if (node == null)
            {
                return;
            }

            Debug.WriteLine("selected " + node.Name);
        }
예제 #9
0
 private static string GetReconPath(TSONode node)
 {
     if (node.parent != null)
     {
         return(GetReconPath(node.parent) + "|" + node.Name);
     }
     else
     {
         return("|" + node.Name);
     }
 }
예제 #10
0
        public TSONode GetSelectedNode()
        {
            if (lvNodes.SelectedItems.Count == 0)
            {
                return(null);
            }

            ListViewItem li   = lvNodes.SelectedItems[0];
            TSONode      node = li.Tag as TSONode;

            return(node);
        }
예제 #11
0
        private void cameraSelectedBoneToolStripMenuItem_Click(object sender, EventArgs e)
        {
            TSONode node = viewer.SelectedNode;

            if (node == null)
            {
                return;
            }

            viewer.Camera.Center = node.GetWorldPosition();
            viewer.Camera.ResetTranslation();
            Invalidate(false);
        }
예제 #12
0
        static void Smooth()
        {
            int len = use_nodes.Count;

            TSONode[] nodes = new TSONode[len];
            Vector3[] node_world_positions = new Vector3[len];

            for (int i = 0; i < len; i++)
            {
                node_world_positions[i] = use_nodes[i].GetWorldPosition();
            }

            float[] distances     = new float[len];
            float[] inv_distances = new float[len];

            foreach (UnifiedPositionVertex v in unified_position_vert_heap.ary)
            {
                for (int i = 0; i < len; i++)
                {
                    nodes[i] = use_nodes[i];
                }

                //頂点vに対して距離が近い順に並べたnodesを得る。
                for (int i = 0; i < len; i++)
                {
                    distances[i] = LengthSq(v.position, node_world_positions[i]);
                }
                Array.Sort(distances, nodes);

                for (int i = 0; i < 4; i++)
                {
                    inv_distances[i] += 1.0f / distances[i];
                }

                //平方距離の逆数の合計
                float sum_inv_distances = 0.0f;

                for (int i = 0; i < 4; i++)
                {
                    sum_inv_distances += inv_distances[i];
                }

                //平方距離の逆数の割合をweightとする。
                for (int i = 0; i < 4; i++)
                {
                    v.skin_weights[i].bone_index = nodes[i].ID;
                    v.skin_weights[i].weight     = inv_distances[i] / sum_inv_distances;
                }
            }
        }
예제 #13
0
        public void UpdateSelectedNodeControls()
        {
            TSONode node = viewer.SelectedNode;

            if (node == null)
            {
                ClearNodeControls();
                return;
            }

            lbNodeName.Text = node.Name;

            Vector3 local = node.Translation;

            UpdateNodeLocalPos(local);

            Vector3 world = node.GetWorldPosition();

            UpdateNodePos(world);

            local = Vector3.TransformCoordinate(world, node.offset_matrix);
            UpdateNodeSub(local);
        }
예제 #14
0
        // -----------------------------------------------------
        // 頂点を作成
        // -----------------------------------------------------
        private void MakePMDVertices(CorrespondTable cor_table, int mod_type)
        {
            List <PMD_Vertex> vertex_list = new List <PMD_Vertex>();
            List <short>      indices     = new List <short>(); // インデックスリスト

            inList_indices.Clear();

            // -----------------------------------------------------
            // Tmoの変形を実行
            fig.TPOList.Transform();
            morph.Morph(fig.Tmo);
            fig.UpdateBoneMatricesWithoutTMOFrame();

            // -----------------------------------------------------
            // 情報をコピー
            int n_inList        = -1; // list中のvertexの番号(処理の前に++するために、初期値は0でなく-1としている)
            int n_mesh          = 0;
            int prevNumIndices  = 0;
            int prevNumVertices = 0;

            foreach (TSOSubMesh sub_mesh in mesh_list)
            {
                int n_inMesh = -1;          // mesh中のvertexの番号(処理の前に++するために、初期値は0でなく-1としている)
                int a = -1, b = -1, c = -1; // 隣合うインデックス

                Matrix[] clipped_boneMatrices = ClipBoneMatrices(sub_mesh, fig.Tmo);

                foreach (Vertex vertex in sub_mesh.vertices)
                {
                    n_inList++; // list中のvertexの番号を一つ増やす
                    n_inMesh++; // mesh中のvertexの番号を一つ増やす

                    // Tmo中のBoneに従って、Mesh中の頂点位置及び法線ベクトルを置き換えて、書き出す

                    Vector3 pos = Vector3.Empty;
                    Vector3 nor = Vector3.Empty;

                    foreach (SkinWeight sw in vertex.skin_weights)
                    {
                        Matrix m = clipped_boneMatrices[sw.bone_index];

                        // 頂点位置
                        pos += Vector3.TransformCoordinate(vertex.position, m) * sw.weight;

                        // 法線ベクトル
                        m.M41 = 0;
                        m.M42 = 0;
                        m.M43 = 0;
                        nor  += Vector3.TransformCoordinate(vertex.normal, m) * sw.weight;
                    }

                    // -----------------------------------------------------
                    // 頂点情報をコピー
                    PMD_Vertex pmd_v = new PMD_Vertex();

                    pmd_v.vec3Pos    = Trans.CopyPos(pos);
                    pmd_v.vec3Normal = Trans.CopyPos(Vector3.Normalize(nor));
                    pmd_v.uvTex.u    = vertex.u;
                    pmd_v.uvTex.v    = vertex.v;

                    pmd_v.cbEdge = 0;

                    // -----------------------------------------------------
                    // スキニング
                    List <string> tmp_b = new List <string>();
                    List <float>  tmp_w = new List <float>();

                    for (int i = 0; i < 4; i++)
                    {
                        TSONode tso_bone = sub_mesh.bones[(int)vertex.skin_weights[i].bone_index];
                        string  bone_name;
                        if (mod_type == 0 || mod_type == 1)
                        {
                            bone_name = cor_table.skinning[tso_bone.Name];
                        }
                        else
                        {
                            bone_name = "センター";
                        }

                        if (tmp_b.IndexOf(bone_name) < 0)
                        {
                            tmp_b.Add(bone_name);
                            tmp_w.Add(vertex.skin_weights[i].weight);
                        }
                        else
                        {
                            tmp_w[tmp_b.IndexOf(bone_name)] += vertex.skin_weights[i].weight;
                        }
                    }

                    float w0 = tmp_w.Max();
                    pmd_v.unBoneName[0] = tmp_b[tmp_w.IndexOf(w0)];
                    tmp_b.RemoveAt(tmp_w.IndexOf(w0));
                    tmp_w.RemoveAt(tmp_w.IndexOf(w0));

                    float w1;
                    if (tmp_b.Count == 0)
                    {
                        w1 = 0.0f;
                        pmd_v.unBoneName[1] = pmd_v.unBoneName[0];
                    }
                    else
                    {
                        w1 = tmp_w.Max();
                        pmd_v.unBoneName[1] = tmp_b[tmp_w.IndexOf(w1)];
                    }

                    pmd_v.cbWeight = (int)(w0 * 100 / (w0 + w1));

                    // -----------------------------------------------------
                    // 頂点リストに頂点を追加

                    // 重複している頂点がないかをチェックし、
                    // 存在すれば、そのインデックスを参照
                    // 存在しなければ、頂点リストに頂点を追加
                    int idx = -1;
                    for (int i = prevNumVertices; i < vertex_list.Count; i++)
                    {
                        if (vertex_list[i].vec3Pos.x == pmd_v.vec3Pos.x &&
                            vertex_list[i].vec3Pos.y == pmd_v.vec3Pos.y &&
                            vertex_list[i].vec3Pos.z == pmd_v.vec3Pos.z &&
                            vertex_list[i].vec3Normal.x == pmd_v.vec3Normal.x &&
                            vertex_list[i].vec3Normal.y == pmd_v.vec3Normal.y &&
                            vertex_list[i].vec3Normal.z == pmd_v.vec3Normal.z &&
                            vertex_list[i].uvTex.u == pmd_v.uvTex.u &&
                            vertex_list[i].uvTex.v == pmd_v.uvTex.v)
                        {
                            idx = i;
                            break;
                        }
                    }
                    if (idx == -1)
                    {
                        vertex_list.Add(pmd_v);
                        idx = vertex_list.Count - 1;
                        inList_indices.Add(idx);
                    }
                    else
                    {
                        inList_indices.Add(-1);
                    }

                    // -----------------------------------------------------
                    // 頂点インデックス

                    // 過去3つまでのインデックスを記憶しておく
                    a = b; b = c; c = idx;

                    // 隣合うインデックスが参照する頂点位置の重複を判定し、
                    // 重複している場合はインデックスの追加を省略する
                    if ((n_inMesh >= 2) &&
                        !((vertex_list[a].vec3Pos.x == vertex_list[b].vec3Pos.x &&
                           vertex_list[a].vec3Pos.y == vertex_list[b].vec3Pos.y &&
                           vertex_list[a].vec3Pos.z == vertex_list[b].vec3Pos.z) ||
                          (vertex_list[b].vec3Pos.x == vertex_list[c].vec3Pos.x &&
                           vertex_list[b].vec3Pos.y == vertex_list[c].vec3Pos.y &&
                           vertex_list[b].vec3Pos.z == vertex_list[c].vec3Pos.z) ||
                          (vertex_list[c].vec3Pos.x == vertex_list[a].vec3Pos.x &&
                           vertex_list[c].vec3Pos.y == vertex_list[a].vec3Pos.y &&
                           vertex_list[c].vec3Pos.z == vertex_list[a].vec3Pos.z)))
                    {
                        if (n_inMesh % 2 == 0)
                        {
                            indices.Add((short)(c));
                            indices.Add((short)(b));
                            indices.Add((short)(a));
                        }
                        else
                        {
                            indices.Add((short)(a));
                            indices.Add((short)(b));
                            indices.Add((short)(c));
                        }
                    }
                }

                // meshごとのインデックス数を記録
                material_list.material_list[n_mesh++].ulNumIndices = indices.Count - prevNumIndices;
                prevNumIndices  = indices.Count;
                prevNumVertices = vertex_list.Count;
            }
            // -----------------------------------------------------
            // リストを配列に代入し直す
            // 頂点情報
            pmd.number_of_vertex = vertex_list.Count;
            pmd.pmd_vertex       = (PMD_Vertex[])vertex_list.ToArray();
            // 頂点インデックス
            pmd.number_of_indices = indices.Count;
            pmd.indices_array     = (short[])indices.ToArray();
            // マテリアル
            if (merge_flag == true)
            {
                material_list.MergeMaterials();
            }
            pmd.number_of_materials = material_list.material_list.Count;
            pmd.pmd_material        = (PMD_Material[])material_list.material_list.ToArray();
            // Toonテクスチャファイル名
            pmd.toon_file_name = material_list.GetToonFileNameList();
        }
예제 #15
0
        // -----------------------------------------------------
        // 頂点を作成
        // -----------------------------------------------------
        private void MakePMDVertices(CorrespondTable cor_table, int mod_type)
        {
            List <PMD_Vertex> vertices = new List <PMD_Vertex>();
            List <int>        indices  = new List <int>();

            Dictionary <string, short> bone_name_idmap = new Dictionary <string, short>();

            {
                short i = 0;
                foreach (PMD_Bone node in pmd.nodes)
                {
                    bone_name_idmap[node.name] = i++;
                }
            }

            inList_indices.Clear();

            // -----------------------------------------------------
            // Tmoの変形を実行
            fig.TPOList.Transform();
            morph.Morph(fig.Tmo);
            fig.UpdateBoneMatricesWithoutTMOFrame();

            // -----------------------------------------------------
            // 情報をコピー
            int n_inList        = -1; // list中のvertexの番号(処理の前に++するために、初期値は0でなく-1としている)
            int n_mesh          = 0;
            int prevNumIndices  = 0;
            int prevNumVertices = 0;

            foreach (TSOSubMesh sub_mesh in meshes)
            {
                int n_inMesh = -1;          // mesh中のvertexの番号(処理の前に++するために、初期値は0でなく-1としている)
                int a = -1, b = -1, c = -1; // 隣合うインデックス

                Matrix[] clipped_boneMatrices = ClipBoneMatrices(sub_mesh, fig.Tmo);

                foreach (Vertex vertex in sub_mesh.vertices)
                {
                    n_inList++; // list中のvertexの番号を一つ増やす
                    n_inMesh++; // mesh中のvertexの番号を一つ増やす

                    // Tmo中のBoneに従って、Mesh中の頂点位置及び法線ベクトルを置き換えて、書き出す

                    Vector3 pos = Vector3.Empty;
                    Vector3 nor = Vector3.Empty;

                    foreach (SkinWeight sw in vertex.skin_weights)
                    {
                        Matrix m = clipped_boneMatrices[sw.bone_index];

                        // 頂点位置
                        pos += Vector3.TransformCoordinate(vertex.position, m) * sw.weight;

                        // 法線ベクトル
                        m.M41 = 0;
                        m.M42 = 0;
                        m.M43 = 0;
                        nor  += Vector3.TransformCoordinate(vertex.normal, m) * sw.weight;
                    }

                    // -----------------------------------------------------
                    // 頂点情報をコピー
                    PMD_Vertex pmd_v = new PMD_Vertex();

                    pmd_v.position = Trans.CopyPos(pos);
                    pmd_v.normal   = Trans.CopyPos(Vector3.Normalize(nor));
                    pmd_v.u        = vertex.u;
                    pmd_v.v        = vertex.v;

                    // -----------------------------------------------------
                    // スキニング
                    if (cor_table != null)
                    {
                        for (int i = 0; i < 4; i++)
                        {
                            TSONode tso_bone  = sub_mesh.bones[vertex.skin_weights[i].bone_index];
                            string  bone_name = cor_table.skinning[tso_bone.Name];
                            pmd_v.skin_weights[i].bone_index = bone_name_idmap[bone_name];
                            pmd_v.skin_weights[i].weight     = vertex.skin_weights[i].weight;
                        }
                    }
                    else
                    {
                        pmd_v.skin_weights[0].bone_index = 0;
                        pmd_v.skin_weights[0].weight     = 1.0f;
                    }

                    // -----------------------------------------------------
                    // 頂点リストに頂点を追加

                    // 重複している頂点がないかをチェックし、
                    // 存在すれば、そのインデックスを参照
                    // 存在しなければ、頂点リストに頂点を追加
                    int idx = -1;
                    for (int i = prevNumVertices; i < vertices.Count; i++)
                    {
                        if (vertices[i].position == pmd_v.position &&
                            vertices[i].normal == pmd_v.normal &&
                            vertices[i].u == pmd_v.u &&
                            vertices[i].v == pmd_v.v)
                        {
                            idx = i;
                            break;
                        }
                    }
                    if (idx == -1)
                    {
                        vertices.Add(pmd_v);
                        idx = vertices.Count - 1;
                        inList_indices.Add(idx);
                    }
                    else
                    {
                        inList_indices.Add(-1);
                    }

                    // -----------------------------------------------------
                    // 頂点インデックス

                    // 過去3つまでのインデックスを記憶しておく
                    a = b; b = c; c = idx;

                    // 隣合うインデックスが参照する頂点位置の重複を判定し、
                    // 重複している場合はインデックスの追加を省略する
                    if ((n_inMesh >= 2) &&
                        !(vertices[a].position == vertices[b].position ||
                          vertices[b].position == vertices[c].position ||
                          vertices[c].position == vertices[a].position))
                    {
                        if (n_inMesh % 2 == 0)
                        {
                            indices.Add(c);
                            indices.Add(b);
                            indices.Add(a);
                        }
                        else
                        {
                            indices.Add(a);
                            indices.Add(b);
                            indices.Add(c);
                        }
                    }
                }

                // meshごとのインデックス数を記録
                material_list.materials[n_mesh++].vindices_count = indices.Count - prevNumIndices;
                prevNumIndices  = indices.Count;
                prevNumVertices = vertices.Count;
            }
            // -----------------------------------------------------
            // リストを配列に代入し直す
            // 頂点情報
            pmd.vertices = vertices.ToArray();
            // 頂点インデックス
            pmd.vindices = indices.ToArray();
            // マテリアル
            if (UniqueMaterial)
            {
                material_list.UniqueMaterials();
            }
            pmd.texture_file_names = material_list.GetTextureFileNameList();
            pmd.materials          = material_list.materials.ToArray();
        }
예제 #16
0
        static void Main(string[] args)
        {
            if (args.Length < 1)
            {
                Console.WriteLine("TSOSmooth.exe <tso file>");
                return;
            }
            string source_file = args[0];

            TSOFile tso = new TSOFile();

            tso.Load(source_file);

            Dictionary <string, TSONode> nodemap = new Dictionary <string, TSONode>();

            foreach (TSONode node in tso.nodes)
            {
                nodemap.Add(node.Name, node);
            }

            string[] nodesets = GetSetsNames().ToArray();

            Console.WriteLine("nodesets:");
            {
                int i = 0;
                foreach (string name in nodesets)
                {
                    Console.WriteLine("{0} {1}", i, name);
                    i++;
                }
            }
            Console.Write("nodesetsを選択 (0-{0}): ", nodesets.Length - 1);
            int sets_idx = 0;

            {
                string line = Console.ReadLine();
                if (line.Length != 0)
                {
                    try
                    {
                        sets_idx = int.Parse(line);
                    }
                    catch (System.FormatException e)
                    {
                        Console.WriteLine(e);
                        return;
                    }
                }
            }
            setsname = nodesets[sets_idx];

            char[] delim = { ' ' };
            using (StreamReader source = new StreamReader(File.OpenRead(GetSetsPath())))
            {
                string line;
                while ((line = source.ReadLine()) != null)
                {
                    string[] tokens = line.Split(delim);
                    string   op     = tokens[0];
                    if (op == "node")
                    {
                        Debug.Assert(tokens.Length == 2, "tokens length should be 2: " + line);
                        string  cnode_name = tokens[1];
                        TSONode cnode      = nodemap[cnode_name];

                        use_nodes.Add(cnode);
                    }
                }
            }

            Console.WriteLine("メッシュ:");
            {
                int i = 0;
                foreach (TSOMesh mesh in tso.meshes)
                {
                    Console.WriteLine("{0} {1}", i, mesh.Name);
                    i++;
                }
            }

            Console.Write("メッシュを選択 (0-{0}): ", tso.meshes.Length - 1);
            int mesh_idx = 0;
            {
                string line = Console.ReadLine();
                if (line.Length != 0)
                {
                    try
                    {
                        mesh_idx = int.Parse(line);
                    }
                    catch (System.FormatException e)
                    {
                        Console.WriteLine(e);
                        return;
                    }
                }
            }

            TSOMesh selected_mesh = null;

            try
            {
                selected_mesh = tso.meshes[mesh_idx];
            }
            catch (IndexOutOfRangeException e)
            {
                Console.WriteLine(e);
                return;
            }

            Console.WriteLine("サブメッシュ:");
            Console.WriteLine("  vertices bone_indices");
            Console.WriteLine("  -------- ------------");
            foreach (TSOSubMesh sub in selected_mesh.sub_meshes)
            {
                Console.WriteLine("  {0,8} {1,12}", sub.vertices.Length, sub.bone_indices.Length);
            }

            int max_palettes = 16;

            RebuildMesh(selected_mesh, max_palettes);

            string dest_path = Path.GetDirectoryName(source_file);
            string dest_file = Path.GetFileNameWithoutExtension(source_file) + @".new.tso";

            dest_path = Path.Combine(dest_path, dest_file);
            Console.WriteLine("Save File: " + dest_path);
            tso.Save(dest_path);
        }