Example #1
0
        private static void ParseJoints(BinaryReader reader, PmxModel pmx)
        {
            var jointCount = reader.ReadInt32();

            pmx.Joints = new List <PmxJoint>();
            for (var i = 0; i < jointCount; i++)
            {
                pmx.Joints.Add(new PmxJoint()
                {
                    NameLocal       = reader.ReadLPString(pmx.Globals.TextEncoding),
                    NameUniversal   = reader.ReadLPString(pmx.Globals.TextEncoding),
                    JointType       = reader.ReadEnum <PmxJointType>(),
                    RigidBodyIndexA = reader.ReadVarInt(pmx.Globals.RigidBodyIndexSize),
                    RigidBodyIndexB = reader.ReadVarInt(pmx.Globals.RigidBodyIndexSize),
                    Position        = reader.ReadStruct <Vec3f>(),
                    Rotation        = reader.ReadStruct <Vec3f>(),
                    PositionMinimum = reader.ReadStruct <Vec3f>(),
                    PositionMaximum = reader.ReadStruct <Vec3f>(),
                    RotationMinimum = reader.ReadStruct <Vec3f>(),
                    RotationMaximum = reader.ReadStruct <Vec3f>(),
                    PositionSpring  = reader.ReadStruct <Vec3f>(),
                    RotationSpring  = reader.ReadStruct <Vec3f>()
                });
            }
        }
Example #2
0
        private static void ParseSoftBodies(BinaryReader reader, PmxModel pmx)
        {
            var softBodyCount = reader.ReadInt32();

            pmx.SoftBodies = new List <PmxSoftBody>();
            for (var i = 0; i < softBodyCount; i++)
            {
                int anchorRigidBodyCount, vertexPinCount;

                pmx.SoftBodies.Add(new PmxSoftBody()
                {
                    NameLocal            = reader.ReadLPString(pmx.Globals.TextEncoding),
                    NameUniversal        = reader.ReadLPString(pmx.Globals.TextEncoding),
                    ShapeType            = reader.ReadEnum <PmxSoftBodyShapeType>(),
                    GroupId              = reader.ReadByte(),
                    NoCollisionMask      = reader.ReadUInt16(),
                    Bullet3DData         = reader.ReadStruct <PmxSoftBodyBullet3dData>(),
                    AnchorRigidBodyCount = anchorRigidBodyCount = reader.ReadInt32(),
                    AnchorRigidBodies    = Enumerable.Range(0, anchorRigidBodyCount).Select(_ => new PmxSoftBodyAnchorRigidBody()
                    {
                        RigidBodyIndex = reader.ReadVarInt(pmx.Globals.RigidBodyIndexSize),
                        VertexIndex    = reader.ReadVarInt(pmx.Globals.VertexIndexSize, true),
                        NearMode       = reader.ReadByte()
                    }).ToList(),
                    VertexPintCount = vertexPinCount = reader.ReadInt32(),
                    VertexPins      = Enumerable.Range(0, anchorRigidBodyCount).Select(_ => new PmxSoftBodyVertexPin()
                    {
                        VertexIndex = reader.ReadVarInt(pmx.Globals.VertexIndexSize, true),
                    }).ToList()
                });
            }
        }
Example #3
0
        private static void ParseMaterials(BinaryReader reader, PmxModel pmx)
        {
            var materialsCount = reader.ReadInt32();
            var encoding       = pmx.Globals.TextEncoding;

            pmx.Materials = new List <PmxMaterial>();
            for (var i = 0; i < materialsCount; i++)
            {
                var material = new PmxMaterial();
                material.NameLocal            = reader.ReadLPString(encoding);
                material.NameUniversal        = reader.ReadLPString(encoding);
                material.DiffuseColor         = reader.ReadStruct <Vec4f>();
                material.SpecularColor        = reader.ReadStruct <Vec3f>();
                material.SpecularStrength     = reader.ReadSingle();
                material.AmbientColor         = reader.ReadStruct <Vec3f>();
                material.DrawingFlags         = reader.ReadEnum <PmxMaterialFlags>();
                material.EdgeColor            = reader.ReadStruct <Vec4f>();
                material.EdgeScale            = reader.ReadSingle();
                material.TextureIndex         = reader.ReadVarInt(pmx.Globals.TextureIndexSize);
                material.EnvironmentIndex     = reader.ReadVarInt(pmx.Globals.TextureIndexSize);
                material.EnvironmentBlendMode = reader.ReadEnum <EnvironmentBlendMode>();
                material.ToonReference        = reader.ReadEnum <ToonReference>();
                material.ToonValue            = material.ToonReference == ToonReference.Internal
                    ? reader.ReadByte()
                    : reader.ReadVarInt(pmx.Globals.TextureIndexSize);
                material.MetaData   = reader.ReadLPString(pmx.Globals.TextEncoding);
                material.IndexCount = reader.ReadInt32();
                pmx.Materials.Add(material);
            }
        }
