Пример #1
0
 public override void Solve(
     IKJoint[] transforms,
     Transform endEffector,
     Vector3 target)
 {
     throw new System.NotImplementedException();
 }
Пример #2
0
 public void Solve(Transform[] transforms, Vector3 target)
 {
     IKJoint[] joints = new IKJoint[transforms.Length];
     for (int i = 0; i < transforms.Length; i++)
         joints[i] = new IKJoint(transforms[i]);
     this.Solve(joints, target);
 }
Пример #3
0
    public override void Solve(IKJoint[] joints, Vector3 target)
    {
        Transform hip = joints[0].transform;
        Transform knee = joints[1].transform;
        Transform ankle = joints[2].transform;

        // Calculate the direction in which the knee should be pointing
        Vector3 vKneeDir = Vector3.Cross(
            ankle.position - hip.position,
            Vector3.Cross(
                ankle.position-hip.position,
                ankle.position-knee.position
            )
        );

        // Get lengths of leg bones
        float fThighLength = (knee.position-hip.position).magnitude;
        float fShinLength = (ankle.position-knee.position).magnitude;

        // Calculate the desired new joint positions
        Vector3 pHip = hip.position;
        Vector3 pAnkle = target;
        Vector3 pKnee = findKnee(pHip,pAnkle,fThighLength,fShinLength,vKneeDir);

        // Rotate the bone transformations to align correctly
        Quaternion hipRot = Quaternion.FromToRotation(knee.position-hip.position, pKnee-pHip) * hip.rotation;
        if (System.Single.IsNaN(hipRot.x)) {
            Debug.LogWarning("hipRot="+hipRot+" pHip="+pHip+" pAnkle="+pAnkle+" fThighLength="+fThighLength+" fShinLength="+fShinLength+" vKneeDir="+vKneeDir);
        }
        else {
            hip.rotation = hipRot;
            knee.rotation = Quaternion.FromToRotation(ankle.position-knee.position, pAnkle-pKnee) * knee.rotation;
        }
    }
Пример #4
0
    public override void Solve(
        IKJoint[] joints, 
        Transform endEffector, 
        Vector3 tarPos)
    {
        float damp = this.dampingMax * Time.deltaTime;
        int link = joints.Length - 1;
        Vector3 endPos = endEffector.position;

        // Cap out the number of iterations
        for (int tries = 0; tries < this.maxIterations; tries++)
        {
            // Are we there yet?
            if ((endPos - tarPos).sqrMagnitude <= epsilon)
                break;
            if (link < 0)
                link = joints.Length - 1;

            endPos = endEffector.position;

            Vector3 rootPos = joints[link].position;
            Vector3 currentDirection = (endPos - rootPos).normalized;
            Vector3 targetDirection = (tarPos - rootPos).normalized;
            float dot = Vector3.Dot(currentDirection, targetDirection);

            if (dot < (1.0f - epsilon))
            {
                float turnRad = Mathf.Acos(dot);
                if (damping == true && turnRad > damp)
                    turnRad = damp;
                float turnDeg = turnRad * Mathf.Rad2Deg;

                // Use the cross product to determine which way to rotate
                Vector3 cross =
                    Vector3.Cross(currentDirection, targetDirection);
                joints[link].rotation =
                    Quaternion.AngleAxis(turnDeg, cross)
                    * joints[link].rotation;
                joints[link].Constrain();
                joints[link].Relax(Time.deltaTime);
            }

            //// Move back in the array
            link--;
        }
    }
Пример #5
0
 public override void Solve(IKJoint[] joints, float angle, Vector3 target)
 {
     throw new System.NotImplementedException();
 }
Пример #6
0
 public abstract void Solve(
     IKJoint[] transforms,
     Transform endEffector,
     Vector3 target);
Пример #7
0
    public int maxIterations = 100; // (If applicable)

    #endregion Fields

    #region Methods

    public abstract void Solve(IKJoint[] joints, Vector3 target);
