private static void ReadRigidBodies(BinaryReader reader, RawMMDModel model, PmxConfig pmxConfig) { var rigidBodyNum = reader.ReadInt32(); model.Rigidbodies = new MMDRigidBody[rigidBodyNum]; for (var i = 0; i < rigidBodyNum; ++i) { var rigidBody = new MMDRigidBody { Name = MMDReaderUtil.ReadSizedString(reader, pmxConfig.Encoding), NameEn = MMDReaderUtil.ReadSizedString(reader, pmxConfig.Encoding), AssociatedBoneIndex = MMDReaderUtil.ReadIndex(reader, pmxConfig.BoneIndexSize), CollisionGroup = reader.ReadByte(), CollisionMask = reader.ReadUInt16(), Shape = (MMDRigidBody.RigidBodyShape)reader.ReadByte(), Dimemsions = MMDReaderUtil.ReadRawCoordinateVector3(reader), Position = MMDReaderUtil.ReadVector3(reader), Rotation = MMDReaderUtil.ReadAmpVector3(reader, Mathf.Rad2Deg), Mass = reader.ReadSingle(), TranslateDamp = reader.ReadSingle(), RotateDamp = reader.ReadSingle(), Restitution = reader.ReadSingle(), Friction = reader.ReadSingle(), Type = (MMDRigidBody.RigidBodyType)reader.ReadByte() }; model.Rigidbodies[i] = rigidBody; } }
private static void ReadModelNameAndDescription(BinaryReader reader, RawMMDModel model, PmxConfig pmxConfig) { model.Name = MMDReaderUtil.ReadSizedString(reader, pmxConfig.Encoding); model.NameEn = MMDReaderUtil.ReadSizedString(reader, pmxConfig.Encoding); model.Description = MMDReaderUtil.ReadSizedString(reader, pmxConfig.Encoding); model.DescriptionEn = MMDReaderUtil.ReadSizedString(reader, pmxConfig.Encoding); }
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 ReadVertices(BinaryReader reader, RawMMDModel model) { var vertexNum = reader.ReadInt32(); model.Vertices = new Vertex[vertexNum]; for (var i = 0; i < vertexNum; ++i) { var vertex = new Vertex { Coordinate = MMDReaderUtil.ReadVector3(reader), Normal = MMDReaderUtil.ReadVector3(reader), UvCoordinate = MMDReaderUtil.ReadVector2(reader) }; var skinningOperator = new SkinningOperator(); var bdef2 = new SkinningOperator.Bdef2(); bdef2.BoneId = new int[2]; bdef2.BoneId[0] = reader.ReadInt16(); bdef2.BoneId[1] = reader.ReadInt16(); bdef2.BoneWeight = reader.ReadSByte() * 0.01f; skinningOperator.Param = bdef2; skinningOperator.Type = SkinningOperator.SkinningType.SkinningBdef2; vertex.SkinningOperator = skinningOperator; var noEdge = reader.ReadByte() != 0; vertex.EdgeScale = noEdge ? 0.0f : 1.0f; model.Vertices[i] = vertex; } }
public override RawMMDModel Read(BinaryReader reader, ModelReadConfig config) { PmxMeta pmxHeader; try { pmxHeader = ReadMeta(reader); } catch { throw new MMDFileParseException("Could not read pmx meta data."); } if (!"PMX ".Equals(pmxHeader.Magic) || Math.Abs(pmxHeader.Version - 2.0f) > 0.0001f || pmxHeader.FileFlagSize != 8) { throw new MMDFileParseException("File is not a PMX 2.0 file"); } var model = new RawMMDModel(); var pmxConfig = ReadPmxConfig(reader, model); ReadModelNameAndDescription(reader, model, pmxConfig); ReadVertices(reader, model, pmxConfig); ReadTriangles(reader, model, pmxConfig); var textureList = ReadTextureList(reader, pmxConfig); ReadParts(reader, config, model, pmxConfig, textureList); ReadBones(reader, model, pmxConfig); ReadMorphs(reader, model, pmxConfig); ReadEntries(reader, pmxConfig); ReadRigidBodies(reader, model, pmxConfig); ReadJoints(reader, model, pmxConfig); model.Normalize(); return(model); }
private static void ReadVertices(BinaryReader reader, RawMMDModel model, PmxConfig pmxConfig) { var vertexNum = reader.ReadInt32(); model.Vertices = new Vertex[vertexNum]; for (uint i = 0; i < vertexNum; ++i) { var vertex = ReadVertex(reader, pmxConfig); model.Vertices[i] = vertex; } }
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 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; } }
private static void ReadTriangles(BinaryReader reader, RawMMDModel model) { var triangleIndexCount = reader.ReadInt32(); model.TriangleIndexes = new int[triangleIndexCount]; if (triangleIndexCount % 3 != 0) { throw new MMDFileParseException("triangle index count " + triangleIndexCount + " is not multiple of 3"); } for (var i = 0; i < triangleIndexCount; ++i) { model.TriangleIndexes[i] = reader.ReadUInt16(); } }
private static void ReadTriangles(BinaryReader reader, RawMMDModel model, PmxConfig pmxConfig) { var triangleIndexCount = reader.ReadInt32(); model.TriangleIndexes = new int[triangleIndexCount]; if (triangleIndexCount % 3 != 0) { throw new MMDFileParseException("triangle index count " + triangleIndexCount + " is not multiple of 3"); } for (var i = 0; i < triangleIndexCount; ++i) { model.TriangleIndexes[i] = MMDReaderUtil.ReadIndex(reader, pmxConfig.VertexIndexSize); } }
private void ReadFaces(BinaryReader reader, RawMMDModel model) { var faceNum = reader.ReadUInt16(); int?baseMorphIndex = null; model.Morphs = new Morph[faceNum]; for (var i = 0; i < faceNum; ++i) { var morph = new Morph(); var fp = ReadPmdFacePreamble(reader); morph.Name = fp.Name; morph.Category = (Morph.MorphCategory)fp.FaceType; if (morph.Category == Morph.MorphCategory.MorphCatSystem) { baseMorphIndex = i; } morph.Type = Morph.MorphType.MorphTypeVertex; morph.MorphDatas = new Morph.MorphData[fp.VertexNum]; for (var j = 0; j < fp.VertexNum; ++j) { var vertexMorphData = new Morph.VertexMorphData(); vertexMorphData.VertexIndex = reader.ReadInt32(); vertexMorphData.Offset = MMDReaderUtil.ReadVector3(reader); morph.MorphDatas[j] = vertexMorphData; } model.Morphs[i] = morph; } if (baseMorphIndex != null) { var baseMorph = model.Morphs[baseMorphIndex.Value]; for (var i = 0; i < faceNum; ++i) { if (i == baseMorphIndex) { continue; } var morph = model.Morphs[i]; for (var j = 0; j < morph.MorphDatas.Length; ++j) { var vertexMorphData = (Morph.VertexMorphData)morph.MorphDatas[j]; var morphDataVertexIndex = vertexMorphData.VertexIndex; vertexMorphData.VertexIndex = ((Morph.VertexMorphData)baseMorph.MorphDatas[morphDataVertexIndex]) .VertexIndex; } } } }
private static PmxConfig ReadPmxConfig(BinaryReader reader, RawMMDModel model) { var pmxConfig = new PmxConfig(); pmxConfig.Utf8Encoding = reader.ReadByte() != 0; pmxConfig.ExtraUvNumber = reader.ReadSByte(); pmxConfig.VertexIndexSize = reader.ReadSByte(); pmxConfig.TextureIndexSize = reader.ReadSByte(); pmxConfig.MaterialIndexSize = reader.ReadSByte(); pmxConfig.BoneIndexSize = reader.ReadSByte(); pmxConfig.MorphIndexSize = reader.ReadSByte(); pmxConfig.RigidBodyIndexSize = reader.ReadSByte(); model.ExtraUvNumber = pmxConfig.ExtraUvNumber; pmxConfig.Encoding = pmxConfig.Utf8Encoding ? Encoding.UTF8 : Encoding.Unicode; return(pmxConfig); }
private static void ReadConstraints(BinaryReader reader, RawMMDModel model) { var constraintNum = reader.ReadUInt32(); model.Joints = new Model.Joint[constraintNum]; for (var i = 0; i < constraintNum; ++i) { var constraint = new Model.Joint(); constraint.Name = MMDReaderUtil.ReadStringFixedLength(reader, 20, Tools.JapaneseEncoding); constraint.AssociatedRigidBodyIndex[0] = reader.ReadInt32(); constraint.AssociatedRigidBodyIndex[1] = reader.ReadInt32(); constraint.Position = MMDReaderUtil.ReadVector3(reader); constraint.Rotation = MMDReaderUtil.ReadAmpVector3(reader, Mathf.Rad2Deg); constraint.PositionLowLimit = MMDReaderUtil.ReadVector3(reader); constraint.PositionHiLimit = MMDReaderUtil.ReadVector3(reader); constraint.RotationLowLimit = MMDReaderUtil.ReadVector3(reader); constraint.RotationHiLimit = MMDReaderUtil.ReadVector3(reader); constraint.SpringTranslate = MMDReaderUtil.ReadVector3(reader); constraint.SpringRotate = MMDReaderUtil.ReadVector3(reader); model.Joints[i] = constraint; } }
private static void ReadParts(BinaryReader reader, ModelReadConfig config, RawMMDModel model, PmxConfig pmxConfig, MMDTexture[] textureList) { var partNum = reader.ReadInt32(); var partBaseShift = 0; model.Parts = new Part[partNum]; for (var i = 0; i < partNum; i++) { var part = new Part(); var material = ReadMaterial(reader, config, pmxConfig.Encoding, pmxConfig.TextureIndexSize, textureList); part.Material = material; var partTriangleIndexNum = reader.ReadInt32(); if (partTriangleIndexNum % 3 != 0) { throw new MMDFileParseException("part" + i + " triangle index count " + partTriangleIndexNum + " is not multiple of 3"); } part.BaseShift = partBaseShift; part.TriangleIndexNum = partTriangleIndexNum; partBaseShift += partTriangleIndexNum; model.Parts[i] = part; } }
private static void ReadJoints(BinaryReader reader, RawMMDModel model, PmxConfig pmxConfig) { var constraintNum = reader.ReadInt32(); model.Joints = new Model.Joint[constraintNum]; for (var i = 0; i < constraintNum; ++i) { var joint = new Model.Joint { Name = MMDReaderUtil.ReadSizedString(reader, pmxConfig.Encoding), NameEn = MMDReaderUtil.ReadSizedString(reader, pmxConfig.Encoding) }; var dofType = reader.ReadByte(); if (dofType == 0) { joint.AssociatedRigidBodyIndex[0] = MMDReaderUtil.ReadIndex(reader, pmxConfig.RigidBodyIndexSize); joint.AssociatedRigidBodyIndex[1] = MMDReaderUtil.ReadIndex(reader, pmxConfig.RigidBodyIndexSize); joint.Position = MMDReaderUtil.ReadVector3(reader); joint.Rotation = MMDReaderUtil.ReadAmpVector3(reader, Mathf.Rad2Deg); joint.PositionLowLimit = MMDReaderUtil.ReadVector3(reader); joint.PositionHiLimit = MMDReaderUtil.ReadVector3(reader); joint.RotationLowLimit = MMDReaderUtil.ReadVector3(reader); joint.RotationHiLimit = MMDReaderUtil.ReadVector3(reader); joint.SpringTranslate = MMDReaderUtil.ReadVector3(reader); joint.SpringRotate = MMDReaderUtil.ReadVector3(reader); } else { throw new MMDFileParseException("Only 6DOF spring joints are supported."); } model.Joints[i] = joint; } }
public UnityEngine.Material[] LoadModelMaterials(MaterialLoader materialLoader, MMDUnityConfig config, RawMMDModel model) { var ret = new UnityEngine.Material[model.Parts.Length]; for (var i = 0; i < model.Parts.Length; i++) { ret[i] = materialLoader.LoadMaterial(model.Parts[i].Material, config); ret[i].name = model.Parts[i].Material.Name; } return(ret); }
private static void ReadDescription(BinaryReader reader, RawMMDModel model) { model.Name = MMDReaderUtil.ReadStringFixedLength(reader, 20, Tools.JapaneseEncoding); model.Description = MMDReaderUtil.ReadStringFixedLength(reader, 256, Tools.JapaneseEncoding); }
private static void ReadMorphs(BinaryReader reader, RawMMDModel model, PmxConfig pmxConfig) { var morphNum = reader.ReadInt32(); int?baseMorphIndex = null; model.Morphs = new Morph[morphNum]; for (var i = 0; i < morphNum; ++i) { var morph = new Morph { Name = MMDReaderUtil.ReadSizedString(reader, pmxConfig.Encoding), NameEn = MMDReaderUtil.ReadSizedString(reader, pmxConfig.Encoding), Category = (Morph.MorphCategory)reader.ReadByte() }; if (morph.Category == Morph.MorphCategory.MorphCatSystem) { baseMorphIndex = i; } morph.Type = (Morph.MorphType)reader.ReadByte(); var morphDataNum = reader.ReadInt32(); morph.MorphDatas = new Morph.MorphData[morphDataNum]; switch (morph.Type) { case Morph.MorphType.MorphTypeGroup: for (var j = 0; j < morphDataNum; ++j) { var morphData = new Morph.GroupMorphData { MorphIndex = MMDReaderUtil.ReadIndex(reader, pmxConfig.MorphIndexSize), MorphRate = reader.ReadSingle() }; morph.MorphDatas[j] = morphData; } break; case Morph.MorphType.MorphTypeVertex: for (var j = 0; j < morphDataNum; ++j) { var morphData = new Morph.VertexMorphData { VertexIndex = MMDReaderUtil.ReadIndex(reader, pmxConfig.VertexIndexSize), Offset = MMDReaderUtil.ReadVector3(reader) }; morph.MorphDatas[j] = morphData; } break; case Morph.MorphType.MorphTypeBone: for (var j = 0; j < morphDataNum; ++j) { var morphData = new Morph.BoneMorphData { BoneIndex = MMDReaderUtil.ReadIndex(reader, pmxConfig.BoneIndexSize), Translation = MMDReaderUtil.ReadVector3(reader), Rotation = MMDReaderUtil.ReadQuaternion(reader) }; morph.MorphDatas[j] = morphData; } break; case Morph.MorphType.MorphTypeUv: case Morph.MorphType.MorphTypeExtUv1: case Morph.MorphType.MorphTypeExtUv2: case Morph.MorphType.MorphTypeExtUv3: case Morph.MorphType.MorphTypeExtUv4: for (var j = 0; j < morphDataNum; ++j) { var morphData = new Morph.UvMorphData { VertexIndex = MMDReaderUtil.ReadIndex(reader, pmxConfig.VertexIndexSize), Offset = MMDReaderUtil.ReadVector4(reader) }; morph.MorphDatas[j] = morphData; } break; case Morph.MorphType.MorphTypeMaterial: for (var j = 0; j < morphDataNum; j++) { var morphData = new Morph.MaterialMorphData(); var mmIndex = MMDReaderUtil.ReadIndex(reader, pmxConfig.MaterialIndexSize); if (mmIndex < model.Parts.Length && mmIndex > 0) //TODO mmdlib的代码里是和bone数比较。确认这个逻辑 { morphData.MaterialIndex = mmIndex; morphData.Global = false; } else { morphData.MaterialIndex = 0; morphData.Global = true; } morphData.Method = (Morph.MaterialMorphData.MaterialMorphMethod)reader.ReadByte(); morphData.Diffuse = MMDReaderUtil.ReadColor(reader, true); morphData.Specular = MMDReaderUtil.ReadColor(reader, false); morphData.Shiness = reader.ReadSingle(); morphData.Ambient = MMDReaderUtil.ReadColor(reader, false); morphData.EdgeColor = MMDReaderUtil.ReadColor(reader, true); morphData.EdgeSize = reader.ReadSingle(); morphData.Texture = MMDReaderUtil.ReadVector4(reader); morphData.SubTexture = MMDReaderUtil.ReadVector4(reader); morphData.ToonTexture = MMDReaderUtil.ReadVector4(reader); morph.MorphDatas[j] = morphData; } break; default: throw new MMDFileParseException("invalid morph type " + morph.Type); } if (baseMorphIndex != null) { //TODO rectify system-reserved category } model.Morphs[i] = morph; } }
private static void ReadParts(BinaryReader reader, RawMMDModel model, List <int> tooTextureIds) { var partNum = reader.ReadInt32(); var partBaseShift = 0; model.Parts = new Part[partNum]; for (var i = 0; i < partNum; ++i) { var material = new MMDMaterial(); material.DiffuseColor = MMDReaderUtil.ReadColor(reader, true); material.Shiness = reader.ReadSingle(); material.SpecularColor = MMDReaderUtil.ReadColor(reader, false); material.AmbientColor = MMDReaderUtil.ReadColor(reader, false); var toonId = reader.ReadByte(); var edgeFlag = reader.ReadSByte(); var vertexNum = reader.ReadInt32(); var textureName = MMDReaderUtil.ReadStringFixedLength(reader, 20, Tools.JapaneseEncoding); material.DrawDoubleFace = material.DiffuseColor.a < 0.9999f; material.DrawGroundShadow = edgeFlag != 0; material.CastSelfShadow = true; material.DrawSelfShadow = true; material.DrawEdge = edgeFlag != 0; material.EdgeColor = Color.black; if (!string.IsNullOrEmpty(textureName)) { var dlmPos = textureName.IndexOf("*", StringComparison.Ordinal); if (dlmPos >= 0) { var texPath = textureName.Substring(0, dlmPos); var sphPath = textureName.Substring(dlmPos + 1); if (!string.IsNullOrEmpty(texPath)) { material.Texture = new MMDTexture(texPath); } if (!string.IsNullOrEmpty(sphPath)) { material.SubTexture = new MMDTexture(sphPath); } if (sphPath.EndsWith("a") || sphPath.EndsWith("A")) { material.SubTextureType = MMDMaterial.SubTextureTypeEnum.MatSubTexSpa; } else { material.SubTextureType = MMDMaterial.SubTextureTypeEnum.MatSubTexSph; } } else { var extDlmPos = textureName.LastIndexOf(".", StringComparison.Ordinal); if (extDlmPos >= 0) { var ext = textureName.Substring(extDlmPos + 1); ext = ext.ToLower(); if (!ext.Equals("sph") && !ext.Equals("spa")) { material.Texture = new MMDTexture(textureName); } else { material.SubTexture = new MMDTexture(textureName); ; if (ext.EndsWith("a")) { material.SubTextureType = MMDMaterial.SubTextureTypeEnum.MatSubTexSpa; } else { material.SubTextureType = MMDMaterial.SubTextureTypeEnum.MatSubTexSph; } } } else { material.Texture = new MMDTexture(textureName); } } } var part = new Part(); part.Material = material; tooTextureIds.Add(toonId); part.BaseShift = partBaseShift; part.TriangleIndexNum = vertexNum; partBaseShift += vertexNum; model.Parts[i] = part; } }
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; }
private static void ReadBones(BinaryReader reader, RawMMDModel model, PmxConfig pmxConfig) { var boneNum = reader.ReadInt32(); model.Bones = new Bone[boneNum]; for (var i = 0; i < boneNum; ++i) { var bone = new Bone { Name = MMDReaderUtil.ReadSizedString(reader, pmxConfig.Encoding), NameEn = MMDReaderUtil.ReadSizedString(reader, pmxConfig.Encoding), Position = MMDReaderUtil.ReadVector3(reader) }; var parentIndex = MMDReaderUtil.ReadIndex(reader, pmxConfig.BoneIndexSize); if (parentIndex < boneNum && parentIndex >= 0) { bone.ParentIndex = parentIndex; } else { bone.ParentIndex = -1; } bone.TransformLevel = reader.ReadInt32(); var flag = reader.ReadUInt16(); bone.ChildBoneVal.ChildUseId = (flag & PmxBoneFlags.PmxBoneChildUseId) != 0; bone.Rotatable = (flag & PmxBoneFlags.PmxBoneRotatable) != 0; bone.Movable = (flag & PmxBoneFlags.PmxBoneMovable) != 0; bone.Visible = (flag & PmxBoneFlags.PmxBoneVisible) != 0; bone.Controllable = (flag & PmxBoneFlags.PmxBoneControllable) != 0; bone.HasIk = (flag & PmxBoneFlags.PmxBoneHasIk) != 0; bone.AppendRotate = (flag & PmxBoneFlags.PmxBoneAcquireRotate) != 0; bone.AppendTranslate = (flag & PmxBoneFlags.PmxBoneAcquireTranslate) != 0; bone.RotAxisFixed = (flag & PmxBoneFlags.PmxBoneRotAxisFixed) != 0; bone.UseLocalAxis = (flag & PmxBoneFlags.PmxBoneUseLocalAxis) != 0; bone.PostPhysics = (flag & PmxBoneFlags.PmxBonePostPhysics) != 0; bone.ReceiveTransform = (flag & PmxBoneFlags.PmxBoneReceiveTransform) != 0; if (bone.ChildBoneVal.ChildUseId) { bone.ChildBoneVal.Index = MMDReaderUtil.ReadIndex(reader, pmxConfig.BoneIndexSize); } else { bone.ChildBoneVal.Offset = MMDReaderUtil.ReadVector3(reader); } if (bone.RotAxisFixed) { bone.RotAxis = MMDReaderUtil.ReadVector3(reader); } if (bone.AppendRotate || bone.AppendTranslate) { bone.AppendBoneVal.Index = MMDReaderUtil.ReadIndex(reader, pmxConfig.BoneIndexSize); bone.AppendBoneVal.Ratio = reader.ReadSingle(); } if (bone.UseLocalAxis) { var localX = MMDReaderUtil.ReadVector3(reader); var localZ = MMDReaderUtil.ReadVector3(reader); var localY = Vector3.Cross(localX, localZ); localZ = Vector3.Cross(localX, localY); localX.Normalize(); localY.Normalize(); localZ.Normalize(); bone.LocalAxisVal.AxisX = localX; bone.LocalAxisVal.AxisY = localY; bone.LocalAxisVal.AxisZ = localZ; } if (bone.ReceiveTransform) { bone.ExportKey = reader.ReadInt32(); } if (bone.HasIk) { ReadBoneIk(reader, bone, pmxConfig.BoneIndexSize); } model.Bones[i] = bone; } }
private static void ReadCustomTextures(BinaryReader reader, ModelReadConfig config, RawMMDModel model, List <int> toonTextureIds) { var customTextures = new MMDTexture[10]; for (var i = 0; i < 10; ++i) { customTextures[i] = new MMDTexture(MMDReaderUtil.ReadStringFixedLength(reader, 100, Tools.JapaneseEncoding)); } for (var i = 0; i < model.Parts.Length; ++i) { var material = model.Parts[i].Material; if (toonTextureIds[i] < 10) { material.Toon = customTextures[toonTextureIds[i]]; } else { material.Toon = MMDTextureUtil.GetGlobalToon(0, config.GlobalToonPath); } } }