Link:INB Home|INB English| INB русский язык|INB العربية|INB Türkiye|INB فارسی|INB Español|INB Français|INB Português|INB Deutsch|INB 國語|INB 中文|INB 日本语|INB 한국어|INB ภาษาไทย|INB tiếng Việt||Уроки 3ds Max Анимация мимики по принципу "Blended Morph"2
INB русский язык Форум
Добро пожаловать! inbforum.COM Интернет без границ Форум Здесь вы можете обсудить с друзьями по всему миру прений, приходите и присоединяйтесь к нам! Постоянный имя: Ruinbforum.forumotion.com
INB русский язык Форум

Добро пожаловать! inbforum.COM Интернет без границ Форум Здесь вы можете обсудить с друзьями по всему миру прений, приходите и присоединяйтесь к нам! Постоянный имя: Ruinbforum.forumotion.com


Вы не подключены. Войдите или зарегистрируйтесь

《《《《《《《上一页INBforum   Перейти вниз

上一页INBforum》》》》》》》Предыдущая тема Следующая тема Перейти вниз  Сообщение [Страница 1 из 1]

1 Уроки 3ds Max Анимация мимики по принципу "Blended Morph"2 в Вс Окт 03, 2010 8:54 am

Admin

avatar
Admin
Создание и привязка морф-целей для бровей
Ну а теперь самый последний и самый сложный этап работы. Брови. Принцип работы бровей будет немного другой, потому что привязка будет не к одной оси, а к двум, поэтому сначала рассмотрим как это работает. При поднятии контрола вверх, поднимается центральная часть брови, при движении поднятого конторла в лево, центральная часть брови опускается, но поднимается левый край брови. При движении поднятого конрола вправо, так же опускаются центр и левый край брови, но поднимается правый край. То же, и при опущенном контроле. Так же, если подвигать в стороны контрол находящийся в нулевой точке, то есть в центре, бровь будет смещаться влево-вправо.
[Вы должны быть зарегистрированы и подключены, чтобы видеть это изображение]
Таким образом, достигается очень гибкое управление бровью.
Теперь рассмотрим один из узлов более детально. Для примера возьмем цель, которая поднимает центр века вверх. Суть данного приема в следующем: при движении контрола (из нулевой точки) вверх, добавляется морф-цель с поднятой серединой века. Но при движении поднятого контрола в стороны, вес этой цели сходит на ноль. Следовательно, каждая морф-цель века реагирует как на положение контрола по Y, так и по X. Для того, чтобы реализовать привязку к двум осям, вместо одной, нам нужно будет немного изменить контроллеры управляющие каждой целью. Сейчас начнем это делать и походу, я поясню, что конкретно нам дает смена контроллера.
Но сначала, надо сделать сами морфы. Нам нужны следующие цели: (с низу вверх) поднятый центр брови, поднятый носовой край брови, поднятый височный край брови, опущенный центр брови, опущенный носовой край брови, опущенный височный край брови, бровь смещенная к носу, бровь смещенная к виску.
[Вы должны быть зарегистрированы и подключены, чтобы видеть это изображение]
Теперь добавляем эти цели в Morpher. Постарайтесь сделать последовательность как у меня, целей много, можно легко запутаться в них. Можно править контроллеры. Как я уже говорил, нам нужно сделать управление одной целью, зависимой от двух параметров, X_Position и Y_Position контрола. Сейчас пока начнем делать, а там я растолкую, что к чему. Итак, выделяем модель головы и идем в Curve Editor и находим там наш Morpher. Выделите все цели бровей, кроме двух последних (бровь влево и бровь вправо) и назначьте им контроллер Float List.
[Вы должны быть зарегистрированы и подключены, чтобы видеть это изображение]
Рассмотрим, что это дает. Как видно на рисунке ниже, у нас в списке есть контроллер Bezier Float. Однако есть и еще один параметр Weight: Bezier Float. Что накое Bezier Float, надеюсь понятно, это собственно контроллер который будет управлять добавлением морф-цели, а вот Weight: Bezier Float ничто иное как вес контроллера в списке. То есть даже если морф-цель в контроллере выведена на 100%, то с помощью веса все равно можно свести ее на нет.
[Вы должны быть зарегистрированы и подключены, чтобы видеть это изображение]
Если все понятно, то поехали делать связи. (Если не понятно, то все равно поехали, по ходу прояснится). Итак, закрываем Curve Editor, выделяем контрол для правой брови, идем в Were Parameters и проделываем все как в прошлые разы, только привязываем Y_position контрола к Bezier Float первой бровной цели (поднятая середина брови).
[Вы должны быть зарегистрированы и подключены, чтобы видеть это изображение]
Привязываем Y_Position к контроллеру Float Wire через множитель, как обычно 20.
[Вы должны быть зарегистрированы и подключены, чтобы видеть это изображение]
А теперь, новый прием, внимание! Тут же, X_Position контрола, привязываем к весу контроллера морф-цели Weight: Float Wire. Выражение для управления весом пмшем:
«if X_Position <=0 then (1 (X_Position*.2)) else (1-(X_Position*.2))»
Это выражение означает, что если контрол по X (по горизронтали) ушел в минусовую сторону, то значение которому будет равен вес контроллера будет 1 (это вес контроллера от 0 до 1) плюс положение контрола по X (может быть от 0 до -5) которое помножено на понижающий коэффициент 0.2, иначе, если контрол ушел в плюс, то значение будет 1 (максимальное значение веса) минус положение контрола по X (возможно от 0 до 5) пониженное через множитель на 0.2 Например если контрол поднять вверх, и сдвинуть его влево (в минус), то морф-цель будет равняться 100%, но вес всего контроллера дудет равен 0, и значит и влияние морф-цели будет равно 0, а выражение следует понимать как «1 (-5*0.2)» в итоге 0. Или если контрол поднять вверх и сдвинуть вправо (в плюс), то морф-цель выведется на 100%, но вес, так же будет 0, а выражение можно понять как «1-(5*0.2)» в итоге опять же 0.
[Вы должны быть зарегистрированы и подключены, чтобы видеть это изображение]
Таким образом, мы привязали управление морф-целью к двум параметрам, к положению контрола по Y и по X.
[Вы должны быть зарегистрированы и подключены, чтобы видеть это изображение]
Выражения для краев бровей, будут немного отличаться, потому, что нам нужно, чтобы край брови поднимался, только при движении контрола в какую-то одну сторону. Поэтому, не закрывая окна привязываем следующую цель, с поднятым краем брови со стороны носа. Выбираем обратно Y_Position, и вяжем его на Float Wire следующей цели с множителем 20.
[Вы должны быть зарегистрированы и подключены, чтобы видеть это изображение]
И так же переходим к X_Position и так же, вяжем его на Weight: Float Wire. Только выражение пишем: «if X_Position <=0 then X_Position=0 else X_Position*.2» Надеюсь, к этому времени вы уже стали великими программерами и выражения больше «разжевывать» не придется.
[Вы должны быть зарегистрированы и подключены, чтобы видеть это изображение]
И опять переходим обратно к Y_Position и вяжем его с Float Wire следующей цели (поднятый височный край брови) с множителем 20.
[Вы должны быть зарегистрированы и подключены, чтобы видеть это изображение]
И опять вяжем X_Position на Weight: Float Wire и выражение пишем: «if X_Position <=0 then -X_Position*0.2 else X_Position=0»
[Вы должны быть зарегистрированы и подключены, чтобы видеть это изображение]
С поднятиями брови закончили.
[Вы должны быть зарегистрированы и подключены, чтобы видеть это изображение]
Опускание брови делается точно так же. Я пошагово объясню что делать но уже обойдемся без картинок.
Итак, разворачиваем в списке следующую цель, опускание центра брови, выбираем Y_Position и вяжем его к Float Wire. Выражение пишем: «-Y_Position*20»
Открываем Weihgts и вяжем X_Position на Weight: Float Wire. Выражение пишем: «if X_Position <=0 then (1 (X_Position*.2)) else (1-(X_Position*.2))»
Цель опускание носового края брови. Выбираем Y_Position и вяжем его к Float Wire. Выражение пишем: «-Y_Position*20»
Открываем Weihgts и вяжем X_Position на Weight: Float Wire. Выражение пишем: «if X_Position <=0 then X_Position=0 else X_Position*0.2»
Цель опускание височного края брови. Выбираем Y_Position и вяжем его к Float Wire. Выражение пишем: «-Y_Position*20»
Открываем Weihgts и вяжем X_Position на Weight: Float Wire. Выражение пишем: «if X_Position <=0 then -X_Position*.2 else X_Position=0»
Готово.
[Вы должны быть зарегистрированы и подключены, чтобы видеть это изображение]
Привязываем оставшиеся две цели. Они смещают бровь влево-вправо. Тут все просто:
Цель смещение брови к носу. Выбираем X_Position и вяжем его к цели. Выражение пишем: «Y_Position*20»
Цель смещение брови к виску. Выбираем X_Position и вяжем его к цели. Выражение пишем: «-Y_Position*20»
Тут можно так же, как и на предыдущих целях, сделать, чтобы от движения по Y, влияние двух последних целей угасало, Но мне это показалось лишним, и я этого делать не стал.
[Вы должны быть зарегистрированы и подключены, чтобы видеть это изображение]
Ура, половину победили! Теперь займемся второй половиной.
Зеркальное копирование морф целей
Ну, что ж, самое трудное позади. Половина лица у нас готова и правильно работает. Осталось сделать все то же самое на другую половину. Для начала нужно подготовить морф-цели, для левой половины лица, но тут есть одно «но». Дело в том, что если просто отзеркалить модель, то ничего не изменится, потому, что точки модели так же зеркалятся, сохраняя значение на позиции. То есть все точки имеют то же имя, и ту же позицию только в зеркальном отображении. Поэтому обычное зеркальное копирование тут не получится. Вот для этого мы и подготавливали модель в самом начале урока.
Для зеркального копирования морф целей, возьмем еще один скрипт Пола Нила:rightAr=#()
leftAr=#()
centerAr=#()
tempAr=#()

