Exemplo n.º 1
0
            private void SolvePelvis()
            {
                // Pelvis target
                if (pelvisPositionWeight > 0f)
                {
                    Quaternion headSolverRotation = head.solverRotation;

                    Vector3 delta = ((IKPositionPelvis + pelvisPositionOffset) - pelvis.solverPosition) * pelvisPositionWeight;
                    foreach (VirtualBone bone in bones)
                    {
                        bone.solverPosition += delta;
                    }

                    Vector3 bendNormal = anchorRotation * Vector3.right;

                    if (hasNeck)
                    {
                        VirtualBone.SolveTrigonometric(bones, 0, 1, bones.Length - 1, headPosition, bendNormal, pelvisPositionWeight * 0.6f);
                        VirtualBone.SolveTrigonometric(bones, 1, 2, bones.Length - 1, headPosition, bendNormal, pelvisPositionWeight * 0.6f);
                        VirtualBone.SolveTrigonometric(bones, 2, 3, bones.Length - 1, headPosition, bendNormal, pelvisPositionWeight * 1f);
                    }
                    else
                    {
                        VirtualBone.SolveTrigonometric(bones, 0, 1, bones.Length - 1, headPosition, bendNormal, pelvisPositionWeight * 0.75f);
                        VirtualBone.SolveTrigonometric(bones, 1, 2, bones.Length - 1, headPosition, bendNormal, pelvisPositionWeight * 1f);
                    }

                    head.solverRotation = headSolverRotation;
                }
            }
Exemplo n.º 2
0
            public void Solve(bool stretch)
            {
                if (stretch && LOD < 1)
                {
                    Stretching();
                }

                // Foot pass
                VirtualBone.SolveTrigonometric(bones, 0, 1, 2, footPosition, bendNormal, 1f);

                // Rotate foot back to where it was before the last solving
                RotateTo(foot, footRotation);

                // Toes pass
                if (!hasToes)
                {
                    FixTwistRotations();
                    return;
                }

                Vector3 b = Vector3.Cross(foot.solverPosition - thigh.solverPosition, toes.solverPosition - foot.solverPosition).normalized;

                VirtualBone.SolveTrigonometric(bones, 0, 2, 3, position, b, 1f);

                // Fix thigh twist relative to target rotation
                FixTwistRotations();

                // Keep toe rotation fixed
                toes.solverRotation = rotation;
            }
            public void Solve()
            {
                // Foot pass
                VirtualBone.SolveTrigonometric(bones, 0, 1, 2, footPosition, bendNormal, 1f);

                // Rotate foot back to where it was before the last solving
                RotateTo(foot, footRotation);

                // Toes pass
                if (!hasToes)
                {
                    return;
                }

                Vector3 b = Vector3.Cross(foot.solverPosition - thigh.solverPosition, toes.solverPosition - foot.solverPosition);

                VirtualBone.SolveTrigonometric(bones, 0, 2, 3, position, b, 1f);

                // Fix calf twist relative to thigh
                Quaternion calfRotation = thigh.solverRotation * calfRelToThigh;
                Quaternion fromTo       = Quaternion.FromToRotation(calfRotation * calf.axis, foot.solverPosition - calf.solverPosition);

                RotateTo(calf, fromTo * calfRotation, 1f);

                // Keep toe rotation fixed
                toes.solverRotation = rotation;
            }
