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; } }
//unused data /// <summary> /// 作者写了一个没有用的标签 /// </summary> /// <param name="reader"></param> /// <param name="pmxConfig"></param> private static void ReadEntries(BinaryReader reader, PmxConfig pmxConfig) { //OYM:注意,这是个void方法...作者把所有的数据都丢了23333 var entryItemNum = reader.ReadInt32(); for (var i = 0; i < entryItemNum; ++i) { MmdReaderUtil.ReadSizedString(reader, pmxConfig.Encoding); //entryItemName MmdReaderUtil.ReadSizedString(reader, pmxConfig.Encoding); //entryItemNameEn reader.ReadByte(); //isSpecial var elementNum = reader.ReadInt32(); for (var j = 0; j < elementNum; ++j) { var isMorph = reader.ReadByte() == 1; if (isMorph) { MmdReaderUtil.ReadIndex(reader, pmxConfig.MorphIndexSize); //morphIndex } else { MmdReaderUtil.ReadIndex(reader, pmxConfig.BoneIndexSize); //boneIndex } } } }
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; } }
/// <summary> /// 一个读取顶点数目的方法 /// </summary> /// <param name="reader"></param> /// <param name="model"></param> /// <param name="pmxConfig"></param> private static void ReadVertices(BinaryReader reader, MmdModel model, PmxConfig pmxConfig) { //OYM:不啰嗦了 var vertexNum = reader.ReadInt32(); model.Vertices = new Vertex[vertexNum]; for (uint i = 0; i < vertexNum; ++i) { var vertex = ReadVertex(reader, pmxConfig); //OYM:对一个顶点进行数据提取 model.Vertices[i] = vertex; //OYM:赋值 } }
private static MMDTexture[] ReadTextureList(BinaryReader reader, PmxConfig pmxConfig) { var textureNum = reader.ReadInt32(); var textureList = new MMDTexture[textureNum]; for (var i = 0; i < textureNum; ++i) { var texturePathEncoding = pmxConfig.Utf8Encoding ? Encoding.UTF8 : Encoding.Unicode; var texturePath = MMDReaderUtil.ReadSizedString(reader, texturePathEncoding); textureList[i] = new MMDTexture(texturePath); } return(textureList); }
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); } }
/// <summary> /// 读取三角形数目 /// </summary> /// <param name="reader"></param> /// <param name="model"></param> /// <param name="pmxConfig"></param> private static void ReadTriangles(BinaryReader reader, MmdModel model, PmxConfig pmxConfig) { var triangleIndexCount = reader.ReadInt32(); model.TriangleIndexes = new int[triangleIndexCount]; if (triangleIndexCount % 3 != 0)//OYM:如果不是三的整数倍就报错(这样子就代表肯定有个三角形的数据丢失了) { 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);//OYM:读取三角形,注意三角形是根据顶点的序号数目生成的 } }
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 PmxConfig ReadPmxConfig(BinaryReader reader, MmdModel model) { //https://www.cnblogs.com/tanding/archive/2012/07/02/2572702.html //OYM:下面一摞方法都是读取一个字节,从0-256到-128-128的方法都有. var pmxConfig = new PmxConfig(); pmxConfig.Utf8Encoding = reader.ReadByte() != 0; //OYM:是否是UTF8 pmxConfig.ExtraUvNumber = reader.ReadSByte(); //OYM:UV数量 pmxConfig.VertexIndexSize = reader.ReadSByte(); //OYM:不知道 pmxConfig.TextureIndexSize = reader.ReadSByte(); //OYM:不知道 pmxConfig.MaterialIndexSize = reader.ReadSByte(); //OYM:不知道,下面都不知道,懒得写了 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 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; } }
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 Vertex ReadVertex(BinaryReader reader, PmxConfig pmxConfig) { var pv = ReadVertexBasic(reader); var vertex = new Vertex { Coordinate = pv.Coordinate, Normal = pv.Normal, UvCoordinate = pv.UvCoordinate }; if (pmxConfig.ExtraUvNumber > 0) { var extraUv = new Vector4[pmxConfig.ExtraUvNumber]; for (var ei = 0; ei < pmxConfig.ExtraUvNumber; ++ei) { extraUv[ei] = MMDReaderUtil.ReadVector4(reader); } vertex.ExtraUvCoordinate = extraUv; } var op = new SkinningOperator(); var skinningType = (SkinningOperator.SkinningType)reader.ReadByte(); op.Type = skinningType; switch (skinningType) { case SkinningOperator.SkinningType.SkinningBdef1: var bdef1 = new SkinningOperator.Bdef1(); bdef1.BoneId = MMDReaderUtil.ReadIndex(reader, pmxConfig.BoneIndexSize); op.Param = bdef1; break; case SkinningOperator.SkinningType.SkinningBdef2: var bdef2 = new SkinningOperator.Bdef2(); bdef2.BoneId[0] = MMDReaderUtil.ReadIndex(reader, pmxConfig.BoneIndexSize); bdef2.BoneId[1] = MMDReaderUtil.ReadIndex(reader, pmxConfig.BoneIndexSize); bdef2.BoneWeight = reader.ReadSingle(); op.Param = bdef2; break; case SkinningOperator.SkinningType.SkinningBdef4: var bdef4 = new SkinningOperator.Bdef4(); for (var j = 0; j < 4; ++j) { bdef4.BoneId[j] = MMDReaderUtil.ReadIndex(reader, pmxConfig.BoneIndexSize); } for (var j = 0; j < 4; ++j) { bdef4.BoneWeight[j] = reader.ReadSingle(); } op.Param = bdef4; break; case SkinningOperator.SkinningType.SkinningSdef: var sdef = new SkinningOperator.Sdef(); sdef.BoneId[0] = MMDReaderUtil.ReadIndex(reader, pmxConfig.BoneIndexSize); sdef.BoneId[1] = MMDReaderUtil.ReadIndex(reader, pmxConfig.BoneIndexSize); sdef.BoneWeight = reader.ReadSingle(); sdef.C = MMDReaderUtil.ReadVector3(reader); sdef.R0 = MMDReaderUtil.ReadVector3(reader); sdef.R1 = MMDReaderUtil.ReadVector3(reader); op.Param = sdef; break; default: throw new MMDFileParseException("invalid skinning type: " + skinningType); } vertex.SkinningOperator = op; vertex.EdgeScale = reader.ReadSingle(); return(vertex); }
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); }
/// <summary> /// 读取骨骼数目 /// </summary> /// <param name="reader"></param> /// <param name="model"></param> /// <param name="pmxConfig"></param> private static void ReadBones(BinaryReader reader, MmdModel model, PmxConfig pmxConfig) { var boneNum = reader.ReadInt32();//OYM:获取骨骼数目 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);//OYM:获取父骨骼的序号 if (parentIndex < boneNum && parentIndex >= 0) { bone.ParentIndex = parentIndex; } else { bone.ParentIndex = -1; } bone.TransformLevel = reader.ReadInt32();//OYM:不知道 //下面一排位运算,跳过 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)//OYM:旋转角固定? { bone.RotAxis = MmdReaderUtil.ReadVector3(reader); } if (bone.AppendRotate || bone.AppendTranslate)//OYM:看不懂,告辞 { bone.AppendBoneVal.Index = MmdReaderUtil.ReadIndex(reader, pmxConfig.BoneIndexSize); bone.AppendBoneVal.Ratio = reader.ReadSingle(); } if (bone.UseLocalAxis)//OYM:使用本地坐标 { Vector3 localX = MmdReaderUtil.ReadVector3(reader); Vector3 localZ = MmdReaderUtil.ReadVector3(reader); Vector3 localY = Vector3.Cross(localX, localZ); //OYM:差积出来你也太懒了吧 localZ = Vector3.Cross(localX, localY); //OYM:再差积一次防止坐标轴反了? 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);//OYM:来看看别人IK怎么描述位置的 } model.Bones[i] = bone; } }
private static void ReadModelNameAndDescription(BinaryReader reader, MmdModel model, PmxConfig pmxConfig) { //OYM:一堆读取信息,没什么好看的 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); }
/// <summary> /// 关键部分 /// </summary> /// <param name="reader"></param> /// <param name="pmxConfig"></param> /// <returns></returns> private static Vertex ReadVertex(BinaryReader reader, PmxConfig pmxConfig) { var pv = ReadVertexBasic(reader); //new一个顶点,赋值 var vertex = new Vertex { Coordinate = pv.Coordinate, Normal = pv.Normal, UvCoordinate = pv.UvCoordinate }; //OYM:如果有额外的uv(在底层设置那里) //OYM:也不知道到底有什么用... if (pmxConfig.ExtraUvNumber > 0) { var extraUv = new Vector4[pmxConfig.ExtraUvNumber]; for (var ei = 0; ei < pmxConfig.ExtraUvNumber; ++ei) { extraUv[ei] = MmdReaderUtil.ReadVector4(reader); } vertex.ExtraUvCoordinate = extraUv; } var op = new SkinningOperator(); var skinningType = (SkinningOperator.SkinningType)reader.ReadByte(); //OYM:蒙皮种类 op.Type = skinningType; //OYM:看不懂就完事了 switch (skinningType) //OYM:应该是权重没跑了 { case SkinningOperator.SkinningType.SkinningBdef1: var bdef1 = new SkinningOperator.Bdef1(); //OYM:注意这里用了父类可以为任意形式子类的方法,很模糊但是还是要好好学 bdef1.BoneId = MmdReaderUtil.ReadIndex(reader, pmxConfig.BoneIndexSize); op.Param = bdef1; break; case SkinningOperator.SkinningType.SkinningBdef2: var bdef2 = new SkinningOperator.Bdef2(); bdef2.BoneId[0] = MmdReaderUtil.ReadIndex(reader, pmxConfig.BoneIndexSize); bdef2.BoneId[1] = MmdReaderUtil.ReadIndex(reader, pmxConfig.BoneIndexSize); bdef2.BoneWeight = reader.ReadSingle(); op.Param = bdef2; break; case SkinningOperator.SkinningType.SkinningBdef4: var bdef4 = new SkinningOperator.Bdef4(); for (var j = 0; j < 4; ++j) { bdef4.BoneId[j] = MmdReaderUtil.ReadIndex(reader, pmxConfig.BoneIndexSize); } for (var j = 0; j < 4; ++j) { bdef4.BoneWeight[j] = reader.ReadSingle(); } op.Param = bdef4; break; case SkinningOperator.SkinningType.SkinningSdef: //OYM:这个猜不准,到时候再看 var sdef = new SkinningOperator.Sdef(); sdef.BoneId[0] = MmdReaderUtil.ReadIndex(reader, pmxConfig.BoneIndexSize); sdef.BoneId[1] = MmdReaderUtil.ReadIndex(reader, pmxConfig.BoneIndexSize); sdef.BoneWeight = reader.ReadSingle(); sdef.C = MmdReaderUtil.ReadVector3(reader); sdef.R0 = MmdReaderUtil.ReadVector3(reader); sdef.R1 = MmdReaderUtil.ReadVector3(reader); op.Param = sdef; break; default: throw new MmdFileParseException("invalid skinning type: " + skinningType); } vertex.SkinningOperator = op; //OYM:顶点的蒙皮操作 vertex.EdgeScale = reader.ReadSingle(); //OYM:这个实在猜不准,但是考虑到就一个单精度,猜一个倍率好了 return(vertex); }
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 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; } }
/// <summary> /// 读取变形 /// </summary> /// <param name="reader"></param> /// <param name="model"></param> /// <param name="pmxConfig"></param> private static void ReadMorphs(BinaryReader reader, MmdModel model, PmxConfig pmxConfig) { var morphNum = reader.ReadInt32();//OYM:表情包数量 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;//OYM:这个就相当于是一个基类吧 } morph.Type = (Morph.MorphType)reader.ReadByte(); //OYM:变形方式 var morphDataNum = reader.ReadInt32(); morph.MorphDatas = new Morph.MorphData[morphDataNum]; //OYM:获取表情变形的数据 switch (morph.Type) { case Morph.MorphType.MorphTypeGroup: //OYM:不知道干啥用的 for (var j = 0; j < morphDataNum; ++j) { var morphData = new Morph.GroupMorph { MorphIndex = MmdReaderUtil.ReadIndex(reader, pmxConfig.MorphIndexSize), MorphRate = reader.ReadSingle() }; morph.MorphDatas[j] = morphData; } break; case Morph.MorphType.MorphTypeVertex: //OYM:喜闻乐见的顶点变形 for (var j = 0; j < morphDataNum; ++j) { var morphData = new Morph.VertexMorph { VertexIndex = MmdReaderUtil.ReadIndex(reader, pmxConfig.VertexIndexSize), //OYM:顶点的序号 Offset = MmdReaderUtil.ReadVector3(reader) //OYM:偏移量 }; morph.MorphDatas[j] = morphData; } break; case Morph.MorphType.MorphTypeBone: //OYM:骨骼变形 for (var j = 0; j < morphDataNum; ++j) { var morphData = new Morph.BoneMorph { BoneIndex = MmdReaderUtil.ReadIndex(reader, pmxConfig.BoneIndexSize), //OYM:骨骼序号 Translation = MmdReaderUtil.ReadVector3(reader), //OYM:移动方向 Rotation = MmdReaderUtil.ReadQuaternion(reader) //OYM:旋转方向 }; morph.MorphDatas[j] = morphData; } break; //OYM:下面一堆case都是执行靠后面那个方法 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) { //OYM:获取信息就完事了 var morphData = new Morph.UvMorph { 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.MaterialMorph(); var mmIndex = MmdReaderUtil.ReadIndex(reader, pmxConfig.MaterialIndexSize); //OYM:补一个,作者居然还顺便修复了一个bug23333 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.MaterialMorph.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 //OYM:不清楚作者要干啥 } model.Morphs[i] = morph; } }