fn getMirrorData threshold:0.05=
(
rightAr=#()
leftAr=#()
centerAr=#()
tempAr=#()

baseObj=$.baseObject
vertSel=(polyOp.getVertSelection baseObj)as array


for i = 1 to vertSel.count do
(
pos=polyOp.getVert baseObj vertSel[i]
if pos.x < -threshold then
(
append rightAr vertSel[i]
)
if pos.x < threshold and pos.x > -threshold then
(
append centerAr vertSel[i]
)
if pos.x > threshold then
(
append tempAr vertSel[i]
)
)

for i in rightAr do
(
pos=polyOp.getVert baseObj i
found=false
for c = 1 to tempAr.count do
(
cPos=(polyOp.getVert baseObj tempAr[c])*[-1,1,1]
dist=distance cPos pos
if dist< threshold then
(
append leftAr tempAr[c]
deleteItem tempAr c
found=true
exit
)
)
if found==false then append leftAr undefined
)
#(rightAr.count,leftAr.count,centerAr.count)
)

fn mirrorMorph symmetry:false=
(
for i = 1 to rightAr.count do
(
if leftAr[i]!=undefined do
(
Rpos=polyOp.getVert $ rightAr[i]
if symmetry==false then Lpos=polyOp.getVert $ leftAr[i]
polyOp.setVert $ leftAr[i] (((Rpos-$.pos)*[-1,1,1]) $.pos)
if symmetry==false then polyOp.setVert $ rightAr[i] (((Lpos-$.pos)*[-1,1,1]) $.pos)
)
)
if symmetry==false then
(
for i = 1 to centerAr.count do
(
Cpos=polyOp.getVert $ centerAr[i]
polyOp.setVert $ centerAr[i] (((Cpos-$.pos)*[-1,1,1]) $.pos)
)
)else
(
for i = 1 to centerAr.count do
(
Cpos=polyOp.getVert $ centerAr[i]
polyOp.setVert $ centerAr[i] (((Cpos-$.pos)*[0,1,1]) $.pos)
)
)
)