Пример #8
0
    public override void Solve(
        IKJoint[] joints,
        Transform endEffector,
        Vector3 target)
    {
        // Get the axis of rotation for each joint
        Vector3[] rotateAxes = new Vector3[joints.Length-2];
        float[] rotateAngles = new float[joints.Length-2];
        Quaternion[] rotations = new Quaternion[joints.Length-2];
        for (int i=0; i<joints.Length-2; i++)
        {
            rotateAxes[i] = Vector3.Cross(
                joints[i+1].position - joints[i].position,
                joints[i+2].position - joints[i+1].position);
            rotateAxes[i] =
                Quaternion.Inverse(joints[i].rotation) * rotateAxes[i];
            rotateAxes[i] = rotateAxes[i].normalized;
            rotateAngles[i] = Vector3.Angle(
                joints[i+1].position - joints[i].position,
                joints[i+1].position - joints[i+2].position);

            rotations[i] = joints[i+1].localRotation;
        }

        // Get the length of each bone
        float[] boneLengths = new float[joints.Length-1];
        float legLength = 0;
        for (int i=0; i<joints.Length-1; i++)
        {
            boneLengths[i] =
                (joints[i+1].position-joints[i].position).magnitude;
            legLength += boneLengths[i];
        }
        epsilon = legLength*0.001f;

        float currentDistance =
            (endEffector.position-joints[0].position).magnitude;
        float targetDistance = (target-joints[0].position).magnitude;

        // Search for right joint bendings to get target distance between
        // the hip and the foot
        float bendingLow, bendingHigh;
        bool minIsFound = false;
        bool bendMore = false;
        if (targetDistance > currentDistance)
        {
            minIsFound = true;
            bendingHigh = 1;
            bendingLow = 0;
        }
        else
        {
            bendMore = true;
            bendingHigh = 1;
            bendingLow = 0;
        }

        int tries = 0;
        float testDistance = Mathf.Abs(currentDistance - targetDistance);
        while (testDistance > epsilon && tries < maxIterations)
        {
            tries++;
            float bendingNew;
            if (minIsFound == true)
                bendingNew = (bendingLow + bendingHigh) / 2;
            else
                bendingNew = bendingHigh;

            for (int i=0; i < joints.Length - 2; i++)
            {
                float newAngle;
                if (bendMore == false)
                    newAngle = Mathf.Lerp(180, rotateAngles[i], bendingNew);
                else
                    newAngle =
                        rotateAngles[i] * (1 - bendingNew)
                        + (rotateAngles[i] - 30) * bendingNew;

                float angleDiff = (rotateAngles[i]-newAngle);
                Quaternion addedRotation =
                    Quaternion.AngleAxis(angleDiff, rotateAxes[i]);
                Quaternion newRotation = addedRotation * rotations[i];
                joints[i + 1].localRotation = newRotation;
            }

            Vector3 difference = endEffector.position - joints[0].position;
            if (targetDistance > difference.magnitude)
                minIsFound = true;

            if (minIsFound == true)
            {
                if (targetDistance > currentDistance)
                    bendingHigh = bendingNew;
                else
                    bendingLow = bendingNew;
                if (bendingHigh < 0.01f)
                    break;
            }
            else
            {
                bendingLow = bendingHigh;
                bendingHigh++;
            }

            testDistance = Mathf.Abs(currentDistance - targetDistance);
        }

        // Rotate hip bone such that foot is at desired position
        float angle =
            Vector3.Angle(
                endEffector.position - joints[0].position,
                target-joints[0].position);
        Vector3 axis =
            Vector3.Cross(
                endEffector.position - joints[0].position,
                target-joints[0].position);
        joints[0].rotation =
            Quaternion.AngleAxis(angle, axis) * joints[0].rotation;
    }
Пример #9
0
 public override void Solve(IKJoint[] joints, Vector3 target)
 {
     this.Solve(joints, joints[joints.Length - 1].transform, target);
 }