Буду делиться тем что делаю.
Моделирование жидкости
Как и обещал, рассказываю как делать физическую модель воды в программе.
Сразу говорю, метод который я вам поведую нужен для моделирования всей массы жидкости, а не только её поверхности.
Итак, начнём!
В этой статье поговорим о том, как смоделировать жидкость методом под названием SPH(Smoothed Particle Hydrodynamics, гидродинамика сглаженных частиц).
Где можно почитать/поглядеть поподробней? Приведу небольшой список того, что я нарыл: Русская вики, буржуйская вики, хорошая статья с примером на С++, основная pdf статья(фактически рассказан алгоритм), pdf-ка, которая не очень нужна, только для понимания, статья про реализацию этого дела, некоторые демки одного чела
Что есть SPH по сути? Идея метода в том, что у нас есть жидкость, она представляется дискретно, несколькими частицами. Частицы взаимодействуют между собой только на каком-то расстоянии. При этом умные дядьки придумывают сложные формулы и странные слова, типа "функция ядра", чтобы всё это дело описать. Функция ядра - это функция, которая зависит от расстояния между двумя частицами.
Реальная жидкость имеет такую особенность, что различные её свойства изменяются в ней непрерывно. Невозможно, чтобы давление в жидкость в одной точке и в точке, очень близкой к ней, были сильно разными. Поэтому эти умные бородатые дядьки, которые разбили воду на частицы своими формулами делают так, чтобы сохранялась эта непрерывность.
Вот их формула, на которой держится вся эта теория:
AS(r) =Σmj*Aj/ρj*W(r−rj ,h)
A - некоторое свойство частиц, m-масса частицы, ρ - плотность жидкости в частице, W(r−rj ,h) - функция ядра, которая зависит от расстояния между частицами и как-бы от расстояния h, на котором они взаимодействуют.
Объясню формулу. Пусть у каждой точки можно задать своё свойство A, тогда если мы знаем значение этого свойства у её соседей, то мы знаем значение свойства и в этой точке. W определяет степень влияния другой точки, в зависимости от удалённости.(если хотите промыть себе мозги на эту тему, читайте тут)
Ну а теперь открою тайну=) То что наверху-ненужный бред! Чтобы всё сделать не надо понимать почти ничего сверхъестественного! Всё что надо знать-элементарную школьную физику. Помните, что на тела могут действовать силы? Что они имеют скорости? Что они имеют массу и положение в пространстве, тогда всё дальше вы поймёте)
Во-первых, как я моделирую физику вообще? Использую так называемую интеграцию верлета. Идея такая:
пусть X(t) - положение частицы в момент времени t,
v(t) - её скорость
a(t) - её ускорение(т.е. сила делённая на массу, но дальше везде m=1)
X(t+dt)=X(t)+V(t)*dt+a(t)*dt^2/2 //Положение в следующий момент времени
X(t-dt)=X(t)-V(t)*dt+a(t)*dt^2/2 //Положение в прошлый момент времени
Сложим эти два равенства, получим:
X(t+dt)+X(t-dt)=2*X(t)+a(t)*dt^2
или по-другому:
X(t+dt)=X(t)+(X(t)-X(t-dt))+a(t)*dt^2
Т.е. новое положение можно определить не зная скорости. Кажется, в чём кайф этой записи? А он в том, что прошлое и новое положение можно менять на своё усмотрение(к примеру при столкновении со стеной надо менять не скорость, а положение точки, всё остальное скорректирует формула).
Теперь ясно, что для каждой частицы нам надо знать 3 величины: X, Xold, a
X и Xold - вычисляются каждый раз, когда мы применяем формулу:
Код:
tmp=x; x=x+(x-xold)+a; xold=tmp;
То есть задачка сводится к поиску ускорения a для каждой частицы, и весь алгоритм сводится к такой схеме:
Код:
для всех частиц a=0 ищем a //Описано ниже применяем формулу выше если x вышла за границы, то возвращаем обратно
Для каждой частицы заводим дополнительные значения ro, ro_near - плотности воды в частицы, press, press_near - давления в частице.
Также храним общие параметры(выбираются до эксперимента): h - радиус взаимодействия частиц, k - коэффициент для преобразования ro в press, k_near - для ro_near в press_near, rest_ro - та плотность, которое должно быть в частице по умолчанию(нулевая плотность, как я буду её звать).
Почему ro и ro_near? Идея в том, что частицы по-разному взаимодействую на разных расстояниях. Вблизи они сильно отталкиваются, вдалеке притягиваются, поэтому считают сразу 2 значения. rest_ro - определяет насколько сильно частицы притягивает друг к другу. Это как для пружины длина нерастянутой пружины. Т.е. частицы притягиваются, если в частице плотность ниже нулевой и отталкиваются в другом случае.
Теперь к алгоритму:
Код:
Обнуляем для каждой частицы p: p.ro, p.ro_near, p.press, p.press_near Ищем все пары частиц на расстоянии d таком, что d<h для каждой пары соседей { считаем параметр q=1-d/h, q2=q*q и q3=q2*q для обеих точек из пары делаем: { p.ro+=q2 p.ro_near+=q3 } } Потом для каждой точки p { p.press = k * (p.ro - rest_ro); p.press_near = k_near * p.ro_near; } Потом для каждой точки p: { s=0 для каждого соседа q точки p: { tmp=(p.x-q.x)*((p.press + q.press)*q + (p.press_near + q.press_near)*q2)/d //q, q2, d для каждой пары свои q.a+=tmp; s+=tmp; } p.a-=s; }
В этом месте советую всё же поглядеть на исходник к этой статье, ибо он прояснит все ваши непонятки.
Всё, алгоритм описан.
Теперь 2 главных вопроса, которые я себе задаю:
1) зачем я всё это написал
2) нужно ли это кому-нибудь
А теперь ответ на ваш закономерный вопрос "ты дурак это во флэше делать?" - да
Если blog.brandonpelfrey.com не работает, то вот эта статья и сходник: ссылка
Удачи!
Всего комментариев 13
Комментарии
22.07.2009 19:02 | |
Герыч,маладца. Я как раз искал алгоритми жидкости, спасибо, есть что почитать.Продолжай в том же духе.
|
22.07.2009 20:56 | |
Будут вопросы, спрашивай
|
04.08.2009 19:51 | |
сапасибо большое, оч интересно, уверен, что пригодится!
|
04.08.2009 20:52 | |
угу) Надо бы ещё описать то, как делать желе..
|
04.08.2009 22:17 | |
Цитата:
Потом для каждой точки p:
s=0 З.Ы блог Брендона Пелфри мертв кстати, так что исходников нема( |
|
Обновил(-а) TERRORist 04.08.2009 в 22:26
|
04.08.2009 22:37 | |
исходники у меня есть, копия странички блога тоже) экстренно из кэша гугла скопировал, пока там была) Вот, качай: http://pingvin.nnov.ru/files/get.php?ind=32
|
04.08.2009 22:39 | |
спасибо!
|
04.08.2009 22:45 | |
да, а в алгоритме я чуток напутал.. уже исправил)
|
05.08.2009 14:56 | |
А ты не пробовал делать просчет через ShaderJob и рисовать шейдерами?
|
05.08.2009 19:27 | |
Я не знаю что это(я вообще не знаю возможностей флэша), но сейчас прочитаю)
|
06.08.2009 02:09 | |
Предполагается, что ShaderJob может быстро переваривать большие объемы инфы, в основном благодаря тому что операции с плавающей точкой быстро выполняются.
На входе ряд каких то данных (числа, байтэррэй, графика), на выходе - обработанные данные... Плюс в том что язык очень простой и быстрый (полное официальное описание на 30 страницах) - как и шейдерный код для 3д ускорителей, минус - примитивный (скажем, циклы не поддерживаются). насчет производительности - флешовые шейдеры вполне шустро рисуют всякое в полноэкранном режиме, попиксельно. http://help.adobe.com/ru_RU/AS3LCR/F...ShaderJob.html http://injun.ru/flash10api/flash/display/ShaderJob.html http://novikovd.com/2009/07/28/eshhe...ixel-blendera/ я в принципе несколько уже шейдеров написал, |
06.08.2009 02:16 | |
а вот отрисовка:
http://pixelero.wordpress.com/2008/1...der-metablobs/ |
Последние записи от Герыч
- Массив объектов или несколько массивов? (16.08.2009)
- SVN (16.08.2009)
- Box2D и магическое 30 (13.08.2009)
- Двойное деление vs Мозги (09.08.2009)
- Желе: убраны многие баги + появилась смена состояний (03.08.2009)