Поиск    Список пользователей    Группы пользователей    Регистрация (Registration)    Профиль (Profile)     Личные сообщения    Вход  

   Форум у C!NEMAXiMUS-a >> Cinema 4D >> X-Presso: thinking particles (Урок-не урок, так личный опыт)
     
Открыть новую тему   Ответить на тему
<< Предыдущая тема :: Следующая тема >>  
Автор Сообщение
magvai
Завсегдатай




Зарегистрирован: 10.01.2005
Сообщений: 285
Страна (Country): Россия
Екатеринбург
Версия Cinema4D (Version):13
X-Presso: thinking particles (Урок-не урок, так личный опыт) Ответить на тему Ответить с цитатой

Решил поделиться личным опытом немного, а то мало уроков по x-presso вообще и особенно по TP
итак

X-Presso: thinking particles или частицы в жидкостях и газах

В первую очередь, определим что же я буду демонстрировать: я хотел бы сделать более или менее адекватное взаимодействие частиц в плотной среде. Например, если вы размешиваете ложкой чай, то чаинки довольно резво устремляются за ложкой. Красиво ручками анимировать такое явление - процесс довольно трудоёмкий, особенно, если учесть турбулентные потоки (а без них будет некрасиво). С другой стороны стандартного средства в cinema-4d для этого просто нет (есть, конечно, отдельные программы и просто плагины для синьки, реализующие это дело, но их мы пока касаться не будем).
Казалось бы - есть обычный симулятор Turbulence, почему бы его не использовать? Ответ довольно прост: симулятор Turbulence не учитывает взаимодействие частиц или потоков.
Ну а разрабатывать мы будем сцену, в которой по аквариуму поднимается поток пузырьков и увлекает за собой вверх неподвижные в начале "чаинки".
Дополнительно я рассчитываю, что вы хотя бы немного знакомы с интерфейсом cinema4d. Хоть я и буду давать максимально подробные комментарии, как открыть то или иное окно, всё же я не могу учесть все мелочи.

Покончили с вводной частью. Теперь step-by-step с теоретическими дополнениями.
Для начала создадим в новой сцене два Null объекта: первый будет у нас эмиттером (источником) пузырьков, второй - просто вспомогательным; назовём их соответственно Emitter и TP_System. Эмиттер мы расположим чуть ниже (y = - 180) и осью Z вверх (чтобы пузырьки поднимались ага). К тому же стоит растянуть время сцены со стандартных 90 F до как минимум 400 F. Я сделал 900 F - для верности, хотя больше 500 не использовал.
Собственно сам эмиттер пока не эмиттер, поэтому дадим ему тэг Xpresso

и в этом теге (двойной клик по иконке у эмиттера для открытия x-presso editor) сделаем простую манипуляцию:
- перетащим Emitter на поле xpresso editor
- создадим в нём два выхода (Global Position и Global Matrix)
- cоздадим нод PStorm: System Operators->Thinking Particles->TP Generator->PStorm
- и проследим за наличием двух входов и одного выхода (Emitter Position, Emitter Alignment и Particle Birth)
- создадим нод PGroup: System Operators->Thinking Particles->TP Standart->PGroup (именно этот из закладки TP Standart)
- создадим в дереве частиц (см ниже) группу particles1 и для неё две подгруппы Group.1 и Group.2
- перетащим Group.2 (это будут наши пузырьки) из дерева частиц на нод PGroup.
- соединим входы-выходы единственным возможным способом

Дерево частиц:

Найти его можно по такому маршруту: в xpresso editor в меню Custom->Thinking Particles Settings...

Результат:


Настройки тут будут нужны только в одном ноде - Pstorm. В принципе, они целиком на ваше усмотрение, я приведу свои:


Второй шаг в подготовке сцены - создание "чаинок" в нашем аквариуме. Я для этого воспользовался MoGraph объектом Matrix (Если кто не знал, то он может генерировать частицы Thinking Particles). Думаю, как что сделать будет ясно по картинке. Ниже мелким шрифтом поясню как именно

