понедельник, 28 января 2008 г.

Растительность. Часть 3( заключительная ). Ветер

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

Для начала нужно определить несколько новых коэффициентов.

max_deflection - максимальное расстояние, на которое может отклониться куст.
flex - На сколько отклонится стебель при ветре 1м/с.
recovery_speed - С какой скоростью модель будет возвращаться к своей первоначальной форме.

Высчитываем смещение стеблей.

static vec2 current_offset( 0.f, 0.f );

float current_offset_lenght = math::vec_lenght( current_offset );
//
vec2 recovery_dir = math::vec_normalize( recovery_dir, -current_offset );
//
float deflection_k = current_offset_lenght / max_deflection;
float wind_power = wind_speed * flex * time_step;
float recovery_power = recovery_speed * deflection_k * time_step;
//
current_offset += wind_dir * wind_power + recovery_dir * recovery_power;

math::clamp( current_offset.x, current_offset.x, -max_deflection, +max_deflection );
math::clamp( current_offset.y, current_offset.y, -max_deflection, +max_deflection );
_Winnie C++ Colorizer


Как видно из вышеуказанного кода, на куст действует одновременно 2 силы - ветер и восстановление. Когда ветер стихает, модель возвращается к своей первоначальной форме.

Кстати, ветер у нас 2-хмерный( т.к. вверх/вниз трава не деформируется ). Поэтому считаем смещение только по X и Z осям.

Трава у нас стала "подчинятся" ветру, но этого мало. В реальном мире она "колышется". Этот эффект( в основном ) достигается за счёт того что ветер никогда не бывает статичным. Он постоянно меняет своё направление и силу в небольшом диапазоне.

Реализовать этот эффект можно, к примеру, так:
const float wind_minmax_k = 0.5f;
float wind_max_power = wind_power;
float wind_min_power = wind_power * wind_minmax_k;
//
static float wind_amplitude = 0.f;
static float wind_amplitude_dir = 1.f;
const float wind_amplitude_speed = 0.5f;
//
float rand_k = math::lerp( 0.25f, 1.f, ( float )rand() / ( float )RAND_MAX );
//
wind_amplitude += wind_amplitude_speed * wind_amplitude_dir * m_time_step * rand_k;

if( wind_amplitude > 1.f || wind_amplitude < 0.f )
wind_amplitude_dir = -wind_amplitude_dir;
//
math::saturate( wind_amplitude, wind_amplitude );

float wind_speed = math::lerp( wind_min_power, wind_max_power, wind_amplitude );
_Winnie C++ Colorizer


Данный код позволяет эмулировать порывы, линейно меняя скорость ветра между двумя значениями. А внесение в расчёты небольшого количества хаоса ( rand_k ) добавит немного естественности.

Трансформация
Мы рассчитали на какое расстояние должен сместиться стебель ( current_offset ), осталось его нарисовать.

Очевидно, что смещать мы должны верхние вершины стеблей. Определить где верх, где низ, очень просто - текстурные координаты у нас идут сверху вниз. Зная это, легко определить высоту вершины ( 1.f - tex_coord.y ).

Может возникнуть соблазн сдвинуть только XZ координаты, как показано тут:
1,64 КБ


Но это неправильно. Возмите ручку, поставьте её вертикально на стол и попробуйте наклонить. Заметьте, что она движется по окружности:
4,11 КБ


Нам нужно поступить аналогично. Делать "честное" смещение по окружности несколько "дороговато", поэтому обойдёмся упрощённой моделью. Уменьшим высоту на ту же величину, на сколько сдвинули её ветром.
1,61 КБ


Вот что у нас получилось в итоге


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

Пора двигаться дальше.

p.s. Если честно, я не очень доволен получившимся ветром. Был потрачен не один день, и всё равно, вышло немного не то что хотелось. Но слишком затягивать тоже не дело, ибо пресловутый "синдром улучшения" может растянуть процесс на неопределённый срок. Может ещё вернусь к этой теме.

3 комментария:

Sergey Miryanov комментирует...

Че то все равно мало хаоса. Судя по видео и ближние и дальние кусты движутся одинаково.

Анонимный комментирует...

А два ветра наложить по масочке?..

А ещё надо график ветра сгладить, чтоб без резких углово, изменений.

Timai комментирует...

Sergey Miryanov
Амплитуда одинакова, но каждый куст рандомно повёрнут в диапазоне -45..+45 градусов.
Но хаоса маловато да, особенно заметно на сильном ветре.

5yber
Кстате неплохая идея, да. Подумаю на досуге.