Уроки: Softimage|XSI

Создание модификатора утолщения средствами ICE

Введение

Здравствуйте, те, кто использует программу Autodesk Softimage, и просто интересующиеся. Настоящий урок посвящен созданию модификатора утолщения объектов средствами ICE. Сразу же сделаем несколько пояснительных комментариев, являющиеся предпосылками к написанию этого урока. Во-первых, не очень давно (на момент публикации) вышла версия Softimage за номером 10, более широко известная, как Softimage 2012. В ней впервые появилась возможность работать с так называемой топологией объектов. Это означает, что появилась возможность создавать, удалять и иначе преобразовывать вершины, ребра и полигоны полигонального объекта (простите за каламбур). Раньше такого не было. Вот и решено было забабахать что-нибудь, что использовало бы новый для этой версии программы функционал. Отметим, что среди многочисленных видео, посвященных демонстрациям работы средств моделирования ICE-ом, встречается одно, где кое-кто из разработчиков показывает, как он сделал модификатор утолщения. Да-да, почти то же самое, о чем и пойдет речь в дальнейшем. Впрочем, его модификатор чрезвычайно плох, так как выдавливает геометрию только в направлении осей координат, написан на еще дорелизной версии программы, и вообще, там ничего не понятно.

Во-вторых, в XSI нет штатных средств утолщения объектов. Вот так вот, нет и все тут. В Максе есть Shell, а тут ничего такого нет. Конечно, написано уже несколько простых дополнений, которые решают эту досадную оплошность, а некоторые говорят, что вообще такой модификатор не нужен, так как утолщение делается несколькими движениями мыши. Но, все же, теперь и мы сделаем такой модификатор, да не просто так, а средствами ICE, потому как все, что не ICE — не айс, а ICE — это, сами понимаете, айс.

В-третьих, в настоящем уроке дается введение в программирование на ICE, потому как логика у него не очень, и есть кое-какие сложности в достижении целей. Это, конечно же, общие слова, когда перейдем к делу, видно будет, где какие сложности.

Давайте теперь оставим досужие разговоры за жизнь и начнем наш урок. Итак, первое, о чем стоит сказать — это интерфейс. На рис. 1 изображен типичный вид окна программы для случая, когда надо что-то писать на ICE: Explorer, чтобы легко было таскать атрибуты объектов, большое окно для дерева нод и маленькое окошко, где крутится объект (так называемый вид Camera).


Рис. 1. Окно программы

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


Рис. 2. Пример геометрии

Убедившись, что наша геометрия зафризена и у нее сброшены все трансформации, создаем ICE Tree (рис. 3).


Рис. 3. Создаем ICE Tree

ICE Tree можно создавать в разных режимах (моделирования, анимации, вторичных деформаций и так далее), в каждом случае есть своя специфика. Для наших целей достаточно будет все время работать в Modeling Constuction Mode. Итак, корневая нода ICETree создана, и теперь самое время переходить к программированию. А тут как раз и лирическо-техническое отступление подоспело. Забудем пока о нашей главной цели и сделаем программку, которая ничего не делает. Может быть кто-нибудь спросит: дескать, а зачем нам что-то делать, чтобы ничего не делать? А ответ простой — чтобы усвоить кое-какие истины.

Все программирование зиждется на работе с переменными (и прочими свойствами классов). Программирование же на ICE зиждется на работе с атрибутами. Что такое атрибут? Ну, это вроде переменной, только значения этих переменных могут относиться не только целиком к объекту, но и к его частям. Примерами могут служить местоположения частиц (у каждой частицы свое положение в пространстве), нормаль к полигону (опять же, каждый полигон имеет свою нормаль). Бывают атрибуты, относящиеся и целиком к объекту. Как уже понял сообразительный читатель, каждый созданный объект обладает уже заранее готовым набором атрибутов. Мы, впрочем, ничем не ограничены и можем сами создавать сколько угодно атрибутов у каждого объекта, при этом записывать в них какую угодно информацию.

