コード例 #1
0
        protected virtual void CopyPoseImp()
        {
            //For some obscure reason, we have to set source and dest to null parent in order to work.
            QuickHumanPoseHandler.GetHumanPose(_source, ref _poseSource);
            QuickHumanPoseHandler.GetHumanPose(_dest, ref _poseDest);

            foreach (QuickHumanBodyBones boneID in _allJoints)
            {
                if (!IsTrackedJoint(boneID))
                {
                    for (int i = 0; i < 3; i++)
                    {
                        int m = QuickHumanTrait.GetMuscleFromBone(boneID, i);
                        if (m != -1)
                        {
                            _poseSource.muscles[m] = _poseDest.muscles[m];
                        }
                    }
                }
            }

            //The hips is a special case, it modifies the bodyPosition and bodyRotation fields
            if (!IsTrackedJointBody(TrackedJointBody.Hips))
            {
                _poseSource.bodyPosition = _poseDest.bodyPosition;
                _poseSource.bodyRotation = _poseDest.bodyRotation;
            }

            QuickHumanPoseHandler.SetHumanPose(_dest, ref _poseSource);
        }
コード例 #2
0
        protected virtual void InitFingersData()
        {
            Animator animator = QuickSingletonManager.GetInstance <QuickVRManager>().GetAnimatorSource();

            QuickHumanFingers[] fingers = QuickHumanTrait.GetHumanFingers();
            int numFingers = fingers.Length;

            _handFingerConfidence = new int[numFingers];
            _vrNodeFingers        = new QuickVRNode[numFingers * NUM_BONES_PER_FINGER];
            _tBoneFingers         = new Transform[numFingers * NUM_BONES_PER_FINGER];

            for (int i = 0; i < numFingers; i++)
            {
                _handFingerConfidence[i] = NUM_FRAMES_CONFIDENCE;
                List <QuickHumanBodyBones> fingerBones = QuickHumanTrait.GetBonesFromFinger(fingers[i], IsLeft());
                for (int j = 0; j < NUM_BONES_PER_FINGER; j++)
                {
                    int       fingerBoneID = (i * NUM_BONES_PER_FINGER) + j;
                    Transform tBone        = animator.GetBoneTransform(fingerBones[j]);

                    _vrNodeFingers[fingerBoneID] = _playArea.GetVRNode(fingerBones[j]);
                    _tBoneFingers[fingerBoneID]  = tBone;
                }
            }
        }
コード例 #3
0
        protected virtual void UpdateVRNodeFingers()
        {
            if (IsTracked() && QuickVRManager._handTrackingMode == QuickVRManager.HandTrackingMode.Controllers)
            {
                //Update the nodes of the fingers
                foreach (QuickHumanFingers f in QuickHumanTrait.GetHumanFingers())
                {
                    List <QuickHumanBodyBones> fingerBones = QuickHumanTrait.GetBonesFromFinger(f, _isLeft);
                    for (int i = 0; i < QuickHumanTrait.NUM_BONES_PER_FINGER; i++)
                    {
                        QuickVRNode nFinger = QuickSingletonManager.GetInstance <QuickVRPlayArea>().GetVRNode(fingerBones[i]);

                        //The finger is tracked.
                        Transform t = _handAnimator[(int)f][i]; // .GetBoneFingerTransform(f, i);
                        nFinger.transform.position = t.position;
                        nFinger.transform.rotation = t.rotation;

                        //Correct the rotation
                        //if (IsLeft())
                        //{
                        //    nFinger.transform.Rotate(Vector3.right, 180, Space.Self);
                        //    nFinger.transform.Rotate(Vector3.up, -90, Space.Self);
                        //}
                        //else
                        //{
                        //    nFinger.transform.Rotate(Vector3.up, 90, Space.Self);
                        //}

                        nFinger.SetTracked(true);
                    }
                }
            }
        }
