Render.ru

Интересные примеры Script & Expression controller

Savin Denis

Модератор форума
Команда форума
Рейтинг
138
#1
В этой ветке предлагаю делиться своими любимы скрипт контроллерами или экспрешн(Expression). (Чтобы было понятно о чем речь, на мой взгляд правильней будет произносить как экспрешн, а не выражения.)



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

Еще проще анимируя например параметр или объект мы можем заставить другой объект допустим выписывать восьмерки или махать крыльями или еще что-то столь полезное.

В общем это та самая волшебная дубинка котороя избавит аниматора от рутинной работы, или просто от работы =)
То чем должен владеть каждый кто занимается сетапом сцены или персонажей.

Теперь об оформлении:
  • Минимальная рабочая версия 3dsmax. (или на которой тестировалось)
    Должно быть описание, что делает контроллер.
    Код контроллера с комментариями поясняющими принцип работы.
    Обязательно указать тип контроллера - куда вешается.
    Обязательно указать от каких объектов, контроллеров, параметров есть зависимость. Указать их тип.
    Инструкция как использовать.

Поскольку речь об анимации анимированые гифы, и Yotube ролики поясняющие работу контроллеров приветствуются.

PS.
Поскольку ветка организованна по просьбе пользователя sylka с него и начнем =).
 

sylka

Пользователь сайта
Рейтинг
4
#5
скрипт контроллер привязывающий движение объекта раба к точке объекта хозяина

работает во всех версиях

ограничение: объект хозяин должен быть обязательно editable poly (по крайней мере в данной конфигурации експрешена :) )

настройка :

1) выбрать объект хозяин
2) выделить необходимую точку если параллельно открыть maxscript listener в верхней половине его при выделении точки появится строчка с указывающая на номер номер вершины. можно еще узнать с помощью команды polyop.getvert $ ввев ее в нижней половине maxscript listener . То ,что )) как мне нравится )) будет написано синеньким в нижней половине будет искомым номером вершины :)
4) выбираем объект раб, ставим во вкладке motion выбираем positon controller => position script
5) в свитке скриптконтроллера назначаем variable с именем ctrobj которой в качестве node назначаем наш обект хозяин

формула:

pos = polyop.getvert ctrobj 7

** 7 - вписана здесь для наглядности примера, а в вашем случае найденная вами вершина

собственно все))

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

мне кажется что с описанием я переборщил... ), что не все умеют работать со скриптами
я постарался дать исчерпывающий ответ, 3 месяца назад сам толком ничего не понимал :)
to Savin Denis или же лучше в предложенном вами виде выкладывать ?впринципе кому надо тот поймет ,тут всетаки главное идея , только с коментариями вот так например:

Код:
faceAttach = 2 -- number of master object face 

obj = convertToPoly (Box())  -- editable poly master
objslave = Box() -- editable poly slave

ctrl = transform_script() -- Controller:Transform_Script
objslave.transform.controller = ctrl -- add Transform_Script  to slave object

------------------------------------script in expression controller----------------------------- 
ctrl.addNode "obj" obj 
fv = polyop.getFaceVerts obj faceAttach
txt = "p1 = polyop.getvert obj " + fv[1] as string + "\n"
txt += "p2 = polyop.getvert obj " + fv[2] as string + "\n"
txt += "p3 = polyop.getvert obj " + fv[3] as string + "\n"
txt += "v1 = normalize (p2-p1)\n"
txt += "v2 = normalize (p3-p1)\n"
txt += "nv1 = normalize (cross v1 v2)\n"
txt += "nv2 = normalize(cross nv1 v1)\n"
txt += "matrix3 v1 nv2 nv1 ((p1+p2+p3)/3)"
-------------------------------------------------------------------------------------------------------
ctrl.setExpression txt -- execute
Коментарий Savin Denis:

Поскольку похоже описание ты привел к какой то своей модификации этого скрипта, то позволю себе прокомментировать этот код:
Версия 3dsmax: От max8
Описание: Скрипт автоматически привязывает любой объект к указанному полигону другого полигонального объекта.
Использование: Просто запустить скрипт на чистой сцене, все остальное сделает сам. В качестве примера создаст два бокса которые и свяжет.
Параметры:
  • obj Объект к которому привяжет. Должен быть EditablePoly !
    objslave Объект который нужно привязать.
    faceAttach Номер фейса к которому произойдет привязка.

Тема в которой можно обсудить.
 

sylka

Пользователь сайта
Рейтинг
4
#6
блин (( хотел кой чего подправить в тексте но уже поздно, если чего не так не судите строго) время уже позднее да и объяснять я не особо честно говоря умею

пример в первом посте тоже рабочий только он привязывает все трансформации (код написан Savin Denis) к объекту мастеру

если надо только вращение для копмплекта так сказать оставить, пишите подправлю и дополню в следующих постах, или кто знает и кому не лень дополните и запостите сами
 

Chebu

Знаток
Рейтинг
59
#7
Название: parentConstraint

Для тех, кому не хватает функциональности link constraint в max до 2010 версии (в частности, совершать любые действия с ключами, как то: копировать, перемещать, удалять и пр.)

Предназначение:
Данный скрипт позволяет создать для объекта определённый список парентов и менять ID парента, за которым объект следует в данный момент. Ключи смены ID можно перемещать, копировать, удалять и т.п.

Использование:
выделяем объект, запускаем скрипт.
в стек модификаторов объекта добавится модификатор attribute holder в качестве контрольной панели. В нём мы видим список парентов (редактируемый кнопками add и delete), а также ID текущего парента. 0 - объект привязан к миру, 1 - к первому паренту в списке, 2 - ко второму и т.п.

ID текущего парента можно анимировать, ОБЯЗАТЕЛЬНО делать ключи типа stepped (перед анимацией параметра можно выставить default in/out tangents for new keys на stepped - кнопка рядом с setkey)

Ограничения скрипта, примечания:
1) на 0 кадре объект, на котором висит данный скриптконтроллер, ДОЛЖЕН быть привязан к миру.
2) данный объект невозможно перемещать/вращать/масштабировать вручную (т.к. нет лист-контроллера для контроллера transform) - легко обходится таким образом: вешаем данный скриптконтроллер на даммик, а целевой объект вяжем за даммик.