Суть работы скрипта в следующем: сначала мы показываем ему нашу модель (которая должна быть симметричной), и он запоминает ее. Причем запоминает он ее не просто всю, а делит ее пополам (относительно Pivot, примерно как модификатор Symmetry), находит и запоминает противоположные (зеркальные) точки. Для поиска зеркальных точек в самом начале скрипта имеется параметр «threshold:0.01». 0.01 означает, что модель должна быть практически идеально симметричной, в противном случае можно немного увеличить threshold. Потом мы берем любую морф-цель, копируем (обычным способом) и применяем скрипт. Скрипт на основе данных об исходной модели, зеркально перекидывает данные о положении точек с левой половины на правую, а с правой на левую. Таким образом, точки модели остаются в том же порядке, по позиция их зеркально меняется. Вот и получается, что цели зеркалятся корректно.
Теперь объясню, как пользоваться.
    1. Сохраните этот скрипт как «PEN_mirrorVerts.ms» (на самом деле имя не имеет значения). Потом запустите его, через MaxScript->Run Script.
    2. Выделите модель головы, перейдите в стеке модификаторов в самое начало к Editable Poly (модель обязательно должна быть в Editable Poly) и перейдите на уровень Vertex. Выделите точки модели (точки не обязательно выделять все, главное, чтобы были выделены точки затронутые морфингом). В данном случае лучше выделить все точки.
    3. Откройте MaxScript Listener, (MaxScript-> MaxScript Listener, по умолчанию F11) и напишите в нем команду которая запускает функцию запоминающую модель: «getMirrorData()» (без кавычек), нажмите ввод. Выделенные точки модели будут запомнены. Если все верно, то Listener покажет что-то типа этого: «#(384, 384, 78)». Это значит, что 384 точек справа соответствует 384 точкам слева, и 78 точек по центру. Выйдете из подобъекта Vertex.
    4. Теперь возьмите любую морф-цель. Скопируйте ее и разместите рядышком. Она (цель для отзеркаливания) должна выть выделена. Идем в Listener и пишем «mirrorMorph()»(без кавычек), ввод. Оп, модель отзеркалилась!
    5. Если что-то пошло не так и скрипт не сработал, значит либо что-то не так с моделью, либо модель не очень симметричная. Попробуйте запустить скрипт немного увеличив параметр threshold и проделайте все сначала.

