Интерполяция ключевых кадров

Это приложение описывает алгоритмы что использование Final Cut Pro для интерполяции ключевых кадров с Кривыми Безье (кроме скорости).

Об интерполяции Final Cut Pro

Final Cut Pro использует и 1D и 2D Кривые Безье для интерполяции ключевых кадров. 2D алгоритм Безье является простым расширением 1D алгоритм.

Основа математики, использование Final Cut Pro для нахождения данной точки на Кривой Безье описано в статье «Quick and Simple Bezier Curve Drawing» Роберта Миллера, появляющегося в Графическом Объеме Драгоценных камней 5, страница 206. Final Cut Pro изменяет этот алгоритм для учета ускорения в кривой. В результате пользователи Final Cut Pro могут изменить скорость движения в и из ключевого кадра.

В Final Cut Pro Кривые Безье представлены приближением кривой, составленной из 40 линейных сегментов. Сам код Безье разделен на две части. Первая часть создает структуру Безье и вычисляет расположение всех 40 составляющих сегментов кривой. Вторая часть кода находит расположение данного времени на кривой.

Для создания структуры, представляющей Кривую Безье Final Cut Pro сначала инициализирует много переменных. Этот первый набор переменных — ускоряющих коэффициентов — позволяет пользователю упростить эффект в конечные точки кривой. Это сделано путем смещения их или в или из конечных точек с помощью экспоненциального масштабного коэффициента для создания кривой питания.

  Ускоряющие коэффициенты перечисления c-1

    leftScale = curve[i].scale[1];
    leftVal = pow(10, -leftScale)- 1.0;
    rightScale = curve[i+1].scale[0];
    rightVal = pow(10, -rightScale) - 1.0;

Значения масштаба leftScale и rightScale получены из виджета UI. Значения этого масштабного коэффициента плавающего располагаются от 1 (смещенный далеко от конечной точки) к -1 (смещенный к конечной точке).

Затем, Final Cut Pro инициализирует Декартово расположение контрольных точек сегмента Кривой Безье путем рассмотрения значений, переданных в как массив точек Безье, FloatPt *seg. Эти значения представляют расположение контрольных точек Кривой Безье.

  Контрольные точки перечисления c-2

MakeBezSegment(Bezier curve, int32 index, FloatPt *seg) {
 
    FloatPt temp;
 
    seg[0] = curve[index].location;
    seg[3] = curve[index+1].location;
 
    if (curve[index].vector[1].length == 0) {
        seg[1].h = seg[0].h + (seg[3].h - seg[0].h) / 2.0 / SCALE_MULT_CONST;
        seg[1].v = seg[0].v + (seg[3].v - seg[0].v) / 2.0 / SCALE_MULT_CONST;
    }
    else {
        PolarToCart(&curve[index].vector[1], &temp);
        seg[1].h = seg[0].h + temp.h * SCALE_MULT_CONST;
        seg[1].v = seg[0].v + temp.v * SCALE_MULT_CONST;
    }
 
    if (curve[index+1].vector[0].length == 0) {
        seg[2].h = seg[3].h + (seg[0].h - seg[3].h) / 2.0 / SCALE_MULT_CONST;
        seg[2].v = seg[3].v + (seg[0].v - seg[3].v) / 2.0 / SCALE_MULT_CONST;
    }
    else {
        PolarToCart(&curve[index+1].vector[0], &temp);
        seg[2].h = seg[3].h + temp.h * SCALE_MULT_CONST;
        seg[2].v = seg[3].v + temp.v * SCALE_MULT_CONST;
    }
}

С этой завершенной работой инициализации Final Cut Pro теперь использует алгоритм, найденный в статье Robert Miller к быстро, и многократно вычислите расположение точек на кривой. Во-первых, Final Cut Pro инициализирует значения вершин многоугольника управления Кривой Безье:

  Расположения перечисления c-3

