ПрограммированиеФорумФизика

Физическое моделирование воды. (Комментарии к статье)

Страницы: 1 2 Следующая »
#0
22:13, 8 мар 2005

Комментарий к Статье Физическое моделирование воды

#1
22:13, 8 мар 2005

Скажу сразу статью я прочитал только что и в детали программы не вникал, поэтому прошу извинить если что.

Вопрос такой. Уравнение

(*)      d2U / dt2 = d2U / dx2 + d2U / dy2

линейное. Это означает что нет взаимодействия между гармониками колебаний.
В реальной воде это конечно не так.
У нас у всех в памяти осталось последнее цунами в ЮВА. Так вот, что характерно для цунами, это то, что оно описывается довольно простым уравнением мелкой воды (длина волны цунами сравнима и даже больше локальной глубины водоема). Я это уравнение придставлю в обозначеениях IronPeterа, оно выглядит примерно так:

(**)    (U/k)^2 * d2U / dt2 = d2U / dx2 + d2U / dy2

здесь  k - некий коэффициент.

Т.е. скорость распространения волны пропорциональна локальной глубине U.
Реально в программе нужно будет задавать функцию глубины U0(x,y). Насколько быстро это можно будет вычислять я не знаю, но картинка будет значительно интересней линейной модели.
Я не знаю, будет ли сходится решение IronPeterа если использовать нелинейность, но думаю, что это расчет можно стабилизировать выбирая произвольный множитель для локальной глубины (т.е. меняя отношение глубина/скорость волны).

#2
0:06, 9 мар 2005

Я модифицировал программу в соответствии с формулой для мелкой воды.
Изменения коснулись в основном только кода для вычисления влияния лапласиана:

#define vis 0.0025f   //вязкость
              float laplas=(n->U[i-1][j]+
                                  n->U[i+1][j]+
                                  n->U[i][j+1]+
                                   n->U[i][j-1])*0.25f-n->U[i][j];

                                               /*4*/

#define U0 (float)(5+(abs(i+j-127)+abs(i-j)))  //функция глубины водоема

#define a2  5.0f/sqrt(U0+n->U[i][j])      //квадрат скорости распространения волн

            p->U[i][j]=(((2.0f-vis)*n->U[i][j]-p->U[i][j]*(1.0f-vis)+ a2*laplas));

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

Движение воды, как и ожидалось хаотично. Т.е. идет обмен энергией между гармониками колебаний.

#3
1:44, 9 мар 2005

Сейчас придумал: совсем необязательно иметь переменную глубину водоема, нам ведь нужен только обмен энергией между гармониками. А это легко достигается, если использовать уравнение

(***)    ((U0+U)/k)^2 * d2U / dt2 = d2U / dx2 + d2U / dy2

где  U0 - некая (константная!) глубина водоема.
        U  - искомая высота волны

В этом случае будет обмен энергией и движение воды будет хаотично.

#4
14:36, 9 мар 2005

Сейчас реализовал задумку для мелкой воды. Глубина постоянная, поэтому все получилось очень простенько:

#define vis 0.00025f   //вязкость

#define U0 .950f       //функция глубины водоема
#define a2	1.0f/(U0+n->U[i][j])         //квадрат скорости распространения волн
		p->U[i][j]=(((2.0f-vis)*n->U[i][j]-p->U[i][j]*(1.0f-vis)+ a2*laplas));

Вязкость я сильно понизил, поскольку есть перераспределение энергии между гармониками и энергия все равно рассеивается из-за увеличения средней амплитуды колебаний.
Решение  дает очень реалистичную картинку из-за того, что
a) существует непрерывный спектр колебаний
b) распределение энергии между гармониками близко к естественному, которое мы обычно и наблюдаем.

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

#5
14:50, 9 мар 2005

Маленькое замечание.

Я здесь везде достаточно свободно определял a2, например так

#define a2  1.0f/(U0+n->U[j])        //квадрат скорости распространения волн

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

