Example #1
0
        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;
            }
        }
Example #2
0
 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;
            }
        }
Example #5
0
        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);
        }
Example #6
0
        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();
            }
        }
Example #10
0
        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;
                    }
                }
            }
        }
Example #12
0
        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;
            }
        }
Example #14
0
        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;
            }
        }
Example #15
0
        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;
            }
        }
Example #16
0
        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);
 }
Example #18
0
        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;
        }
Example #21
0
        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);
                }
            }
        }