- создали объект Matrix
- подняли его вверх на y = 270
- в поле Generate выбрали Thinking Particles
- в появившееся поле TP Group перетащили группу частиц Group.2 (это будут "чаинки") из дерева объектов.
- остальные настройки с картинки

"Чаинки" можно создавать любым удобным для вас способом - мне этот понравился. К тому же, на него действует Random Effector, который я и не упустил возможности использовать.

Ну теперь, если не считать визуального оформления, мы получили хорошую заготовку в сцене. При попытке проиграть анимацию, мы будем наблюдать порывающийся вверх поток синих частиц и неподвижно висящие зелёные частицы. Пока не очень естественно, правда? Что ж, смотрим далее
23.03.2012 13:12
View user's profile Отправить личное сообщение
magvai
Завсегдатай




Зарегистрирован: 10.01.2005
Сообщений: 285
Страна (Country): Россия
Екатеринбург
Версия Cinema4D (Version):13
Ответить на тему Ответить с цитатой

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

Как должны вести себя реальные частицы вообще и реальные частицы в жидкости?
Во-первых, частицы явным образом взаимодействуют между собой сталкиваясь. В этом случае у них наблюдаются следующие пути развития:
- упругое рассеяние (в реальной жизни, естественно, с диссипацией),
- неупругое соударение или слипание,
- разрушение.
Во всех случаях выполняется Закон Сохранения Энергии, Закон Сохранения Импульса и Закон Сохранения Массы (в ньютоновской механике).
Это воздействие имеет очень ограниченный характер - выполняется только тогда, когда расстояние между частицами совпадает с их геометрическими размерами.
Во-вторых, частицы взаимодействуют через посредника - поля или сплошную среду (например, жидкость, которая при более мелком рассмотрении всё равно становится системой частиц, но мы ограничимся приближением сплошной среды в силу ограниченных вычислительных мощностей). Вариантов и тут точно также всего три - два привычных со школьной скамьи и одно более хитрое:
- притяжение,
- отталкивание,
- вязкое трение.
Это взаимодействие, наоборот, имеет дальнодействующий характер, а интенсивность, как правило, спадает с увеличением расстояния между частицами обратно пропорционально квадрату расстояния. Получается такое бесконечнодалёкое взаимодействие. Однако Законы выполняются и тут.

Теперь хорошо бы построить модель взаимодействия частиц в нашей 3-d сцене. По причине того, что у меня нет под рукой вычислительного кластера этак на пару миллионов процессоров, я не хочу максимально приближаться реальности и строить максимально точную модель. Мне достаточно чтобы это выглядело реалистичнее. Поэтому мне придётся пренебречь многими реальными явлениями, не забыв выбрать важное. Это и называется построением модели и является практически самым трудным в любой науке - от физики и химии до экономики и лигвистики. Прежде чем получить более или менее удачный результат, я несколько дней строил разные модели и проверял их на практике. Некоторые были на столько труднопрограммирумыми, что приходилось их даже не проверять. А жаль - они сулили более изящное и точное решение. На публику я предоставлю лишь последнюю модель - наиболее простую для программирования средствами x-presso и наиболее удачно описывающую явление.

Надо отметить, что в X-presso - thinking particles нет простого понятия "взаимодействие" частиц. Есть только один более или менее похожий на реальность метод - в ноде PRepulse&Bounce. К сожалению, он предназначен для решения другого класса задач и нам не подходит. А о силах, действующих на частицы, вообще говорить не приходится. С этой задачей призваны справляться всего четыре (c натяжкой) весьма узких метода
- PDeflector осуществляет упругий отскок частицы от геометрии,
- PFriction - аэродинамическое трение частиц,
- PGravity отвечает за поле силы, которое может быть только однородным или центральным (сюда можно отнести и PWind, который отличается от PGravity возможностью наложить неоднородность в виде шейдера),
- PPosition Follow это интересный метод притяжения частицы к указанным координатам - с постоянной скоростью или "пружинкой".
И всё. Нам тут ничего не подходит - никакого упругого столкновения частиц, никакого слипания, разрушения при соударении, притяжения, отталкивания, вязкого трения. Увы, нельзя даже задать конкретную силу, действующую на отдельную частицу (в нашем случае же на каждую частицу будет действовать своя сила).

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

