Esempio n. 1
0
        /// 使うボーン対応表を結合して得ます。
        public CorrespondTable GetCorrespondTable()
        {
            CorrespondTable cortable = new CorrespondTable();

            List <string> names = new List <string>();

            switch (BoneKind)
            {
            case CorrespondTableListBoneKind.man:
                names.Add("Man2Miku_Default");
                break;

            case CorrespondTableListBoneKind.woman:
                names.Add("Girl2Miku_Default");

                foreach (string name in Selection.Keys)
                {
                    if (Selection[name])
                    {
                        names.Add(name);
                    }
                }
                break;
            }

            string source_path = GetSourcePath();

            foreach (string name in names)
            {
                cortable.Load(Path.Combine(source_path, name));
            }

            return(cortable);
        }
Esempio n. 2
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();
        }
Esempio n. 3
0
        // -----------------------------------------------------
        // FigureデータよりPmdFileデータを作成
        // -----------------------------------------------------
        public string Figure2PmdFileDataWithHumanBone()
        {
            CorrespondTable cor_table = null;
            int             mod_type  = 0;

            if (fig.Tmo.nodes.Length == 227)
            {
                corTable_list.SetManFlag = false;
                cor_table = corTable_list.GetCorrespondTable();
                mod_type  = 0;
            }
            else if (fig.Tmo.nodes.Length == 75)
            {
                corTable_list.SetManFlag = true;
                cor_table = corTable_list.GetCorrespondTable();
                mod_type  = 1;
            }
            else
            {
                return("未対応のボーン構造です。\n人型以外を変換する場合は、\n出力ボーンに”1ボーン”を指定してください。");
            }

            // -----------------------------------------------------
            // 予め、情報をコピーするmeshを選定し、並び替えておく
            // -----------------------------------------------------
            SelectMeshes();

            // -----------------------------------------------------
            // 頂点
            // -----------------------------------------------------
            MakePMDVertices(cor_table, mod_type);

            // 頂点数が上限を超えてないかチェックし、超えていたらエラーを出して終了
            if (pmd.number_of_vertex > 65535)
            {
                return("頂点数(" + pmd.number_of_vertex.ToString() + ")が上限(65535)を超えています。");
            }

            // -----------------------------------------------------
            // 表情
            // -----------------------------------------------------
            if (mod_type == 0)
            {
                InitializePMDFaces();
                MakePMDBaseFace();
                MakePMDFaces();
            }
            else if (mod_type == 1)
            {
                InitializePMDFaces();
                MakePMDBaseFace();
                pmd.number_of_face = 0;
            }

            // -----------------------------------------------------
            // 表情枠
            // -----------------------------------------------------
            if (mod_type == 0)
            {
                pmd.skin_disp_count = pmd.number_of_face - 1; // 表情枠に表示する表情数
                pmd.skin_index      = new int[pmd.skin_disp_count];
                for (int i = 0; i < pmd.skin_disp_count; i++)
                {
                    pmd.skin_index[i] = i + 1; // 表情番号
                }
            }
            else if (mod_type == 1)
            {
                pmd.skin_disp_count = 0; // 表情枠に表示する表情数
            }

            // -----------------------------------------------------
            // ボーン情報
            // -----------------------------------------------------
            List <PMD_Bone> bone_list = new List <PMD_Bone>();

            foreach (KeyValuePair <string, PMD_Bone> bone_kvp in cor_table.boneStructure)
            {
                PMD_Bone pmd_b = new PMD_Bone();
                PMD_Bone bone  = bone_kvp.Value;

                pmd_b.szName       = bone.szName;
                pmd_b.cbKind       = bone.cbKind; // ボーンの種類 0:回転 1:回転と移動 2:IK 3:不明 4:IK影響下 5:回転影響下 6:IK接続先 7:非表示 8:捻り 9:回転運動
                pmd_b.ParentName   = bone.ParentName;
                pmd_b.ChildName    = bone.ChildName;
                pmd_b.IKTargetName = bone.IKTargetName;

                string bone_name = null;
                cor_table.bonePosition.TryGetValue(pmd_b.szName, out bone_name);
                if (bone_name != null)
                {
                    pmd_b.vec3Position
                        = Trans.CopyMat2Pos(fig.Tmo.FindNodeByName(bone_name).combined_matrix); // モデル原点からの位置
                }

                bone_list.Add(pmd_b);
            }

            // -----------------------------------------------------
            // 親と子の前後関係を並び替える
            for (int i = 0; i < bone_list.Count; i++)
            {
                for (int j = 0; j < bone_list.Count; j++)
                {
                    if (bone_list[i].szName == bone_list[j].ParentName)
                    {
                        if (i > j)
                        {
                            bone_list.Insert(j, bone_list[i]);
                            bone_list.RemoveAt(i + 1);
                        }
                    }
                }
            }

            // -----------------------------------------------------
            // リストを配列に代入し直す
            pmd.number_of_bone = bone_list.Count;
            pmd.pmd_bone       = (PMD_Bone[])bone_list.ToArray();

            // -----------------------------------------------------
            // センターボーンの位置調整
            pmd.getBoneByName("センター").vec3Position
                = new MmdVector3(
                      0.0f,
                      pmd.getBoneByName("下半身").vec3Position.y * 0.65f,
                      0.0f);
            pmd.getBoneByName("センター先").vec3Position
                = new MmdVector3(
                      0.0f,
                      0.0f,
                      0.0f);

            // -----------------------------------------------------
            // 両目ボーンの位置調整
            if (mod_type == 0)
            {
                pmd.getBoneByName("両目").vec3Position
                    = new MmdVector3(
                          0.0f,
                          pmd.getBoneByName("左目").vec3Position.y + pmd.getBoneByName("左目").vec3Position.x * 4.0f,
                          pmd.getBoneByName("左目").vec3Position.z - pmd.getBoneByName("左目").vec3Position.x * 2.0f);
                pmd.getBoneByName("両目先").vec3Position
                    = new MmdVector3(
                          pmd.getBoneByName("両目").vec3Position.x,
                          pmd.getBoneByName("両目").vec3Position.y,
                          pmd.getBoneByName("両目").vec3Position.z - 1.0f);
            }

            // -----------------------------------------------------
            // IK先ボーンの位置調整
            pmd.getBoneByName("左足IK先").vec3Position
                = new MmdVector3(
                      pmd.getBoneByName("左足IK").vec3Position.x,
                      pmd.getBoneByName("左足IK").vec3Position.y,
                      pmd.getBoneByName("左足IK").vec3Position.z + 1.7f);
            pmd.getBoneByName("右足IK先").vec3Position
                = new MmdVector3(
                      pmd.getBoneByName("右足IK").vec3Position.x,
                      pmd.getBoneByName("右足IK").vec3Position.y,
                      pmd.getBoneByName("右足IK").vec3Position.z + 1.7f);

            pmd.getBoneByName("左つま先").vec3Position.y   = 0.0f;
            pmd.getBoneByName("左つま先IK").vec3Position.y = 0.0f;
            pmd.getBoneByName("左つま先IK先").vec3Position
                = new MmdVector3(
                      pmd.getBoneByName("左つま先IK").vec3Position.x,
                      pmd.getBoneByName("左つま先IK").vec3Position.y - 1.0f,
                      pmd.getBoneByName("左つま先IK").vec3Position.z);

            pmd.getBoneByName("右つま先").vec3Position.y   = 0.0f;
            pmd.getBoneByName("右つま先IK").vec3Position.y = 0.0f;
            pmd.getBoneByName("右つま先IK先").vec3Position
                = new MmdVector3(
                      pmd.getBoneByName("右つま先IK").vec3Position.x,
                      pmd.getBoneByName("右つま先IK").vec3Position.y - 1.0f,
                      pmd.getBoneByName("右つま先IK").vec3Position.z);

            // -----------------------------------------------------
            // IK配列
            // -----------------------------------------------------
            pmd.number_of_ik = cor_table.IKBone.Count;
            pmd.pmd_ik       = (PMD_IK[])cor_table.IKBone.ToArray();

            // -----------------------------------------------------
            // ボーン枠用枠名リスト
            // -----------------------------------------------------
            pmd.bone_disp_name_count = cor_table.dispBoneGroup.Count;        // ボーン枠用の枠名数
            pmd.disp_name            = new string[pmd.bone_disp_name_count]; // 枠名(50Bytes/枠)

            for (int i = 0; i < cor_table.dispBoneGroup.Count; i++)
            {
                pmd.disp_name[i] = cor_table.dispBoneGroup[i].group_name + Convert.ToChar(Convert.ToInt16("0A", 16));
            }
            //PMDEditorを使う場合は、枠名を0x0A00で終わらせる必要があります(0x00のみだと表示されません)。

            // -----------------------------------------------------
            // ボーン枠用表示リスト
            // -----------------------------------------------------
            // 枠に表示するボーン数
            pmd.bone_disp_count = 0;
            for (int i = 0; i < cor_table.dispBoneGroup.Count; i++)
            {
                pmd.bone_disp_count += cor_table.dispBoneGroup[i].bone_name_list.Count;
            }

            // 枠用ボーンデータ (3Bytes/bone)
            pmd.bone_disp = new PMD_BoneDisp[pmd.bone_disp_count];

            int n      = 0; // 通し番号
            int n_disp = 1;

            foreach (DispBoneGroup dbg in cor_table.dispBoneGroup)
            {
                foreach (string name in dbg.bone_name_list)
                {
                    pmd.bone_disp[n]           = new PMD_BoneDisp();
                    pmd.bone_disp[n].bone_name = name;                 // 枠用ボーン名
                    pmd.bone_disp[n++].bone_disp_frame_index = n_disp; // 表示枠番号
                }
                n_disp++;
            }

            // -----------------------------------------------------
            // 英名対応(0:英名対応なし, 1:英名対応あり)
            // -----------------------------------------------------
            pmd.english_name_compatibility = 0;

            // -----------------------------------------------------
            // 剛体&ジョイント
            // -----------------------------------------------------
            // -----------------------------------------------------
            // 物理オブジェクトを生成
            physOb_list = new T2PPhysObjectList(bone_list);

            // -----------------------------------------------------
            // テンプレートを適用
            template_list.PhysObExecute(ref physOb_list);

            // -----------------------------------------------------
            // 剛体&ジョイントを配列に代入し直す
            pmd.rigidbody_count = physOb_list.body_list.Count;
            pmd.rigidbody       = (PMD_RigidBody[])physOb_list.body_list.ToArray();

            pmd.joint_count = physOb_list.joint_list.Count;
            pmd.joint       = (PMD_Joint[])physOb_list.joint_list.ToArray();

            // -----------------------------------------------------
            // 終了
            return("");
        }
Esempio n. 4
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();
        }