Exemple #1
0
    void Update()
    {
        if (target.position.y > 1.25f)
        {
            for (int i = 0; i < joints.Length; i++)
            {
                jointsPositions[i] = new MyVector3(joints[i].position.x, joints[i].position.y, joints[i].position.z);
            }
            targetPosition = new MyVector3(target.position.x, target.position.y, target.position.z);

            // Copy the joints positions to work with
            // and calculate all the distances
            for (int i = 0; i < copy.Length; i++)
            {
                copy[i] = jointsPositions[i];
                if (i < distances.Length)
                {
                    distances[i] = (jointsPositions[i + 1] - jointsPositions[i]).magnitude();
                }
            }

            done = (targetPosition - jointsPositions[jointsPositions.Length - 1]).magnitude() < threshold_distance;
            if (!done)
            {
                float targetRootDist = MyVector3.Distance(copy[0], targetPosition);

                // Update joint positions
                if (targetRootDist > distances.Sum())
                {
                    // The target is unreachable
                    for (int i = 0; i < copy.Length - 1; i++)
                    {
                        float dist = (targetPosition - copy[i]).magnitude();
                        float lam  = distances[i] / dist;
                        copy[i + 1] = (1 - lam) * copy[i] + lam * targetPosition;
                    }
                }
                else
                {
                    // The target is reachable
                    iter = 0;
                    while (!done /*|| iter < maxIter*/)
                    {
                        // STAGE 1: FORWARD REACHING
                        copy[copy.Length - 1] = targetPosition;
                        for (int i = copy.Length - 1; i > 0; i--)
                        {
                            MyVector3 temp = (copy[i - 1] - copy[i]).normalized();
                            temp        = temp * distances[i - 1];
                            copy[i - 1] = temp + copy[i];
                        }

                        // STAGE 2: BACKWARD REACHING
                        copy[0] = jointsPositions[0];
                        for (int i = 0; i < copy.Length - 2; i++)
                        {
                            MyVector3 temp = (copy[i + 1] - copy[i]).normalized();
                            temp        = temp * distances[i];
                            copy[i + 1] = temp + copy[i];
                        }

                        done = (targetPosition - copy[copy.Length - 1]).magnitude() < threshold_distance;
                        iter++;
                    }
                }

                // Update original joint rotations
                for (int i = 0; i <= joints.Length - 2; i++)
                {
                    MyVector3 a = jointsPositions[i + 1] - jointsPositions[i];

                    MyVector3 b    = copy[i + 1] - copy[i];
                    MyVector3 axis = MyVector3.Cross(a, b).normalized();

                    float cosa = MyVector3.Dot(a, b) / (a.magnitude() * b.magnitude());
                    float sina = MyVector3.Cross(a.normalized(), b.normalized()).magnitude();

                    float angle = Mathf.Atan2(sina, cosa);

                    MyQuaternion q         = new MyQuaternion(Mathf.Cos(angle / 2), axis.x * Mathf.Sin(angle / 2), axis.y * Mathf.Sin(angle / 2), axis.z * Mathf.Sin(angle / 2));
                    MyQuaternion actualRot = new MyQuaternion(joints[i].rotation.w, joints[i].rotation.x, joints[i].rotation.y, joints[i].rotation.z);
                    MyQuaternion newRot    = MyQuaternion.multiply(q, actualRot);


                    jointsPositions[i] = copy[i];
                    joints[i].position = new Vector3(jointsPositions[i].x, jointsPositions[i].y, jointsPositions[i].z);
                    joints[i].rotation = new Quaternion(newRot.x, newRot.y, newRot.z, newRot.w);

                    for (int j = i; j < joints.Length; j++)   //Actualizar posiciones de los hijos despues de rotar
                    {
                        jointsPositions[j] = new MyVector3(joints[j].position.x, joints[j].position.y, joints[j].position.z);
                    }
                }
            }
        }
    }