Example #4
0
        private static void ParseRigidBodies(BinaryReader reader, PmxModel pmx)
        {
            var rigidBodyCount = reader.ReadInt32();

            pmx.RigidBodies = new List <PmxRigidBody>();
            for (var i = 0; i < rigidBodyCount; i++)
            {
                pmx.RigidBodies.Add(new PmxRigidBody()
                {
                    NameLocal         = reader.ReadLPString(pmx.Globals.TextEncoding),
                    NameUniversal     = reader.ReadLPString(pmx.Globals.TextEncoding),
                    RelatedBoneIndex  = reader.ReadVarInt(pmx.Globals.BoneIndexSize),
                    GroupId           = reader.ReadByte(),
                    NonCollisionMask  = reader.ReadUInt16(),
                    Shape             = reader.ReadEnum <PmxRigidBodyShapeType>(),
                    ShapeSize         = reader.ReadStruct <Vec3f>(),
                    ShapePosition     = reader.ReadStruct <Vec3f>(),
                    ShapeRotation     = reader.ReadStruct <Vec3f>(),
                    Mass              = reader.ReadSingle(),
                    MoveAttenuation   = reader.ReadSingle(),
                    RotationDampening = reader.ReadSingle(),
                    Repulsion         = reader.ReadSingle(),
                    FrictionForce     = reader.ReadSingle(),
                    PhysicsMode       = reader.ReadEnum <PmxRigidBodyPhysicsMode>()
                });
            }
        }
Example #5
0
        private static void ParseTextures(BinaryReader reader, PmxModel pmx)
        {
            var textureCount = reader.ReadInt32();
            var encoding     = pmx.Globals.TextEncoding;

            pmx.Textures = Enumerable.Range(0, textureCount).Select(i => reader.ReadLPString(encoding)).ToList();
        }
Example #6
0
        private static void ParseVertexData(BinaryReader reader, PmxModel pmx)
        {
            var vertexCount = reader.ReadInt32();

            pmx.Vertices = new List <PmxVertexData>();
            int additionalVec4Count = pmx.Globals.AdditionalVec4Count;

            for (var i = 0; i < vertexCount; i++)
            {
                var vertex = new PmxVertexData();

                vertex.Position       = reader.ReadStruct <Vec3f>();
                vertex.Normal         = reader.ReadStruct <Vec3f>();
                vertex.UV             = reader.ReadStruct <Vec2f>();
                vertex.AdditionalVec4 = new Vec4f[pmx.Globals.AdditionalVec4Count];

                for (var j = 0; j < additionalVec4Count; j++)
                {
                    vertex.AdditionalVec4[j] = reader.ReadStruct <Vec4f>();
                }

                vertex.DeformType = reader.ReadEnum <BoneWeightDeformType>();
                switch (vertex.DeformType)
                {
                case BoneWeightDeformType.BDEF1:
                    vertex.DeformData = BDEF1.Read(reader, pmx.Globals);
                    break;

                case BoneWeightDeformType.BDEF2:
                    vertex.DeformData = BDEF2.Read(reader, pmx.Globals);
                    break;

                case BoneWeightDeformType.BDEF4:
                    vertex.DeformData = BDEF4.Read(reader, pmx.Globals);
                    break;

                case BoneWeightDeformType.SDEF:
                    vertex.DeformData = SDEF.Read(reader, pmx.Globals);
                    break;

                case BoneWeightDeformType.QDEF:
                    vertex.DeformData = QDEF.Read(reader, pmx.Globals);
                    break;

                default:
                    throw new LibMMDParserException($"Unknown deform type: {vertex.DeformType}");
                }

                vertex.EdgeScale = reader.ReadSingle();

                pmx.Vertices.Add(vertex);
            }
        }
