Сглаживание делало Ускорение сообщений - PullRequest
0 голосов
/ 12 ноября 2009

Я работаю над чем-то похожим на инклинометр. Я поворачиваю изображение на основе угла, рассчитанного в didAccelerate (из UIAccelerometerDelegate), используя переданную переменную в UIAcceleration. Изображение нервное или дерганное. Даже когда телефон лежит на спине и не двигается. В магазине приложений есть несколько инклинометров, которые очень плавные. Я попытался сгладить это, проверив последнее чтение и, если оно находится в пределах диапазона, ничего не делать. Это останавливает некоторые подергивания, но затем вы попадаете в нечто, похожее на остановку анимации. Как я могу получить более плавный эффект?

1 Ответ

3 голосов
/ 12 ноября 2009

Я бы предложил сглаживание с использованием «критически затухающей пружины».

По сути, вы рассчитываете вращение цели (то, что у вас есть сейчас). Вместо того, чтобы применять это непосредственно к повороту изображения, вы прикрепляете поворот изображения к целевому повороту с помощью пружины или куска упругости. Пружина демпфируется так, что вы не получаете колебаний.

Вам понадобится одна константа, чтобы настроить скорость реакции системы, мы назовем ее SpringConstant.

По сути, мы прикладываем две силы к вращению, а затем интегрируем это с течением времени. Первая сила, которая применяется пружиной, Fs = SpringConstant * DistanceToTarget. Второе - это демпфирующая сила, Fd = -CurrentVelocity * 2 * sqrt (SpringConstant)

CurrentVelocity является частью состояния системы и может быть инициализирован до нуля.

На каждом шаге вы умножаете сумму этих двух сил на временной шаг. Это дает вам изменение значения CurrentVelocity.

Умножьте это на шаг по времени снова, и это даст вам смещение.

Мы добавляем это к фактическому повороту изображения.

В коде c ++:

float CriticallyDampedSpring( float a_Target,
                              float a_Current,
                              float & a_Velocity,
                              float a_TimeStep )
{
    float currentToTarget = a_Target - a_Current;
    float springForce = currentToTarget * SPRING_CONSTANT;
    float dampingForce = -a_Velocity * 2 * sqrt( SPRING_CONSTANT );
    float force = springForce + dampingForce;
    a_Velocity += force * a_TimeStep;
    float displacement = a_Velocity * a_TimeStep;
    return a_Current + displacement;
}

Я полагаю, у вас есть два измерения вращения. Вам просто нужно использовать это один раз для каждого измерения и отслеживать скорость каждого измерения в отдельности.

В системах, с которыми я работал, 5 было хорошим значением для постоянной пружины, но вам придется экспериментировать для вашей ситуации. Установка слишком высокого значения не избавит от рывка, установка слишком низкого значения будет слишком медленной.

Кроме того, вам лучше всего создать класс, который будет поддерживать состояние скорости, а не передавать его в функцию снова и снова.

Надеюсь, это полезно:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...