Переходим к конкретному примеру. Добавляем ноду Get Point Position. Где ее найти? Да в левой части окна ICE Tree. Пишем в строке поиска примерное название ноды, и все, что подходит, тут же появляется. Нам остается только найти нужную ноду и перетащить ее куда следует (рис. 4). Конечно, все ноды разбиты по категориям, и можно искать нужную ноду в соответствующей категории, но это кому как удобнее.


Рис. 4. Нашли ноду Get Point Position

Теперь время спросить себя, а что же делает нода Get Point Position. Ответ — она возвращает местоположение в пространстве каждой вершины объекта, причем приподносится это, как тройка (координаты по X, Y и Z), сопоставленная каждой вершине. Чтобы углядеть все это более явно, добавляем ноду Set Point Position. Здесь уже все сами понимают, что надо делать. Связываем выход Get Point Position со входом Set Point Position, и, наконец, все это связываем с портом Port1 корневой ноды (рис. 5).


Рис. 5. Связали Get PP и Set PP

Что делает нода Set Point Position? Сообразительный читатель уже понял, что она просто задает каждой вершине объекта ее местоположение в пространстве. Так как мы только что взяли это местоположение и тут же его обратно задали, конечно же, ничего не произошло. Но зато теперь мы можем посмотреть, а какая же информация передается от одной ноды к другой. Для этого жамкаем правой клавишей на линии, соединяющей Get PP и Set PP, и выбираем Show Values (рис. 6).


Рис. 6. Выбираем Show Values

В выскочившей, как чертик из табакерки, менюшке выбираем отображение информации числовым методом (рис. 7) и жмем OK.


Рис. 7. Выбираем тип Numeric

Теперь время ахать. Что же мы видим в окне камеры, где раньше была тишь и благодать, и ничто не предвещало беды? Теперь же там неразбери-поймешь что творится (рис. 8). В каждой вершине объекта написаны ее координаты в пространстве, сиречь Point Poistion. Вот это и есть то, что называется контекст атрибута. Point Position является не массивом координат, но координатами каждой вершины в отдельности. Еще это называют per Point. Поэтому, когда хочется перекидывать информацию из одного атрибута в другой, надо следить, чтобы у них совпадал контекст, а иначе чуда не произойдет.


Рис. 8. Координаты вершин объекта

Чтобы закончить наше лирическо-техническое отступление, узнаем, а какие еще бывают атрибуты у объекта. Сделать это просто. Необходимо добавить ноду Get Data (используем поиск, рис. 9). Сразу видно, что новоявленной ноде неловко. А все потому, что не знает она, какой атрибут от нее требуют, только смотрят пристально, да языком прицыкивают.


Рис. 9. Добавляем ноду Get Data

Чтобы исправить ситуацию, жамкаем на Get Data два раза, набираем в единственной свободной строке self. (не забываем про точку), и жмем Enter. Нода стала голубенькой, потому как уже кое-что она возвращает (собственно она возвращает теперь весь объект). Нажимаем кнопочку Explorer, и вот они, родненькие, атрибуты наши (рис. 10). Не очень их много, но они есть. На этом разрешите окончить вводную часть и позвольте перейти к основному содержанию урока.


Рис. 10. Атрибуты наши родненькие

Работа с топологией

Начинаем конструировать наш модификатор утолщения. Первым делом хорошо было бы сохранить в отдельный атрибут (читай переменную) всю изначальную топологию. Что есть топология? Может быть некоторые думают, что топология — это множество подмножеств множества X, удовлетворяющее ряду аксиом? А вот и нет! В XSI (да и вообще в CG) топология — это суть совокупность вершин, ребер, полигонов и связей между ними (так называемое отношение смежности).

Так вот, сохранить топологию необходимо для того, чтобы потом, изменив геометрию, можно было как-то использовать изначальную геометрию. В общем, понадобится потом это, точно говорю. Сохранение топологии делается очень просто. Добавляем ноду Get Data, в ней прописываем, как мы учили, self., и потом из раскрывающегося списка выбираем атрибут Topology (Рис. 11). Наблюдательный читатель заметил, что на скрине написано не self.Topology, а this.Topology. В принципе это одно и то же, XSI сама заменяет одно на другое, когда ей вздумается.