Example #7
0
        private static void ParseDisplayData(BinaryReader reader, PmxModel pmx)
        {
            var displayDataCount = reader.ReadInt32();

            pmx.DisplayData = new List <PmxDisplayData>();
            for (var i = 0; i < displayDataCount; i++)
            {
                var frameCount  = 0;
                var displayData = new PmxDisplayData()
                {
                    NameLocal     = reader.ReadLPString(pmx.Globals.TextEncoding),
                    NameUniversal = reader.ReadLPString(pmx.Globals.TextEncoding),
                    IsSpecial     = reader.ReadBoolean(),
                    FrameCount    = frameCount = reader.ReadInt32(),
                    Frames        = Enumerable.Range(0, frameCount).Select <int, FrameData>(_ =>
                    {
                        var type = reader.ReadEnum <PmxDisplayFrameType>();
                        switch (type)
                        {
                        case PmxDisplayFrameType.Bone:
                            return(new FrameData <BoneFrameData>()
                            {
                                FrameType = type,
                                Data = new BoneFrameData()
                                {
                                    BoneIndex = reader.ReadVarInt(pmx.Globals.BoneIndexSize)
                                }
                            });

                        case PmxDisplayFrameType.Morph:
                            return(new FrameData <MorphFrameData>()
                            {
                                FrameType = type,
                                Data = new MorphFrameData()
                                {
                                    MorphIndex = reader.ReadVarInt(pmx.Globals.MorphIndexSize)
                                }
                            });

                        default:
                            throw new LibMMDParserException($"Invalid DisplayFrameType {type}");
                        }
                    }).ToList()
                };
            }
        }
Example #8
0
        private static void ParseModelInformation(BinaryReader reader, PmxModel pmx)
        {
            var magic = reader.ReadUInt32();

            if (magic != PMX_MAGIC)
            {
                throw new LibMMDInvalidHeaderException("PMX magic mismatch");
            }

            pmx.Version = reader.ReadSingle();
            var globalsCount = reader.ReadByte();

            pmx.Globals = new PmxGlobalData(reader.ReadBytes(globalsCount).Extend(8));

            var encoding = pmx.Globals.TextEncoding;

            pmx.ModelNameLocal         = reader.ReadLPString(encoding);
            pmx.ModelNameUniversal     = reader.ReadLPString(encoding);
            pmx.ModelCommentsLocal     = reader.ReadLPString(encoding);
            pmx.ModelCommentsUniversal = reader.ReadLPString(encoding);
        }
Example #9
0
        public static PmxModel Parse(BinaryReader reader)
        {
            var pmx = new PmxModel();

            ParseModelInformation(reader, pmx);
            ParseVertexData(reader, pmx);
            ParseIndices(reader, pmx);
            ParseTextures(reader, pmx);
            ParseMaterials(reader, pmx);
            ParseBones(reader, pmx);
            ParseMorphs(reader, pmx);
            ParseDisplayData(reader, pmx);
            ParseRigidBodies(reader, pmx);
            ParseJoints(reader, pmx);
            if (pmx.Version > 2.0)
            {
                ParseSoftBodies(reader, pmx);
            }

            return(pmx);
        }
Example #10
0
        private static void ParseIndices(BinaryReader reader, PmxModel pmx)
        {
            var indexCount = reader.ReadInt32();

            pmx.Indices = new List <int>();
            switch (pmx.Globals.VertexIndexSize)
            {
            case 1:
                pmx.Indices = reader.ReadArray <byte>(indexCount).Select(x => (int)x).ToList();
                break;

            case 2:
                pmx.Indices = reader.ReadArray <ushort>(indexCount).Select(x => (int)x).ToList();
                break;

            case 4:
                pmx.Indices = reader.ReadArray <int>(indexCount).ToList();
                break;

            default:
                throw new LibMMDParserException($"Unsupported vertex index size: {pmx.Globals.VertexIndexSize}");
            }
        }