コード例 #4
0
        protected virtual void UpdateVRNodeFingers()
        {
            if (IsInitialized())
            {
                if (!_physicsInitialized)
                {
                    CreatePhysics();
                    _physicsInitialized = true;
                }

                if (!_fingersDataInitialized)
                {
                    InitFingersData();
                    _fingersDataInitialized = true;
                }

                //Update the nodes of the fingers
                foreach (QuickHumanFingers f in QuickHumanTrait.GetHumanFingers())
                {
                    _handFingerConfidence[(int)f] = IsDataHighConfidence ? Mathf.Min(_handFingerConfidence[(int)f] + 1, NUM_FRAMES_CONFIDENCE) : 0;

                    for (int i = 0; i < NUM_BONES_PER_FINGER; i++)
                    {
                        int         boneID  = ((int)f) * NUM_BONES_PER_FINGER + i;
                        QuickVRNode nFinger = _vrNodeFingers[boneID]; //_playArea.GetVRNode(fingerBones[i]);

                        if (IsDataHighConfidenceFinger(f))
                        {
                            //The finger is tracked.
                            OVRSkeleton.BoneId ovrBoneID = _ovrFingerBones[boneID];
                            Transform          ovrBone   = GetOVRBoneTransform(ovrBoneID);
                            nFinger.transform.position = ovrBone.position;
                            nFinger.transform.rotation = ovrBone.rotation;

                            //Correct the rotation
                            if (IsLeft())
                            {
                                nFinger.transform.Rotate(Vector3.right, 180, Space.Self);
                                nFinger.transform.Rotate(Vector3.up, -90, Space.Self);
                            }
                            else
                            {
                                nFinger.transform.Rotate(Vector3.up, 90, Space.Self);
                            }


                            //nFinger.SetTracked(true);
                        }
                        else
                        {
                            //The finger is not tracked. Restore the last valid local rotation.
                            //nFinger.SetTracked(false);
                        }

                        nFinger.SetTracked(true);
                    }
                }
            }
        }
コード例 #5
0
 protected virtual bool IsTrackedJoint(QuickHumanBodyBones boneID)
 {
     if (QuickHumanTrait.IsBoneFingerLeft(boneID))
     {
         return(IsTrackedJointHandLeft(QuickHumanTrait.GetFingerFromBone(boneID)));
     }
     else if (QuickHumanTrait.IsBoneFingerRight(boneID))
     {
         return(IsTrackedJointHandRight(QuickHumanTrait.GetFingerFromBone(boneID)));
     }
     return(IsTrackedJointBody(_toTrackedJointBody[boneID]));
 }
コード例 #6
0
        protected virtual Transform GetBoneMid(HumanBodyBones boneLimbID)
        {
            if (boneLimbID == HumanBodyBones.Hips || boneLimbID == HumanBodyBones.Head)
            {
                return(_animator.GetBoneTransform(HumanBodyBones.Spine));
            }
            else if (boneLimbID == HumanBodyBones.LeftEye || boneLimbID == HumanBodyBones.RightEye)
            {
                return(_animator.GetBoneTransform(HumanBodyBones.Head));
            }

            return(_animator.GetBoneTransform(QuickHumanTrait.GetParentBone(boneLimbID)));
        }
コード例 #7
0
        private static void Init()
        {
            _allJoints = QuickUtils.ParseEnum <QuickHumanBodyBones, TrackedJointBody>();
            foreach (QuickHumanFingers f in QuickHumanTrait.GetHumanFingers())
            {
                _allJoints.AddRange(QuickHumanTrait.GetBonesFromFinger(f, true));
                _allJoints.AddRange(QuickHumanTrait.GetBonesFromFinger(f, false));
            }

            foreach (TrackedJointBody j in QuickUtils.GetEnumValues <TrackedJointBody>())
            {
                _toTrackedJointBody[QuickUtils.ParseEnum <QuickHumanBodyBones>(j.ToString())] = j;
            }
        }
コード例 #8
0
 protected virtual void InitBoneFingers()
 {
     _boneFingers = new List <KeyValuePair <Transform, Transform> >();
     foreach (bool b in new bool[] { true, false })
     {
         foreach (QuickHumanFingers f in QuickHumanTrait.GetHumanFingers())
         {
             List <QuickHumanBodyBones> fingerBones = QuickHumanTrait.GetBonesFromFinger(f, b);
             for (int i = 0; i < fingerBones.Count; i++)
             {
                 QuickHumanBodyBones fBoneID = fingerBones[i];
                 _boneFingers.Add(new KeyValuePair <Transform, Transform>(_animator.GetBoneTransform(fBoneID), _vrPlayArea.GetVRNode(fBoneID).GetTrackedObject().transform));
             }
         }
     }
 }