Рис. 11. Получили топологию

Альтернативный способ получить топологию заключается в том, чтобы воспользоваться нодой Get Topology (рис. 12). Обратите внимание, что в этом случае необходимо в графе Transform Mode выставить значение No Transform.


Рис. 12. Нода Get Topology

Наконец, сохраняем топологию в отдельный атрибут. Для этого добавляем ноду Set Data (рис. 13), вписываем self.Thic_OriginalTopo (рис. 14), и связываем все между собой (рис. 15). 


Рис. 13. Добавляем Set Data


Рис. 14. Добавляем новый атрибут


Рис. 15. Связываем все в одну ветвь

Поясним, что же только что было сделано. Мы сохранили всю текущую топологию объекта в отдельный атрибут, который назвали Thic_OriginalTopo. Здесь каждый мог написать свое собственное имя, но лучше их все как-то выделять, чтобы потом долго не искать и не путаться (например, добавлять префикс Thic_). Убедимся, что атрибут действительно создан. Для этого добавляем ноду Get Data, пишем self., и видим, что созданный атрибут имеет место быть (рис. 16).


Рис. 16. Созданный атрибут присутствует

Поехали дальше. Теперь необходимо выдавить полигоны. Сделаем мы это с помощью ноды Extrude Polygon Island (рис. 17). Результатом работы этой ноды является новая топология, поэтому, чтобы геометрия объекта обновилась после преобразования, ее необходимо пропустить через ноду Set Topology (см. рисунок 18, на котором мы связали все три сиреневые ноды в одну ветвь. Также изменен параметр Inset, чтобы видеть, к какому полигону применяется преобразование). Кстати говоря, измененный полигон имеет индекс 0.


Рис. 17. Нода Extrude Polygon Island


Рис. 18. Нода Extrude Polygon Island в действии

Необходимо, чтобы преобразование выдавливания применялось не к одному-единственному полигону, но ко всем сразу. Сделать это так же просто, как и все то, что было до этого. Добавляем ноду Get Polygon Index и связываем ее с портом Polygon Index ноды Extrude Polygon Island (рис. 19). Смысл проделанных операций предельно ясен, тут даже и несообразительный читатель поймет, в чем дело.


Рис. 19. Теперь преобразованы все полигоны

Придаем параметру Inset прежнее значение 0, при этом все крайние полигоны становятся бесконечно тонкими, но тем не менее никуда не пропадают. На рисунке 20 мы специально отодвинули парочку вершин, чтобы убедиться, что полигоны есть и они никуда не ушли.


Рис. 20. Граничным полигонам быть

Дальше — один из ключевых моментов. Нам необходимо применить ко всем неграничным вершинам нашего объекта модификатор Push. Прямо сейчас мы его и соорудим. Итак, нам понадобится положение каждой вершины (нода Get Point Position), нормаль к каждой вершине (нода Get Point Normal), ну и, конечно же, нода Set Point Position, записывающая все изменения местоположений вершин (рис. 21).


Рис. 21. Готовим ноды

Еще нам понадобится информация о том, является ли вершина граничной или нет. Если она граничная — то мы оставляем ее неподвижной, а если не граничная — сдвигаем в направлении нормали. Получить необходимую информацию можно из атрибута VertexIsBorder (рис. 22). Значением данного атрибута является булеановское (либо 1/0, либо истина/ложь, кому как удобнее) значение в каждой вершине.


Рис. 22. Атрибут VertexIsBorder

Мы должны сделать следующее: хватаем каждую вершину по очереди, смотрим, является ли она граничной, и, если нет, то добавляем к ее местоположению (которое является трехмерным вектором) вектор нормали. Сумма векторов — снова вектор, поэтому результат можно объявить новым местоположением вершины. Отметим, что все используемые атрибуты имеют контекст per Point, а поэтому над ними можно совершать операции, и все будет работать, причем сразу для всех вершин. Реализуем наши действия.