Example #11
0
        private static void ParseMorphs(BinaryReader reader, PmxModel pmx)
        {
            var morphCount = reader.ReadInt32();

            pmx.Morphs = new List <PmxMorph>();
            for (var i = 0; i < morphCount; i++)
            {
                var morphNameLocal     = reader.ReadLPString(pmx.Globals.TextEncoding);
                var morphNameUniversal = reader.ReadLPString(pmx.Globals.TextEncoding);
                var panelType          = reader.ReadByte();
                var morphType          = reader.ReadEnum <PmxMorphType>();
                var morphDataCount     = reader.ReadInt32();

                switch (morphType)
                {
                case PmxMorphType.Group:
                    pmx.Morphs.Add(new PmxMorph <GroupMorph>()
                    {
                        Index         = i,
                        NameLocal     = morphNameLocal,
                        NameUniversal = morphNameUniversal,
                        PanelType     = panelType,
                        MorphType     = morphType,
                        Count         = morphDataCount,
                        Data          = Enumerable.Range(0, morphDataCount).Select(_ => new GroupMorph()
                        {
                            MorphIndex = reader.ReadVarInt(pmx.Globals.MorphIndexSize),
                            Influence  = reader.ReadSingle()
                        }).ToList()
                    });
                    break;

                case PmxMorphType.Vertex:
                    pmx.Morphs.Add(new PmxMorph <VertexMorph>()
                    {
                        Index         = i,
                        NameLocal     = morphNameLocal,
                        NameUniversal = morphNameUniversal,
                        PanelType     = panelType,
                        MorphType     = morphType,
                        Count         = morphDataCount,
                        Data          = Enumerable.Range(0, morphDataCount).Select(_ => new VertexMorph()
                        {
                            VertexIndex = reader.ReadVarInt(pmx.Globals.VertexIndexSize, true),
                            Translation = reader.ReadStruct <Vec3f>()
                        }).ToList()
                    });
                    break;

                case PmxMorphType.Bone:
                    pmx.Morphs.Add(new PmxMorph <BoneMorph>()
                    {
                        Index         = i,
                        NameLocal     = morphNameLocal,
                        NameUniversal = morphNameUniversal,
                        PanelType     = panelType,
                        MorphType     = morphType,
                        Count         = morphDataCount,
                        Data          = Enumerable.Range(0, morphDataCount).Select(_ => new BoneMorph()
                        {
                            BoneIndex   = reader.ReadVarInt(pmx.Globals.BoneIndexSize),
                            Translation = reader.ReadStruct <Vec3f>(),
                            Rotation    = reader.ReadStruct <Vec4f>()
                        }).ToList()
                    });
                    break;

                case PmxMorphType.UV:
                case PmxMorphType.UVExt1:
                case PmxMorphType.UVExt2:
                case PmxMorphType.UVExt3:
                case PmxMorphType.UVExt4:
                    pmx.Morphs.Add(new PmxMorph <UVMorph>()
                    {
                        Index         = i,
                        NameLocal     = morphNameLocal,
                        NameUniversal = morphNameUniversal,
                        PanelType     = panelType,
                        MorphType     = morphType,
                        Count         = morphDataCount,
                        Data          = Enumerable.Range(0, morphDataCount).Select(_ => new UVMorph()
                        {
                            VertexIndex = reader.ReadVarInt(pmx.Globals.VertexIndexSize, true),
                            Changes     = reader.ReadStruct <Vec4f>()
                        }).ToList()
                    });
                    break;

                case PmxMorphType.Material:
                    pmx.Morphs.Add(new PmxMorph <MaterialMorph>()
                    {
                        Index         = i,
                        NameLocal     = morphNameLocal,
                        NameUniversal = morphNameUniversal,
                        PanelType     = panelType,
                        MorphType     = morphType,
                        Count         = morphDataCount,
                        Data          = Enumerable.Range(0, morphDataCount).Select(_ => new MaterialMorph()
                        {
                            MaterialIndex   = reader.ReadVarInt(pmx.Globals.MaterialIndexSize),
                            Unkn            = reader.ReadByte(),
                            DiffuseColor    = reader.ReadStruct <Vec4f>(),
                            SpecularColor   = reader.ReadStruct <Vec3f>(),
                            Specularity     = reader.ReadSingle(),
                            AmbientColor    = reader.ReadStruct <Vec3f>(),
                            EdgeColor       = reader.ReadStruct <Vec4f>(),
                            EdgeSize        = reader.ReadSingle(),
                            TextureTint     = reader.ReadStruct <Vec4f>(),
                            EnvironmentTint = reader.ReadStruct <Vec4f>(),
                            ToonTint        = reader.ReadStruct <Vec4f>()
                        }).ToList()
                    });
                    break;

                case PmxMorphType.Flip:
                    pmx.Morphs.Add(new PmxMorph <FlipMorph>()
                    {
                        Index         = i,
                        NameLocal     = morphNameLocal,
                        NameUniversal = morphNameUniversal,
                        PanelType     = panelType,
                        MorphType     = morphType,
                        Count         = morphDataCount,
                        Data          = Enumerable.Range(0, morphDataCount).Select(_ => new FlipMorph()
                        {
                            MorphIndex = reader.ReadVarInt(pmx.Globals.MorphIndexSize),
                            Influence  = reader.ReadSingle()
                        }).ToList()
                    });
                    break;

                case PmxMorphType.Impulse:
                    pmx.Morphs.Add(new PmxMorph <ImpulseMorph>()
                    {
                        Index         = i,
                        NameLocal     = morphNameLocal,
                        NameUniversal = morphNameUniversal,
                        PanelType     = panelType,
                        MorphType     = morphType,
                        Count         = morphDataCount,
                        Data          = Enumerable.Range(0, morphDataCount).Select(_ => new ImpulseMorph()
                        {
                            RigidBodyIndex = reader.ReadVarInt(pmx.Globals.RigidBodyIndexSize),
                            LocalFlag      = reader.ReadByte(),
                            MovementSpeed  = reader.ReadStruct <Vec3f>(),
                            RotationTorque = reader.ReadStruct <Vec3f>()
                        }).ToList()
                    });
                    break;

                default:
                    throw new LibMMDParserException($"MorphType {morphType} is unknown");
                }
            }
        }
