Exemple #1
0
        public static PmxDocument Parse(Stream stream)
        {
            // leave open
            var br     = new BinaryReader(stream);
            var header = Encoding.ASCII.GetString(br.ReadBytes(4));
            var rt     = new PmxDocument();

            if (header != "PMX ")
            {
                throw new InvalidOperationException("invalid format");
            }

            rt.Version = br.ReadSingle();

            if (rt.Version != 2 &&
                rt.Version != 2.1f)
            {
                throw new NotSupportedException("specified format version not supported");
            }

            rt.Header           = PmxHeader.Parse(br);
            rt.ModelInformation = PmxModelInformation.Parse(br, rt);
            rt.Vertices         = Enumerable.Range(0, br.ReadInt32()).Select(_ => PmxVertex.Parse(br, rt)).ToList();
            rt.Indices          = Enumerable.Range(0, br.ReadInt32()).Select(_ => rt.ReadIndex(br, PmxIndexKind.Vertex)).ToList();
            rt.Textures         = Enumerable.Range(0, br.ReadInt32()).Select(_ => rt.ReadString(br)).ToList();
            rt.Materials        = Enumerable.Range(0, br.ReadInt32()).Select(_ => PmxMaterial.Parse(br, rt)).ToList();
            rt.Bones            = Enumerable.Range(0, br.ReadInt32()).Select(_ => PmxBone.Parse(br, rt)).ToList();
            rt.Morphs           = Enumerable.Range(0, br.ReadInt32()).Select(_ => PmxMorph.Parse(br, rt)).ToList();
            rt.DisplayList      = Enumerable.Range(0, br.ReadInt32()).Select(_ => PmxDisplayList.Parse(br, rt)).ToList();
            rt.Rigids           = Enumerable.Range(0, br.ReadInt32()).Select(_ => PmxRigidBody.Parse(br, rt)).ToList();
            rt.Constraints      = Enumerable.Range(0, br.ReadInt32()).Select(_ => PmxConstraint.Parse(br, rt)).ToList();

            if (rt.Version > 2)
            {
                rt.SoftBodies = Enumerable.Range(0, br.ReadInt32()).Select(_ => PmxSoftBody.Parse(br, rt)).ToList();
            }

            return(rt);
        }