Exemplo n.º 4
0
            public void Solve(bool stretch)
            {
                if (stretch)
                {
                    Stretching();
                }

                // Foot pass
                VirtualBone.SolveTrigonometric(bones, 0, 1, 2, footPosition, bendNormal, 1f);

                // Rotate foot back to where it was before the last solving
                RotateTo(foot, footRotation);

                // Toes pass
                if (!hasToes)
                {
                    return;
                }

                Vector3 b = Vector3.Cross(foot.solverPosition - thigh.solverPosition, toes.solverPosition - foot.solverPosition);

                VirtualBone.SolveTrigonometric(bones, 0, 2, 3, position, b, 1f);

                // Fix thigh twist relative to target rotation
                if (bendToTargetWeight > 0f)
                {
                    Quaternion thighRotation = rotation * thighRelToFoot;
                    Quaternion f             = Quaternion.FromToRotation(thighRotation * thigh.axis, calf.solverPosition - thigh.solverPosition);
                    if (bendToTargetWeight < 1f)
                    {
                        thigh.solverRotation = Quaternion.Slerp(thigh.solverRotation, f * thighRotation, bendToTargetWeight);
                    }
                    else
                    {
                        thigh.solverRotation = f * thighRotation;
                    }
                }

                // Fix calf twist relative to thigh
                Quaternion calfRotation = thigh.solverRotation * calfRelToThigh;
                Quaternion fromTo       = Quaternion.FromToRotation(calfRotation * calf.axis, foot.solverPosition - calf.solverPosition);

                calf.solverRotation = fromTo * calfRotation;

                // Keep toe rotation fixed
                toes.solverRotation = rotation;
            }
Exemplo n.º 5
0
            private void SolvePelvis()
            {
                // Pelvis target
                if (pelvisPositionWeight > 0f)
                {
                    Quaternion headSolverRotation = head.solverRotation;

                    Vector3 delta = ((IKPositionPelvis + pelvisPositionOffset) - pelvis.solverPosition) * pelvisPositionWeight;
                    foreach (VirtualBone bone in bones)
                    {
                        bone.solverPosition += delta;
                    }

                    Vector3 bendNormal = anchorRotation * Vector3.right;

                    if (hasChest && hasNeck)
                    {
                        VirtualBone.SolveTrigonometric(bones, pelvisIndex, spineIndex, headIndex, headPosition, bendNormal, pelvisPositionWeight * 0.6f);
                        VirtualBone.SolveTrigonometric(bones, spineIndex, chestIndex, headIndex, headPosition, bendNormal, pelvisPositionWeight * 0.6f);
                        VirtualBone.SolveTrigonometric(bones, chestIndex, neckIndex, headIndex, headPosition, bendNormal, pelvisPositionWeight * 1f);
                    }
                    else if (hasChest && !hasNeck)
                    {
                        VirtualBone.SolveTrigonometric(bones, pelvisIndex, spineIndex, headIndex, headPosition, bendNormal, pelvisPositionWeight * 0.75f);
                        VirtualBone.SolveTrigonometric(bones, spineIndex, chestIndex, headIndex, headPosition, bendNormal, pelvisPositionWeight * 1f);
                    }
                    else if (!hasChest && hasNeck)
                    {
                        VirtualBone.SolveTrigonometric(bones, pelvisIndex, spineIndex, headIndex, headPosition, bendNormal, pelvisPositionWeight * 0.75f);
                        VirtualBone.SolveTrigonometric(bones, spineIndex, neckIndex, headIndex, headPosition, bendNormal, pelvisPositionWeight * 1f);
                    }
                    else if (!hasNeck && !hasChest)
                    {
                        VirtualBone.SolveTrigonometric(bones, pelvisIndex, spineIndex, headIndex, headPosition, bendNormal, pelvisPositionWeight);
                    }

                    head.solverRotation = headSolverRotation;
                }
            }
