private static void ReadInfoEn(BinaryReader reader, RawMMDModel model, PmdReadContext context) { var hasInfoEn = reader.ReadSByte() == 1; if (!hasInfoEn) { return; } model.NameEn = MMDReaderUtil.ReadStringFixedLength(reader, 20, Tools.JapaneseEncoding); model.DescriptionEn = MMDReaderUtil.ReadStringFixedLength(reader, 256, Tools.JapaneseEncoding); for (var i = 0; i < context.BoneNum; ++i) { var bone = model.Bones[i]; bone.NameEn = MMDReaderUtil.ReadStringFixedLength(reader, 20, Tools.JapaneseEncoding); } if (model.Morphs.Length > 0) { model.Morphs[0].NameEn = model.Morphs[0].Name; } for (var i = 1; i < model.Morphs.Length; ++i) { var morph = model.Morphs[i]; morph.NameEn = MMDReaderUtil.ReadStringFixedLength(reader, 20, Tools.JapaneseEncoding); } // UNDONE for (var i = 0; i < context.BoneNameListNum; ++i) { MMDReaderUtil.ReadStringFixedLength(reader, 50, Tools.JapaneseEncoding); } }
private static void ReadBoneNameList(BinaryReader reader, PmdReadContext context) { int boneNameListNum = reader.ReadSByte(); context.BoneNameListNum = boneNameListNum; for (var i = 0; i < boneNameListNum; ++i) { MMDReaderUtil.ReadStringFixedLength(reader, 50, Tools.JapaneseEncoding); } }
private static void ReadRigidBodies(BinaryReader reader, RawMMDModel model, PmdReadContext context) { var rigidBodyNum = reader.ReadInt32(); model.Rigidbodies = new MMDRigidBody[rigidBodyNum]; for (var i = 0; i < rigidBodyNum; ++i) { var rigidBody = new MMDRigidBody(); rigidBody.Name = MMDReaderUtil.ReadStringFixedLength(reader, 20, Tools.JapaneseEncoding).Trim(); var boneIndex = reader.ReadUInt16(); if (boneIndex < context.BoneNum) { rigidBody.AssociatedBoneIndex = boneIndex; } else { if (context.CenterBoneIndex == null) { rigidBody.AssociatedBoneIndex = 0; } else { rigidBody.AssociatedBoneIndex = context.CenterBoneIndex.Value; } } rigidBody.CollisionGroup = reader.ReadSByte(); rigidBody.CollisionMask = reader.ReadUInt16(); rigidBody.Shape = (MMDRigidBody.RigidBodyShape)reader.ReadByte(); rigidBody.Dimemsions = MMDReaderUtil.ReadVector3(reader); var rbPosition = MMDReaderUtil.ReadVector3(reader); rigidBody.Position = model.Bones[rigidBody.AssociatedBoneIndex].Position + rbPosition; rigidBody.Rotation = MMDReaderUtil.ReadVector3(reader); rigidBody.Mass = reader.ReadSingle(); rigidBody.TranslateDamp = reader.ReadSingle(); rigidBody.RotateDamp = reader.ReadSingle(); rigidBody.Restitution = reader.ReadSingle(); rigidBody.Friction = reader.ReadSingle(); var type = reader.ReadByte(); if (boneIndex < context.BoneNum) { rigidBody.Type = (MMDRigidBody.RigidBodyType)type; } else { rigidBody.Type = MMDRigidBody.RigidBodyType.RigidTypePhysicsGhost; } model.Rigidbodies[i] = rigidBody; } }
public override RawMMDModel Read(BinaryReader reader, ModelReadConfig config) { var model = new RawMMDModel(); var context = new PmdReadContext(); var meta = ReadMeta(reader); if (!"Pmd".Equals(meta.Magic) || Math.Abs(meta.Version - 1.0f) > 0.0001f) { throw new MMDFileParseException("File is not a PMD 1.0 file"); } ReadDescription(reader, model); ReadVertices(reader, model); ReadTriangles(reader, model); var toonTextureIds = new List <int>(); ReadParts(reader, model, toonTextureIds); ReadBonesAndIks(reader, model, context); ReadFaces(reader, model); ReadFacdDisplayListNames(reader); ReadBoneNameList(reader, context); ReadBoneDisp(reader); if (MMDReaderUtil.Eof(reader)) { goto PMD_READER_READ_LEGACY_30; } ReadInfoEn(reader, model, context); if (MMDReaderUtil.Eof(reader)) { goto PMD_READER_READ_LEGACY_30; } ReadCustomTextures(reader, config, model, toonTextureIds); if (MMDReaderUtil.Eof(reader)) { goto PMD_READER_READ_LEGACY_50; } ReadRigidBodies(reader, model, context); ReadConstraints(reader, model); goto PMD_READER_READ_SUCCEED; PMD_READER_READ_LEGACY_30: for (var i = 0; i < model.Parts.Length; ++i) { var material = model.Parts[i].Material; material.Toon = MMDTextureUtil.GetGlobalToon(toonTextureIds[i], config.GlobalToonPath); } PMD_READER_READ_LEGACY_50: PMD_READER_READ_SUCCEED: model.Normalize(); return(model); }
private void ReadBonesAndIks(BinaryReader reader, RawMMDModel model, PmdReadContext context) { int boneNum = reader.ReadUInt16(); context.BoneNum = boneNum; var rawBones = new PmdBone[boneNum]; for (var i = 0; i < boneNum; ++i) { rawBones[i] = ReadPmdBone(reader); } var ikBoneIds = new HashSet <int>(); int ikNum = reader.ReadUInt16(); var rawIkList = new List <PmdRawIk>(ikNum); for (var i = 0; i < ikNum; ++i) { var rawIk = new PmdRawIk(); rawIk.Preamble = ReadPmdIkPreamable(reader); ikBoneIds.Add(rawIk.Preamble.IkBoneIndex); rawIk.Chain = new int[rawIk.Preamble.IkChainLength]; for (var j = 0; j < rawIk.Preamble.IkChainLength; ++j) { rawIk.Chain[j] = reader.ReadUInt16(); } rawIkList.Add(rawIk); } rawIkList.Sort((ik1, ik2) => { var a1 = 0; var a2 = 0; if (ik1.Chain.Length > 0) { a1 = ik1.Chain[0]; } if (ik2.Chain.Length > 0) { a2 = ik2.Chain[0]; } return(a1.CompareTo(a2)); }); var boneList = new List <Bone>(); int?centerBoneIndex = null; model.Bones = new Bone[boneNum]; for (var i = 0; i < boneNum; ++i) { var bone = new Bone(); boneList.Add(bone); var rawBone = rawBones[i]; bone.Name = rawBone.Name; if ("\u30BB\u30F3\u30BF\u30FC".Equals(bone.Name)) //TODO 验证是不是这个值 { centerBoneIndex = i; } bone.Position = rawBone.Position; // TODO - workaround here, need fix, see [1]. if (i != rawBone.ParentId) { bone.ParentIndex = rawBone.ParentId; } else { bone.ParentIndex = 0; //TODO mmdlib里是nil } bone.TransformLevel = 0; bone.ChildBoneVal.ChildUseId = true; bone.ChildBoneVal.Index = rawBone.ChildId; bone.Rotatable = true; var type = (PmdBoneTypes)rawBone.Type; bone.HasIk = type == PmdBoneTypes.PmdBoneIk || ikBoneIds.Contains(i); bone.Movable = type == PmdBoneTypes.PmdBoneRotateAndTranslate || bone.HasIk; bone.Visible = type != PmdBoneTypes.PmdBoneIkTo && type != PmdBoneTypes.PmdBoneInvisible && type != PmdBoneTypes.PmdBoneRotateRatio; bone.Controllable = true; bone.AppendRotate = type == PmdBoneTypes.PmdBoneRotateEffect || type == PmdBoneTypes.PmdBoneRotateRatio; bone.AppendTranslate = false; bone.RotAxisFixed = type == PmdBoneTypes.PmdBoneTwist; bone.UseLocalAxis = false; bone.PostPhysics = false; bone.ReceiveTransform = false; if (bone.AppendRotate) { if (type == PmdBoneTypes.PmdBoneRotateEffect) { bone.AppendBoneVal.Index = rawBone.IkNumber; bone.AppendBoneVal.Ratio = 1.0f; bone.TransformLevel = 2; } else { bone.ChildBoneVal.ChildUseId = false; bone.ChildBoneVal.Offset = Vector3.zero; bone.AppendBoneVal.Index = rawBone.ChildId; bone.AppendBoneVal.Ratio = rawBone.IkNumber * 0.01f; } } if (bone.HasIk) { bone.TransformLevel = 1; } if (bone.RotAxisFixed) { var childId = rawBone.ChildId; if (childId > boneNum) { childId = 0; } bone.RotAxis = (rawBones[childId].Position - bone.Position).normalized; if (bone.ChildBoneVal.ChildUseId) { bone.ChildBoneVal.ChildUseId = false; bone.ChildBoneVal.Offset = Vector3.zero; } } model.Bones[i] = bone; } var loLimit = Vector3.zero; var hiLimit = Vector3.zero; loLimit.x = (float)-Math.PI; hiLimit.x = (float)(-0.5f / 180.0f * Math.PI); for (var i = 0; i < boneNum; ++i) { if (!ikBoneIds.Contains(i)) { boneList[i].IkInfoVal = new Bone.IkInfo { IkLinks = new Bone.IkLink[0] }; continue; } var associatedIkCount = 0; for (var j = 0; j < ikNum; ++j) { var rawIk = rawIkList[j]; if (i != rawIk.Preamble.IkBoneIndex) { continue; } Bone bone; if (associatedIkCount == 0) { bone = boneList[i]; } else { var originalBone = boneList[i]; bone = Bone.CopyOf(originalBone); boneList.Add(bone); bone.Name = "[IK]" + originalBone.Name; bone.NameEn = "[IK]" + originalBone.NameEn; bone.ParentIndex = i; bone.ChildBoneVal.ChildUseId = false; bone.ChildBoneVal.Offset = Vector3.zero; bone.Visible = false; bone.IkInfoVal.IkLinks = new Bone.IkLink[rawIk.Preamble.IkChainLength]; bone.HasIk = true; } bone.IkInfoVal = new Bone.IkInfo(); bone.IkInfoVal.IkTargetIndex = rawIk.Preamble.IkTargetBoneIndex; bone.IkInfoVal.CcdIterateLimit = rawIk.Preamble.CcdIterateLimit; bone.IkInfoVal.CcdAngleLimit = rawIk.Preamble.CcdAngleLimit; bone.IkInfoVal.IkLinks = new Bone.IkLink[rawIk.Preamble.IkChainLength]; for (var k = 0; k < rawIk.Preamble.IkChainLength; ++k) { var link = new Bone.IkLink(); link.LinkIndex = rawIk.Chain[k]; var linkName = model.Bones[link.LinkIndex].Name; if ("\u5DE6\u3072\u3056".Equals(linkName) || "\u53F3\u3072\u3056".Equals(linkName)) { link.HasLimit = true; link.LoLimit = loLimit; link.HiLimit = hiLimit; } else { link.HasLimit = false; } bone.IkInfoVal.IkLinks[k] = link; } associatedIkCount++; } } model.Bones = boneList.ToArray(); // TODO - need verification for (var i = 0; i < boneNum; ++i) { var stable = true; for (var j = 0; j < boneNum; ++j) { var bone = model.Bones[j]; var transformLevel = bone.TransformLevel; var parentId = bone.ParentIndex; while (parentId < boneNum) { var parentTransformLevel = model.Bones[parentId].TransformLevel; if (transformLevel < parentTransformLevel) { transformLevel = parentTransformLevel; stable = false; } parentId = model.Bones[parentId].ParentIndex; } bone.TransformLevel = transformLevel; } if (stable) { break; } } context.CenterBoneIndex = centerBoneIndex; }