Урок по position script контроллеру в 3Ds Max

Всем привет. Предлагаю вашему вниманию урок по скриптованию в максе. Речь пойдет о написании коттроллера анимации Position Script. После просмотра титульного видео к уроку( оно в конце :-)) предчуствую что у многих форумчан возникнут вопросы. А за чем это надо - для такой вроде не сложной анимации городить огород, скрипт какой-то? Можно ведь частицами или вообче в ручную. Дабы предупредить подобные вопросы сразу отвечу. Смысл урока не в создании анимации как таковой а в научении написания скрипта, поняв которое (надеюсь) вы уже сможете лепить свое. Во вторых, научившись пользоваться скриптами вы забудете про создание анимации подобного рода в ручную (это не вариант это точно). В третьих скрипты дают не меньше а в некоторых cлучаях и больше возможностей чем частицы (которые тоже не плохо в свою очередь скриптуются). И в четвертых это весьма не плохая жевачка для мозгов. И так со вступлением я закончил и перехожу к делу.

В своем предыдущем уроке я изложил базовые основы и правила написания скриптов http://www.render.ru/books/show_book.php?book_id=2121  По этому повторяться я не буду а сразу преступлю к подготовке сцены. Все что небыло освещено там буду объяснять по ходу пьессы. Итак открываем макс и создаем бокс. Длина высота ширина по 10. Мои системные единицы на рис. 1 и рис. 2.Выбираем наш бокс открываем панель инструментов вкладку иерархия нажимаем воздействие только на опорную точку и расположение ее по центру объекта рис.3. Снимаем Affect Pivot и распологаем наш обьект в центре координат рис 4. Должно получиться как на рис 5.

рис. 1

рис. 2

рис. 3

рис. 4

рис. 5

На этот кубик мы будем накладывать наш контроллер Position script. Теперь создадим сферу и поместим ее в точку с координатами [-100,0,0] рис 6. Эта сфера будет служить нам контролирующим обьектом. Через ее перемещения мы будем задавать перемещения нашего кубика. Также создадим пустышку (Dummy001) и выровняем ее по боксу рис. 7.(выбираем пустышку за тем выравнивание за тем бокс и настройки на рис.). За чем она нужна будет понятно в дальнейшем. Собственно можно приступать к созданию скрипт-контроллера но вначале мы оформим его концепцию и отработаем его команды в редакторе скриптов. И так первым делом нужно уяснить чего мы хотим а мы хотим чтобы при приближении сферы к боксу тот улетал вверх а при удалении опускался на свое начальное место. Для этого мы привяжем  вертикальную координату z кокса (сори бокса)  к расстоянию между пустышкой, которая как раз будет покоиться в начальном состоянии бокса, и сферой. И так принцип я думаю понятен да он вроде и не сложен, осталось реализовать его в скрипте. Откроем рдактор скриптов maxscript editor  также отладчик max script listener. Первой строкой в редакторе создадим переменную b и присвоим ей наш кубик рис. 8. Значек $ после равно говорит что будет взят объект сцены с последующим именем. Не забывайте про пробелы. Да и еще имена в скрипте и имена объектов должны совпадать. После написания строки оставляем на ней курсор и жмем шифт+ентер (выполнить выделенное, можно также воспользоватся соотв. кнопкой в меню Tools редактора). Успех выполнения отразится в отладчике синей строкой (см. рис.) Провал красной. В этом случае смотрите что не так, например может не соотв. имя бокса. Далее по аналогии создаем переменные s и d  назначаем на них сферу и пустышку. Теперь создадим переменную x и присвоим ей дистанцию между сферой и пустышкой. Для этого есть команда distance, а аргументами для нее служат конечные объекты. Вся строка выглядит так x = distance s d. В случае успеха отладчик выдаст значение дистанции (у нас дложно быть 100 см. рис. 9). Стоит отметить что строка пройдет только в случае успешного прохождения двух предидущих. Следующей строкой создадим переменную z1 и назначим ей константу 100. Это будет максимальный подъем нашего кубика. Далее создадим переменную z и присвоим ей выражение z1 - x , это будет как раз величина подъема кубика (стоит понимать что здесь z это просто имя переменной а не обозначение координаты). Логика думаю понятна. При приближении сферы к пустышке дистанция x уменьшается и z тремится к z1 тоесть к 100 при удалении x растет а z уменьшается. Но что будет когда дистанция станет больше 100 - тогда z танет меньше нуля и кубик пойдет в отрицательную зону а нам этого не надо. Чтобы это устранить применим команду условия if. Cледующая строка выгдядит так if z < 0 do z = 0. Дословно - если z меньше нуля делаем z равным нулю. Думаю понятно. Здесь сразу сделаю пояснение, строки которые я привожу это всего лишь варианты написания команд. С другими вариантами вы можете ознакомиться (а это придется сделать при дальнейшем изучении) открыв справку по максскрипт. И последней строкой мы зададим z на вертикальную позицию кубика. Для этого есть команда position ( можно сокращенно pos) она пишется через точку после переменной для которой определяется. В нашем случае это b (наш кубик) после нее также через точку идет коодината позиции  и вся строка выглядит так b.pos.z = z и весь скрипт должен выглядеть так

