public static void Output(ref CharacterMuscleOutput o, CharacterParts p)
 {
     p.LegLUpper.TargetRotation = Quaternion.Euler(o.LegLUpperPitch, o.LegLUpperRoll, o.LegLUpperClose);
     p.LegRUpper.TargetRotation = Quaternion.Euler(o.LegRUpperPitch, o.LegRUpperRoll, o.LegRUpperClose);
     p.LegLLower.TargetRotation = Quaternion.Euler(o.LegLLowerPitch, 0f, 0f);
     p.LegRLower.TargetRotation = Quaternion.Euler(o.LegRLowerPitch, 0f, 0f);
     p.ArmLUpper.TargetRotation = Quaternion.Euler(o.ArmLUpperPitch, o.ArmLUpperRoll, o.ArmLClose);
     p.ArmRUpper.TargetRotation = Quaternion.Euler(o.ArmRUpperPitch, o.ArmRUpperRoll, o.ArmRClose);
     p.ArmLLower.TargetRotation = Quaternion.Euler(o.ArmLLowerPitch, 0f, 0f);
     p.ArmRLower.TargetRotation = Quaternion.Euler(o.ArmRLowerPitch, 0f, 0f);
     p.Torso.TargetRotation     = Quaternion.Euler(o.TorsoPitch, o.TorsoRoll, o.TorsoYaw);
     p.ArmLUpper.TargetPosition = new Vector3(0f, 0f, o.ShoulderLPitch);
     p.ArmRUpper.TargetPosition = new Vector3(0f, 0f, o.ShoulderRPitch);
 }
        private void AnimateParachute(ParachuteInput input, CharacterMuscleLimits limits, CharacterParts parts)
        {
            CharacterMuscleOutput o = new CharacterMuscleOutput();

            Vector2 lineInput = Max(input.Brakes, input.FrontRisers, input.RearRisers);

            /* Todo: Lower body has to try and cancel out oscillations about harness pivot
             * I suspect that if we can get a rough version of this going it'll be enough
             */

            o.ArmLClose       = -lineInput.x * 0.6f;
            o.ArmRClose       = lineInput.y * 0.6f;
            o.LegLUpperPitch  = Mathf.Abs(input.WeightShift.y) * 0.66f;
            o.LegRUpperPitch  = Mathf.Abs(input.WeightShift.y) * 0.66f;
            o.LegLLowerPitch  = input.WeightShift.y;
            o.LegRLowerPitch  = input.WeightShift.y;
            o.LegLUpperClose -= input.WeightShift.x;
            o.LegRUpperClose -= input.WeightShift.x;
            o.TorsoPitch      = -input.WeightShift.y;
            o.TorsoRoll       = input.WeightShift.x * 0.66f;

            CharacterMuscleOutput.Clamp(ref o);
            CharacterMuscleOutput.ScaleToLimits(ref o, limits);
            CharacterMuscleOutput.ApplyPose(ref o, _parachutePose);
            CharacterMuscleOutput.Output(ref o, parts);
        }
        private void AnimateWingsuit(CharacterInput input, CharacterMuscleLimits limits, CharacterParts parts)
        {
            PlayerPose.Lerp(ref _currentPose, _defaultPose, _curledPose, input.Cannonball);

            float normalizedSpeed = Mathf.Clamp01(_target.RelativeVelocity.magnitude / _wingsuitStabilizerConfig.MaxSpeed);

            input.CloseLeftArm  += Mathf.Pow(normalizedSpeed, 1.5f) * 0.25f;
            input.CloseRightArm += Mathf.Pow(normalizedSpeed, 1.5f) * 0.25f;

            float pitchUp   = Mathf.Min(0f, input.Pitch);
            float pitchDown = Mathf.Min(0f, -input.Pitch);

            CharacterMuscleOutput o = new CharacterMuscleOutput();

            /* Transform user input into joint angle modifications. (still in unit values) */
            o.ShoulderLPitch = input.Pitch + input.Roll - input.CloseLeftArm;
            o.ShoulderRPitch = input.Pitch - input.Roll - input.CloseRightArm;
            o.ArmLUpperPitch = input.Roll * 0.3f + pitchDown * 0f - input.CloseLeftArm * 0.5f;
            o.ArmRUpperPitch = -input.Roll * 0.3f + pitchDown * 0f - input.CloseRightArm * 0.5f;
            o.ArmLUpperRoll  = -input.Pitch;
            o.ArmRUpperRoll  = input.Pitch;
            o.ArmLLowerPitch = -input.Pitch * 1f + -input.Roll * 0.5f + input.CloseLeftArm * 0.0f;
            o.ArmRLowerPitch = -input.Pitch * 1f + input.Roll * 0.5f + input.CloseRightArm * 0.0f;
            o.ArmLClose      = -input.CloseLeftArm * 1f + pitchDown * 1f + input.Roll * (input.Roll < 0f ? 1f : 0f);
            o.ArmRClose      = input.CloseRightArm * 1f - pitchDown * 1f + input.Roll * (input.Roll > 0f ? 1f : 0f);
            o.LegLUpperPitch = pitchUp * 1.0f + Mathf.Pow(pitchDown, 2f) * 0.5f + input.Yaw * 0.25f;
            o.LegRUpperPitch = pitchUp * 1.0f + Mathf.Pow(pitchDown, 2f) * 0.5f - input.Yaw * 0.25f;
            o.LegLUpperRoll  = input.Roll;
            o.LegRUpperRoll  = input.Roll;
            o.LegLLowerPitch = pitchUp * 1f + Mathf.Pow(pitchDown, 2f) + input.Yaw * 1f;
            o.LegRLowerPitch = pitchUp * 1f + Mathf.Pow(pitchDown, 2f) - input.Yaw * 1f;
            o.TorsoPitch     = pitchUp * 0.5f;
            o.TorsoRoll      = input.Roll * 1f + input.Yaw * 1f;
            o.TorsoYaw       = input.Yaw * 0.5f;

            CharacterMuscleOutput.Clamp(ref o);
            CharacterMuscleOutput.ScaleToLimits(ref o, limits);
            CharacterMuscleOutput.ApplyPose(ref o, _currentPose);

            /* Apply a specific stability effect to just the arms (Todo: move this elsewhere, make configurable) */

            float armUpperPitchHeadingStability = 10f * Mathf.InverseLerp(15f, -5f, _target.AngleOfAttack);

            o.ArmLUpperPitch += armUpperPitchHeadingStability;
            o.ArmRUpperPitch += armUpperPitchHeadingStability;

            float armLowerPitchHeadingStability = 15f * Mathf.InverseLerp(20f, -5f, _target.AngleOfAttack);

            o.ArmLLowerPitch += armLowerPitchHeadingStability;
            o.ArmRLowerPitch += armLowerPitchHeadingStability;

            /* Apply user-configured pitch attitude offset */

            o.TorsoPitch     += limits.PitchAttitudeTorsoMax * _userConfig.PitchAttitude;
            o.LegLUpperPitch += limits.PitchAttitudeLegsMax * _userConfig.PitchAttitude;
            o.LegRUpperPitch += limits.PitchAttitudeLegsMax * _userConfig.PitchAttitude;

            /* Send new targets to all the joints */

            CharacterMuscleOutput.Output(ref o, parts);
        }