BezierForm(FloatPt *p, FloatPt *c, int numCtlPoints) {
 
    Int32 i, multiplier;
 
    for (i = 0; i <= numCtlPoints - 1; i++) {
        if (i == 0) multiplier = 1;
        else if (i == 1) multiplier = numCtlPoints - 1;
        else multiplier = multiplier * (numCtlPoints - i) / i;
 
        c[k].h = p[k].h * multiplier;
        c[k].v = p[k].v * multiplier;
    }
}

Теперь Final Cut Pro готов вычислить заключительную позицию каждого линейного сегмента, представляющего Кривую Безье. Это делает это вычисление с помощью заключительных контрольных точек кривой и ускоряющих коэффициентов, вычисленных ранее.

Циклы Final Cut Pro по 40 сегментам, составляющим кривую. Для каждой точки это вычисляет расстояние вдоль кривой как часть, например 0, 1/40-й, 2/40-й, 3/40-й, … 39/40-й, 40/40-й. Тогда это определяет, является ли точка на левой или правой половине кривой и применяет надлежащее ускоряющее значение. Это сеть магазинов, которую постоянное ускорение вычислило в начале фактором вклада, приводящим к желаемому ускоряющему фактору.

  Сегменты Linear перечисления c-4

percent = (float)i / 40;
if (percent <= 0.5) {
if (leftScale != 0.0) {
        contribution = (1.0 - (percent * 2));
        contribution *= contribution;           // ^2
        contribution *= contribution;           // ^4
        contribution *= contribution;           // ^8
        scale = 1.0 + leftVal * contribution;
}
else scale = 1.0;
}
else {
    if (rightScale != 0.0) {
        contribution = ((percent * 2) - 1.0);
        contribution *= contribution;           // ^2
        contribution *= contribution;           // ^4
        contribution *= contribution;           // ^8
        scale = 1.0 + rightVal * contribution;
    }
    else scale = 1.0;
}

В действительности эти вычисления продвигают сегменты кривой в одном направлении или другом, или «хлюпание» сегментов кривой к конечной точке или «получение по запросу» их далеко.

Теперь Final Cut Pro сплачивает эти значения. Сначала. это фиксирует позицию каждой контрольной точки, вычисленной с помощью алгоритма Миллера BezierForm. См., что Перечисление c-3 Использует заключительный масштабный коэффициент, вычисленный в Перечислении c-4, программа может расширить или уменьшить величину этого линейного сегмента кривой. Это может вычислить значение кривой в любой точке путем интерполяции между этими контрольными точками.

  Кривая Безье перечисления c-5

BezierCurve(FloatPt *c, FloatPt *pt, float t) {
 
    int32               i, n;
    float               t1, tt, u;
    FloatPt         b[NUM_CONTL_POINTS];
 
    n = NUM_CONTL_POINTS - 1;
    u = t;
 
    b[0].h = c[0].h;
    b[0].v = c[0].v;
    for (i =1; i <=n; i++) {
        b[i].h = c[i].h * u;
        b[i].v = c[i].v * u;
        u = u * t;
    }
 
    (*pt).h = b[n].h;  (*pt).v = b[n].v;
 
    t1 = 1 - t;
    tt = t1;
    for (k = n - 1; i >= 0; i--) {
        (*pt).h += b[i].h * tt;
        (*pt).v += b[i].v * tt;
        tt = tt * t1;
    }
}

Теперь, когда Final Cut Pro имеет всю информацию, необходимую о Декартовой позиции текущего линейного сегмента вдоль фактической кривой, это может обновить структуру Безье, представляющую кривую с этими данными. Этот процесс включает запись запуска и позиции конца сегмента и вычисления строки, соединяющей эти точки при масштабировании линейного сегмента расчетным ускоряющим фактором. Цикличное выполнение вокруг от точка-точка, приложение вычисляет позицию всех 40 точек кривой.

Наконец, прежде, чем закончиться с этим сегментом кривой, Final Cut Pro вычисляет временную стоимость для каждой точки сегмента. Позже, это использует эти временные стоимости, чтобы искать и интерполировать значения между точками сегмента. Этот процесс является простым вопросом вычисления текущей позиции на кривой и затем использовании этого значения для вычислений общего времени вдоль кривой, которую представляет эта позиция.