b = $Box001
s = $sphere001
d = $dummy001
x = distance s d
z1 = 100
z =  z1 - x
if z < 0 do z = 0
b.pos.z = z

Подвигайте сферу около пустышки (кубика) по оси x и повыполняйте скрипт Ctrl+E и вы увидите в случае успешного выпорлнения как  кубик будет подниматься и опускаться. При удалении сферы от пустышки более чем на сто кубик останется на месте. Это как раз то что нам нужно и если у вас все так именно и получилось то идем далее и приступаем контроллеру. Если не получилось то смотрите отладчик и исправляйте ошибки.

рис. 6

рис. 7

 рис. 8

 рис. 9

Итак скрипт контроллер. Но для начала кратко о том что это такое и с чем едят. По сути это тот же контроллер что и остальные (ограничение по пути или ориентации например) только с возможностью самому настраивать характер движения объектов на которые он накладывается. Тоесть штука весьма мощная, обладающая гораздо большими возможностями чем любой другой из кортроллеров. Теперь приступим к делу. Выбираем бокс, идем в панель инструментов - Motion,  кликаем Assign Controller  строка Position и далее кнопка с листком и зел. галочкой над ней рис. 10.  Из появившегося списка выбираем Position Script и увидим всплывшее окно нашего скрипт контроллера. Оно разделено на несколько зон. Вверху слева зона создания переменных. Здесь вбиваются имена пер. которые мы хотим ввести в скрипт. Под ней список уже созданных переменных. Там будут четыре пер. созданные по умолчанию. Все они относятся ко времени. Под списком четыре кнопки назначения переменных. Нажав на них созданной переменной можно присвоить константу, другой контроллер, трек анимации или объект сцены. Сверху справа распологается зона текста скрипта. Под ней зона описания и отладки. По умолчанию в зоне скрипта находятся координаты объекта на момент наложения контроллера.(у нас [0,0,0]) Эта единственная строка текста скрипта говорит что координаты объекта такие как указаны в квадратных скобках и другими быть не могут. Если мы попробуем подвигать кубик то это не получится - стоит намертво. Для начала введем в контроллер наши объекты. Для этого создадим переменные аналогичные созданным с редакторе скриптов. Сразу скажу что переменную b которой присвоен наш бокс создавать не надо это вызовет ошибку выполнения контроллера т. к. нельзя ввести в контроллер объект на который он и так наложен. По этому создаем переменную d вбив эту букву в поле Name и кликнув создать. Она сразу появится в списке. Выбираем ее если она не выбрана и  кликаем assign node рис. 11. Из появившегося списка выбираем пустышку. Она назначится на переменную и это отразит надпись внизу. Осталось ввести сферу.  Создадим переменную sph (переменную с именем s создать нельзя т. к. это имя уже занято переменной по умолчанию) и присвоим ей сферу по аналогии. Создадим также реременную z1 и присвоим ей константу (assign const) 100 рис. 12. Можно приступить к написанию самого текста скрипт-контроллера. Его строки аналогичны созданным нами в редакторе.  Да забыл. Строку с нулями сразу удаляем.

x = distance sph d
z =  z1 - x
if z < 0 do z = 0
[d.pos.x,d.pos.y,z]

     Первая строка задает дистанцию между пустышкой и сферой. Вторая создает величину поднятия бокса, вычитая из макс. поднятия нашу дистанцию.  Третья исключает опускания в отрицательную зону. И последняя строка определяет координаты положения кубика. По горизонтали они такие же как у пустышки. А по вертикали это наша величина поднятия z.

рис. 10

рис. 11

рис. 12

рис. 13

Вбейте или просто скопируйте эти строки в зону скрипта (рис.13) и подвигайте сферой вреред назад по оси х. О чудо - наш кубик взлетает и опускается на свое место (видео 1).  Если у вас именно так то значит все правильно и можно идти далее.  Плюс метода еще и в том что горизонтальным положением кубика можно управлять двигая пустышку.

видео 1