コード例 #9
0
        public virtual void EvaluateHumanPose(float time, ref HumanPose pose)
        {
            if (_animator.isHuman)
            {
                pose.bodyPosition = GetAnimationCurve(CURVE_BODY_POSITION).EvaluateVector3(time);
                pose.bodyRotation = GetAnimationCurve(CURVE_BODY_ROTATION).EvaluateQuaternion(time);

                List <float> muscles = new List <float>();
                for (int i = 0; i < QuickHumanTrait.GetNumMuscles(); i++)
                {
                    muscles.Add(_curves[QuickHumanTrait.GetMuscleName(i)].Evaluate(time));
                }

                pose.muscles = muscles.ToArray();
            }
        }
コード例 #10
0
 protected virtual Transform GetIKTargetParent(HumanBodyBones boneID)
 {
     if (boneID == HumanBodyBones.LeftEye || boneID == HumanBodyBones.RightEye)
     {
         return(GetIKSolver(IKBone.Head)._targetLimb);
     }
     if (QuickHumanTrait.IsBoneFingerLeft(boneID))
     {
         return(GetIKSolver(IKBone.LeftHand)._targetLimb);
     }
     if (QuickHumanTrait.IsBoneFingerRight(boneID))
     {
         return(GetIKSolver(IKBone.RightHand)._targetLimb);
     }
     return(_ikTargetsRoot);
 }
コード例 #11
0
        protected virtual void CopyPose(QuickHumanBodyBones boneID)
        {
            QuickHumanBodyBones nextBoneID   = QuickHumanTrait.GetNextBoneInChain(boneID);
            Transform           tBoneSrc     = _source.GetBoneTransform(boneID);
            Transform           tBoneSrcNext = _source.GetBoneTransform(nextBoneID);
            Transform           tBoneDst     = _dest.GetBoneTransform(boneID);
            Transform           tBoneDstNext = _dest.GetBoneTransform(nextBoneID);

            Vector3 currentDir = tBoneDstNext.position - tBoneDst.position;
            Vector3 targetDir  = tBoneSrcNext.position - tBoneSrc.position;

            Vector3 rotAxis  = Vector3.Cross(currentDir, targetDir);
            float   rotAngle = Vector3.Angle(currentDir, targetDir);

            tBoneDst.Rotate(rotAxis, rotAngle, Space.World);
        }
コード例 #12
0
        public virtual AnimationClip ToAnimationClip()
        {
            AnimationClip anim = new AnimationClip();

            QuickAnimationCurve curvePos = GetAnimationCurve(CURVE_BODY_POSITION);

            anim.SetCurve("", typeof(Animator), "RootT.x", curvePos[0]);
            anim.SetCurve("", typeof(Animator), "RootT.y", curvePos[1]);
            anim.SetCurve("", typeof(Animator), "RootT.z", curvePos[2]);

            QuickAnimationCurve curveRot = GetAnimationCurve(CURVE_BODY_ROTATION);

            anim.SetCurve("", typeof(Animator), "RootQ.x", curveRot[0]);
            anim.SetCurve("", typeof(Animator), "RootQ.y", curveRot[1]);
            anim.SetCurve("", typeof(Animator), "RootQ.z", curveRot[2]);
            anim.SetCurve("", typeof(Animator), "RootQ.w", curveRot[3]);

            curvePos = GetAnimationCurve(CURVE_LEFT_FOOT_IK_GOAL_POSITION);
            anim.SetCurve("", typeof(Animator), "LeftFootT.x", curvePos[0]);
            anim.SetCurve("", typeof(Animator), "LeftFootT.y", curvePos[1]);
            anim.SetCurve("", typeof(Animator), "LeftFootT.z", curvePos[2]);

            curveRot = GetAnimationCurve(CURVE_LEFT_FOOT_IK_GOAL_ROTATION);
            anim.SetCurve("", typeof(Animator), "LeftFootQ.x", curveRot[0]);
            anim.SetCurve("", typeof(Animator), "LeftFootQ.y", curveRot[1]);
            anim.SetCurve("", typeof(Animator), "LeftFootQ.z", curveRot[2]);
            anim.SetCurve("", typeof(Animator), "LeftFootQ.w", curveRot[3]);

            curvePos = GetAnimationCurve(CURVE_RIGHT_FOOT_IK_GOAL_POSITION);
            anim.SetCurve("", typeof(Animator), "RightFootT.x", curvePos[0]);
            anim.SetCurve("", typeof(Animator), "RightFootT.y", curvePos[1]);
            anim.SetCurve("", typeof(Animator), "RightFootT.z", curvePos[2]);

            curveRot = GetAnimationCurve(CURVE_RIGHT_FOOT_IK_GOAL_ROTATION);
            anim.SetCurve("", typeof(Animator), "RightFootQ.x", curveRot[0]);
            anim.SetCurve("", typeof(Animator), "RightFootQ.y", curveRot[1]);
            anim.SetCurve("", typeof(Animator), "RightFootQ.z", curveRot[2]);
            anim.SetCurve("", typeof(Animator), "RightFootQ.w", curveRot[3]);

            for (int i = 0; i < QuickHumanTrait.GetNumMuscles(); i++)
            {
                string muscleName = QuickHumanTrait.GetMuscleName(i);
                anim.SetCurve("", typeof(Animator), muscleName, _curves[muscleName][0]);
            }

            return(anim);
        }