Полезной оказывается нода Filter, у которой есть два входных порта. В нижний порт подается любая величина, а в верхний — булеановское значение. Если оно оказывается истинным, то любая величина (из второго порта) пропускается дальше, в противном случае, величина не пропускается и, как следствие, не меняется в дальнейшей цепочке. Поэтому делаем следующее: добавляем ноду Filter, ее значение (порт Value) связываем с Get Point Position, а условие — с VertexIsBorder. Далее добавляем ноду Add, которая складывает значения, один из портов которой связываем с выходом ноды Filter, а другой — с Get Point Normal. Ну и, наконец, результат сложения связываем с Set Point Position. Сейчас все работает с точностью до наоборот: если вершина граничная, то она пропускается сквозь фильтр и следовательно сдвигается. Чтобы исправить это досадное недоразумение, просто добавляем ноду Not между фильтром и VertexIsBorder. Итоговая ветвь изображена на рисунке 23.


Рис. 23. Сдвигаем все вершины, кроме граничных

Теперь наступает очередь второго ключевого момента: необходимо добавить исходную геометрию так, чтобы получилась утолщенная поверхность. Делать это будем с помощью ноды Merge Topo. Результатом ее работы является топология, поэтому перед подключением к корневой ноде ICETree пропускаем все через Set Topology (рис. 24).


Рис. 24. Нода Merge Topo

Как мы с удовольствием наблюдаем, входными параметрами ноды Merge Topo являются топологии в произвольном (в разумных рамках) количестве. Нам необходимо объединить текущую топологию и ту, что ранее была сохранена в специально отведенный для этого атрибут. Так и поступаем: добавляем ноды Get Topology и Get Data. В последней выбираем наш атрибут Thic_OriginalTopo (рис. 25).


Рис. 25. Берем ранее сохраненную топологию

Соединяем все вместе, и — вуаля! — получаем не то, что надо (рис. 26).


Рис. 26. Получили не то, что хотели

Почему это не то, что надо? — спросит несообразительный читатель. Мы так тихонько посмеемся, отечески похлопаем его по плечу, ухмыльнемся, вздохнем, но выложим всю правду, как на духу. Нормали-то у внутренней стенки перевернуты! Это надо срочно исправлять. Добавляем ноду Invert Polygon (рис. 27). Если мы просто пропустим связь от Thic_OriginalTopo к Merge Topo сквозь ноду Invert Polygon, то инвертируется только один полигон. Инвертирование необходимо применить ко всем полигонам, поэтому добавляем ноду Get Polygon Index, и связываем ее с портом Polygon Index (рис. 28). Теперь хорошо видно, что нормали у всех полигонов повернуты куда следует.


Рис. 27. Добавляем ноду Invert Polygon


Рис. 28. Инвертируем все полигоны

Сделаем небольшое отступление и добавим возможность регулировать толщину объекта. Для этого надо вспомнить, что толщина объекта определяется в тот момент, когда все неграничные вершины сдвигались в направлениях их нормалей. По умолчанию нормаль имеет единичную длину, поэтому толщина объекта получается, грубо говоря, единичная. Чтобы менять толщину, достаточно умножать вектор нормали на некоторое число. Делается это с помощью ноды Multiply by Scalar (рис. 29). Вот и все, крутим значение параметра Factor, и толщина объекта меняется. Это было первое отступление.


Рис. 29. Регулятор толщины

Второе отступление заключается в следующем: к настоящему моменту дерево с нодами у нас не сильно перегружено, но в скором времени мы добавим еще кое-чего, и будет вообще караул. Поэтому удобно, хотя бы визуально, логически законченные куски отделять друг от друга. Сделать это можно с помощью ноды Execute. Она выполняет ту же роль, что и корневая нода дерева — собирает в себе действия. С ней можно связать некоторые ветви, и утащить куда-нибудь в сторону (рис. 30). При этом сама корневая нода ICETree разгрузится, и будет логически отделен некоторый фрагмент дерева.


Рис. 30. Нода Execute

Объединение вершин

