예제 #1
0
        private static void ReadBoneIk(BinaryReader reader, Bone bone, int boneIndexSize)
        {
            bone.IkInfoVal = new Bone.IkInfo();
            bone.IkInfoVal.IkTargetIndex   = MMDReaderUtil.ReadIndex(reader, boneIndexSize);
            bone.IkInfoVal.CcdIterateLimit = reader.ReadInt32();
            bone.IkInfoVal.CcdAngleLimit   = reader.ReadSingle();
            var ikLinkNum = reader.ReadInt32();

            bone.IkInfoVal.IkLinks = new Bone.IkLink[ikLinkNum];
            for (var j = 0; j < ikLinkNum; ++j)
            {
                var link = new Bone.IkLink();
                link.LinkIndex = MMDReaderUtil.ReadIndex(reader, boneIndexSize);
                link.HasLimit  = reader.ReadByte() != 0;
                if (link.HasLimit)
                {
                    link.LoLimit = MMDReaderUtil.ReadVector3(reader);
                    link.HiLimit = MMDReaderUtil.ReadVector3(reader);
                }
                bone.IkInfoVal.IkLinks[j] = link;
            }
        }
예제 #2
0
        /// <summary>
        /// 读取模型骨骼的IK
        /// </summary>
        /// <param name="reader"></param>
        /// <param name="bone"></param>
        /// <param name="boneIndexSize"></param>
        private static void ReadBoneIk(BinaryReader reader, Bone bone, int boneIndexSize)
        {
            bone.IkInfoVal = new Bone.IkInfo();
            bone.IkInfoVal.IkTargetIndex   = MmdReaderUtil.ReadIndex(reader, boneIndexSize); //OYM:IK目标
            bone.IkInfoVal.CcdIterateLimit = reader.ReadInt32();                             //OYM:我想起来了,这是IK解算的术语
            bone.IkInfoVal.CcdAngleLimit   = reader.ReadSingle();                            //OYM:同上
            var ikLinkNum = reader.ReadInt32();

            bone.IkInfoVal.IkLinks = new Bone.IkLink[ikLinkNum];
            for (var j = 0; j < ikLinkNum; ++j)
            {
                var link = new Bone.IkLink();
                link.LinkIndex = MmdReaderUtil.ReadIndex(reader, boneIndexSize); //OYM:IK的link?
                link.HasLimit  = reader.ReadByte() != 0;                         //OYM:有限制
                if (link.HasLimit)
                {
                    link.LoLimit = MmdReaderUtil.ReadVector3(reader);
                    link.HiLimit = MmdReaderUtil.ReadVector3(reader);
                }
                bone.IkInfoVal.IkLinks[j] = link;//OYM:反正看不懂,等下找下在哪调用的看看好了
            }
        }
예제 #3
0
        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;
        }