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); }
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; } }
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); }
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); } }