#define a2 .70f/pow((U0+n->U[j]),2)    //квадрат скорости распространения волн

Такой вариант я естественно тоже проверил, но чисто визуально мне больше понравился вариант #define a2  1.0f/(U0+n->U[j]), поэтому его я и представил.

#6
15:13, 9 мар 2005

Теперь пару типичных картинок для сравнения.
Первая картинка - это решение для линейного уравнения, по исходной программе IronPeterа.

Изображение удалено

Такое конечно в принципе можно иногда увидидеть в тихую погоду на маленкой луже и в редком случае на меленком пруде.
А вот картинка  решение для нелинейного уравнения, по модифицированной программе

Изображение удалено

Для полного реализма этому решению не хватает только пены и барашек на волнах, их срыва и т.п. Но все это уже в рамках этой модели невозможно; тут нужно кое-что получше.

#7
16:41, 9 мар 2005

эуэ... дяденька... вы с кем разговариваете?...

#8
16:59, 9 мар 2005

А что, здесь полагается с кем-то разговаривать?
Была идея и я всего лишь дополнил статью. Вот и все.

#9
17:55, 9 мар 2005

Федор
И правильно, дополнять надо :))

#10
20:09, 9 мар 2005

Федор
Реалистичных колебаний можно достичь бросая случайно капли (расчет по ыормуле в статье), при этом вода с затуханием. Так получается надежно и управляемо ( можно менять характер колебаний в зависимости от частоты, размера и силы капель ).
Вообще этот расчет очень затратен по CPU, даже на 2ГГц при частоте обновления воды 25 ФПС (для плавности анимации хватает как раз) - максимум 128х128, уже при 512х512 тормоза не совместимые с реальной игрой.

#11
20:37, 9 мар 2005

Timm
>Вообще этот расчет очень затратен по CPU
Что бы добиться такой картинки ( как у IronPeter'а ) на GPU, имхо, придется потрать намного больше _ресурсов_..

#12
20:48, 9 мар 2005

Timm
Да, это так. Но таким путем, каплями сложно (в смысле: затратно) достижение настоящего хаоса. И все равно это будет псевдохаос.
Тот метод, который я предложил не увеличивает затрат, но вы с Иннокентийем конечно правы в том, что действительно при нынешних мощах компьютера малореально в игре изобразить волнующееся море.
Нужен другой метод.

#13
20:56, 9 мар 2005

Федор

Cпасибо.

если гнаться за реализмом для больших океанских просторов, то думаю, что надо складывать несколько гармоник (скажем 4, и скажем, с коэффициентом умножения не двойка, а четверка). Гармоника - массив 128x128.

Timm

Гм... не знаю, какой именно процессор у тебя, но  на моих 2.3 гигагерцах та самая демка дает 750 fps (если откомпилировать IntelC,  вариант от VC в полтора раза медленнее). Ясно, что glBegin()...glEnd() не особо рулит, и скорость можно увеличить раза в два.

Но для больших океанских просторов я бы все равно использовал несколько гармоник волн.

PS... Я ли писал этот код?  > printf("FPS  = %f \n",2*100000.0f/(clock()-cl)); зачем на два умножать ;-? Поделил на два...

#14
21:15, 9 мар 2005

О суммировании гармоник я тоже думал и если их взять достаточно много, то поверхность будет выглядеть, если конечно недалеко смотреть, почти случайно.
Другая идея: нужно решать уравнение поверхности на ограничекнной области, например, квадрате, причем с повторяющимися условиями (левая граница = правая граница, дальняя граница = ближняя граница), но решение представлять для всего "моря".

Третья идея:
А нужно ли вообще море изображать волнующимся, в смысле изображать волнующиюся поверхность?
Может быть проще изобразить только вид блещущигося на солнце (или в свете луны, тоже неплохо) моря?
Я имею в виду конечно случайно, по определенному закону естественно, меняющиеся  нормали поверхности.

Страницы: 1 2 Следующая »
ПрограммированиеФорумФизика

Тема в архиве.