Exemple #2
0
        private PmxModel ReadPmxModel()
        {
            var model = new PmxModel();

            model.Name           = ReadString() ?? string.Empty;
            model.NameEnglish    = ReadString() ?? string.Empty;
            model.Comment        = ReadString() ?? string.Empty;
            model.CommentEnglish = ReadString() ?? string.Empty;

            ReadVertexInfo();
            ReadFaceInfo();
            ReadTextureInfo();
            ReadMaterialInfo();
            ReadBoneInfo();
            ReadMorphInfo();
            ReadNodeInfo();
            ReadRigidBodyInfo();
            ReadJointInfo();
            ReadSoftBodyInfo();

            return(model);

            void ReadVertexInfo()
            {
                var vertexCount = _reader.ReadInt32();
                var vertices    = new PmxVertex[vertexCount];

                for (var i = 0; i < vertexCount; ++i)
                {
                    vertices[i] = ReadPmxVertex();
                }

                model.Vertices = vertices;
            }

            void ReadFaceInfo()
            {
                var faceCount   = _reader.ReadInt32();
                var faceIndices = new int[faceCount];

                for (var i = 0; i < faceCount; ++i)
                {
                    faceIndices[i] = _reader.ReadVarLenIntAsInt32(VertexElementSize, true);
                }

                model.FaceTriangles = faceIndices;
            }

            void ReadTextureInfo()
            {
                var textureCount       = _reader.ReadInt32();
                var textureNameMap     = new Dictionary <int, string>();
                var textureIndexLookup = new Dictionary <string, int>();

                for (var i = 0; i < textureCount; ++i)
                {
                    var textureName = ReadString() ?? string.Empty;
                    textureNameMap[i] = textureName;
                    textureIndexLookup[textureName] = i;
                }

                textureNameMap[-1] = string.Empty;

                TextureNameMap     = textureNameMap;
                TextureIndexLookup = textureIndexLookup;
            }

            void ReadMaterialInfo()
            {
                var materialCount = _reader.ReadInt32();
                var materials     = new PmxMaterial[materialCount];

                for (var i = 0; i < materialCount; ++i)
                {
                    materials[i] = ReadPmxMaterial();
                }

                model.Materials = materials;
            }

            void ReadBoneInfo()
            {
                var boneCount = _reader.ReadInt32();
                var bones     = new PmxBone[boneCount];

                for (var i = 0; i < boneCount; ++i)
                {
                    bones[i]           = ReadPmxBone();
                    bones[i].BoneIndex = i;
                }

                model.Bones           = bones;
                model.BonesDictionary = bones.ToDictionary(bone => bone.Name);

                var rootBoneIndexList = new List <int>();

                for (var i = 0; i < bones.Length; ++i)
                {
                    var bone = bones[i];

                    if (bone.ParentIndex < 0)
                    {
                        rootBoneIndexList.Add(i);
                    }
                    else
                    {
                        bone.Parent = bones[bone.ParentIndex];
                    }

                    if (bone.AppendParentIndex >= 0)
                    {
                        bone.AppendParent = bones[bone.AppendParentIndex];
                    }

                    if (bone.ExternalParentIndex >= 0)
                    {
                        bone.ExternalParent = bones[bone.ExternalParentIndex];
                    }

                    if (bone.HasFlag(BoneFlags.IK))
                    {
                        var ik = bone.IK;

                        Debug.Assert(ik != null, nameof(ik) + " != null");

                        ik.TargetBone = bones[ik.TargetBoneIndex];

                        foreach (var link in ik.Links)
                        {
                            if (link.BoneIndex >= 0)
                            {
                                link.Bone = bones[link.BoneIndex];
                            }
                        }
                    }
                }

                model.RootBoneIndices = rootBoneIndexList.ToArray();

                foreach (var bone in bones)
                {
                    bone.SetToBindingPose();
                }
            }

            void ReadMorphInfo()
            {
                var morphCount = _reader.ReadInt32();
                var morphs     = new PmxMorph[morphCount];

                for (var i = 0; i < morphCount; ++i)
                {
                    morphs[i] = ReadPmxMorph();
                }

                model.Morphs = morphs;
            }

            void ReadNodeInfo()
            {
                var nodeCount = _reader.ReadInt32();
                var nodes     = new PmxNode[nodeCount];

                for (var i = 0; i < nodeCount; ++i)
                {
                    var node = ReadPmxNode();

                    nodes[i] = node;

                    if (node.IsSystemNode)
                    {
                        if (node.Name == "Root")
                        {
                            model.RootNodeIndex = i;
                        }
                        else if (node.Name == "表情")
                        {
                            model.FacialExpressionNodeIndex = i;
                        }
                    }
                }

                model.Nodes = nodes;
            }

            void ReadRigidBodyInfo()
            {
                var bodyCount = _reader.ReadInt32();
                var bodies    = new PmxRigidBody[bodyCount];

                for (var i = 0; i < bodyCount; ++i)
                {
                    bodies[i] = ReadPmxRigidBody();
                }

                model.RigidBodies = bodies;
            }

            void ReadJointInfo()
            {
                var jointCount = _reader.ReadInt32();
                var joints     = new PmxJoint[jointCount];

                for (var i = 0; i < jointCount; ++i)
                {
                    joints[i] = ReadPmxJoint();
                }

                model.Joints = joints;
            }

            void ReadSoftBodyInfo()
            {
                if (DetailedVersion < 2.1f)
                {
                    return;
                }

                var bodyCount = _reader.ReadInt32();
                var bodies    = new PmxSoftBody[bodyCount];

                for (var i = 0; i < bodyCount; ++i)
                {
                    bodies[i] = ReadPmxSoftBody();
                }

                model.SoftBodies = bodies;
            }
        }
