/**
* 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);
}
}
}