Exemplo n.º 6
0
            public void Solve(bool isLeft)
            {
                chestRotation = Quaternion.LookRotation(rootRotation * chestForwardAxis, rootRotation * chestUpAxis);
                chestForward  = chestRotation * Vector3.forward;
                chestUp       = chestRotation * Vector3.up;

                //Debug.DrawRay (Vector3.up * 2f, chestForward);
                //Debug.DrawRay (Vector3.up * 2f, chestUp);

                if (hasShoulder && shoulderRotationWeight > 0f)
                {
                    switch (shoulderRotationMode)
                    {
                    case ShoulderRotationMode.YawPitch:
                        Vector3 sDir = position - shoulder.solverPosition;
                        sDir = sDir.normalized;

                        // Shoulder Yaw
                        float      yOA          = isLeft? yawOffsetAngle: -yawOffsetAngle;
                        Quaternion yawOffset    = Quaternion.AngleAxis((isLeft? -90f: 90f) + yOA, chestUp);
                        Quaternion workingSpace = yawOffset * chestRotation;

                        //Debug.DrawRay(Vector3.up * 2f, workingSpace * Vector3.forward);
                        //Debug.DrawRay(Vector3.up * 2f, workingSpace * Vector3.up);

                        Vector3 sDirWorking = Quaternion.Inverse(workingSpace) * sDir;

                        //Debug.DrawRay(Vector3.up * 2f, sDirWorking);

                        float yaw = Mathf.Atan2(sDirWorking.x, sDirWorking.z) * Mathf.Rad2Deg;

                        float dotY = Vector3.Dot(sDirWorking, Vector3.up);
                        dotY = 1f - Mathf.Abs(dotY);
                        yaw *= dotY;

                        yaw -= yOA;
                        float yawLimitMin = isLeft? -20f: -50f;
                        float yawLimitMax = isLeft? 50f: 20f;
                        yaw = DamperValue(yaw, yawLimitMin - yOA, yawLimitMax - yOA, 0.7f);                         // back, forward

                        Vector3    f           = shoulder.solverRotation * shoulder.axis;
                        Vector3    t           = workingSpace * (Quaternion.AngleAxis(yaw, Vector3.up) * Vector3.forward);
                        Quaternion yawRotation = Quaternion.FromToRotation(f, t);

                        //Debug.DrawRay(Vector3.up * 2f, f, Color.red);
                        //Debug.DrawRay(Vector3.up * 2f, t, Color.green);

                        //Debug.DrawRay(Vector3.up * 2f, yawRotation * Vector3.forward, Color.blue);
                        //Debug.DrawRay(Vector3.up * 2f, yawRotation * Vector3.up, Color.green);
                        //Debug.DrawRay(Vector3.up * 2f, yawRotation * Vector3.right, Color.red);

                        // Shoulder Pitch
                        Quaternion pitchOffset = Quaternion.AngleAxis(isLeft? -90f: 90f, chestUp);
                        workingSpace = pitchOffset * chestRotation;
                        workingSpace = Quaternion.AngleAxis(isLeft? pitchOffsetAngle: -pitchOffsetAngle, chestForward) * workingSpace;

                        //Debug.DrawRay(Vector3.up * 2f, workingSpace * Vector3.forward);
                        //Debug.DrawRay(Vector3.up * 2f, workingSpace * Vector3.up);

                        sDir        = position - (shoulder.solverPosition + chestRotation * (isLeft? Vector3.right: Vector3.left) * mag);
                        sDirWorking = Quaternion.Inverse(workingSpace) * sDir;

                        //Debug.DrawRay(Vector3.up * 2f, sDirWorking);

                        float pitch = Mathf.Atan2(sDirWorking.y, sDirWorking.z) * Mathf.Rad2Deg;

                        pitch -= pitchOffsetAngle;
                        pitch  = DamperValue(pitch, -45f - pitchOffsetAngle, 45f - pitchOffsetAngle);
                        Quaternion pitchRotation = Quaternion.AngleAxis(-pitch, workingSpace * Vector3.right);

                        //Debug.DrawRay(Vector3.up * 2f, pitchRotation * Vector3.forward, Color.green);
                        //Debug.DrawRay(Vector3.up * 2f, pitchRotation * Vector3.up, Color.green);

                        // Rotate bones
                        Quaternion sR = pitchRotation * yawRotation;
                        if (shoulderRotationWeight * positionWeight < 1f)
                        {
                            sR = Quaternion.Lerp(Quaternion.identity, sR, shoulderRotationWeight * positionWeight);
                        }
                        VirtualBone.RotateBy(bones, sR);

                        Stretching();

                        // Solve trigonometric
                        VirtualBone.SolveTrigonometric(bones, 1, 2, 3, position, GetBendNormal(position - upperArm.solverPosition), positionWeight);

                        float p = Mathf.Clamp(pitch * positionWeight * shoulderRotationWeight * shoulderTwistWeight * 2f, 0f, 180f);
                        shoulder.solverRotation = Quaternion.AngleAxis(p, shoulder.solverRotation * (isLeft? shoulder.axis: -shoulder.axis)) * shoulder.solverRotation;
                        upperArm.solverRotation = Quaternion.AngleAxis(p, upperArm.solverRotation * (isLeft? upperArm.axis: -upperArm.axis)) * upperArm.solverRotation;

                        // Additional pass to reach with the shoulders
                        //VirtualBone.SolveTrigonometric(bones, 0, 1, 3, position, Vector3.Cross(upperArm.solverPosition - shoulder.solverPosition, hand.solverPosition - shoulder.solverPosition), positionWeight * 0.5f);
                        break;

                    case ShoulderRotationMode.FromTo:
                        Quaternion shoulderRotation = shoulder.solverRotation;

                        Quaternion r = Quaternion.FromToRotation((upperArm.solverPosition - shoulder.solverPosition).normalized + chestForward, position - shoulder.solverPosition);
                        r = Quaternion.Slerp(Quaternion.identity, r, 0.5f * shoulderRotationWeight * positionWeight);
                        VirtualBone.RotateBy(bones, r);

                        Stretching();

                        VirtualBone.SolveTrigonometric(bones, 0, 2, 3, position, Vector3.Cross(forearm.solverPosition - shoulder.solverPosition, hand.solverPosition - shoulder.solverPosition), 0.5f * shoulderRotationWeight * positionWeight);
                        VirtualBone.SolveTrigonometric(bones, 1, 2, 3, position, GetBendNormal(position - upperArm.solverPosition), positionWeight);

                        // Twist shoulder and upper arm bones when holding hands up
                        Quaternion q           = Quaternion.Inverse(Quaternion.LookRotation(chestUp, chestForward));
                        Vector3    vBefore     = q * (shoulderRotation * shoulder.axis);
                        Vector3    vAfter      = q * (shoulder.solverRotation * shoulder.axis);
                        float      angleBefore = Mathf.Atan2(vBefore.x, vBefore.z) * Mathf.Rad2Deg;
                        float      angleAfter  = Mathf.Atan2(vAfter.x, vAfter.z) * Mathf.Rad2Deg;
                        float      pitchAngle  = Mathf.DeltaAngle(angleBefore, angleAfter);
                        if (isLeft)
                        {
                            pitchAngle = -pitchAngle;
                        }
                        pitchAngle = Mathf.Clamp(pitchAngle * shoulderRotationWeight * shoulderTwistWeight * 2f * positionWeight, 0f, 180f);

                        shoulder.solverRotation = Quaternion.AngleAxis(pitchAngle, shoulder.solverRotation * (isLeft? shoulder.axis: -shoulder.axis)) * shoulder.solverRotation;
                        upperArm.solverRotation = Quaternion.AngleAxis(pitchAngle, upperArm.solverRotation * (isLeft? upperArm.axis: -upperArm.axis)) * upperArm.solverRotation;
                        break;
                    }
                }
                else
                {
                    Stretching();

                    // Solve arm trigonometric
                    if (hasShoulder)
                    {
                        VirtualBone.SolveTrigonometric(bones, 1, 2, 3, position, GetBendNormal(position - upperArm.solverPosition), positionWeight);
                    }
                    else
                    {
                        VirtualBone.SolveTrigonometric(bones, 0, 1, 2, position, GetBendNormal(position - upperArm.solverPosition), positionWeight);
                    }
                }

                // Fix forearm twist relative to upper arm
                Quaternion forearmFixed = upperArm.solverRotation * forearmRelToUpperArm;
                Quaternion fromTo       = Quaternion.FromToRotation(forearmFixed * forearm.axis, hand.solverPosition - forearm.solverPosition);

                RotateTo(forearm, fromTo * forearmFixed, positionWeight);

                // Set hand rotation
                if (rotationWeight >= 1f)
                {
                    hand.solverRotation = rotation;
                }
                else if (rotationWeight > 0f)
                {
                    hand.solverRotation = Quaternion.Lerp(hand.solverRotation, rotation, rotationWeight);
                }
            }