Exemple #3
0
        private PmxSoftBody ReadPmxSoftBody()
        {
            var body = new PmxSoftBody();

            body.Name        = ReadString() ?? string.Empty;
            body.NameEnglish = ReadString() ?? string.Empty;

            body.Shape         = (SoftBodyShape)_reader.ReadByte(); // TODO: Signed? Unsigned?
            body.MaterialIndex = _reader.ReadVarLenIntAsInt32(MaterialElementSize);
            body.GroupIndex    = _reader.ReadByte();                // TODO: Signed? Unsigned?

            var bits      = _reader.ReadUInt16();
            var passGroup = PmxBodyPassGroup.FromFlagBits(bits);

            body.PassGroup = passGroup;

            body.Flags = (SoftBodyFlags)_reader.ReadByte();
            body.BendingLinkDistance = _reader.ReadInt32();
            body.ClusterCount        = _reader.ReadInt32();
            body.TotalMass           = _reader.ReadSingle();
            body.Margin = _reader.ReadSingle();

            var config = body.Config;

            config.AeroModel  = _reader.ReadInt32();
            config.VCF        = _reader.ReadSingle();
            config.DP         = _reader.ReadSingle();
            config.DG         = _reader.ReadSingle();
            config.LF         = _reader.ReadSingle();
            config.PR         = _reader.ReadSingle();
            config.VC         = _reader.ReadSingle();
            config.DF         = _reader.ReadSingle();
            config.MT         = _reader.ReadSingle();
            config.CHR        = _reader.ReadSingle();
            config.KHR        = _reader.ReadSingle();
            config.SHR        = _reader.ReadSingle();
            config.AHR        = _reader.ReadSingle();
            config.SRHR_CL    = _reader.ReadSingle();
            config.SKHR_CL    = _reader.ReadSingle();
            config.SSHR_CL    = _reader.ReadSingle();
            config.SR_SPLT_CL = _reader.ReadSingle();
            config.SK_SPLT_CL = _reader.ReadSingle();
            config.SS_SPLT_CL = _reader.ReadSingle();
            config.V_IT       = _reader.ReadInt32();
            config.P_IT       = _reader.ReadInt32();
            config.D_IT       = _reader.ReadInt32();
            config.C_IT       = _reader.ReadInt32();

            var matCfg = body.MaterialConfig;

            matCfg.LST = _reader.ReadSingle();
            matCfg.AST = _reader.ReadSingle();
            matCfg.VST = _reader.ReadSingle();

            var bodyAnchorCount = _reader.ReadInt32();
            var bodyAnchors     = new BodyAnchor[bodyAnchorCount];

            for (var i = 0; i < bodyAnchorCount; ++i)
            {
                bodyAnchors[i] = ReadBodyAnchor();
            }

            body.BodyAnchors = bodyAnchors.Distinct().ToArray();

            var vertexPinCount = _reader.ReadInt32();
            var vertexPins     = new VertexPin[vertexPinCount];

            for (var i = 0; i < vertexPinCount; ++i)
            {
                vertexPins[i] = ReadVertexPin();
            }

            body.VertexPins = vertexPins.Distinct().ToArray();

            return(body);
        }
Exemple #4
0
        private void WritePmxSoftBody([NotNull] PmxSoftBody body)
        {
            WriteString(body.Name);
            WriteString(body.NameEnglish);

            _writer.Write((byte)body.Shape);
            _writer.WriteInt32AsVarLenInt(body.MaterialIndex, MaterialElementSize);
            _writer.Write((byte)body.GroupIndex);

            _writer.Write(body.PassGroup.ToFlagBits());

            _writer.Write((byte)body.Flags);
            _writer.Write(body.BendingLinkDistance);
            _writer.Write(body.ClusterCount);
            _writer.Write(body.TotalMass);
            _writer.Write(body.Margin);

            var config = body.Config;

            _writer.Write(config.AeroModel);
            _writer.Write(config.VCF);
            _writer.Write(config.DP);
            _writer.Write(config.DG);
            _writer.Write(config.LF);
            _writer.Write(config.PR);
            _writer.Write(config.VC);
            _writer.Write(config.DF);
            _writer.Write(config.MT);
            _writer.Write(config.CHR);
            _writer.Write(config.KHR);
            _writer.Write(config.SHR);
            _writer.Write(config.AHR);
            _writer.Write(config.SRHR_CL);
            _writer.Write(config.SKHR_CL);
            _writer.Write(config.SSHR_CL);
            _writer.Write(config.SR_SPLT_CL);
            _writer.Write(config.SK_SPLT_CL);
            _writer.Write(config.SS_SPLT_CL);
            _writer.Write(config.V_IT);
            _writer.Write(config.P_IT);
            _writer.Write(config.D_IT);
            _writer.Write(config.C_IT);

            var matCfg = body.MaterialConfig;

            _writer.Write(matCfg.LST);
            _writer.Write(matCfg.AST);
            _writer.Write(matCfg.VST);

            _writer.Write(body.BodyAnchors.Length);

            foreach (var anchor in body.BodyAnchors)
            {
                WriteBodyAnchor(anchor);
            }

            _writer.Write(body.VertexPins.Length);

            foreach (var pin in body.VertexPins)
            {
                WriteVertexPin(pin);
            }
        }