Основы Particle Flow Tools: Box#3

Вступление

Система частиц PFlow была интегрирована в 3ds Max 6. Основным ее разработчиком является Олег Байбородин (Oleg Bayborodin), основатель Orbaz Technologies. Впоследствии были разработаны: Particle Flow Tools: Box#1 (интегрирован в 3ds Max 2010), Particle Flow Tools: Box#3 — 2006 г. (отдельный плагин), Particle Flow Tools: Box#2 — 2009 г. (отдельный плагин, в основе лежит интеграция с PhysX).

Сайт и форум: www.orbaz.com.

1. Основы

В данном уроке мы рассмотрим Box#3.

Данный плагин значительно расширяет возможности стандартного Pflow. После установки плагина в Depot появятся новые операторы (рис. 1):

BlurWind* и Random Walk* — это готовые пресеты. BlurWind* — оператор, имитирующий силу ветра, Random Walk* добавляет партиклам хаотичное движение.

Data Icon*, Data Operator*, Data Icon test*, Data test* — это основа плагина, операторы, в структуре которых находятся субоператоры. т. е., простыми словами, конструкторы, с помощью которых можно собирать свои пресеты и операторы.

Data Preset* — оператор, в который можно загружать пресеты.

Caсhe Disk*, Caсhe Selective* — операторы кэширования.

Display Data* — позволяет просматривать информацию каких-либо свойств частиц во вьюпорте. Удобно для отладки.

Рассмотрим Data-операторы детальнее.

  1. Нажимаем на клавиатуре цифру 6, откроется окно Pflow.
  2. Перетягиваем иконку Data Operator* в основное окно (рис. 2)
  3. Нажимаем Edit Data Flow (Редактирование потока данных) (рис. 2), откроется дополнительно окно, похожее на окно самого Pflow (рис. 3). Это и есть окно с субоператорами.

Разберем сам принцип работы.

У каждого партикла есть данные, которые меняются с течением времени. Например, Age (возраст), Speed vector (вектор направления скорости), Position vector (вектор положения) и т. п.

