/// <summary>
        ///     指定されたストリームから読み込む。
        /// </summary>
        internal static 表示枠リスト 読み込む(Stream fs, PMXヘッダ header)
        {
            int 表示枠数 = ParserHelper.get_Int(fs);

            Debug.WriteLine($"表示枠数: {表示枠数}");

            var list = new 表示枠リスト(表示枠数);

            for (int i = 0; i < 表示枠数; i++)
            {
                list.Add(表示枠.読み込む(fs, header));
            }

            return(list);
        }
Example #2
0
        /// <summary>
        ///     指定されたストリームから読み込む。
        /// </summary>
        internal static ボーンリスト 読み込む(FileStream fs, PMXヘッダ header)
        {
            int ボーン数 = ParserHelper.get_Int(fs);

            Debug.WriteLine($"ボーン数: {ボーン数}");

            var list = new ボーンリスト(ボーン数);

            for (int i = 0; i < ボーン数; i++)
            {
                list.Add(ボーン.読み込む(fs, header));
            }

            return(list);
        }
Example #3
0
        /// <summary>
        ///     指定されたストリームから読み込む。
        /// </summary>
        internal static 材質リスト 読み込む(FileStream fs, PMXヘッダ header)
        {
            int 材質数 = ParserHelper.get_Int(fs);

            Debug.WriteLine($"材質数: {材質数}");

            var list = new 材質リスト(材質数);

            for (int i = 0; i < 材質数; i++)
            {
                list.Add(材質.読み込む(fs, header));
            }

            return(list);
        }
        /// <summary>
        ///     指定されたストリームから読み込む。
        /// </summary>
        internal static モーフリスト 読み込む(FileStream fs, PMXヘッダ header)
        {
            int モーフ数 = ParserHelper.get_Int(fs);

            Debug.WriteLine($"モーフ数: {モーフ数}");

            var list = new モーフリスト(モーフ数);

            for (int i = 0; i < モーフ数; i++)
            {
                list.Add(モーフ.読み込む(fs, header));
            }

            return(list);
        }
        /// <summary>
        ///     指定されたストリームから読み込む。
        /// </summary>
        internal static テクスチャリスト 読み込む(FileStream fs, PMXヘッダ header)
        {
            int テクスチャ数 = ParserHelper.get_Int(fs);

            Debug.WriteLine($"テクスチャ数: {テクスチャ数}");

            var list = new テクスチャリスト(テクスチャ数);

            for (int i = 0; i < テクスチャ数; i++)
            {
                list.Add(ParserHelper.get_TextBuf(fs, header.エンコード方式));
            }

            return(list);
        }
        /// <summary>
        ///     指定されたストリームから読み込む。
        /// </summary>
        internal static ジョイントリスト 読み込む(Stream fs, PMXヘッダ header)
        {
            int ジョイント数 = ParserHelper.get_Int(fs);

            Debug.WriteLine($"ジョイント数: {ジョイント数}");

            var list = new ジョイントリスト(ジョイント数);

            for (int i = 0; i < ジョイント数; i++)
            {
                list.Add(ジョイント.読み込む(fs, header));
            }

            return(list);
        }
        /// <summary>
        ///     指定されたストリームから読み込む。
        /// </summary>
        internal static 剛体リスト 読み込む(Stream fs, PMXヘッダ header)
        {
            int 剛体数 = ParserHelper.get_Int(fs);

            Debug.WriteLine($"剛体数: {剛体数}");

            var list = new 剛体リスト(剛体数);

            for (int i = 0; i < 剛体数; i++)
            {
                list.Add(剛体.読み込む(fs, header));
            }

            return(list);
        }
Example #8
0
            }                                                   // 角度制限あり の場合

            /// <summary>
            ///     指定されたストリームから読み込む。
            /// </summary>
            internal static IKリンク 読み込む(FileStream fs, PMXヘッダ header)
            {
                var ikLinkData = new IKリンク();

                ikLinkData.リンクボーンのボーンインデックス = ParserHelper.get_Index(fs, header.ボーンインデックスサイズ);
                ikLinkData.角度制限あり           = ParserHelper.get_Byte(fs) == 1 ? true : false;

                if (ikLinkData.角度制限あり)
                {
                    ikLinkData.角度制限の下限rad = ParserHelper.get_Float3(fs);
                    ikLinkData.角度制限の上限rad = ParserHelper.get_Float3(fs);
                }

                return(ikLinkData);
            }
