private void WritePmxJoint([NotNull] PmxJoint joint) { WriteString(joint.Name); WriteString(joint.NameEnglish); _writer.Write((byte)joint.Kind); _writer.WriteInt32AsVarLenInt(joint.BodyIndex1, RigidBodyElementSize); _writer.WriteInt32AsVarLenInt(joint.BodyIndex2, RigidBodyElementSize); _writer.Write(joint.Position); _writer.Write(joint.Rotation); _writer.Write(joint.LowerTranslationLimit); _writer.Write(joint.UpperTranslationLimit); _writer.Write(joint.LowerRotationLimit); _writer.Write(joint.UpperRotationLimit); _writer.Write(joint.TranslationSpringConstants); _writer.Write(joint.RotationSpringConstants); }
private PmxJoint ReadPmxJoint() { var joint = new PmxJoint(); joint.Name = ReadString() ?? string.Empty; joint.NameEnglish = ReadString() ?? string.Empty; joint.Kind = (JointKind)_reader.ReadByte(); joint.BodyIndex1 = _reader.ReadVarLenIntAsInt32(RigidBodyElementSize); joint.BodyIndex2 = _reader.ReadVarLenIntAsInt32(RigidBodyElementSize); joint.Position = _reader.ReadVector3(); joint.Rotation = _reader.ReadVector3(); joint.LowerTranslationLimit = _reader.ReadVector3(); joint.UpperTranslationLimit = _reader.ReadVector3(); joint.LowerRotationLimit = _reader.ReadVector3(); joint.UpperRotationLimit = _reader.ReadVector3(); joint.TranslationSpringConstants = _reader.ReadVector3(); joint.RotationSpringConstants = _reader.ReadVector3(); return(joint); }
private PmxJoint ReadPmxJoint() { var joint = new PmxJoint(); joint.Name = ReadString() ?? string.Empty; joint.NameEnglish = ReadString() ?? string.Empty; joint.Kind = (JointKind)_reader.ReadByte(); joint.BodyIndex1 = _reader.ReadVarLenIntAsInt32(RigidBodyElementSize); joint.BodyIndex2 = _reader.ReadVarLenIntAsInt32(RigidBodyElementSize); joint.Position = _reader.ReadVector3(); joint.RotationAngles = _reader.ReadVector3(); joint.LimitMoveLower = _reader.ReadVector3(); joint.LimitMoveUpper = _reader.ReadVector3(); joint.LimitAngleLower = _reader.ReadVector3(); joint.LimitAngleUpper = _reader.ReadVector3(); joint.SpConst_Move = _reader.ReadVector3(); joint.SpConst_Rotate = _reader.ReadVector3(); return(joint); }
private void AppendJoints([NotNull, ItemNotNull] PmxBone[] bones, [NotNull, ItemNotNull] List <PmxRigidBody> bodies, [NotNull, ItemNotNull] List <PmxJoint> joints) { foreach (var body in bodies) { var addJoint = false; switch (body.Part) { case CoordSystemPart.Torso: case CoordSystemPart.LeftArm: case CoordSystemPart.RightArm: case CoordSystemPart.Legs: case CoordSystemPart.Head: break; case CoordSystemPart.Skirt: case CoordSystemPart.Hair: case CoordSystemPart.Breasts: addJoint = true; break; case CoordSystemPart.Accessories: break; default: throw new ArgumentOutOfRangeException(); } if (!addJoint) { continue; } var pmxBone = bones[body.BoneIndex]; var parentBone = bones[pmxBone.ParentIndex]; var parentBody = bodies.Find(bo => bo.BoneIndex == parentBone.BoneIndex); // This rigid body is attached to a semi-root bone. Create it as a new "root" for its sub rigid bodies. if (parentBody == null) { switch (body.Part) { case CoordSystemPart.Skirt: var koshi = _pmxCreator._boneLookup.GetPmxBoneName("MODEL_00/BASE/KOSHI"); parentBody = bodies.Find(bo => bones[bo.BoneIndex].Name == koshi); break; case CoordSystemPart.Hair: { var l = bodies.FindAll(bo => bones[bo.BoneIndex].Name == "ATAMA"); // The first one is the one on body (which is larger). // The second one is what should be applied to the hair. parentBody = l.Count >= 2 ? l[1] : null; break; } case CoordSystemPart.Breasts: var mune2 = _pmxCreator._boneLookup.GetPmxBoneName("MODEL_00/BASE/MUNE1/MUNE2"); parentBody = bodies.Find(bo => bones[bo.BoneIndex].Name == mune2); break; default: throw new ArgumentOutOfRangeException(); } } // Now calculate rotation for this joint. var childBones = bones.WhereToArray(b => b.ParentIndex == pmxBone.BoneIndex); // Some models may have more than one child bone in the hair chain, e.g. ex001_003mik foreach (var childBone in childBones) { var joint = new PmxJoint(); joint.BodyIndex1 = bodies.IndexOf(parentBody); joint.BodyIndex2 = bodies.IndexOf(body); joint.Name = body.Name; joint.NameEnglish = body.NameEnglish; switch (body.Part) { case CoordSystemPart.Hair: case CoordSystemPart.Skirt: joint.Kind = JointKind.Spring6Dof; break; default: joint.Kind = JointKind.Spring6Dof; break; } joint.Position = pmxBone.InitialPosition; PmxBone rotBone1, rotBone2; if (childBones.Length == 0) { rotBone1 = parentBone; rotBone2 = pmxBone; } else { rotBone1 = pmxBone; rotBone2 = childBone; } Debug.Assert(rotBone2 != null, nameof(rotBone2) + " != null"); var delta = rotBone2.InitialPosition - rotBone1.InitialPosition; var qy = (float)Math.Atan2(delta.X, delta.Z); var qx = (float)Math.Atan2(delta.Y, delta.Z); const float qz = 0; joint.Rotation = new Vector3(qx, qy, qz); joints.Add(joint); } } }
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 static void AppendJoints([NotNull, ItemNotNull] IReadOnlyList <PmxBone> bones, [NotNull, ItemNotNull] List <PmxRigidBody> bodies, [NotNull, ItemNotNull] List <PmxJoint> joints) { foreach (var body in bodies) { var addJoint = false; switch (body.Part) { case CoordSystemPart.Torso: case CoordSystemPart.LeftArm: case CoordSystemPart.RightArm: case CoordSystemPart.Legs: case CoordSystemPart.Head: break; case CoordSystemPart.Skirt: case CoordSystemPart.Hair: case CoordSystemPart.Breasts: addJoint = true; break; case CoordSystemPart.Accessories: break; default: throw new ArgumentOutOfRangeException(); } if (!addJoint) { continue; } var pmxBone = bones[body.BoneIndex]; var parentBone = bones[pmxBone.ParentIndex]; var parentBody = bodies.Find(bo => bo.BoneIndex == parentBone.BoneIndex); // This rigid body is attached to a semi-root bone. Create it as a new "root" for its sub rigid bodies. if (parentBody == null) { switch (body.Part) { case CoordSystemPart.Skirt: var koshi = BoneUtils.GetPmxBoneName("MODEL_00/BASE/KOSHI"); parentBody = bodies.FirstOrDefault(bo => bones[bo.BoneIndex].Name == koshi); break; case CoordSystemPart.Hair: // The first one is the one on body (which is larger). // The second one is what should be applied to the hair. parentBody = bodies.Where(bo => bones[bo.BoneIndex].Name == "ATAMA").Skip(1).FirstOrDefault(); break; case CoordSystemPart.Breasts: var mune2 = BoneUtils.GetPmxBoneName("MODEL_00/BASE/MUNE1/MUNE2"); parentBody = bodies.FirstOrDefault(bo => bones[bo.BoneIndex].Name == mune2); break; default: throw new ArgumentOutOfRangeException(); } } var joint = new PmxJoint(); joint.BodyIndex1 = bodies.IndexOf(parentBody); joint.BodyIndex2 = bodies.IndexOf(body); joint.Name = body.Name; joint.NameEnglish = body.NameEnglish; switch (body.Part) { case CoordSystemPart.Hair: case CoordSystemPart.Skirt: joint.Kind = JointKind.Spring6Dof; break; default: joint.Kind = JointKind.Spring6Dof; break; } joint.Position = pmxBone.InitialPosition; // Now calculate rotation for this joint. var childBones = bones.Where(b => b.ParentIndex == pmxBone.BoneIndex).ToArray(); if (childBones.Length > 1) { Debug.Print("Warning: more than one child bone for joint rotation calculation. Aborting."); continue; } PmxBone rotBone1, rotBone2; if (childBones.Length == 0) { rotBone1 = parentBone; rotBone2 = pmxBone; } else { rotBone1 = pmxBone; rotBone2 = childBones[0]; } var delta = rotBone2.InitialPosition - rotBone1.InitialPosition; var qy = (float)Math.Atan2(delta.X, delta.Z); var qx = (float)Math.Atan2(delta.Y, delta.Z); //const float qx = 0; //var qz = (float)Math.Atan2(delta.X, delta.Y); const float qz = 0; joint.Rotation = new Vector3(qx, qy, qz); if (joint != null) { joints.Add(joint); } } }
// PMDEditor.Pmx internal static Pmx FromStream(Stream s, PmxElementFormat f = null) { var Ret = new Pmx(); var pmxHeader = new PmxHeader(2f); pmxHeader.FromStreamEx(s, null); Ret.Header = pmxHeader; if (pmxHeader.Ver <= 1f) { var mMD_Pmd = new MMD_Pmd(); s.Seek(0L, SeekOrigin.Begin); mMD_Pmd.FromStreamEx(s, null); Ret.FromPmx(PmxConvert.PmdToPmx(mMD_Pmd)); return(Ret); } Ret.ModelInfo = new PmxModelInfo(); Ret.ModelInfo.FromStreamEx(s, pmxHeader.ElementFormat); var num = PmxStreamHelper.ReadElement_Int32(s, 4, true); Ret.VertexList = new List <PmxVertex>(); Ret.VertexList.Clear(); Ret.VertexList.Capacity = num; for (var i = 0; i < num; i++) { var pmxVertex = new PmxVertex(); pmxVertex.FromStreamEx(s, pmxHeader.ElementFormat); Ret.VertexList.Add(pmxVertex); } num = PmxStreamHelper.ReadElement_Int32(s, 4, true); Ret.FaceList = new List <int>(); Ret.FaceList.Clear(); Ret.FaceList.Capacity = num; for (var j = 0; j < num; j++) { var item = PmxStreamHelper.ReadElement_Int32(s, pmxHeader.ElementFormat.VertexSize, false); Ret.FaceList.Add(item); } var pmxTextureTable = new PmxTextureTable(); pmxTextureTable.FromStreamEx(s, pmxHeader.ElementFormat); num = PmxStreamHelper.ReadElement_Int32(s, 4, true); Ret.MaterialList = new List <PmxMaterial>(); Ret.MaterialList.Clear(); Ret.MaterialList.Capacity = num; for (var k = 0; k < num; k++) { var pmxMaterial = new PmxMaterial(); pmxMaterial.FromStreamEx_TexTable(s, pmxTextureTable, pmxHeader.ElementFormat); Ret.MaterialList.Add(pmxMaterial); } num = PmxStreamHelper.ReadElement_Int32(s, 4, true); Ret.BoneList = new List <PmxBone>(); Ret.BoneList.Clear(); Ret.BoneList.Capacity = num; for (var l = 0; l < num; l++) { var pmxBone = new PmxBone(); pmxBone.FromStreamEx(s, pmxHeader.ElementFormat); Ret.BoneList.Add(pmxBone); } num = PmxStreamHelper.ReadElement_Int32(s, 4, true); Ret.MorphList = new List <PmxMorph>(); Ret.MorphList.Clear(); Ret.MorphList.Capacity = num; for (var m = 0; m < num; m++) { var pmxMorph = new PmxMorph(); pmxMorph.FromStreamEx(s, pmxHeader.ElementFormat); Ret.MorphList.Add(pmxMorph); } num = PmxStreamHelper.ReadElement_Int32(s, 4, true); Ret.NodeList = new List <PmxNode>(); Ret.NodeList.Clear(); Ret.NodeList.Capacity = num; for (var n = 0; n < num; n++) { var pmxNode = new PmxNode(); pmxNode.FromStreamEx(s, pmxHeader.ElementFormat); Ret.NodeList.Add(pmxNode); if (Ret.NodeList[n].SystemNode) { if (Ret.NodeList[n].Name == "Root") { Ret.RootNode = Ret.NodeList[n]; } else if (Ret.NodeList[n].Name == "表情") { Ret.ExpNode = Ret.NodeList[n]; } } } num = PmxStreamHelper.ReadElement_Int32(s, 4, true); Ret.BodyList = new List <PmxBody>(); Ret.BodyList.Clear(); Ret.BodyList.Capacity = num; for (var num2 = 0; num2 < num; num2++) { var pmxBody = new PmxBody(); pmxBody.FromStreamEx(s, pmxHeader.ElementFormat); Ret.BodyList.Add(pmxBody); } num = PmxStreamHelper.ReadElement_Int32(s, 4, true); Ret.JointList = new List <PmxJoint>(); Ret.JointList.Clear(); Ret.JointList.Capacity = num; for (var num3 = 0; num3 < num; num3++) { var pmxJoint = new PmxJoint(); pmxJoint.FromStreamEx(s, pmxHeader.ElementFormat); Ret.JointList.Add(pmxJoint); } return(Ret); }