/// <summary>
        /// we need to offset the root to achieve the results
        /// </summary>
        private void OffsetTargets()
        {
            Vector3 _newRootPos = Root().position;
            float   _toRight    = Vector3.Distance(_newRootPos, rightLeg.GetIKPosition());
            float   _toLeft     = Vector3.Distance(_newRootPos, leftLeg.GetIKPosition());
            float   _rootOffset = Mathf.Max(_toLeft, _toRight) - Mathf.Min(_toRight, _toLeft);

            rootY          = Mathf.Lerp(rootY, _rootOffset, rootLerp * Time.fixedDeltaTime);
            _newRootPos.y -= rootY;


            for (int i = 0; i < 2; i++)
            {
                Vector3 _targetOffset = i == 0 ? rightLeg.GetIKPosition() : leftLeg.GetIKPosition();
                _targetOffset += Vector3.up * footHeight;
                offsetedIK[i]  = GenericMaths.Interpolate(offsetedIK[i], _targetOffset, footLerp * Time.fixedDeltaTime);
            }

            rightLeg.SetIKPosition(offsetedIK[0]);
            leftLeg.SetIKPosition(offsetedIK[1]);
            Root().position = _newRootPos;

            //RayArtist.DrawHitPoints(rightLeg.GetEndEffector().position + Vector3.up * maxStep + Vector3.right * 0.3f, rightLeg.GetIKPosition() + Vector3.right * 0.3f, Color.red);
            //RayArtist.DrawHitPoints(leftLeg.GetEndEffector().position + Vector3.up * maxStep + Vector3.left * 0.2f, leftLeg.GetIKPosition() + Vector3.left * 0.2f, Color.red);
        }
示例#2
0
        /// <summary>
        /// correct the orientation of the bones after the solve
        /// </summary>
        private void CorrectRotation()
        {
            for (int i = 0; i < chain.joints.Count - 1; i++)
            {
                //apply the new pos
                chain.joints[i].transform.position = chain.joints[i].solvePos;

                Vector3    _targetDir = chain.joints[i + 1].transform.position - chain.joints[i].transform.position;
                Quaternion _sourceRot = chain.joints[i].transform.rotation;
                Quaternion _targetRot = RootIK.RotateFromTo(RootIK.TransformVector(Vector3.up, _sourceRot), _targetDir);

                _targetRot = Quaternion.Inverse(_targetRot);
                chain.joints[i].transform.rotation = Quaternion.Lerp(_sourceRot, GenericMaths.ApplyQuaternion(_targetRot, _sourceRot), chain.weight);
            }

            //Bounce back to the 1st bone before the endeffector and correct its rotation
            Vector3    _t  = chain.GetIKPosition() - chain.joints[chain.joints.Count - 2].transform.position;
            Vector3    _t2 = RootIK.TransformVector(Vector3.up, chain.joints[chain.joints.Count - 2].transform.rotation);
            Quaternion _s  = chain.joints[chain.joints.Count - 2].transform.rotation;
            Quaternion _tr = RootIK.RotateFromTo(_t, _t2);

            chain.joints[chain.joints.Count - 2].transform.rotation = Quaternion.Lerp(_s, GenericMaths.ApplyQuaternion(_tr, _s), chain.weight);

            chain.joints[chain.joints.Count - 1].transform.rotation = chain.GetIKRotation();   //apply end effector rotation
        }