Example #9
0
        /// <summary>
        ///     指定されたストリームから読み込む。
        /// </summary>
        internal static 材質 読み込む(FileStream fs, PMXヘッダ header)
        {
            var material = new 材質();

            material.材質名                = ParserHelper.get_TextBuf(fs, header.エンコード方式);
            material.材質名_英              = ParserHelper.get_TextBuf(fs, header.エンコード方式);
            material.拡散色                = ParserHelper.get_Float4(fs);
            material.反射色                = ParserHelper.get_Float3(fs);
            material.反射強度               = ParserHelper.get_Float(fs);
            material.環境色                = ParserHelper.get_Float3(fs);
            material.描画フラグ              = (描画フラグ)ParserHelper.get_Byte(fs);
            material.エッジ色               = ParserHelper.get_Float4(fs);
            material.エッジサイズ             = ParserHelper.get_Float(fs);
            material.通常テクスチャの参照インデックス   = ParserHelper.get_Index(fs, header.テクスチャインデックスサイズ);
            material.スフィアテクスチャの参照インデックス = ParserHelper.get_Index(fs, header.テクスチャインデックスサイズ);

            switch (ParserHelper.get_Byte(fs))
            {
            case 0:
                material.スフィアモード = スフィアモード.無効;
                break;

            case 1:
                material.スフィアモード = スフィアモード.乗算;
                break;

            case 2:
                material.スフィアモード = スフィアモード.加算;
                break;

            case 3:
                material.スフィアモード = スフィアモード.サブテクスチャ;
                break;

            default:
                throw new InvalidDataException("スフィアモード値が異常です。");
            }

            material.共有Toonフラグ            = ParserHelper.get_Byte(fs);
            material.共有Toonのテクスチャ参照インデックス = material.共有Toonフラグ == 0 ? ParserHelper.get_Index(fs, header.テクスチャインデックスサイズ) : ParserHelper.get_Byte(fs);
            material.メモ  = ParserHelper.get_TextBuf(fs, header.エンコード方式);
            material.頂点数 = ParserHelper.get_Int(fs);
            if (material.頂点数 % 3 != 0)
            {
                throw new InvalidDataException();   // 3 の倍数じゃなければエラー。
            }
            return(material);
        }
Example #10
0
        /// <summary>
        ///     指定されたストリームから読み込む。
        /// </summary>
        internal static 枠内要素 読み込む(Stream fs, PMXヘッダ header)
        {
            var data = new 枠内要素();

            data.要素対象 = (ParserHelper.get_Byte(fs) == 1);

            if (data.要素対象)
            {
                data.要素対象インデックス = ParserHelper.get_Index(fs, header.モーフインデックスサイズ);
            }
            else
            {
                data.要素対象インデックス = ParserHelper.get_Index(fs, header.ボーンインデックスサイズ);
            }

            return(data);
        }
Example #11
0
        /// <summary>
        ///     指定されたストリームから読み込む。
        /// </summary>
        internal static 表示枠 読み込む(Stream fs, PMXヘッダ header)
        {
            var data = new 表示枠();

            data.枠名     = ParserHelper.get_TextBuf(fs, header.エンコード方式);
            data.枠名_英   = ParserHelper.get_TextBuf(fs, header.エンコード方式);
            data.特殊枠フラグ = ParserHelper.get_Byte(fs) == 1;
            int 枠内要素数 = ParserHelper.get_Int(fs);

            data.枠内要素リスト = new List <枠内要素>(枠内要素数);
            for (int i = 0; i < 枠内要素数; i++)
            {
                data.枠内要素リスト.Add(枠内要素.読み込む(fs, header));
            }

            return(data);
        }
Example #12
0
        /// <summary>
        ///     指定されたストリームから読み込む。
        /// </summary>
        internal static 面リスト 読み込む(FileStream fs, PMXヘッダ header)
        {
            int 面数 = ParserHelper.get_Int(fs);

            Debug.WriteLine($"面数: {面数 / 3}");

            var list = new 面リスト(面数 / 3);

            for (int i = 0; i < 面数 / 3; i++)
            {
                list.Add(
                    new 面(
                        ParserHelper.get_VertexIndex(fs, header.頂点インデックスサイズ),
                        ParserHelper.get_VertexIndex(fs, header.頂点インデックスサイズ),
                        ParserHelper.get_VertexIndex(fs, header.頂点インデックスサイズ)));
            }

            return(list);
        }