Этот параграф является третьим основным пунктом настоящего урока. Все, что нам осталось сделать — это попарно объединить граничные вершины. Пока ничего толкового в голову не идет, давайте посмотрим на индексы граничных вершин. Сделать это просто. Добавляем ноду Get Data и берем из нее значение атрибута VertexIndex (рис. 31).


Рис. 31. Get Data и VertexIndex

Далее добавляем ноду Set Data и записываем информацию в новый атрибут, который можно обозвать Thic_Temp (рис. 32).


Рис. 32. Создаем вспомогательный атрибут Thic_Temp

Наконец, соединяем всю ветвь и выводим на экран передаваемую информацию (рис. 33).


Рис. 33. Индексы граничных точек

Мы специально раздвинули вершины с индексами 4 и 116, чтобы можно было ясно видеть эти номера. Любознательный читатель сам быстренько потягает вершины и убедится, что разность между индексами граничных вершин, которые должны быть объединены вместе, постоянна. В нашем случае эта постоянная величина равна 112. Хорошо было бы научиться считать эту величину в независимости от конкретной геометрии. Давайте для начала посчитаем число вершин у исходного объекта, а также определим, сколько из этих вершин являются граничными.

Добавляем ноду Get Data и считываем значение атрибута VertexIndex (рис. 34). Полученное значение имеет контекст per Point, то есть является целым числом, сопоставленным каждой вершине. Нам же хочется узнать, сколько всего этих чисел. Добавляем ноду Build Array From Set (рис. 35). Эта нода возвращает одни массив, состоящий из индексов вершин, и имеющий контекст per Object. Это хорошо. Добавляем ноду Get Array Size, которая, судя по названию, возвращает число элементов в массиве. Наконец, добавляем последнюю ноду Set Data и создаем новый атрибут, который будет хранить в себе число вершин исходного объекта. Назовем этот атрибут Thic_OriginalVertexCount (рис. 36).


Рис. 34. VertexIndex


Рис. 35. Нода Build Array From Set


Рис. 36. Ноды Get Array Size и Set Data

Соединяем все вместе (рис. 37). Важным моментом является номер порта в корневой ноде ICETree, с которым связывается выход ноды Set Data. Этот порт должен быть выше порта, через который происходит выдавливание геометрии. Иначе мы посчитаем число вершин уже измененной геометрии, что совершенно ни к чему.


Рис. 37. Соединяем всю ветвь

Поехали дальше. Теперь давайте считать число граничных вершин. Расчехляем атрибут VertexIsBorder и так же, как и раньше, строим из него один массив (рис. 38). Необходимо узнать, сколько в массиве значений true. Для этого используется нода Find In Array. В порт Array отправляем собственно наш массив, а для того, чтобы указать, что значение Value должно быть true, можно либо поставить галочку в свойствах ноды, либо создать константу true и связать ее с портом Value (рис. 39).


Рис. 38. Строим массив из true/false


Рис. 39. Нода Find In Array

Выходной порт Index Array ноды Find In Array содержит индексы всех вершин, которые в ранее построенном массиве имели значения true. Нам надо определить их число. Делаем это так же, как и раньше. Полученное значение записываем в атрибут Thic_BoundaryVertexCount (рис. 40).


Рис. 40. Считаем число граничных вершин

Проверяем, и действительно, наши созданные атрибуты содержат значения 80 и 32, сумма которых как раз равняется 112 (рис. 41). Вообще, результат предсказуем. Мы же объединяли два объекта в один, поэтому естественно, что сначала нумеруются вершины первого объекта, а потом второго. Следовательно, номера вершин второго объекта больше числа вершин первого объекта, что мы и наблюдаем.


Рис. 41. Проверяем сохраненные значения

Теперь вырисовывается примерная схема, как же можно попарно объединить граничные вершины. Давайте найдем сначала индексы всех граничных вершин, а потом будем циклически хватать какой-либо индекс, добавлять к нему 112 и объединять соответствующие вершины. Потом будем удалять эти два использованных индекса из массива, и заново по кругу до тех пор, пока не выйдут вон все индексы. Это лишь примерная схема, тут есть несколько нюансов, но мы их решим по мере поступления.