示例#3
0
        /// <summary>
        /// the _source vector will rotate to point at the _target vector
        /// </summary>
        /// <param name="_source"></param>
        /// <param name="_target"></param>
        /// <returns></returns>
        public static Quaternion RotateFromTo(Vector3 _source, Vector3 _target)
        {
            _source.Normalize();
            _target.Normalize();

            Quaternion q = GenericMaths.QuaternionFromAngleAxis(Vector3.Cross(_source, _target).normalized, GenericMaths.VectorsAngle(_source, _target));

            return(Quaternion.Inverse(q));
        }
        /// <summary>
        /// Prepare the solver and solve the IK problem analytically with specific axis of rotation
        /// (the chain must contain 2 joints, no more and no less)
        /// </summary>
        /// <param name="_hingeChain">the chain</param>
        /// <param name="_direction">direction of the player</param>
        /// <param name="_axis">axis of rotation for the 2nd joint (the Hinge joint)</param>
        public void SolveAnalytically(RootIK.Chain _hingeChain, Vector3 _direction, Vector3 _axis)
        {
            if (_hingeChain.joints.Count > 3)
            {
                return;
            }
            if (_hingeChain.iterations <= 0)
            {
                return;
            }
            if (_hingeChain.joints.Count <= 0)
            {
                return;
            }


            //calculate bone length;
            upperLength  = Vector3.Distance(_hingeChain.joints[0].transform.position, _hingeChain.joints[1].transform.position);
            lowerLength  = Vector3.Distance(_hingeChain.joints[1].transform.position, _hingeChain.joints[2].transform.position);
            systemLength = Vector3.Distance(_hingeChain.joints[0].transform.position, _hingeChain.GetIKPosition());

            //lowerjoint 1DOF
            float _angle = GenericMaths.Formula(upperLength, lowerLength, systemLength) + Mathf.PI * Mathf.Rad2Deg;

            if (_axis == Vector3.zero)
            {
                _axis = Vector3.Cross(RootIK.TransformVector(Vector3.up, _hingeChain.joints[1].transform.rotation), _direction);
            }
            else
            {
                _axis = Vector3.Cross(RootIK.TransformVector(_axis, _hingeChain.joints[1].transform.rotation), _direction);
            }
            Quaternion _src      = _hingeChain.joints[1].transform.rotation;
            Quaternion _t        = GenericMaths.QuaternionFromAngleAxis(_axis, _angle + Mathf.Acos(Mathf.Clamp(_src.w, -1f, 1f)) * 10f);
            Quaternion _finalRot = Quaternion.Lerp(Quaternion.identity, _t, _hingeChain.weight);

            _hingeChain.joints[1].transform.rotation = GenericMaths.ApplyQuaternion(_finalRot, _src);


            //Upperjoint 3DOF
            Vector3    _v1        = _hingeChain.GetIKPosition() - _hingeChain.joints[0].transform.position;
            Vector3    _v2        = _hingeChain.joints[2].transform.position - _hingeChain.joints[0].transform.position;
            Quaternion _src2      = _hingeChain.joints[0].transform.rotation;
            Quaternion _t2        = RootIK.RotateFromTo(_v2, _v1);
            Quaternion _finalRot2 = Quaternion.Lerp(Quaternion.identity, _t2, _hingeChain.weight);

            _hingeChain.joints[0].transform.rotation = GenericMaths.ApplyQuaternion(Quaternion.Inverse(_finalRot2), _src2);

            //foot 6DOF
            _hingeChain.GetEndEffector().rotation = _hingeChain.GetIKRotation();
        }
示例#5
0
        /// <summary>
        /// solve the joints forward
        /// </summary>
        private void SolveOutward()
        {
            chain.joints[0].solvePos = chain.joints[0].transform.position;

            for (int i = 1; i < chain.joints.Count; i++)
            {
                Vector3 _v1 = chain.joints[i - 1].solvePos;
                Vector3 _v0 = chain.joints[i].solvePos - _v1;

                _v0.Normalize();
                _v0 *= Vector3.Distance(chain.joints[i].transform.position, chain.joints[i - 1].transform.position);

                chain.joints[i].solvePos = GenericMaths.Interpolate(chain.joints[i].transform.position, _v0 + _v1, chain.weight);
            }
        }
示例#6
0
        /// <summary>
        /// solve the joints backward
        /// </summary>
        private void SolveInward()
        {
            chain.joints[chain.joints.Count - 1].solvePos = GenericMaths.Interpolate(chain.GetEndEffector().position, chain.GetIKPosition(), chain.weight);

            for (int i = chain.joints.Count - 2; i >= 0; i--)
            {
                Vector3 _v1 = chain.joints[i + 1].solvePos;
                Vector3 _v0 = chain.joints[i].solvePos - _v1;

                _v0.Normalize();
                _v0 *= Vector3.Distance(chain.joints[i].transform.position, chain.joints[i + 1].transform.position);

                chain.joints[i].solvePos = GenericMaths.Interpolate(chain.joints[i].transform.position, _v0 + _v1, chain.weight);
            }
        }