Теперь приступаем к завершающей стадии урока. В ней мы размножим кубик и пустышку и напишем скрипт который автоматом создаст контроллеры для всех кубиков. Выделяем бокс и пустышку вместе. Переходим на вид сверху. Включаем трехмерную привязку на главном меню кликаем по ней правой кнопкой и выбираем привязку к узлам сетки рис. 14. Двигаем бокс и сферу по оси х от сферы с нажатой кнопкой шифт так чтобы копии встали грань к грани рис. 15.  Выставляем кол-во копий 50. Выбираем получившиеся кубики и пустышки и копируем их по оси у аналогичным способом. Кол-во копий 10. Должно получиться как на рис 16. Теперь можно подвигать сферой в гор. плоскости. Анимация должна работать (видео 2). Уже интереснее, но мы пойдем дальше и слегка изменим наши контроллеры а именно добавим хаотичности на подъем. Для этого мы напишем скрипт который будет автоматом создавать нужные  контроллеры для каждого бокса. Я поступлю так. Выложу скрипт ролностью а за тем разберу его по строкам.

рис. 14

рис. 15

рис. 16

видео 2

 boxes = selection as array
dums = selection as array
n = dums.count
for i = 1 to n do
(
b = boxes[i]
b.position.controller =position_script()
b.position.controller.addNode "sphere" ($Sphere001)
b.position.controller.addNode "dummy" (dums[i])
b.position.controller.addConstant "z1" (random 30 200)
b.position.controller.script = "x = distance dummy sphere
z =  z1 - x
if z < 0 do z = 0
[dummy.pos.x,dummy.pos.y,z]
"
)

Первая строка создает переменную с именем boxes и назначает на нее массив из выбранных объектов сцены. Вторая строка создает переменную с именем dums и так же назначает на нее массив из выбранных объектов. Третья строка создает переменную n и назначает на нее количество элементов второго массива т. е. количество пустышек(кубиков). Четвертая строка открывает цикл который будет проходить от первого до последнего бокса.  Пятая это скоба открывающая область цикла.  Шестая создает переменную b  и назначает ей элемент массива боксов с индексом i. То-есть это будет первый бокс на первом шаге цикла второй на втором и т. д. до последнего. Седьмая строка назначает на переменную b (бокс на текущем шаге) контроллер position_script с настройками по умолчанию. Восьмая строка добавляет в контроллер переменную с именем sphere и назначает на нее нашу контролирующую сферу. Девятая строка добавляет переменную dummy и назначает на нее элемент массива пустышек с индексом i т. е. пустышку соотв. кубику на который накладываетса контроллер. Неболльшое отступление на счет переменных в скриптах. Они делятся на две группы глобальные и локальные. Разници меж ними в том что переназначение глобальных переменных действует во всех зонах скрипта. Локальные переменные переназначаются только  в тех зонах в которых они определены. Другими словами в своих зонах локальные переменные с одинаковыми именами могут иметь разное значение. Понимание этого нужно в силу того что все переменные вводимые в скрипт контроллер прописываются там как локальные т. е. наша переменная dummy в каждом контроллере будет иметь одно и тоже имя но разное значение (свою пустышку). Надеюсь с этим понятно. Все это мутно конечно но понимание этого нужно.Десятая строка добавляет в контроллер пер. z1 (наша высота подъема) и назначает на нее константу, которую выбирает из случайных чисел от 30 до 200 (команда random 30 200). Одинадцатая строка добавляет в контроллер сам текст скрипта. Его разбирать не буду т. к. мы ето уже прошли. Скажу только что сам текст заключается в кавычки, он пишется по строкам с поддержанием написания всех правил для строковых величин. Последняя строка закрывает цикл. Вот собственно и весь скрипт. Он не сложный и надеюсь вы поняли его. Пеперь как он работает. Первым делом выделяем все кубики и запускаем первую строку. Смотрим на результат в отладчике. Там появится список массива синим цветом. Только за тем выделяем все пустышки и запускаем вторую строку. Результат в отладчике. Если все норм то запускаем остальные строки (с третьей по последнюю) и только их. Такая последовательность действий для того что нам нужно создавать переменные и назначать на них соотв. массивы для правильного выполнения последующих строк. Ну я надеюсь вы это уже поняли. После выполнения скрипта снова двигаем сферой. Если все верно то характер анимации изменится (видео 3). В завершение скажу что аналогичнам способом можно анимиповать вращение и масштаб п также смешивать все это на сколько хватит фантазии и умения, создавая интересные анимации.

Желаю удачи и дачи.

 видео 3