Example #13
0
        /// <summary>
        ///     指定されたストリームから読み込む。
        /// </summary>
        internal static PMXヘッダ 読み込む(FileStream fs)
        {
            var header = new PMXヘッダ();

            // マジックナンバー("PMX "の4バイト)の読み取り

            var MagicNumberbuf = new byte[4];

            fs.Read(MagicNumberbuf, 0, 4);
            if (Encoding.Unicode.GetString(MagicNumberbuf, 0, 4) != "PMX " &&
                Encoding.UTF8.GetString(MagicNumberbuf, 0, 4) != "PMX ")
            {
                throw new InvalidDataException("PMXファイルのマジックナンバーが間違っています。ファイルが破損しているか、対応バージョンではありません。");
            }

            // バージョン情報の読み取り

            header.PMXバージョン = ParserHelper.get_Float(fs);

            // 後のデータ列のバイト列

            if (ParserHelper.get_Byte(fs) != 8)
            {
                throw new NotImplementedException();  // PMX2.0 は 8 で固定
            }
            byte[] descriptionbuf = new byte[8];

            // 詳細のデータ(8バイト固定)

            fs.Read(descriptionbuf, 0, 8);
            header.エンコード方式        = descriptionbuf[0] == 1 ? EncodeType.UTF8 : EncodeType.UTF16LE;
            header.追加UV数          = descriptionbuf[1];
            header.頂点インデックスサイズ    = descriptionbuf[2];
            header.テクスチャインデックスサイズ = descriptionbuf[3];
            header.材質インデックスサイズ    = descriptionbuf[4];
            header.ボーンインデックスサイズ   = descriptionbuf[5];
            header.モーフインデックスサイズ   = descriptionbuf[6];
            header.剛体インデックスサイズ    = descriptionbuf[7];

            return(header);
        }
Example #14
0
        /// <summary>
        ///     指定されたストリームから読み込む。
        /// </summary>
        public static PMXモデル 読み込む(FileStream fs)
        {
            var model = new PMXモデル();

            model.ヘッダ      = PMXヘッダ.読み込む(fs);
            model.モデル情報    = PMXモデル情報.読み込む(fs, model.ヘッダ);
            model.頂点リスト    = 頂点リスト.読み込む(fs, model.ヘッダ);
            model.面リスト     = 面リスト.読み込む(fs, model.ヘッダ);
            model.テクスチャリスト = テクスチャリスト.読み込む(fs, model.ヘッダ);
            model.材質リスト    = 材質リスト.読み込む(fs, model.ヘッダ);
            model.ボーンリスト   = ボーンリスト.読み込む(fs, model.ヘッダ);
            model.モーフリスト   = モーフリスト.読み込む(fs, model.ヘッダ);
            model.表示枠リスト   = 表示枠リスト.読み込む(fs, model.ヘッダ);
            model.剛体リスト    = 剛体リスト.読み込む(fs, model.ヘッダ);
            model.ジョイントリスト = ジョイントリスト.読み込む(fs, model.ヘッダ);
            if (model.ヘッダ.PMXバージョン >= 2.1)
            {
                // Todo: SoftBody の読み込みは未対応
                //model.SoftBodyデータリスト = SoftBodyリスト.読み込む( fs, model.ヘッダ );
            }
            return(model);
        }