Теперь два слова о том, как я пользуюсь этим скриптом. Я сохранил скрипт с именем «PEN_mirrorVerts.ms» и разместил его в 3dsmax root/scripts/startup, написал макроскрипт под названием «PEN_mirrorVerts.mcr»:macroScript GetMirrorData
buttontext:"GetMirrorData"
category:"Morph Mirror Targets"
internalCategory:"Morph Mirror Targets"
tooltip:"GetMirrorData"
(
getMirrorData()
)

macroScript MirrorMorph
buttontext:"MirrorMorph"
category:"Morph Mirror Targets"
internalCategory:"Morph Mirror Targets"
tooltip:"MirrorMorph"
(
mirrorMorph()
)

и разместил его в 3dsmax root/UI/MacroScripts. После чего добавил его себе в Quad Menu.
[Вы должны быть зарегистрированы и подключены, чтобы видеть это изображение]
И теперь, этот инструмент у меня теперь всегда наготове, не надо ничего запускать и ничего писать.
Зеркальное копирования морф-целей
Но вернемся к нашим «зайцам». Выделите модель головы, войдите в подобъект Vertex и выделите все точки. Откройте Listener и напишите в нем getMirrorData(), нажмите ввод.
[Вы должны быть зарегистрированы и подключены, чтобы видеть это изображение]
Теперь скопируйте морф-цель (можете скопировать сразу все морф-цели), и выделяя их по очереди пишем в Listener mirrorMorph(), нажимаем ввод.
Таким образом нужно подготовить все морф-цели.
Настройка второй половины лица
Когда все зеркальные цели готовы и удобным образом названы (!), добавляем их по порядку в Morpher и начинаем привязывать. Делается это точно так же как и при настройке первой половины. Поэтому растолковывать тут больше ничего не буду. Просто дам параметры для всех остальных целей.
Губы (контрол для левой половины губ)
X_Position –> цель с губами «в трубочку», выражение: -X_Position*20
X_Position –> цель с губами растянутыми в сторону, выражение: X_Position*20
Y_Position –> цель с губами выгнутыми вниз, выражение: -Y_Position*20
Y_Position –> цель с губами выгнутыми вверх, выражение: Y_Position*20