F=m*a
a=(v0-v1)/Δt

Здесь, как и везде в научных изданиях, векторные величины указываются жирным шрифтом.
Но единицу времени нам навязали уже - это длительность кадра. Отлично, примем её за единицу (не важно, используем мы 60, 30 или 24 FPS) и получим, что приращение скорости у нас прямопропрционально силе. Ну и славно. Ну и здорово! Мы не можем задать силу, но можем задать приращение скорости (есть же прекрасный нод PVelocity).
В свете этого, мы можем во всех законах и формулах заменить понятие вектора силы на вектор приращения скорости.
Тут мы немного грешим, не учитывая массу частиц (но для простоты сделаем все частицы одной массы: в конце-концов, изначально моя идея была во взаимодействии не столько частиц, сколько физически малых объёмов жидкости, которые в модели вполне могут обладать одинаковой массой и объёмом) и считая промежуток времени в 1F достаточно малым. По хорошему, для проверки промежутка времени на малость, надо составить дифур, исследовать численное решение на сходимость в зависимости от выбранного разбиения, выбрать наиболее оптимальное разбиение и отталкиваться от него. Но это долго, нудно и большие шансы попасть в тот же порядок, что мы и выбрали.
Ко всему прочему у нас в формулах теперь должен быть коэффициент m/Δt. Но я его просто выкину из рассмотрения: в дальнейшем у нас всё равно возникнут множители - физические константы - которые нам придётся подбирать. Сделаем вид, что этот коэффициент у нас является частью констант. В конце концов, практика показала состоятельность моих (не обоснованных доселе) допущений.

Итак - первое допущение модели: "масса и размеры всех частиц одинаковые"

Это не фундаментальное допущение - можно потом учесть и массы и размеры.

Второе допущение касается упругого взаимодействия. Модель упругих шариков не подходит - где вы видели чаинки, которые отскакивали друг от друга как бильярдные шары?
Неееет, друзья, чаинки отталкиваются от чаинок и пузырьков воздуха очень мягко. Простейший вариант решения - прямоугольный потенциальны барьер. Конечный. В переводе с языка физики на русский это будет звучать так: частица, попавшая в "радиус отталкивания" испытывает постоянную силу, которая направлена из центра выталкивания.

Поясним рисунком в пэйнте:


При этом как говаривал Альберт Эйнштейн, всё относительно: если частица 1 выталкивает частицу 2 из своего "радиуса отталкивания", то и частица 2 выталкивает частицу 1. (а вообще-то это третий закон Ньютона)
23.03.2012 13:13
View user's profile Отправить личное сообщение
magvai
Завсегдатай




Зарегистрирован: 10.01.2005
Сообщений: 285
Страна (Country): Россия
Екатеринбург
Версия Cinema4D (Version):13
Ответить на тему Ответить с цитатой