Итак, строим массив (в контексте per Object) всех граничных вершин. Это уже проходили, поэтому просто покажу картинку (рис. 42). Обращаем внимание, что теперь все действия снова связываем с нижними портами корневой ноды ICETree. Сам массив мы записали в атрибут с именем Thic_BoundaryVertexIndexes.


Рис. 42. Массив индексов граничных вершин

Переходим к объединению вершин. Понятно, надо добавить ноды Get Topology, Set Topology и, самое главное, Merge Vertices (рис. 43).


Рис. 43. Нода Merge Vertices

Внимательно смотрим на ноду Merge Vertices и видим, что объединяемые вершины должны подаваться одним массивом в порт Vertex Index Array. У нас вершины объединяются попарно, поэтому мы должны сформировать массив всего из двух индексов. Сделать это можно следующим образом. У нас же есть массив всех граничных вершин. Выбираем из него наибольший индекс, потом вычитаем 112 и формируем из этих двух чисел искомый массив. Давайте так и сделаем.

Добавляем ноду Get Data и считываем значение атрибута BoundaryVertexIndexes. С помощью ноды Get Array Maximum выбираем из этого массива наибольшее значение. Наконец, формируем новый массив с помощью ноды Build Array (рис. 44).


Рис. 44. Наибольший индекс граничной точки

Сформированный массив содержит в себе индекс одной вершины, а надо индексы двух вершин. Складываем значения атрибутов Thic_BoundaryVertexCount и Thic_OriginalVertexCount (рис. 45). Как мы раньше выяснили, сумма равна 112.


Рис. 45. Получаем число 112

Вычитаем из ранее выбранного максимального индекса граничной вершины число 112 и добавляем полученный индекс в массив (рис. 46).


Рис. 46. Формируем второй элемент массива

Тягаем вершину с индексом 188, и — о чудо! — вершины объединились (рис. 47). Вот до чего плюсики и минусики довести могут.


Рис. 47. Вершины объединены

Отметим, что с тем же успехом мы могли бы выбирать из массива не наибольшее значение, а наименьшее, и к нему добавлять 112. Это было бы хорошо, если бы не было плохо. При таком подходе после объединения вершин все индексы пересчитываются, и созданный ранее массив индексов граничных вершин оказывается не у дел. В подходе, который мы реализовали, перенумерация также происходит, но нам этого не видно, так как все вершины которые нам нужны будут иметь те же самые индексы, что и раньше. Это связано с логикой и последовательностью операций внутри самого ICE, поэтому нечего тут пенять и сокрушаться, можно только подстраиваться.

Продолжаем. Необходимо выкинуть использованные индексы из массива. Добавляем ноду Set Data, в которой выбираем атрибут Thic_BoundaryVertexIndexes (будем переопределять его содержимое). Потом добавляем ноду Remove From Array (рис. 48).


Рис. 48. Нода Remove From Array

С входным портом Array ноды Remove From Array связываем используемый нами массив индексов граничных вершин, а в порт Index мы должны передать индекс в массиве максимального значения. Для этого можно использовать ноду Find In Array. Итоговые связи изображены на рисунке 49.


Рис. 49. Удаляем первый элемент массива

Второй элемент массива удаляется так же легко. Сначала находим его индекс в массиве с помощью ноды Find In Array, а потом выкидываем с помощью ноды Remove From Array (рис. 50).


Рис. 50. Удаляем второй элемент массива

Мы уже почти приблизились к концу. Осталось только несколько раз повторить все вышеописанные действия. Для этого добавляем ноду Repeat, которая как раз и повторяет ту или иную ветвь дерева несколько раз. Входной порт для действий у ноды Repeat один, поэтому целесообразно операции с массивом индексов граничных вершин и с объединением вершин пропустить через ноду Execute (рис. 51).


Рис. 51. Нода Repeat

Если два раза жамкнуть на ноду Repeat и потаскать единственный манипулятор, то можно увидеть маленькое чудо. Голубая полоска граничных ребер местами начинает заменяться на беленькие ребра. Это все потому, что вершины объединяются. Ура, товарищи! Впрочем, мы четко знаем, сколько необходимо итераций в ноде Repeat. Ровно столько, сколько граничных вершин было у исходного объекта, а это в точности значение атрибута Thic_BoundaryVertexCount (рис. 52). Вот и все, на этом основная часть создания модификатора утолщения средствами ICE закончена.