Глаз (контрол для левого глаза)
Y_Position –> цель с полузакрытым верхним веком, выражение: if Y_Position >= 0 then (100-Y_Position*20) else (100 Y_Position*20)
Y_Position –> цель с закрытым верхним веком, выражение: -Y_Position *20
Y_Position –> цель с открытым верхним веком, выражение: Y_Position *20
Y_Position –> цель с закрытым нижним веком, выражение: -Y_Position *15
Y_Position –> цель с открытым нижним веком, выражение: Y_Position *20
X_Position –> цель с веком смещенным в сторону носа, выражение: -X_Position *20
X_Position –> цель с веком смещенным в сторону виска, выражение: X_Position *20

Бровь (контрол для левой брови) Не забываем назначать List контроллеры.
Y_Position –> цель с поднятым центром брови, выражение: Y_Position *20
X_Position –> цель с поднятым центром брови, выражение: if X_Position <=0 then (1 (X_Position*.2)) else (1-(X_Position*.2))
Y_Position –> цель с поднятым краем брови со стороны носа, выражение: Y_Position *20
X_Position –> цель с поднятым краем брови со стороны носа, выражение: if X_Position <=0 then -X_Position*.2 else X_Position=0
Y_Position –> цель с поднятым краем брови со стороны виска, выражение: Y_Position *20
X_Position –> цель с поднятым краем брови со стороны виска, выражение: if X_Position <=0 then X_Position=0 else X_Position*.2

Y_Position –> цель с опущенным центром брови, выражение: -Y_Position *20
X_Position –> цель с опущенным центром брови, выражение: if X_Position <=0 then (1 (X_Position*.2)) else (1-(X_Position*.2))
Y_Position –> цель с опущенным краем брови со стороны носа, выражение: -Y_Position *20
X_Position –> цель с опущенным краем брови со стороны носа, выражение: if X_Position <=0 then -X_Position*.2 else X_Position=0
Y_Position –> цель с опущенным краем брови со стороны виска, выражение: -Y_Position *20
X_Position –> цель с опущенным краем брови со стороны виска, выражение: if X_Position <=0 then X_Position=0 else X_Position*.2

X_Position –> цель с бровью смещенной в сторону носа, выражение: -X_Position *20
X_Position –> цель с бровью смещенной в сторону виска, выражение: X_Position*20

Ну вот, наше лицо полностью готово готово! Не забывайте, что вы можете добавлять сюда какие угодно цели, на свое усмотрение, "губы в дудку" и другие специальные цели для реализации фонемных особенностей, морщины и даже язык, можно сделать подобным образом. Так что, тут вам все карты, как говорится.
[Вы должны быть зарегистрированы и подключены, чтобы видеть это изображение]
Если после этого урока у вас не пропало желание работать в 3dsmax, то могу вас поздравить, в ваших жилах течет крепкий бульон! Удачных работ и профессионального роста вам. Пока!]

Посмотреть профиль http://ru.inbforum.com

上一页INBforum   Перейти вниз

上一页INBforumПредыдущая тема Следующая тема Вернуться к началу  Сообщение [Страница 1 из 1]

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

Copyright ©2009-2010 LTD Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.

IT:SINGLESERVGoogle谷歌翻译TranslateFORUMSOFTLAYERGoogle谷歌广告联盟AdSenseAsia

 

Создать форум | © PunBB | Бесплатный форум поддержки | Контакты | Сообщить о нарушении | Blog2x2.ru