コード例 #13
0
        public virtual float GetFingerLength(QuickHumanFingers f, bool isLeft)
        {
            List <QuickHumanBodyBones> boneFingers = QuickHumanTrait.GetBonesFromFinger(f, isLeft);
            HumanBodyBones             boneID      = (HumanBodyBones)boneFingers[0];

            if (_fingerLength[boneID] == 0)
            {
                QuickVRNode n0 = GetVRNode(boneFingers[0]);
                QuickVRNode n1 = GetVRNode(boneFingers[1]);
                QuickVRNode n2 = GetVRNode(boneFingers[2]);

                if (n0.IsTracked() && n1.IsTracked() && n2.IsTracked())
                {
                    _fingerLength[boneID] = Vector3.Distance(n0.transform.position, n1.transform.position) + Vector3.Distance(n1.transform.position, n2.transform.position);
                }
            }

            return(_fingerLength[boneID]);
        }
コード例 #14
0
        public virtual void LoadTPose()
        {
            _animator.EnforceTPose();

            //Reset the IKTargets
            for (IKBone ikBone = 0; ikBone < IKBone.LastBone; ikBone++)
            {
                QuickIKSolver  ikSolver = GetIKSolver(ikBone);
                HumanBodyBones boneID   = ToHumanBodyBones(ikBone);
                ResetIKTarget(boneID, ikSolver._targetLimb);
                ikSolver._targetLimb.parent = GetIKTargetParent(boneID);

                if (ikSolver._targetLimb.childCount > 0)
                {
                    ikSolver._targetLimb.GetChild(0).rotation = ikSolver._boneLimb.rotation;
                }

                if (ikSolver._targetHint)
                {
                    ResetIKTarget(QuickHumanTrait.GetParentBone(boneID), ikSolver._targetHint);
                }
            }
        }
コード例 #15
0
        public virtual void AddKey(float time, bool forceAdd = false)
        {
            GetAnimationCurve(CURVE_TRANSFORM_POSITION).AddKey(time, _animator.transform.position, forceAdd);
            GetAnimationCurve(CURVE_TRANSFORM_ROTATION).AddKey(time, _animator.transform.rotation, forceAdd);

            if (_animator.isHuman)
            {
                QuickHumanPoseHandler.GetHumanPose(_animator, ref _pose);
                Vector3    bodyPosition = _pose.bodyPosition;
                Quaternion bodyRotation = _pose.bodyRotation;

                GetAnimationCurve(CURVE_BODY_POSITION).AddKey(time, bodyPosition, forceAdd);
                GetAnimationCurve(CURVE_BODY_ROTATION).AddKey(time, bodyRotation, forceAdd);

                Vector3    ikGoalPos;
                Quaternion ikGoalRot;
                _animator.GetIKGoalFromBodyPose(AvatarIKGoal.LeftFoot, bodyPosition, bodyRotation, out ikGoalPos, out ikGoalRot);
                GetAnimationCurve(CURVE_LEFT_FOOT_IK_GOAL_POSITION).AddKey(time, ikGoalPos, forceAdd);
                GetAnimationCurve(CURVE_LEFT_FOOT_IK_GOAL_ROTATION).AddKey(time, ikGoalRot, forceAdd);

                _animator.GetIKGoalFromBodyPose(AvatarIKGoal.RightFoot, bodyPosition, bodyRotation, out ikGoalPos, out ikGoalRot);
                GetAnimationCurve(CURVE_RIGHT_FOOT_IK_GOAL_POSITION).AddKey(time, ikGoalPos, forceAdd);
                GetAnimationCurve(CURVE_RIGHT_FOOT_IK_GOAL_ROTATION).AddKey(time, ikGoalRot, forceAdd);

                for (int i = 0; i < _pose.muscles.Length; i++)
                {
                    string muscleName = QuickHumanTrait.GetMuscleName(i);
                    GetAnimationCurve(muscleName).AddKey(time, _pose.muscles[i], forceAdd);
                }
            }

            if (time > _timeLength)
            {
                _timeLength = time;
            }
        }