Example #15
0
        /// <summary>
        ///     指定されたストリームから読み込む。
        /// </summary>
        internal static 剛体 読み込む(Stream fs, PMXヘッダ header)
        {
            var data = new 剛体();

            data.剛体名         = ParserHelper.get_TextBuf(fs, header.エンコード方式);
            data.剛体名_英       = ParserHelper.get_TextBuf(fs, header.エンコード方式);
            data.関連ボーンインデックス = ParserHelper.get_Index(fs, header.ボーンインデックスサイズ);
            data.グループ        = ParserHelper.get_Byte(fs);
            data.非衝突グループフラグ  = ParserHelper.get_UShort(fs);
            data.形状          = (剛体形状)ParserHelper.get_Byte(fs);
            data.サイズ         = ParserHelper.get_Float3(fs);
            data.位置          = ParserHelper.get_Float3(fs);
            data.回転rad       = ParserHelper.get_Float3(fs);
            data.質量          = ParserHelper.get_Float(fs);
            data.移動減衰        = ParserHelper.get_Float(fs);
            data.回転減衰        = ParserHelper.get_Float(fs);
            data.反発力         = ParserHelper.get_Float(fs);
            data.摩擦力         = ParserHelper.get_Float(fs);
            data.物理演算        = (剛体の物理演算)ParserHelper.get_Byte(fs);

            return(data);
        }
Example #16
0
        /// <summary>
        ///     指定されたストリームから読み込む。
        /// </summary>
        internal static モーフ 読み込む(FileStream fs, PMXヘッダ header)
        {
            var morph = new モーフ();

            morph.モーフオフセットリスト = new List <モーフオフセット>();
            morph.モーフ名        = ParserHelper.get_TextBuf(fs, header.エンコード方式);
            morph.モーフ名_英      = ParserHelper.get_TextBuf(fs, header.エンコード方式);
            morph.操作パネル       = ParserHelper.get_Byte(fs);
            byte Morphtype = ParserHelper.get_Byte(fs);

            morph.モーフオフセット数 = ParserHelper.get_Int(fs);

            for (int i = 0; i < morph.モーフオフセット数; i++)
            {
                switch (Morphtype)
                {
                case 0:
                    //Group Morph
                    morph.モーフ種類 = モーフ種類.グループ;
                    morph.モーフオフセットリスト.Add(グループモーフオフセット.読み込む(fs, header));
                    break;

                case 1:
                    //Vertex Morph
                    morph.モーフ種類 = モーフ種類.頂点;
                    morph.モーフオフセットリスト.Add(頂点モーフオフセット.読み込む(fs, header));
                    break;

                case 2:
                    morph.モーフ種類 = モーフ種類.ボーン;
                    morph.モーフオフセットリスト.Add(ボーンモーフオフセット.読み込む(fs, header));
                    break;

                //3~7はすべてUVMorph
                case 3:
                    morph.モーフ種類 = モーフ種類.UV;
                    morph.モーフオフセットリスト.Add(UVモーフオフセット.読み込む(fs, header, モーフ種類.UV));
                    break;

                case 4:
                    morph.モーフ種類 = モーフ種類.追加UV1;
                    morph.モーフオフセットリスト.Add(UVモーフオフセット.読み込む(fs, header, モーフ種類.追加UV1));
                    break;

                case 5:
                    morph.モーフ種類 = モーフ種類.追加UV2;
                    morph.モーフオフセットリスト.Add(UVモーフオフセット.読み込む(fs, header, モーフ種類.追加UV2));
                    break;

                case 6:
                    morph.モーフ種類 = モーフ種類.追加UV3;
                    morph.モーフオフセットリスト.Add(UVモーフオフセット.読み込む(fs, header, モーフ種類.追加UV3));
                    break;

                case 7:
                    morph.モーフ種類 = モーフ種類.追加UV4;
                    morph.モーフオフセットリスト.Add(UVモーフオフセット.読み込む(fs, header, モーフ種類.追加UV4));
                    break;

                case 8:
                    //Material Morph
                    morph.モーフ種類 = モーフ種類.材質;
                    morph.モーフオフセットリスト.Add(材質モーフオフセット.読み込む(fs, header));
                    break;

                case 9:
                    if (header.PMXバージョン < 2.1)
                    {
                        throw new InvalidDataException("FlipモーフはPMX2.1以降でサポートされています。");
                    }
                    morph.モーフ種類 = モーフ種類.フリップ;
                    morph.モーフオフセットリスト.Add(フリップモーフオフセット.読み込む(fs, header));
                    break;

                case 10:
                    if (header.PMXバージョン < 2.1)
                    {
                        throw new InvalidDataException("ImpulseモーフはPMX2.1以降でサポートされています。");
                    }
                    morph.モーフ種類 = モーフ種類.インパルス;
                    morph.モーフオフセットリスト.Add(インパルスモーフオフセット.読み込む(fs, header));
                    break;
                }
            }
            return(morph);
        }