Вот мы и дошли до первой части скрипта.
Все предыдущие теоретические выкладки реализуются довольно просто. Сделаю даже небольшое уточнение: сила отталкивания будет не постоянная, а кулоновская - будет обратнопропорциональна расстоянию между частицами в квадрате.
- объекту TP_System тоже назначим xpresso тэг и в нём создадим три нода:
- P Pass AB (System Operators->Thinking Particles->TP Iterator->P Pass AB),
- Math:Divide (System Operators->XPresso->Calculate->Math:add) и заменим в нём функцию с "add" на "divide",
- PVelocity (System Operators->Thinking Particles->TP Dynamic->PVelocity.

В ноде P Pass AB добавляем два выхода: Distance AB и Vector AB (обратите внимание, они не подписаны на рисунке); в ноде Math:Divide добавим один вход Input; в ноде PVelocity добавляем входы Speed и Direction.



Соединяем как показано на картинке: Distance AB направляем на два нижних инпута в Math:Divide, Vector AB направляем на Direction, ParticleA (верхний) направляем на Particle. Output из Math:Divide идёт в Speed.

В параметрах P Pass AB указываем обе группы как particles1 (разумеется, сюда включатся и подгруппы Group.1 и Group.2)
Теперь свойство Distance Type может принимать одно из трёх значений: None Inside Outside. Нужно указать Inside - тогда на выходах итератора будут появляться только те пары частиц, для которых расстояние между центрами меньше указанного в поле Distance (у меня 20 - это и будет эффективным радиусом частицы). Смотрим рисунок:



В Math:Divide у нас заняты нижние два инпута, поэтому в верхнем инпуте (он один доступен в атрибутах) коэффициент расталкивания - та самая физическая константа, в которую мы внесём m/Δt. Я сделал -1000. Минус - потому что не притягиваются, а отталкиваются. 1000 - просто наугад ткнул. Угадал.

В параметрах PVelocity обязательно должно стоять Speed&Direction и тип Added.


Запускаем - проверяем. Всё работает. Частицы спокойно проносятся мимо друг друга, но иногда действительно сталкиваются и отскакивают. А если эффективный радиус сделать не 20 а, к примеру, 100, то мы увидим, что частицы прямо панически начинают бояться друг друга!

Таким образом у нас получается, что каждая частица сравнивается с каждой и, в случае попадания в эффективный радиус, одна из них (частица B) получает дополнительный пинок в сторону. Когда же она оказывается на выходе частицы A, то пинок получает и вторая частица (которая оказывается на выходе B). Частица сама с собой не взаимодействует - Math:Divide не делит на ноль, и этот шаг пропускается.
23.03.2012 13:13
View user's profile Отправить личное сообщение
magvai
Завсегдатай




Зарегистрирован: 10.01.2005
Сообщений: 285
Страна (Country): Россия
Екатеринбург
Версия Cinema4D (Version):13
Ответить на тему Ответить с цитатой

Теперь будет самая сложная часть скрипта. Нам надо как-то придумать, а потом и запрограммировать взаимодействие частиц не прямое, а через жидкость. В общем эту задачу я решил так:
Частица, которая движется в жидкости, перед собой создаёт область повышенного давления, а за собой и по бокам - разряжённую область. В область пониженного давления частицы должно влечь, а из области повышенного давления - выталкивать.
Так как сплошной среды у нас в кармане не завалялось, да и трудновато будет просчитывать (одна из моделей, от которой я отказался ранее), я сделал немного другое.
Предположим, у нас есть две частицы, которые движутся. Очевидно, что в свете вышесказанного они должны расталкиваться, если они идут на сближение, и притягиваться, если разбегаются или идут параллельно (помним, почему утонул "Титаник" ага?). Итак, берём относительную скорость (разность скоростей VA-VB) и частице А даём дополнительный пинок в сторону частицы B, если относительная скорость и вектор AB составляют угол больше 90° и в противоположную, если угол меньше. Смотрим пэйнт-иллюстрацию:


Ну для физичности надо учесть, что параллельно движущиеся частицы всё-таки притягиваются: скажем, что угол у нас должен быть не 90°, а где-то 80°. Ну примерно - не будем сейчас считать, ага. Тем более, что я не знаю как.

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

Вроде, трёх мне хватило. Да и больше тут просто нечего приплести, кроме, пожалуй, положения звёзд на небе и фазы Луны.
23.03.2012 13:14
View user's profile Отправить личное сообщение
magvai
Завсегдатай




Зарегистрирован: 10.01.2005
Сообщений: 285
Страна (Country): Россия
Екатеринбург
Версия Cinema4D (Version):13
Ответить на тему Ответить с цитатой

Вот всё это у нас и будет реализовывать следующий скрипт.

Во-первых, я так и не нашёл в синьке метод определения угла между векторами. Не проблема: угол можно найти из скалярного произведения. Точнее, косинус угла. Функция арккосинуса у нас, хвала богам, есть. Теория проста как банный лист:

(a,b) = a*b*cos(α) = ax*bx+ay*by+az*bz (*)

Лепота. Смотрим, как это будет на экране:

В том же тэге у TP_System снова создаём

- P Pass AB, в нём два дополнительных порта - Vector AB и Distance AB, указываем в обоих слотах группу "particles1"
- Два PGetData (System Operators->Thinking Particles->TP Helper->PGetData) с дополнительными выходами Velocity.
- Math:Substract с типом данных Vector в параметрах

Соединяем вот таким образом:

(в P Pass AB сверху вниз: ParticleA ParticleB DistanceAB VectorAB)

Это у нас получилась относительная скорость - вектор.

Добавим дальше вот такую цепочку:

Здесь Math:Multiply имеет тип данных Vector, а Add и Divide - Real. Vector2Reals можно добыть по адресу System Operators->XPresso->Adapter->Vector2Reals
Левые три пункта материализуют нам скалярное произведение в координатах (сама правая часть соотношения (*)), поэтому на входы первого Math:Multiply подаём векторы относительной скорости и Vector AB из P Pass AB:



Отмечу, что метод Math:Multiply для векторов работает как-то странно. Он выдаёт не скалярное и не векторное произведение, а совершенно новый вектор, в котором просто попарно перемножаются соответствующие координаты исходных векторов. Для чего это сделано, я так и не понял. Собственно, поэтому и такой сырбор с переводом из вектора в числа.

Ну и всё, собственно, осталось это поделить (для этого у нас есть Divide с тремя входами) на длину вектора Vector AB и модуль относительной скорости: соединяем DistanceAB из P Pass AB со вторым input'ом в Divide и вектор относительной скорости (предварительно надо его пропустить через нод Distance (System Operators->XPresso->Calculate->Distance), чтобы у нас не было проблемы, будто мы делим на вектор, а не на его длину). Смотрим:



Ура! На выходе мы имеем косинус угла между вектором относительной скорости и вектором AB - соединяющим две частицы.

Для получения непосредственно угла воспользуемся нодом Formula (System Operators->XPresso->Calculate->Formula). Создадим ему новый вход, обзовём его x и настроим атрибуты вот так:
23.03.2012 13:14
View user's profile Отправить личное сообщение
magvai
Завсегдатай




Зарегистрирован: 10.01.2005
Сообщений: 285
Страна (Country): Россия
Екатеринбург
Версия Cinema4D (Version):13
Ответить на тему Ответить с цитатой

У нас есть угол в радианах, у нас есть вектор относительной скорости (и его длина), у нас есть расстояние между частицами. Соединяем всё это воедино:
сила притяжения/оттлакивания
F ~ VAB*P(α)/(AB в чёртикакой степени)
Модуль скорости у нас получился после нода Distance, так вот, нам надо поделить его на некоторую функцию от Distance AB (то ли квадрат, то ли куб, то ли четвёртая степень - хз), а потом что получилось умножить на опять же непонятную функцию от угла.
Это дело нам решат два Range Mapper'а (System Operators->XPresso->Calculate->Range Mapper). Тут я сам уже не помню как, но как-то я их построил, поэтому предлагаю слизать их настройки 1-в-1 с моего. Можете потом поиграться, а я объясню те настройки, которые я сам понял, что написал.

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



Input Lower и Input Upper
Это диапазон углов в радианах, который мы рассматриваем. Между векторами угол может быть только от 0 до pi - поэтому только так.

Input Lower и Input Upper
сюда вводим максимальное и минимальное значения функции P(α). Заметьте, что максимальное и минимальное значения совпадают с точностью до знака - это значит, что притягиваться разлетающиеся частицы будут точно также как и отталкиваться слетающиеся.

Асимметричность в сплайне нам даёт именно то, о чём мы раньше говорили - частицы, которые движутся параллельно тоже будут притягиваться. К тому же сплайн у меня линейный - это сделано для существенного ускорения просчёта. Я делал сначала гладкий - считало ОЧЕНЬ долго. Линейка сократила время до примерно секунды.

И второй ранджмэппер - опишет функцию влияния расстояния на силу притяжения/отталкивания



Здесь аналогично
Input Lower и Input Upper
задаёт минимальное и максимальное расстояние, на котором у нас расстояние будет влиять на силу. 500 вполне достаточно
Раз уж у нас максимальная дальность в функции 500, то в P Pass AB обязательно надо поставить distance type = inside и distance = 500
Input Lower и Input Upper
минимальное и максимальное значение этого влияния. На сей раз минимальная сила - 0, максимальная 0,1. Этого достаточно.

Осталось перемножить все три результата (дада, именно перемножить. Делить на функцию расстояния мы не будем, потому что я эту функцию уже подобрал так, как надо. Что-то среднее между обратной экспонентой и обратным квадратом. Уже обратное. Поэтому умно_жать надо) и направить в новый PVelocity во вход Speed. Создадим PVelocity мы точно также как и в предыдущем случае, все те же настройки. В Direction посылаем vectorAB а в Particle - ParticleA из P Pass AB.





Сохраняемся(!), запускаем. Ву а ля.

Остаётся добавить только немного визуализации - как это сделать смотрите в других местах (устал я уже писанину разводить такую). Я ещё для красоты сделал, чтобы пузырики у меня колебя.. кобеля... колебались, методом PBuble и сделал, чтобы частицы дохли, дойдя до верха аквариума, в чём мне помог метод PDie
Смотрим результ на ютьюбе
23.03.2012 13:16
View user's profile Отправить личное сообщение
magvai
Завсегдатай




Зарегистрирован: 10.01.2005
Сообщений: 285
Страна (Country): Россия
Екатеринбург
Версия Cinema4D (Version):13
Ответить на тему Ответить с цитатой

ещё вдогонку добавлю - напоролся в интернете - хорошее описалово для нодов X-Presso Thinking Particles
23.03.2012 13:37
View user's profile Отправить личное сообщение
sataneev
Завсегдатай




Зарегистрирован: 07.03.2009
Сообщений: 469
Страна (Country): Украина
Одесса / Киев
Версия Cinema4D (Version):AIO
Ответить на тему Ответить с цитатой

Молодец Smile


_________________
23.03.2012 14:25
View user's profile Отправить личное сообщение
magvai
Завсегдатай




Зарегистрирован: 10.01.2005
Сообщений: 285
Страна (Country): Россия
Екатеринбург
Версия Cinema4D (Version):13
Ответить на тему Ответить с цитатой

дада. Знаю такой. Но тут больше урок по xpresso. Ты бы лучше урок оценил и указал, что непонятно
PS да, ещё я тут про взаимодействие частиц больше разливался, чем про турбулентности всякие
23.03.2012 17:25
View user's profile Отправить личное сообщение
sataneev
Завсегдатай




Зарегистрирован: 07.03.2009
Сообщений: 469
Страна (Country): Украина
Одесса / Киев
Версия Cinema4D (Version):AIO
Ответить на тему Ответить с цитатой

Я ж написал, шо молодец)
Почитаю позже, бо ща ваще времени нема.

_________________
24.03.2012 05:14
View user's profile Отправить личное сообщение
Показать сообщения за последний(-ие):   
Открыть новую тему   Ответить на тему    Форум у C!NEMAXiMUS-a >> Cinema 4D Все даты указаны в GMT + 2 ч.
Страница 1 из 1

 
Перейти к:  
Вы не можете открывать новые темы в этом форуме
Вы не можете отвечать на темы в этом форуме
Вы не можете редактировать Ваши сообщения в этом форуме
Вы не можете удалять Ваши сообщения в этом форуме
Вы не можете учавствовать в опросах на этом форуме




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

Copyright © 2003-2010 C!NEMAXiMUS