Beispiel #1
0
 public void Reader(ContentReader reader)
 {
     //count of chains
     IKChainCount = reader.ReadUInt16();
     //for all chain
     ikChains = new IkChain[IKChainCount];
     for (int i = 0; i < IKChainCount; i++)
     {
         IkChains[i] = new IkChain();
         IkChains[i].Read(reader);
     }
 }
Beispiel #2
0
        /// <summary>
        /// limit the bone rotate
        /// </summary>
        /// <param name="bonePos"></param>
        /// <returns></returns>
        Transform  AdjustTotalBoneMove(int boneIndex, IkChain chain, float deltaAngle)
        {
            bool result = false;

            for (int i = 0; i < chain.IkNodeCount; i++)
            {
                if (tempBoneList[boneIndex].Name == "左ひざ" || tempBoneList[boneIndex].Name == "右ひざ")
                {
                    result = true;
                }
            }
            if (!result)
            {
                return(boneLocalTransform[boneIndex]);//don't change anything
            }
            Matrix boneTrans = boneLocalTransform[boneIndex].ToMatrix();
            Matrix bonePose  = boneLocalPose[boneIndex].ToMatrix();
            Matrix moveMat   = boneTrans * Matrix.Invert(bonePose);

            //get rotation & translation & ^=___=^
            Vector3    temp, trans;
            Quaternion rot;

            moveMat.Decompose(out temp, out rot, out trans);
            float YRot, XRot, ZRot;

            DecompositeQuaternion(rot, out YRot, out XRot, out ZRot);

            //Watch Out!
            //limit rotation angle
            if (XRot < -MathHelper.PiOver2)
            {
                XRot = -MathHelper.PiOver2;
            }
            else if (XRot > -MathHelper.ToRadians(3f))
            {
                XRot = -MathHelper.ToRadians(3f);
            }

            //XRot=XRot>0?-XRot:XRot;
            //we dont change Yrot and Zrot
            //if (bFirstIteration)
            //{
            //XRot = -Math.Abs(deltaAngle);
            //}
            //if(YRot<0.9f)
            if (!(Math.Abs(YRot) > 1 && Math.Abs(ZRot) > 2))//&& Math.Abs(XRot) < 1
            {
                YRot = 0.0f;
                ZRot = 0.0f;
            }
            return(new Transform(trans, Quaternion.CreateFromYawPitchRoll(YRot, XRot, ZRot)) * boneLocalPose[boneIndex]);
        }
Beispiel #3
0
        /// <summary>
        /// apply transform to world transform
        /// </summary>
        /// <param name="chain"></param>
        void ApplyTransform(IkChain chain)
        {
            Transform boneBase = GetWorldTransform(BoneParent[chain.IkNodes[0]]);

            for (int i = 0; i < chain.IkNodeCount; i++)
            {
                if (i == 0)
                {
                    boneFinalPos[chain.IkNodes[i]] = boneLocalTransform[chain.IkNodes[i]] * boneBase;
                }
                else
                {
                    boneFinalPos[chain.IkNodes[i]] = boneLocalTransform[chain.IkNodes[i]] * boneFinalPos[chain.IkNodes[i - 1]];
                }
            }
        }
Beispiel #4
0
        void Solve(Vector3 targetPos, IkChain chain)
        {
            ushort  maxIterations    = chain.MaxIterationCount;
            Vector3 localTargetPos   = Vector3.One;
            Vector3 localEffectorPos = Vector3.Zero;

            //[75,8,7,6]---->6
            //[6,7,8,75]---->6
            Transform IKBase = GetWorldTransform(BoneParent[chain.IkNodes[0]]);

#if true //!WINDOWS_PHONE
            for (int it = 0; it < maxIterations; it++)
#else
            for (int it = 0; it < 1; it++)
#endif
            {
                //6,7,8---order:8-7-6
                for (int i = chain.IkNodeCount - 2; i >= 0; i--)
                {
                    Transform qTrans = IKBase;
                    for (int j = 0; j <= i; j++)//6->7->8
                    {
                        qTrans = boneLocalTransform[chain.IkNodes[j]] * qTrans;
                    }
                    Transform objectLoc = qTrans;
                    //get new end
                    for (int j = i + 1; j < chain.IkNodeCount; j++)//6->7->8
                    {
                        objectLoc = boneLocalTransform[chain.IkNodes[j]] * objectLoc;
                    }

                    Matrix invCoord = Matrix.Invert(qTrans.ToMatrix());
                    //to node i coordinate
                    localEffectorPos = Vector3.Transform(objectLoc.Pos, invCoord);
                    localTargetPos   = Vector3.Transform(targetPos, invCoord);
                    //if we reach to the target
                    if ((localEffectorPos - localTargetPos).LengthSquared() < 1.0e-8f)//
                    {
                        return;
                    }
                    Vector3 basis2Effector = Vector3.Normalize(localEffectorPos);
                    Vector3 basis2Target   = Vector3.Normalize(localTargetPos);
                    //rotate angle
                    float rotationDotProduct = Vector3.Dot(basis2Effector, basis2Target);
                    float rotationAngle      = (float)Math.Acos(rotationDotProduct);

                    //limit the angle TODO:Control weight

                    if (rotationAngle > MathHelper.Pi * chain.MaxAngleBetween)
                    {
                        rotationAngle = MathHelper.Pi * chain.MaxAngleBetween;
                    }
                    else if (rotationAngle < -MathHelper.Pi * chain.MaxAngleBetween)
                    {
                        rotationAngle = -MathHelper.Pi * chain.MaxAngleBetween;
                    }

                    if (!float.IsNaN(rotationAngle))
                    {
                        //we get a valid angle
                        Vector3 rotationAxis;
                        rotationAxis = Vector3.Cross(basis2Effector, basis2Target);
                        rotationAxis.Normalize();

                        //fix the bone's rotation
                        if ((!float.IsNaN(rotationAxis.X)) &&
                            (!float.IsNaN(rotationAxis.Y)) &&
                            (!float.IsNaN(rotationAxis.Z)))
                        {
                            boneLocalTransform[chain.IkNodes[i]] = new Transform(new Vector3(0, 0, 0), Quaternion.CreateFromAxisAngle(rotationAxis, rotationAngle)) *
                                                                   boneLocalTransform[chain.IkNodes[i]];
                        }

                        boneLocalTransform[chain.IkNodes[i]] = AdjustTotalBoneMove(chain.IkNodes[i], chain, rotationAngle);
                    }
                }
                if (bFirstIteration)
                {
                    bFirstIteration = false;
                }
            }
        }