Example #12
0
        private static void ParseBones(BinaryReader reader, PmxModel pmx)
        {
            var boneCount = reader.ReadInt32();

            pmx.Bones = new List <PmxBone>();
            for (var i = 0; i < boneCount; i++)
            {
                var bone = new PmxBone();
                bone.NameLocal       = reader.ReadLPString(pmx.Globals.TextEncoding);
                bone.NameUniversal   = reader.ReadLPString(pmx.Globals.TextEncoding);
                bone.Position        = reader.ReadStruct <Vec3f>();
                bone.ParentBoneIndex = reader.ReadVarInt(pmx.Globals.BoneIndexSize);
                bone.Layer           = reader.ReadInt32();
                bone.Flags           = reader.ReadEnum <BoneFlags>();

                if (bone.Flags.HasFlag(BoneFlags.IndexedTailPosition))
                {
                    bone.TailPositionBoneIndex = reader.ReadVarInt(pmx.Globals.BoneIndexSize);
                }
                else
                {
                    bone.TailPosition = reader.ReadStruct <Vec3f>();
                }

                if ((bone.Flags & (BoneFlags.InheritTranslation | BoneFlags.InheritRotation)) > 0)
                {
                    bone.InheritBone = new InheritBone()
                    {
                        ParentIndex  = reader.ReadVarInt(pmx.Globals.BoneIndexSize),
                        ParentWeight = reader.ReadSingle()
                    }
                }
                ;

                if (bone.Flags.HasFlag(BoneFlags.FixedAxis))
                {
                    bone.BoneFixedAxis = reader.ReadStruct <Vec3f>();
                }

                if (bone.Flags.HasFlag(BoneFlags.LocalCoordinate))
                {
                    bone.LocalCoordinates = reader.ReadStruct <BoneLocalCoordinates>();
                }

                if (bone.Flags.HasFlag(BoneFlags.ExternalParentDeform))
                {
                    //bone.ExternalParent = reader.ReadVarInt(pmx.Globals.BoneIndexSize);
                    bone.ExternalParent = reader.ReadInt32();
                }

                if (bone.Flags.HasFlag(BoneFlags.InverseKinematics))
                {
                    int linkCount;
                    var boneIk = new BoneInverseKinematic();
                    boneIk.TargetIndex = reader.ReadVarInt(pmx.Globals.BoneIndexSize);
                    boneIk.LoopCount   = reader.ReadInt32();
                    boneIk.LimitRadian = reader.ReadSingle();
                    boneIk.LinkCount   = (linkCount = reader.ReadInt32());
                    boneIk.BoneLinks   = Enumerable.Range(0, linkCount).Select(_ =>
                    {
                        var ikLink = new BoneLink
                        {
                            BoneIndex = reader.ReadVarInt(pmx.Globals.BoneIndexSize),
                            HasLimits = reader.ReadBoolean()
                        };

                        if (ikLink.HasLimits)
                        {
                            ikLink.LimitMinimum = reader.ReadStruct <Vec3f>();
                            ikLink.LimitMaximum = reader.ReadStruct <Vec3f>();
                        }

                        return(ikLink);
                    }).ToList();
                    bone.InverseKinematic = boneIk;
                }
                pmx.Bones.Add(bone);
            }
        }