示例#7
0
        /// <summary>
        /// Solve the KinematicBone
        /// </summary>
        /// <param name="_bone"></param>
        public void SolveBone(RootIK.KinematicBone _bone)
        {
            if (_bone.weight <= 0)
            {
                return;
            }
            if (_bone.target == null)
            {
                Debug.LogError("No target was assigned");
                return;
            }

            Vector3    _v0        = RootIK.TransformVector(_bone.axis == Vector3.zero ? Vector3.forward : _bone.axis, _bone.bone.rotation);
            Vector3    _v1        = _bone.target.position - _bone.bone.position;
            Quaternion _targetRot = Quaternion.Lerp(Quaternion.identity, RootIK.RotateFromTo(_v0, _v1), _bone.weight);

            _targetRot          = Quaternion.Inverse(_targetRot);
            _bone.bone.rotation = GenericMaths.ApplyQuaternion(_targetRot, _bone.bone.rotation);
        }
        private void FindGround()
        {
            for (int i = 0; i < 2; i++)
            {
                Vector3    _endEffector = i == 0 ? rightLeg.GetEndEffector().position : leftLeg.GetEndEffector().position;
                Ray        _ray         = new Ray(_endEffector + Vector3.up * maxStep, Vector3.down);
                RaycastHit _hit         = new RaycastHit();

                if (Physics.Raycast(_ray, out _hit, rayLength, solverLayer))
                {
                    Quaternion _ankleRot = RootIK.RotateFromTo(_hit.normal, RootIK.TransformVector(Vector3.up, Root().rotation));

                    rightLeg.SetIKRotation(i == 0 ? GenericMaths.ApplyQuaternion(_ankleRot, rightLeg.GetEndEffector().rotation) : rightLeg.GetIKRotation());
                    leftLeg.SetIKRotation(i == 1 ? GenericMaths.ApplyQuaternion(_ankleRot, leftLeg.GetEndEffector().rotation) : leftLeg.GetIKRotation());

                    IKTarget[i] = _hit.point;
                }
            }

            rightLeg.SetIKPosition(IKTarget[0]);
            leftLeg.SetIKPosition(IKTarget[1]);
        }
示例#9
0
        /// <summary>
        /// Solve the IK chain using CCD method
        /// </summary>
        /// <param name="_IKChain"></param>
        public void SolveCCD(RootIK.Chain _IKChain)
        {
            if (_IKChain.weight <= 0f)
            {
                return;
            }
            if (_IKChain.joints.Count <= 0)
            {
                return;
            }

            _IKChain.SetIKPosition(_IKChain.target ? Vector3.zero : _IKChain.GetIKPosition());

            for (int j = 0; j < _IKChain.iterations; j++)
            {
                for (int i = _IKChain.joints.Count - 1; i >= 0; i--)
                {
                    _IKChain.weight = Mathf.Clamp(_IKChain.weight, 0f, 1f);

                    float _weight = _IKChain.weight * _IKChain.joints[i].weight;

                    Vector3 _v0 = _IKChain.GetIKPosition() - _IKChain.joints[i].transform.position;
                    Vector3 _v1 = _IKChain.joints[_IKChain.joints.Count - 1].transform.position - _IKChain.joints[i].transform.position;

                    Quaternion _sourceRotation = _IKChain.joints[i].transform.rotation;
                    Quaternion _targetRotation = Quaternion.Lerp(Quaternion.identity, RootIK.RotateFromTo(_v0, _v1), _weight);

                    _IKChain.joints[i].transform.rotation = Quaternion.Lerp(_sourceRotation, GenericMaths.ApplyQuaternion(_targetRotation, _sourceRotation), _weight);
                }
            }

            _IKChain.joints[_IKChain.joints.Count - 1].transform.rotation = _IKChain.GetIKRotation();
        }