752 0 850 30
18
2014-03-27
Хорошая темка вообще то.. прикрутить скейл и ротейт еще... да в зависимости от гизмо. Хотяс ейчас подобных уже несколько скриптов, но платные... а тут так сказать своими силами. Молодец автор, давай уроки в тему!
2014-03-28
Автору огромное спасибо! Человек очень выручил когда я обратился за помощью... Побольше бы таких людей на свете и жизнь изменится в лучшую сторону))))))))))))))))) СПАСИБО!
2014-03-31
Урок понравился
2014-04-20
Может и мне кто-то подскажет. Каким образом с помощью конроллеров (если возможно) связать 3 дамми. На рисунке схематично показано, что должно получится. Вся эта "конструкция" должна вращаться вокруг точки "3". Точка "2" жестко прикреплена к "3", "1" двигается вправо-влево. Движение "1", чтоб она всегда смотрела на "2" я знаю как сделать, с помощью LookAt, но оно работает, когда ось вращения механизма находится в точке "2". А вот перенести ось в точку "3" никак не получается, перерыл и перепробовал все, что знал. Надеюсь, кто-то поможет, буду очень благодарен. Заранее спасибо.
2014-04-20
Забыл прикрепить картинку [img]http://postimg.org/image/fo97mdle1/[/img]
2014-04-20
опишите подробнее механику движения которую нужно создать а то после просмотра рисунка возникли вопросы. например точка 1 по рис движется по лучу 1-2 но при туаком движении она и так смотрит на точку 2 так за чем же лук эт. да и по поводу вращения всей конструкции тоже не все допонял. объясните как должнн двигаться каждый обьект.
2014-04-24
[quote=Виталий Мартынов] [/quote] Вся конструкция может только вращаться вокруг точки 3, но при этом еще точка 1 может двигаться в сторону точки 2 или в противоположную. Точка 2 "жестко" закреплена относительно 3, то есть она может только вращаться относительно 3, описывая круг с центром в точке 3. Точка 1 должна быть "главной" в этом механизме, то есть она задает движение. Надеюсь теперь получилось обьяснить [url]http://postimg.org/image/jtkkro03t/[/url]
2014-04-25
ну тогда нужно связывать объекты от первого к третьему по вращению ( связь параметров) опоры для вращения пнрвого и второго объекта поставить в точке три, опору для перемещения первого в точке два. это схема гипотетическая потому как сейчас вне рабочего компа но может поможет
2014-04-28
Гипотетически я понимаю, а вот на практике ничего не получается, тем более я не очень силен в контроллерах...
2014-05-03
Ничего на первый взгляд но очень круто :) Уважение автору за раскрытие подобных тем
2014-05-03
*Ничего не понятно на первый взгляд, но ....
2014-05-07
Здравствуйте! Очень занятный урок! Автору спасибо. Совершенно не разбираюсь в MaxScript, и заинтересовала задачка как можно построить зависимость не от константы а от поверхности объекта? Иными словами хочется вместо сферы использовать объект, текст, или волнообразную поверхность, или ещё что в голову придёт. Чтобы кубики от поверхности отталкивались на определённое расстояние. Если может кто то решал похожие задачки поделится информацией, или ссылку на тутор даст какой нибудь? Премного благодарен всем.))
2014-05-08
для решения вашей задачи есть редактор частиц. уроков по нему полно в сети и на сайте.
2014-05-08
скрипт контроллером у меня подобное сделать не получилось, вернее получилось но скрипт робит не вполне корректно в силу ошибок просчета столкновений. Будет время попробую отладить тогда и поделюсь инфой.
2014-05-25
Урок очень интересный. :) Спасибо автору, и я бы ещё хотел видеть что в стиле (МАНИПУЛЯЦИИ над ОБЪЕКТАМИ ККРИПТАМИ :)
2015-05-15
мега полезная статья. автор, очень хотел бы пообщаться лично (ЛС)!
2015-05-17
Автор. Как работает x = distance s d. Во первых переменная x нигде не задавалась. Во вторых, когда я начинаю делать подобное мне макс выдаёт unable to convert 88.5745746 to point 3 
2015-08-19
Извиняюсь за запоздалый ответ, долго был не в теме но может лучше поздно чем никогда. Разберу строку x = distance s d. Команда  x = создает переменную и присваивает ей значение стоящее после знака равно, отдельно эту переменную создавать не надо. Команда distance s d выдает константу равную расстоянию между ее аргументами s и d  если они определены как объекты сцены. Никакого поинт 3 здесь нет. Чтобы понять как все работает создайте два объекта, назначьте их на две переменные и выполните команду distance.
RENDER.RU