Рис. 52. Повторяем нужное число раз

Заключение

Общий вид получившегося дерева ICE изображен на рисунке 53. 


Рис. 53. Общий вид дерева ICE

Давайте создадим теперь нашу собственную ноду утолщения. Первым делом надо сделать так, чтобы с корневой нодой ICETree была связана только одна ветвь (рис. 54).


Рис. 54. Добавляем ноду Execute

Далее выделяем все ноды, кроме корневой, жмем правой клавишей и выбираем пункт Create Compound (рис. 55).


Рис. 55. Создаем компонент

Заходим внутрь компаунда (так прямо по-русски и называется), нажав на букву e в кружочке над верхним левым углом прямоугольника. Жмем два раза на имя компаунда и вписываем туда все, что угодно, например Thickness_ICE (рис. 56).


Рис. 56. Задаем имя компаунда

Еще хотелось бы, чтобы у компаунда были кое-какие параметры, например, регулятор толщины. Чтобы достичь желаемого, перетаскиваем входной порт ноды Multiply by Scalar на черный кружок на левой панели (рис. 57).


Рис. 57. Выводим редактируемый параметр

Вот и все, теперь подключив наш компаунд к любому полигональному объекту, можно ему задавать произвольную толщину (рис. 58).


Рис. 58. Итог работы

Следует сказать, что модификатор получился хоть и рабочим, но не очень-то и хорошим. Работает медленно. Хоть и ICE, хоть и многопоточность, но вот прямо чувствуется, как компьютер начинает работать, когда крутишь разные (пока весьма немногочисленные) параметры у компаунда. В этом отношении старые добрые дополнения, о которых упоминалось во введении, гораздо эффективнее.

Напоследок, в приложенном файле лежит немного доработанный аналогичный компаунд. В нем добавлена возможность утолщения в обе стороны (как во внешнюю часть объекта, так и во внутреннюю). Также он не портит исходного объекта, а должен подсоединяться к ICETree пустого полигонального объекта. С портом Original Mesh связывается объект, который хотелось бы утолстить. Да и вообще, теперь каждый сам с удовольствием разберет на винтики этот компаунд, так как после прохождения урока там все должно стать предельно ясным.

Засим разрешите откланяться и пожелать успеха в освоении столь важного и нужного инструмента, как ICE.

13042 Автор:
Актуальность: 607
Качество: 700
Суммарный балл: 1307
Выбор Публики
Голосов: 68 оценки

Отзывы посетителей:

2 | След.
аватар
 
sea 2 0
Что есть топология? Может быть некоторые думают, что топология — это множество подмножеств множества X, удовлетворяющее ряду аксиом? А вот и нет! В XSI (да и вообще в CG) топология — это суть совокупность вершин, ребер, полигонов и связей между ними (так называемое отношение смежности).


Перельман поперхнулся бы чаем!

А вообще написано классно, остроумно, читать очень приятно

спасибо за урок!
аватар
 
al_long 1 0
Вообще люди не понял, всей полемики вокруг сравнения макса и кси, кси гораздо проще, по принципу как думаю так и делаю, не надо лезть в модификаторы. Многие вещи просто движением линий и полигонов делаются. В максе для этого чёрти куда лезть надо. Просто кси это больше философия чем программа.
аватар
 
al_long 1 0
Не понял, сути всех этих телодвижений. Прсто Ctrl+D ,отмаштобировать и дальще выровнять точки с COG-ом, если что развернуть полигоны.
аватар
 
Paradox072 2 0
Цитирую sky_myth:
Я только не понял зачем все эти сложности. Как урок, да полезно. А практическое применение не очень вижу

