/** * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. */ using Live2D.Cubism.Core; using UnityEngine; namespace Live2D.Cubism.Framework.Physics { /// /// Math utilities for physics. /// internal static class CubismPhysicsMath { /// /// Gets radian from degrees. /// /// Degrees. /// Radian. public static float DegreesToRadian(float degrees) { return (degrees / 180.0f) * Mathf.PI; } /// /// Gets degrees from radian. /// /// Radian. /// Degrees. public static float RadianToDegrees(float radian) { return (radian * 180.0f) / Mathf.PI; } /// /// Gets angle from both vector direction. /// /// From vector. /// To vector. /// Angle of radian. public static float DirectionToRadian(Vector2 from, Vector2 to) { var q1 = Mathf.Atan2(to.y, to.x); var q2 = Mathf.Atan2(from.y, from.x); return GetAngleDiff(q1, q2); } /// /// Gets difference of angle. /// /// /// /// public static float GetAngleDiff(float q1, float q2) { var ret = q1 - q2; while (ret < -Mathf.PI) { ret += (Mathf.PI * 2.0f); } while (ret > Mathf.PI) { ret -= (Mathf.PI * 2.0f); } return ret; } /// /// Gets angle from both vector direction. /// /// From vector. /// To vector. /// Angle of degrees. public static float DirectionToDegrees(Vector2 from, Vector2 to) { var radian = DirectionToRadian(from, to); var degree = (float)RadianToDegrees(radian); if ((to.x - from.x) > 0.0f) { degree = -degree; } return degree; } /// /// Gets vector direction from angle. /// /// Radian. /// Direction of vector. public static Vector2 RadianToDirection(float totalAngle) { var ret = Vector2.zero; ret.x = Mathf.Sin(totalAngle); ret.y = (float)Mathf.Cos(totalAngle); return ret; } /// /// Gets range of value. /// /// Minimum value. /// Maximum value. /// private static float GetRangeValue(float min, float max) { var maxValue = Mathf.Max(min, max); var minValue = Mathf.Min(min, max); return Mathf.Abs(maxValue - minValue); } /// /// Gets middle value. /// /// Minimum value. /// Maximum value. /// private static float GetDefaultValue(float min, float max) { var minValue = Mathf.Min(min, max); return minValue + (GetRangeValue(min, max) / 2.0f); } /// /// Normalize parameter value. /// /// Target parameter. /// Value of normalized minimum. /// Value of normalized maximum. /// Value of normalized default. /// True if input is inverted; otherwise. /// public static float Normalize(CubismParameter parameter, float normalizedMinimum, float normalizedMaximum, float normalizedDefault, bool isInverted = false) { var result = 0.0f; var maxValue = Mathf.Max(parameter.MaximumValue, parameter.MinimumValue); if (maxValue < parameter.Value) { parameter.Value = maxValue; } var minValue = Mathf.Min(parameter.MaximumValue, parameter.MinimumValue); if (minValue > parameter.Value) { parameter.Value = minValue; } var minNormValue = Mathf.Min(normalizedMinimum, normalizedMaximum); var maxNormValue = Mathf.Max(normalizedMinimum, normalizedMaximum); var middleNormValue = normalizedDefault; var middleValue = GetDefaultValue(minValue, maxValue); var paramValue = parameter.Value - middleValue; switch ((int)Mathf.Sign(paramValue)) { case 1: { var nLength = maxNormValue - middleNormValue; var pLength = maxValue - middleValue; if (pLength != 0.0f) { result = paramValue * (nLength / pLength); result += middleNormValue; } break; } case -1: { var nLength = minNormValue - middleNormValue; var pLength = minValue - middleValue; if (pLength != 0.0f) { result = paramValue * (nLength / pLength); result += middleNormValue; } break; } case 0: { result = middleNormValue; break; } } return (isInverted) ? result : (result * -1.0f); } } }