Субоператоры позволяют получить доступ к этим данным и выполнить нужные нам манипуляции. Как организовать доступ к этим данным? Смотрим рис. 4. Операторы Input Custom, Input PhysX (субоператор работает только с Box#2), Input Proxy, Input Standard служат для того, чтобы получить исходные данные. Операторы: Output New, Output PhysX (субоператор работает только с Box#2), Output Standard — для вывода данных. Все остальные субоператоры нужны для вспомогательных целей и для изменения данных.

Соединяются субоператоры с помощью wire data (нитями данных) нажатием и перетаскиванием от выхода (снизу) ко входу нужного субоператора (сверху).

Каждый тип данных имеет свой уникальный цвет, например, Boolean — синий, Real — красный, Vector — фиолетовый (рис. 5а).

Если субоператоры соединены одной нитью (рис. 5б), их можно сшить друг с другом (впоследствии можно разъединить при надобности) перетаскиванием (субоператоры должны подсветиться желтой рамкой).

Также субоператоры можно группировать для удобства (рис. 6).

2. Практика

Единицы измерения: у меня установлены System Units Setup — сантиметры, Display unit scaleGeneric Units.

Открываем окно PF (клавиша 6). Перетаскиваем с Depot иконку Standard Flow в рабочую зону.

Заходим в свойства Birth (рождение), устанавливаем Emit Start (начало испускания) — 0, Emit Stop (конец испускания) — 100, Amount (кол-во) — 500.

Удаляем оператор Rotation (вращение). Переворачиваем иконку PF во вьюпорте на 180 градусов, чтобы испускание партиклов шло вверх.

Устанавливаем в операторе Shape (форма ) Size (размер) — 2. В Display Type (тип отображения) устанавливаем — Type : Geometry (рис. 7).

Тестовая заготовка готова. Сделаем несколько простых операторов.

2.1 Оператор удаления партиклов по Z координате

Создадим простой оператор удаления партиклов, если их положение по оси Z превысит 30 единиц.

Добавляем Data Operator в Event 001.

(Обратите внимание на Auto Update и Update (рис. 8а). По умолчанию, галочка на Auto Update снята. Это означает, что все, что мы будем изменять в окне субоператоров, не будет отражаться во вьюпорте. Если нам будет необходимо обновить данные во вьюпорте вручную, нужно будет нажать кнопку Update (обновить). В тестовых и несложных сценах Auto Update нужно ставить. Как только PF начнет долго считать, галочку лучше снять.)

Ставим галочку Auto Update и нажимаем Edit Data Flow, чтобы открыть окно субоператоров.

С Depot (уже субоператоров) перетягиваем в рабочую зону Input Standard (рис. 8б). В его свойствах выбираем из выпадающего меню Position → Z component (Вектор — трехкомпонентная величина, но нам пока нужна только Z координата.)

Перетаскиваем из Depot субоператор Condition. Это оператор проверки условия, на выходе у него тип Boolean (т. е. true (да) или false (нет)). На входе у нас Real, как и у Input Standard — значит, их можно соединять без проблем. В свойствах оператора устанавливаем A = 30 (рисунок 9а).

Добавляем оператор Amount Change — это оператор деления или удаления партиклов, в зависимости от выбранной опции выпадающего меню.

Выбираем Type: Delete и устанавливаем True to delete (если на входе будет true — партикл удаляется) (рис. 9б).

Прокрутите слайдер анимации — партиклы испускаются и, при значении Z = 30, удаляются.

Теперь рассмотрим, как просматривать потоковые данные.

Вариант №1: прямо в окне субоператоров.  

Нажимаем правую кнопку на субоператоре Condition, выбираем Show Data (показать данные, рис 10а), появится всплывающее окно, в котором будут два столбца: номер партикла и значение, которое он получает из данного субопертора (в данном случае, партиклы с индексом 0 и 1 удаляются, т. к. их значения True) (рис. 10б).

Вариант №2: просматривать данные с помощью оператора Display Data.

Сначала добавим субоператор Output New (рис. 11а). Этот оператор позволяет создать пользовательский поток данных.

В свойствах выбираем Data Type (тип данных): Real. Изменим Data Access Scope (область видимости данных) на global, иначе наш Display Data оператор не увидит этот поток данных. Priority and Execution Order (приоритет запуска) установим в Post — это гарантирует более точные данные, потому что субоператор будет выполняться в последнюю очередь.

Для удобства изменим имя субоператора на Zpos ( рис 11б).

Теперь добавляем Display Data* в основном окне PF под наш Data Operator. В его свойствах в Show Data Channel нажимаем кнопку «None» и выбираем наш канал данных Zpos.

Во вьюпорте возле каждого партикла появилась Z координата. Поменяем цвет на желтый.

В Screen Offset (смещение на экране) left/right поставим 25 пикслей. Цифры сместятся вправо. Precision позволяет задавать количество знаков после запятой.

И последнее: ставим Execution order в Post, как до этого ставили в Zpos (рис. 12).  

Возникает вопрос: откуда появились 33.9 и 38 — ведь мы задали в условиях не больше 30. Это потому, что вычисления по умолчанию идут каждый кадр для вьюпорта, и нам, чтобы получить более точные данные, нужно увеличить число итераций за кадр.

Нажимаем на названии PF source 001, в свойствах находим Integration Step — viewport — Frame. Меняем на Half Frame (вычисления 2 раза за кадр) — пропадет партикл с Z=38, меняем на 1/4 Frame (4 раза за кадр) — пропадет партикл с Z=33,9 (рис 13).

2.2. Оператор удаления партиклов внутри или снаружи объекта.

Создаем новую тестовую сцену — Plane с размерами 100×100, пивот в 0, 0, 0 и сферу радиусом 10 с центром тоже в 0,0,0 (рис. 14)

Теперь нажимаем клавишу 6, в PF создаем Standard Flow, Emit Start и Emit Stop устанавливаем в 0, т. к. мы будем размещатьпартиклы на плоскости. Amount ставим 2000.

Вместо Position icon ставим Position Object (находим его в Depot и перетаскиваем прямо на Position Icon).

В его свойствах Emitter Object нажимаем add и кликаем во вьюпорте по Plane (плоскости). Separation (разделение):Distance ставим 2,5, так партиклы не будут друг на друга наслаиваться.

Speed и Rotation удаляем (нам не нужно, чтобы партиклы двигались). В Shape (форма) устанавливаем значение Size=1 и в Display меняем Type на Geometry (рис. 15).

Собственно сцена теперь выглядит так (рис. 16а).

 

Добавляем Data Operator под Position Object. В его свойствах ставим галочку Auto Update и нажимаем Edit Data Flow (рис16б).

Перетаскиваем из Depot субоператор Select Object (выделить объект). Заходим в его свойства, нажимаем на кнопку «None» и выбираем сферу. Этот субоператор служит исходным звеном в получении данных от объекта (рис 17а).

Далее добавляем субоператор Geometry — этот субоператор позволяет получить данные о геометрии, цвете и т. п. уже выделенного объекта. Поэтому на входе у него стоит поток данных «O». Находим в его свойствах Object Property и в выпадающем свитке выбираем Inside Objects (рис. 17б).

Соединяем оба субоператора. Добавляем субоператор Amount Change. Ставим Type в Delete и соединяем с Geometry. Во вьюпорте сразу пропали партиклы, которые не находятся в сфере.

Нажимаем F3 и видим, что партиклы есть только в сфере. Можете покрутить радиус сферы.

Если нам нужно удалить партиклы, которые находятся внутри сферы, в Amount Change установите кнопку в True to Delete.

Каждый раз заходить в окно субоператоров, чтобы выделять объект, неудобно. Поэтому параметры, которые нам нужно контролировать, можно вынести в общее окно PF.

Закрываем окно субоператоров. В свойствах Data Operator нажимаем кнопку Expose Parameters. Откроется дополнительное окно, в котором показано, какие параметры мы можем вынести за пределы окна субоператоров.

Выделяем параметр Object. В label пишем нужное нам название, например, «Sel Obj:» и нажимаем Add (рис. 19а). Теперь в свойствах Data Operator добавилась строка Sel Obj:.

Сейчас можно менять объект, не заходя в окно субоператоров.

Операторы можно сохранять либо как Data Preset, либо как оператор, который будет отображаться в Depot (рис. 19б).

Сохраненным операторам можно добавлять свои иконки или выбрать из стандартных. Если сохранить оператор для Depot, нужно перегрузить 3ds max, тогда имя оператора появится в Depot. В свойствах этого оператора как раз и будут те параметры, которые вы зададите в Expose Parameters. Минус такого сохранения оператора в том, что доступ к редактированию субоператоров будет закрыт.

Операторы и пресеты сохраняются на жесткий диск как Name.pfp в эту папку (для Windows 7):

C:\Users\Name\AppData\Local\Autodesk\3dsMax\2011 — 64bit\enu\plugcfg\Particle Flow Data Presets

2.3 Оператор проверки условия расстояния

Сцена остается такая же. Переименуем Data Operator удаления партиклов внутри сферы в Delete Inside.

Добавим Data Test под оператором Delete Inside. Ставим галочку Auto Update. Нажимаем Edit Data Flow (рис. 20).

Data Test имеет в арсенале один уникальный субоператор Output Test.

Добавим Select Object субоператор, в его свойствах жмем «None» и выделяем сферу, такое мы уже делали в предыдущем примере. 

Добавляем субоператор Geometry, в выпадающем списке Object Property (свойства объекта) выбираем «Closest Point Distance» (ближайшее расстояние до точки). На выходе будет тип данных Real. Это величина будет расстоянием от партикла до ближайшей точки на поверхности. 

Добавляем субоператор Condition. В его свойствах ставим галочку And Less Then Value B (и меньше чем параметр B). Соедините оператор с предыдущим (рис. 21a).

Теперь попробуйте сшить все операторы в одно целое.

У нас есть объект сфера, есть расстояние от каждого партикла до ближайшей точки на поверхности, и мы проверяем, находится ли это расстояние в пределах от 0 до 10 (пока что эти цифры не трогаем).

На выходе у нас булевая величина.

Создайте материал MultiSub Object с двумя слотами (Set Number установить в 2). В каждом слоте простой Standard материал. Первый материал будет с дифузом — синий цвет, второй с дифузом — красный цвет (рис. 21б). 

В основном окне PF добавим оператор Material Static, в его слот материала установим наш созданный материал (рис. 22a). Во вьюпорте все кубики стали синими.

В окне субоператоров добавляем Pipe. Этот субоператор пропускает те значения, которые удовлетворяют поданному на вход. В его свойствах поменяем Data Type на Integer. У нас появилось еще два входа I2 и I3, т. е., если у нас на входе будет True, то Pipe пропустит I3, если False то I2. Это все описано в Pipe Conditions (рис. 22б).

Два раза добавляем субоператор Scalar. Этот простой субоператор подает на вход другого какое-либо значение. В свойствах каждого выбираем Output Type — Integer. В первом оставляем Value = 1, во втором ставим Value = 2. И соединяем с Pipe (рис. 23а).

Добавляем Output Standard. Устанавливаем кнопку в Material Index и соединяем с Pipe. Прокрутите слайдер анимации, если вьюпорт не обновился. Теперь все партиклы, которые находятся рядом со сферой на расстоянии от 0 до 10, изменили цвет на красный (рис. 23б). Подвигайте сферу в разные стороны.

Добавляем Output Test субоператор и соединяем с Condition. Закрываем окно субоператоров (рис. 24а).

Создаем второй event. В свободное поле перетаскиваем оператор Random Walk* и добавляем оператор Shape с предыдущего event. Затем меняем тип Display — Type на Geometry. Соединяем с первым event. Прокрутив слайдер анимации, мы увидим, как красные партиклы разлетаются по сторонам (рис. 24б).

3. Последний пример

Создадим что-то наподобие брызгов от лодки.

Сцена содержит часть водной поверхности — плоскость размерами 1400х1400, сегменты 100х100. Сверху в стеке модификатор Noise : Strength (сила) Z = 40, поставлена галочка на Animate Noise. Анимация длится 100 кадров. Phase в 0 кадре = 0, в 100 кадре =25 (рис. 25).

Добавим лодку — какой-нибудь простой лоупольный объект — и сделаем простую анимацию по кривой. Я также сделал лоупольный туннель вдоль анимации лодки, чтобы впоследствии использовать его для удаления партиклов, лежащих вне линии движения лодки (рис. 26).

Создаем Standard Flow. Удаляем все, кроме Birth, Shape и Display. В Birth устанавливаем Emit Start и Emit Stop в 0, Amount : 2000. В Display — Type: Geometry.

Добавляем Data Operator под Birth. Называем его Position Object. Ставим Auto Update, нажимаем Edit Data Flow (рис. 27а).

В окне субоператоров добавляем Select Object и выбираем наше море (рис.27б).

Добавляем Geometry. В Object Property выпадающем меню выбираем: Closest Point By Surface (ближайщая точка на поверхности). В Objects выбираем: Animated Surface (анимированый объект) — это нужно, чтобы партиклы следовали за объектом, а не стояли на месте; в Subframe Sampling ставим галочки на Placement и Geometry (это увеличит точность размещения партиклов на поверхности) (рис. 27в).

Скопируем предыдущий субоператор Geometry, выберем в Object PropertyPoint Position (позиция точки)(рис. 27г)

Добавляем Output Standard и соединяем с предыдущим(рис.28)

Теперь партиклы будут следовать за поверхностью моря. Остается разместить их на объекте.

Добавляем еще один Geometry. В Object Property устанавливаем Random Surface Point (случайная точка на поверхности). Соединяем его с Select Object(рис.29a).

Очередной Geometry. В Object Property выбираем Point Position (позиция точки)(рис.29б).

Замыкает цепь Output Standard как Position Vector(рис. 29в).

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

Затем нам нужен вектор позиции этой точки, и мы выводим данные в PF.

Возникают вопросы:

1. Мы выводим одни и те же данные Position Vector. Как определить порядок вывода? Для этого, чтобы не путать, PF нужно определить, кто будет выводить данные первым. Нам сначала нужно разместить партиклы на объекте, а затем уже привязывать их к точке поверхности. Поэтому Execution Order должен быть как на картинке (рис. 29).

2. Прокрутите слайдер анимации. С каждым кадром партиклы бегают по всей поверхности. Это потому, что Random Surface Point вычисляется каждый кадр. Нам это не нужно. Поэтому мы добавляем Input Standard, устанавливаем его в New In Event и соединяем с входом Random Surface Point. Теперь вычисления случайной точки на поверхности будут производиться только один раз в начале анимации (рис. 30). 

С этим оператором все. Окно субоператоров закрываем.

Переходим в основное PF. Добавляем Data Operator под предыдущий. Называем его Delete Inside Boat.

Он будет удалять партиклы внутри лодки. Мы точно такой же делали в 2.2 (рис. 31).

Копируем Delete Inside Boat. Называем его Delete Outside Tunnel. Этот оператор будет удалять партиклы снаружи обьема тунелля, который мы сделали по ходу двиижения лодки. Т. е., в последнем субоператоре у него будет «False To delete».

Еще один момент. В дальнейшем этот оператор может удалять и наши брызги, когда они будут вылетать за его обьем, нам это не надо, поэтому мы его будем запускать только в начале event, как в предыдущем примере с Random Surface Point (рис. 32).

Следующий оператор точно такой же, как и в пункте 2.3. Я назвал его Dist Threshold.

Distance Threshold это субоператор Output New с Data Access Scope установленным в Global. Мы делали похожий, когда выводили данные во вьюпорт в 2.1. Я создал его, чтобы использовать эти данные в следующем Data-операторе (рис. 33). 

Последний Data-оператор, который мы рассмотрим, будет выполнять два действия: направлять партиклы от лодки по нормали и затем поднимать их в воздух.

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

Субоператор Select Object — выбираем нашу лодку (рис. 34а).

Субоператор Geometry — выбираем из меню Object Property — Closest Point By Surface (ближайшую точку на поверхности от партикла) (рис. 34б).

Субоператор Geometry — выбираем из меню Object Property — Point Normal (нормаль точки). Это дает нам нормаль ближайшей точки поверхности лодки (рис. 34в).

Субоператор Function — мы умножаем наш вектор нормали на число, чтобы контролировать величину вектора (рис. 34е).

Субоператор Random — генератор случайных чисел. Я установил Distributionт в Uniform и Minimum:17, Maximum:25 (рис. 34г).

Субоператор Function — добавил, чтобы уменьшить значение Random субоператора. Post factor установил в 0,001 — получилось простое умножение (рис. 34д).

Субоператор Output Standard установлен в Speed Vector. Т. е., по сути, мы с небольшими преобразованиями передаем вектор нормали точки поверхности в вектор скорости (рис. 34з).

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

Для этого я в прошлом операторе и выводил отдельно данные Distance Threshold.

Субоператор Input Custom — в свойствах его есть кнопка Data Channel. Нажимаем на нее, выбираем Distance Threshold и соединяем, как на рисунке. Теперь только те партиклы, которые рядом с лодкой, будут двигаться от нее (рис. 34ж).

Вторая ветвь простая. Мы получаем доступ к Z-компоненту вектора, умножаем его, как в первой ветке, и выводим обратно. Цель второй ветви — поднять партиклы немного в воздух (рис.  35). 

Последний оператор Output Standard тоже ограничиваем через Dist Threshold.

С субоператорами все. Закрываем окно.

Дальше, в PF окне добавляем Speed Test оператор. Теперь нам надо отсеять партиклы, у которых скорость 0, которые просто лежат на поверхности (рис. 36а).

Ставим Test Value в 0. 

Добавляем в сцену Gravity. Оно находится в Space Warps — Forces. В PF создаем оператор Force и добавляем в него Gravity. Influence (влияние) я уменьшил до 100 (по умолчанию 1000). У Вас, возможно, будут другие значения (рис. 36б). 

Скопируем Delete Inside Boat как Instance в Event 002.

Добавим Data Preset и в меню пресетов выберем готовый Delete By Elevation. Это стандартный пресет, идущий с плагином. Он удаляет парктиклы на определенной высоте (как мы делали в первом примере с осью Z). Если партиклы провалятся под геометрию моря, они удалятся, как задано в операторе. Значение высоты подбирается опытным путем (рис. 37а).

Теперь добавляем Krakatoa collision Test. Можно использовать и стандартный, но, по заверениям разработчиков Krakatoa, их тест работает в десятки раз быстрее. Выбираем наше море.

Последним копируем наш Position object оператор и удаляем левую часть, т. е., все, что касается расположения партиклов на поверхности. Теперь, после Krakatoa Сollision Test, наши партиклы перемещаются в новый event и остаются на поверхности моря (рис. 38). 

Все. После удовлетворительных тестов можно увеличить количество партиклов и отрендерить в Кракатоа.

Тест на скорую руку. Извиняюсь за анимацию.

Примечание:
скорость в 3ds max интерпретируется как величина на каждый tick. Ticks — величина приращения времени в 3ds max. В секунду их 4800. Поэтому все величины, касающиеся скорости, прийдется очень сильно уменьшать.

Основной проблемой Box#3, как, наверное, и всего PF в целом, являются тормоза. Ну, и не помешал бы оператор фрагментации, как в TP.

Что можно посмотреть по теме:

  • два выпуска PFlow Toolbox Office, автор Anselm von Seherr www.turbosquid.com/FullPreview/index.cfm/ID/520846
  • его недавний шоурил работ, выполненных с помощью Box#2#3

  • ну, и форум www.orbaz.com/forum/. На форуме есть раздел, где люди выкладывают свои пресеты.

Если что-то непонятно — пишите.

808 0 850 35
12
2011-06-28
Отличный материал! В рунете редко такое найдешь! Автору мега-респект!
2011-06-28
очень круто, автору огромное спасибо, просто огромное!
2011-06-28
Супер! Спасибо!
2011-06-28
спасибо за урок!
2011-06-29
присоединяюсь отличный урок
2011-06-30
Грамотно ! Спасибо !
2011-07-01
Спасибо! Спасибо !
2011-07-07
почему нельзя поставить оценку 500? замечательный урок!
2011-07-23
Спасибо за отзывы. Вторая часть тут: [url]http://www.render.ru/books/show_book.php?book_id=1145[/url]
2011-09-22
Я прошу прощения за офтоп, но подскажите пожалуйста кто-то, в решении моей проблемы: есть сцена, в которой используется оператор Lock\Bond, во вьюпорте партиклы ведут себя нормально, все работает правильно, но при рендере, показывает совершенно другой результат, в чем может быть проблема? Спасибо!
2012-01-19
хороший урок, долго не мог заставить себя взяться за тулбокс -боялся!, а тут прочитал, и сразу вьехал в тему
2017-05-23
Отличная статья! Люто плюсую.
RENDER.RU