Example #17
0
        /// <summary>
        ///     指定されたストリームから読み込む。
        /// </summary>
        internal static 頂点 読み込む(FileStream fs, PMXヘッダ header)
        {
            var vertex = new 頂点();

            vertex.位置   = ParserHelper.get_Float3(fs);
            vertex.法線   = ParserHelper.get_Float3(fs);
            vertex.UV   = ParserHelper.get_Float2(fs);
            vertex.追加UV = new Vector4[header.追加UV数];

            for (int i = 0; i < header.追加UV数; i++)
            {
                vertex.追加UV[i] = ParserHelper.get_Float4(fs);
            }

            switch ((BoneWeight.形方式)ParserHelper.get_Byte(fs))
            {
            case BoneWeight.形方式.BDEF1:
                vertex.ウェイト変形方式 = BoneWeight.形方式.BDEF1;
                vertex.ボーンウェイト  = new BoneWeight.BDEF1()
                {
                    boneReferenceIndex = ParserHelper.get_Index(fs, header.ボーンインデックスサイズ),
                };
                break;

            case BoneWeight.形方式.BDEF2:
                vertex.ウェイト変形方式 = BoneWeight.形方式.BDEF2;
                vertex.ボーンウェイト  = new BoneWeight.BDEF2()
                {
                    Bone1ReferenceIndex = ParserHelper.get_Index(fs, header.ボーンインデックスサイズ),
                    Bone2ReferenceIndex = ParserHelper.get_Index(fs, header.ボーンインデックスサイズ),
                    Bone1Weight         = ParserHelper.get_Float(fs),
                };
                break;

            case BoneWeight.形方式.BDEF4:
                vertex.ウェイト変形方式 = BoneWeight.形方式.BDEF4;
                vertex.ボーンウェイト  = new BoneWeight.BDEF4()
                {
                    Bone1ReferenceIndex = ParserHelper.get_Index(fs, header.ボーンインデックスサイズ),
                    Bone2ReferenceIndex = ParserHelper.get_Index(fs, header.ボーンインデックスサイズ),
                    Bone3ReferenceIndex = ParserHelper.get_Index(fs, header.ボーンインデックスサイズ),
                    Bone4ReferenceIndex = ParserHelper.get_Index(fs, header.ボーンインデックスサイズ),
                    Weights             = ParserHelper.get_Float4(fs),
                };
                break;

            case BoneWeight.形方式.SDEF:
                vertex.ウェイト変形方式 = BoneWeight.形方式.SDEF;
                vertex.ボーンウェイト  = new BoneWeight.SDEF()
                {
                    Bone1ReferenceIndex = ParserHelper.get_Index(fs, header.ボーンインデックスサイズ),
                    Bone2ReferenceIndex = ParserHelper.get_Index(fs, header.ボーンインデックスサイズ),
                    Bone1Weight         = ParserHelper.get_Float(fs),
                    SDEF_C  = ParserHelper.get_Float3(fs),
                    SDEF_R0 = ParserHelper.get_Float3(fs),
                    SDEF_R1 = ParserHelper.get_Float3(fs),
                };
                break;

            case BoneWeight.形方式.QDEF:
                if (header.PMXバージョン < 2.1f)
                {
                    throw new InvalidDataException("QDEFはPMX2.1以降でのみサポートされます。");
                }
                vertex.ウェイト変形方式 = BoneWeight.形方式.QDEF;
                vertex.ボーンウェイト  = new BoneWeight.QDEF()
                {
                    Bone1ReferenceIndex = ParserHelper.get_Index(fs, header.ボーンインデックスサイズ),
                    Bone2ReferenceIndex = ParserHelper.get_Index(fs, header.ボーンインデックスサイズ),
                    Bone3ReferenceIndex = ParserHelper.get_Index(fs, header.ボーンインデックスサイズ),
                    Bone4ReferenceIndex = ParserHelper.get_Index(fs, header.ボーンインデックスサイズ),
                    Weights             = ParserHelper.get_Float4(fs),
                };
                break;

            default:
                throw new InvalidDataException();
            }

            vertex.エッジ倍率 = ParserHelper.get_Float(fs);

            return(vertex);
        }
