Делая синусоину круче?

Я написал небольшую функцию, которая дает мне значение, основанное на синусоидальной волне, когда я помещаю float между 0 и 1. Я использую его для lerp в игре.

public static class Utilities 
{
    public static float SineMe(float prop)
    {
        float output = (prop*180f)-90f;

        output = Mathf.Sin(output*Mathf.Deg2Rad);

        output = (output+1f)/2f;

        return output;
    }
}

Это прекрасно работает. Но мне было интересно, есть ли математический способ изменения синусоиды, чтобы я мог сделать его "круче" или "более мелким" посередине? На приведенной ниже диаграмме синяя кривая представляет собой синусоидальную волну, мне интересно, могу ли я сделать ее более похожей на зеленую линию.

enter image description here

Ответ 1

То, что вы показываете уже, на самом деле не является синусоидальным - диапазон синусов находится между -1 и +1. Вы применяете линейную функцию f(x) = (x+1)/2 для изменения этого диапазона. Поэтому поместите другую функцию между синусом и этим преобразованием.

Чтобы изменить форму, вам нужна нелинейная функция. Итак, вот кубическое уравнение, которое вы можете попробовать...

g(x) = Ax^3 + Bx^2 + Cx + D

D = 0
C = p
B = 3 - 3C
A = 1 - (B + C)

Параметру p следует присвоить значение от 0,0 до 9,0. Если это 1,0, g (x) - функция тождества (выход - это немодифицированный ввод). При значениях от 0.0 до 1.0 это будет иметь тенденцию "откармливать" вашу синусоидальную волну (отталкивайте ее от 0.0 до 1.0 или -1.0), что, как вам кажется, требуется.

Я однажды "спроектировал" эту функцию как способ получить "фрактальные волны". Используя значения p между 1.0 и 9.0 (и особенно между около 3.0 и 6.0), итерационное применение этой формулы хаотично. Я украл эту идею из хаотической функции флуктуации численности населения Р. М. Май, но что квадратичный - я хотел что-то симметричное, поэтому мне нужна кубическая функция. На самом деле это не очень важно, и довольно сильная идея, как это происходит. Хотя вы, безусловно, получаете хаотические сигналы, что на самом деле означает огромные проблемы с aliassing - изменение частоты дискретизации, и вы получаете совсем другой звук. Тем не менее, без итерации, возможно, это даст вам то, что вам нужно.

Если вы повторяете достаточно времени с p между 0.0 и 1.0, вы получите квадратную волну со слегка закругленными углами.

Скорее всего, вы можете просто выбрать значение p между 0.0 и 1.0, применить эту функцию один раз, а затем применить свою функцию для изменения диапазона, и вы получите то, что хотите.

Кстати, уже есть комментарий, предлагающий чит-лист "облегчающих функций". "Ослабление" - это термин из анимации, а компьютерная анимационная программа часто использует кривые Безье для этой цели - те же кривые Безье, которые часто используют программное обеспечение векторной графики. Кривые Безье представлены в квадратичных и кубических вариантах, причем кубическое является более распространенным. Так что, вероятно, это не так. Однако кубическое упрощение Bezier дает вам больше контроля - вы можете управлять "легкостью" независимо от "облегчения", когда моя функция предоставляет только один параметр.

Ответ 2

Вы можете использовать функцию y(x) = 1-(1-x)^n, когда x = [0..1], как функцию преобразования.

Вам просто нужно заменить x на абсолютное значение вашего sinus и сообщить результат sinus к результату. Таким образом, вы можете настроить наклон синуса, увеличив n. Итак, что вы хотите, так это:

float sinus = Mathf.Sin(output*Mathf.Deg2Rad);
int sign = (sinus >= 0 ? 1 : -1);

int n = 4; // slope parameter

float waveform = sign * ( 1-Mathf.Pow(1-Mathf.Abs(sinus), n) );