надеюсь, кому-нибудь пригодится) лично я от использования link constraint теперь отказался вообще.

скрипт:
Код:
if (selection.count == 1) do
(

fn deleteAllDefs sel = 
(
	attrs = custAttributes.getDefs sel
	if (attrs != undefined) do
	for i = 1 to attrs.count do
	(
		custattributes.delete sel 1
	)
)

def = attributes pconstr
(
	parameters pconstr_params 
	(
		pID type:#integer animatable:true default:0
		p type:#nodeTab animatable:false tabsizevariable:true
		initTransform type:#matrix3 animatable:false			
	)
)

contr = transform_script()
deletealldefs contr
custattributes.add contr def
contr.pid.controller = bezier_float()
contr.script = 
"
	fn getTransformAtTime t = 
	(
		c = this.pid.controller
		sortKeys c
		PrevKeys = #()
		for key in c.keys do
		(
			if(key.time <= t) do append prevKeys key.time
		)

		tr = this.initTransform
		offset = matrix3 1
		prevID = 0
		currID = 0
		for key in prevKeys do
		(		
			at time (key-1)
			(
				prevID = this.pID
			)
			
			at time (key)
			(
				currID = this.pID
				if (prevID != 0) then
				(		
					tr = offset * (this.p[prevID].transform)
				)
				if ( currID != 0 ) then
				(
					offset = tr * inverse(this.p[currID].transform)
				)
				else offset = matrix3 1
			)
		)
		
		if (currID != 0) then tr = offset * (this.p[currID].transform)
		
		tr
	)

getTransformAtTime currentTime

"

at time 0
(
	contr.initTransform = $.transform
	$.transform.controller = contr
)


attrDef = attributes pconstr
(
	parameters pconstrParams rollout:params
	(
		pID type:#integer animateble:true default:0 ui:spn1
		pcontr type:#maxobject
	)	
	
	rollout params "pConstr_params" width:183 height:196
	(
		listbox lbx1 "parents list" pos:[6,4] width:171 height:9
		button btn6 "remove" pos:[96,148] width:71 height:16
		
		pickbutton btn12 "add" pos:[15,148] width:71 height:16
		spinner spn1 "active parent ID" pos:[36,177] width:110 height:16 type:#integer
		
		fn updatelist = 
		(
			arrNames = #()
			for obj in pcontr.p do
			(
				append arrNames obj.name
			)
			lbx1.items = arrNames
		)
		
		
		
		on params open do
		(
			updatelist()
		)
		on btn6 pressed do
		(
			if(lbx1.selection>0) do
			(
				if(lbx1.selection <= pcontr.p.count) do 
				(
					pcontr.deleteVariable (pcontr.p[lbx1.selection].name+"_var")
					deleteItem pcontr.p lbx1.selection
				)
			)
			
			updatelist()
		)
		on btn12 picked obj do
		(
			appendifunique pcontr.p obj
			pcontr.addnode (obj.name+"_var") obj
			updatelist()
		)
		on spn1 changed val do
		(
			if (val < 0) do spn1.value = 0
			if (val > pcontr.p.count) do spn1.value = pcontr.p.count
		)
	)
)

attrholder = emptymodifier()
custAttributes.add attrholder attrDef

attrholder.pid.controller = contr.pid.controller
attrholder.pcontr = contr

addmodifier $ attrholder
)
 

Арт.К

Знаток
Рейтинг
65
#8
Полезная тема. Однако, прошу простить за вопрос по другому поводу, но, возможно, здесь кто-то знает решение следующей проблемы. После апдейта объекта в сцене (посредством импорта и т,л.) сохраняются привязки через линк и через /Position Constraint/, а также через /Orientation Constraint/, но не сохраняются привязки через /Wire parameters/, а также через /Float Expression/. То есть необходимо заново вносить эти связи. Вопрос - есть ли возможность (как-то указать условия) чтоб эти связи сохранялись?
Или, подошел бы вариант, когда бы можно было задействовать один из указанных типов связи (/Wire parameters/ или /Float Expression/) для прилинкованого объекта. То есть, чтоб объект "C" считывал (посредством /Wire parameters/ или /Float Expression/) параметры перемещения с объекта "D" который прилинкован к третьему объекту. Поскольку указаные привязки не воспринимают перемещения прилинкованого объекта, в отличии от таких привязок, как /Position Constraint/ и т.д. Возможно тоже можно как-то указать условия, чтоб параметры считывались?
 

Арт.К

Знаток
Рейтинг
65
#9
Всем спасибо, вопрос предыдущего сообщения уже не актуален. Решение подсказано пользователем в другой теме.
 
Сверху