Example #18
0
        /// <summary>
        ///     指定されたストリームから読み込む。
        /// </summary>
        internal static ボーン 読み込む(FileStream fs, PMXヘッダ header)
        {
            var bone = new ボーン();

            bone.IKリンクリスト    = new List <IKリンク>();
            bone.ボーン名        = ParserHelper.get_TextBuf(fs, header.エンコード方式);
            bone.ボーン名_英      = ParserHelper.get_TextBuf(fs, header.エンコード方式);
            bone.位置          = ParserHelper.get_Float3(fs);
            bone.親ボーンのインデックス = ParserHelper.get_Index(fs, header.ボーンインデックスサイズ);
            bone.形階層         = ParserHelper.get_Int(fs);

            var flag = new byte[2];

            flag[0] = ParserHelper.get_Byte(fs);
            flag[1] = ParserHelper.get_Byte(fs);
            Int16 flagnum = BitConverter.ToInt16(flag, 0);

            bone.ボーンの接続先表示方法 = ParserHelper.isFlagEnabled(flagnum, 0x0001) ? E接続先表示方法.ボーンで指定 : E接続先表示方法.相対座標で指定;
            bone.回転可能である     = ParserHelper.isFlagEnabled(flagnum, 0x0002);
            bone.移動可能である     = ParserHelper.isFlagEnabled(flagnum, 0x0004);
            bone.表示可能である     = ParserHelper.isFlagEnabled(flagnum, 0x0008);
            bone.操作可能である     = ParserHelper.isFlagEnabled(flagnum, 0x0010);
            bone.IKボーンである    = ParserHelper.isFlagEnabled(flagnum, 0x0020);
            bone.ローカル付与対象    = ParserHelper.isFlagEnabled(flagnum, 0x0080) ? Eローカル付与対象.親のローカル変形量 : Eローカル付与対象.ユーザ変形値_IKリンク_多重付与;
            bone.回転付与される     = ParserHelper.isFlagEnabled(flagnum, 0x0100);
            bone.移動付与される     = ParserHelper.isFlagEnabled(flagnum, 0x0200);
            bone.回転軸あり       = ParserHelper.isFlagEnabled(flagnum, 0x0400);
            bone.ローカル軸あり     = ParserHelper.isFlagEnabled(flagnum, 0x0800);
            bone.物理後変形である    = ParserHelper.isFlagEnabled(flagnum, 0x1000);
            bone.外部親変形である    = ParserHelper.isFlagEnabled(flagnum, 0x2000);

            if (bone.ボーンの接続先表示方法 == E接続先表示方法.相対座標で指定)
            {
                bone.ボーン位置からの相対位置 = ParserHelper.get_Float3(fs);
            }
            else
            {
                bone.接続先ボーンのボーンインデックス = ParserHelper.get_Index(fs, header.ボーンインデックスサイズ);
            }

            if (bone.回転付与される || bone.移動付与される)
            {
                bone.付与親ボーンインデックス = ParserHelper.get_Index(fs, header.ボーンインデックスサイズ);
                bone.付与率          = ParserHelper.get_Float(fs);
            }

            if (bone.回転軸あり)
            {
                bone.回転軸の方向ベクトル = ParserHelper.get_Float3(fs);
            }

            if (bone.ローカル軸あり)
            {
                bone.ローカル軸のX軸の方向ベクトル = ParserHelper.get_Float3(fs);
                bone.ローカル軸のZ軸の方向ベクトル = ParserHelper.get_Float3(fs);
            }

            if (bone.外部親変形である)
            {
                bone.親Key = ParserHelper.get_Int(fs);
            }

            if (bone.IKボーンである)
            {
                bone.IKターゲットボーンインデックス = ParserHelper.get_Index(fs, header.ボーンインデックスサイズ);
                bone.IKループ回数          = ParserHelper.get_Int(fs);
                bone.IK単位角rad         = ParserHelper.get_Float(fs);
                int IKリンク数 = ParserHelper.get_Int(fs);
                for (int i = 0; i < IKリンク数; i++)
                {
                    bone.IKリンクリスト.Add(IKリンク.読み込む(fs, header));
                }
            }

            return(bone);
        }