コード例 #16
0
        protected override void UpdateIKFingers()
        {
            if (_vrPlayArea)
            {
                //if (_boneFingers == null)
                //{
                //    InitBoneFingers();
                //}

                //for (int j = 0; j < _boneFingers.Count; j+= 4)
                //{
                //    if (_boneFingers[j].Key != null)
                //    {
                //        for (int i = 0; i < 3; i++)
                //        {
                //            if ((i == 0 && (j == 0 || j == 20)) && QuickVRManager._handTrackingMode == QuickVRManager.HandTrackingMode.Controllers)
                //            {
                //                //HACK
                //                //Avoid applying the rotation to the thumb distal fingers as the results look weird. Look for a better method
                //                //of transfering the bone rotations when using the controllers.
                //                continue;
                //            }
                //            ApplyFingerRotation(_boneFingers[j + i], _boneFingers[j + i + 1]);
                //        }
                //    }
                //}


                //foreach (bool b in new bool[] { true, false })
                //{
                //    foreach (QuickHumanFingers f in QuickHumanTrait.GetHumanFingers())
                //    {
                //        List<QuickHumanBodyBones> fingerBones = QuickHumanTrait.GetBonesFromFinger(f, b);
                //        List<Quaternion> initialFingerBonesLocalRotations = new List<Quaternion>();

                //        for (int i = 0; i < fingerBones.Count - 1; i++)
                //        {
                //            QuickHumanBodyBones fBoneID = fingerBones[i];
                //            initialFingerBonesLocalRotations.Add(_animator.GetBoneTransform(fBoneID).localRotation);

                //            if (_animator.GetBoneTransform(fBoneID) && _vrPlayArea.GetVRNode(fBoneID).IsTracked())
                //            {
                //                ApplyFingerRotation(fBoneID, fingerBones[i + 1]);
                //            }
                //        }

                //        //At this point the finger is correctly aligned. Set the targets to match this.
                //        //HumanBodyBones boneID = (HumanBodyBones)fingerBones[2];
                //        //QuickIKSolver ikSolver = GetIKSolver(boneID);
                //        //Transform tBone = _animator.GetBoneTransform(boneID);

                //        //ikSolver._targetLimb.position = tBone.position;
                //        //ikSolver._targetLimb.GetChild(0).rotation = tBone.rotation;
                //        //ikSolver._targetHint.position = ikSolver._boneMid.position + (ikSolver._boneMid.position - ikSolver._boneUpper.position) + (ikSolver._boneMid.position - ikSolver._boneLimb.position);

                //        ////Restore the rotation of the bone fingers
                //        //ikSolver._boneUpper.localRotation = initialFingerBonesLocalRotations[0];
                //        //ikSolver._boneMid.localRotation = initialFingerBonesLocalRotations[1];
                //        //ikSolver._boneLimb.localRotation = initialFingerBonesLocalRotations[2];
                //    }
                //}



                //foreach (bool b in new bool[] { true, false })
                //{
                //    foreach (QuickHumanFingers f in QuickHumanTrait.GetHumanFingers())
                //    {
                //        List<QuickHumanBodyBones> fingerBones = QuickHumanTrait.GetBonesFromFinger(f, b);
                //        List<Quaternion> initialFingerBonesLocalRotations = new List<Quaternion>();

                //        for (int i = 0; i < fingerBones.Count - 1; i++)
                //        {
                //            QuickHumanBodyBones fBoneID = fingerBones[i];
                //            initialFingerBonesLocalRotations.Add(_animator.GetBoneTransform(fBoneID).localRotation);

                //            if (_animator.GetBoneTransform(fBoneID) && _vrPlayArea.GetVRNode(fBoneID).IsTracked())
                //            {
                //                ApplyFingerRotation(fBoneID, fingerBones[i + 1]);
                //            }
                //        }

                //        //At this point the finger is correctly aligned. Set the targets to match this.
                //        //HumanBodyBones boneID = (HumanBodyBones)fingerBones[2];
                //        //QuickIKSolver ikSolver = GetIKSolver(boneID);
                //        //Transform tBone = _animator.GetBoneTransform(boneID);

                //        //ikSolver._targetLimb.position = tBone.position;
                //        //ikSolver._targetLimb.GetChild(0).rotation = tBone.rotation;
                //        //ikSolver._targetHint.position = ikSolver._boneMid.position + (ikSolver._boneMid.position - ikSolver._boneUpper.position) + (ikSolver._boneMid.position - ikSolver._boneLimb.position);

                //        ////Restore the rotation of the bone fingers
                //        //ikSolver._boneUpper.localRotation = initialFingerBonesLocalRotations[0];
                //        //ikSolver._boneMid.localRotation = initialFingerBonesLocalRotations[1];
                //        //ikSolver._boneLimb.localRotation = initialFingerBonesLocalRotations[2];
                //    }
                //}

                //foreach (bool isLeft in new bool[] { true, false })
                //{
                //    foreach (QuickHumanFingers f in QuickHumanTrait.GetHumanFingers())
                //    {
                //        float fLength = _vrPlayArea.GetFingerLength(f, isLeft);
                //        if (fLength > 0)
                //        {
                //            List<QuickHumanBodyBones> fingerBones = QuickHumanTrait.GetBonesFromFinger(f, isLeft);
                //            QuickVRNode n0 = _vrPlayArea.GetVRNode(fingerBones[0]);
                //            QuickVRNode n1 = _vrPlayArea.GetVRNode(fingerBones[1]);
                //            QuickVRNode n2 = _vrPlayArea.GetVRNode(fingerBones[2]);

                //            QuickIKSolver ikSolver = GetIKSolver((HumanBodyBones)fingerBones[2]);

                //            if (n0.IsTracked() && n2.IsTracked())
                //            {
                //                float sf = ikSolver.GetChainLength() / fLength;
                //                Vector3 v = sf * (n2.transform.position - n0.transform.position);

                //                ikSolver._targetLimb.position = ikSolver._boneUpper.position + v;
                //                ikSolver._targetHint.position = ikSolver._boneMid.position + (n1.transform.position - n0.transform.position) + (n1.transform.position - n2.transform.position);
                //            }
                //        }
                //    }
                //}

                foreach (bool isLeft in new bool[] { true, false })
                {
                    foreach (QuickHumanFingers f in QuickHumanTrait.GetHumanFingers())
                    {
                        List <QuickHumanBodyBones> fingerBones = QuickHumanTrait.GetBonesFromFinger(f, isLeft);
                        QuickVRNode n0 = _vrPlayArea.GetVRNode(fingerBones[0]);
                        QuickVRNode n1 = _vrPlayArea.GetVRNode(fingerBones[1]);
                        QuickVRNode n2 = _vrPlayArea.GetVRNode(fingerBones[2]);

                        if (n0.IsTracked() && n1.IsTracked() && n2.IsTracked())
                        {
                            QuickIKSolver ikSolver = GetIKSolver((HumanBodyBones)fingerBones[2]);

                            Vector3 v = (n1.transform.position - n0.transform.position).normalized;
                            Vector3 w = (n2.transform.position - n1.transform.position).normalized;

                            ikSolver._targetLimb.position = ikSolver._boneUpper.position + v * ikSolver.GetUpperLength() + w * ikSolver.GetMidLength();
                            ikSolver._targetLimb.rotation = n2.transform.rotation;
                            ikSolver._targetHint.position = ikSolver._boneMid.position + n1.transform.up * DEFAULT_TARGET_HINT_FINGER_DISTANCE;
                            ikSolver._targetHint.rotation = n1.transform.rotation;
                            //ikSolver._targetHint.position = ikSolver._boneMid.position + (n1.transform.position - n0.transform.position) + (n1.transform.position - n2.transform.position);
                        }
                    }
                }
            }

            base.UpdateIKFingers();
        }