Подобную тему однажды демонстрировал один человек, он обитает на youtube под ником mschoennagel, в этом видео http://youtu.be/do1kzR6gVYk начиная где то с 10 минуты, он рассказывал преимущество использования ice для создания собственных модификаторов. Самый главный плюс использования подобной штуки в том, что все просчитывается в несколько раз быстрее, ICE работает gscnhtt стандартных скриптов с++, еще плюсом там была тема про то, что все это можно сделать очень кастомным и так далее. В общем ICE лучше потому что ты делаешь все сам, и настраиваешь по себя, и считается это все в разы быстрее.
P.S. Урок не читал.
аватар
 
Андрей Павлов 2 0
Никогда не работал Softimage но если ICE хотя-бы немного похож на Grasshopper для Rhinoceros то это однозначно очень нужная и полезная штука! Единственный явный недостаток по сравнению с Grasshopper это не очень наглядный интерфейс, ну и конечно подобную функцию в Grasshopper можно сделать гораздо проще (не пользуясь стандартным Shell, который в нём есть))
аватар
 
Алексей Артемьев 43 0
Большое СПАСИБО за урок!
аватар
 
sky_myth 23 0
Я только не понял зачем все эти сложности. Как урок, да полезно. А практическое применение не очень вижу
аватар
 
leonhart 1 0
Спасибо за труд и столь подробный урок:) ICE штука, конечно, не простая, но поняв как работает эта чертова векторная математика, открываешь для себя большие возможности. Хотя порой количество нод в ICE tree... м-м... впечатляет:)
аватар
 
Kratinov Alexander 6 0
не не, меряться не нада
это я на риторический вопрос случайно ответил
Цитирую LabEG:
Вот смотришь на 55 картинку и и длину страницы и думаешь, а нафиг оно ваще надо. Даешь Мах.ехе и работу в два клика!
аватар
 
Strannick 5 0
Цитирую Kratinov Alexander:
в ICE, зачастую меньшими усилиями можно создавать штуки недостижимые в 3dsmax


к чему это вообще? ни чем мы меряться не собираемя, надеюсь? )
аватар
 
slava85 80 0
еще!!! еще!!!,я хочу еще таких уроков!!! автор вы только не останавливайтесь!!!
аватар
 
Sl1m 45 0
Жесть какая...
аватар
 
Nicod 38 0
Грассхоппер для поликов? Занятно-занятно
аватар
 
Mr.Core 11 0
havok
это значит что нету глобальных нод для операций типа паш, надо делать их из нескольких примитивных действий
я имел ввиду под низкоуровневостью не скорость, а гибкость, как например возможность напрямую работать с отдельно взятым поликом или каким-то специфическим аттрибутом
аватар
 
Итан 74 0
Цитирую:Раньше и в Максе его не было и не страдали от этого.
- Это инструмент первой необходимости. Я еще не говорю о оснастке с его применением, друзья мои.
аватар
 
JBond 37 0
Цитирую Mr.Core:
Mr.Core
07.05.2011 17:19
этот урок кстати, наглядно показывает, что текущий инструментарий очень и очень низкоуровневый

Что подразумевается под очень низкоуровневым? Если оно тормозит значит там далеко не низкоуровеный код под капотом.

Вероятно если написать все вручную тормозить не должно.
С нодами конечно намного интереснее работать в визуальном плане.
аватар
 
qf 255 0
Или проще - Interactive Thickness ver.1.1
ссылкаhttp://artifacts.sakura.ne.jp/sakanaya/2008/03/softimagexsi_interactive_thick.htm
аватар
 
Kratinov Alexander 6 0
Цитирую 12sunflowers:


freeze transforms
duplicate
deform -> push
polymesh ->invert polygons
merge с оригиналом (blend on)
аватар
 
12sunflowers -7 0
а как ручками можно шелл в кси сделать?
аватар
 
Kratinov Alexander 6 0
к сведению уважаемых труженников макса, в ICE, зачастую меньшими усилиями можно создавать штуки недостижимые в 3dsmax.
а shell затронул много аспектов работы с ICE, как тема для урока - в самый раз)
5/5
2 | След.
Зарегистрируйтесь, чтобы добавить комментарий.
Эту страницу просмотрели: 337 уникальных посетителей