пропуск определенного количества кадров на временной шкале - PullRequest
2 голосов
/ 10 мая 2010

У меня есть математическая проблема, которую немного сложно описать, но я все равно попробую.

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

например, у меня есть 10 кадров, и я хочу пропустить 5, тогда решение простое: мы пропускаем каждый второй кадр. 10/5 = 2

if (frame%2 == 0)
    skip();

а что если приведенное выше деление приведет к плавающему числу?

например в 44 кадрах я хочу пропустить 15 раз. Как я могу определить 15 кадров, которые должны быть пропущены?

В основном я ищу алгоритм, который распределяет эти 15 кадров максимально равномерно по 44 кадрам. вероятно, это будет выглядеть как пропуск через 2, а затем через 3 кадра поочередно.

спасибо!

Ответы [ 4 ]

3 голосов
/ 10 мая 2010

Вы можете сохранить дополнительное значение с плавающей точкой, t, которое соответствует следующему кадру для пропуска, и обновлять его каждый раз, когда пропускаете. Как это:

int frame_num = 44; 
int skips_num = 15; 
double dt =((double)(frame_num))/skips_num;
double t = 0.0;
...
// then, in your loop
if (frame == (int)t) {  
  skip();   
  t += dt; 
}
2 голосов
/ 10 мая 2010

Меня удивляет, что проблема смешивания пропусков с не пропусками немного похожа на проблему смешивания шагов, которые идут по диагонали вниз с шагами, которые идут прямо при рисовании линии с пикселями. Проблема рисования линий решена очень подробно на http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm

2 голосов
/ 10 мая 2010

Очевидно, что вы не всегда можете делать это действительно равномерно, если количество пропускаемых кадров не является делителем общего количества кадров. Поэтому, если важно всегда пропускать как минимум желаемого количества кадров, выполните разделение по полу (totalFrames / framesToSkip).

Сказав это, вы можете применить тот же трюк, который вы предложили.

if (totalFrames % floor(totalFrames/framesToSkip) == 0)
    skip();

Обратите внимание, что в случае 44 и 15 вы пропускаете намного больше 15. Другой возможностью является потолок вместо пола, в этом случае вы не пропустите 15 кадров, но 14 кадров.

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

1 голос
/ 10 мая 2010

Я решил написать решение, которое улучшит решение Игоря, но в конце концов единственное улучшение, которое я действительно обнаружил, это явное утверждение, что вместо (int)t следует использовать round(t). Итак, вот снова решение Игоря (с изменением некоторых имен переменных, чтобы оно было более очевидным и с использованием функции округления).

int frame_num = 44; 
int skips_num = 15; 
double frames_between_skips =((double)(frame_num))/skips_num;
double next_skip = 0.0;
...
// then, in your loop
if (current_frame == round(next_skip)) {  
  skip();   
  next_skip += frames_between_skips; 
}

Использование round(t) сделает его наиболее справедливым и попытается отбросить кадр (int), ближайший к идеальному пропускающему кадру (double), при этом сохраняя таймер полной точности (next_skip).

Пара заметок

  • позаботьтесь о том, чтобы кадр начинался с 0 или с 1, и отрегулируйте соответственно,
  • позаботьтесь о том, чтобы frame_num отличался от> skips_num (если он будет увеличивать next_skip более чем на кадр при каждом его отбрасывании, в противном случае вы прекратите увеличивать next_skip, и больше не будет кадров опускаем)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...