Анимация мимики по принципу "Blended Morph"

Об авторе:

Зовут меня Поклонов Максим, родился живу и тружусь в городе-герое Усть-Каменогорске, том, что в Казахстане. Графикой занимаюсь где-то года с 99, естественно персонажкой занялся много позже, пройдя множество трудностей и поборов кучу глюков, наработал кладезь ценного материала, коим спешу поделиться с вами.

Введение

Привет, друзья. Это снова я, и я хочу порадовать вас, очередным уроком. Я расскажу о довольно мало известном, но весьма интересном приеме анимации мимики при помощи морфинга. В этом уроке я буду использовать уже известного персонажа для мульт заставок игры Air Xonix, изготовленного мной для компании Axysoft. Правда, для демонстрации возможностей данного приема анимации, лицо персонажа пришлось немного модифицировать.

Идея данного способа, скрипты и некоторые специальные наработки были почерпнуты мной в четвертом DVD Пола Нила (Paul Neale) «Facial Rigging Techniques». Эта идея была полностью переработана и настроена под меня, так что на DVD Пола Нила все будет по другому. В этом уроке я покажу только сам способ анимации, ну а если вам этого будет мало, и вы захотите научиться сохранять мимические позы, или научиться делать костную анимацию на профессиональном уровне, и так далее, то ищите DVD Пола Нила (Paul Neale) «Facial Rigging Techniques», он будет для вас невероятно полезен.

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

Сразу определимся со сторонами лево-право. Все что касается лица персонажа, надо понимать с его точки зрения, то есть, что для него лево, то для нас право. Все что не касается непосредственно модели, следует рассматривать с нашей позиции, то есть где лево - там лево, и где право, там соответственно право.

Подготовка модели к анимации

По мере написания урока мне пришлось столкнуться с одной досадной ошибкой. Когда я полностью настроил правую половину лица персонажа, и принялся копировать и зеркалить морф-цели, то выяснилось, что модель содержит скрытые ошибки, не склеенные точки, и даже Pivot немного смещен. В результате мне не удалось правильно отзеркалить цели. И мне пришлось править модель и все начинать по новой. Чтобы избежать подобной ошибки, в самом начале давайте подготовим модель. Для начала преобразуйте ее в Editable Poly (если она таковой не является). Первым делом надо склеить разлепленные точки, их может быть не видно во вьюпорте, но они могут доставить массу неожиданных сюрпризов. Для этого войдите в подобъект «Vertex», выделите все точки модели и примените к ним операцию «Weld». Ее можно вызвать как в панели инструментов Editable Poly, так и Quad Menu (на мышке).

Обратите внимание, что операция «Weld» вызывается нажатием не на саму надпись, а на изображение окошка, рядом с ней. Это дает нам возможность настроить параметры в окошке с настройками.

Включите во вьюпорте отображение сетки, и внимательно смотрите, какие точки склеиваются при увеличении параметра Weld Threshold. Этот параметр должен быть минимальным, чтобы склеить только незаметные для глаза точки. В секции Numbers of Vertices можно видеть, что даже при минимальном значении параметра Weld Threshold количество точек стало существенно меньше. После того как точки склеены, визуально проверяем модель, и исправляем все ошибочки, если найдем.

Затем нужно обнулить Pivot. Для этого выделяем модель головы, заходим в панель Hierarchy, выравниваем Pivot по центру модели (Center to Object) и сбрасываем трансформации вращения (Align to World).

После этого, применяем к модели модификатор Symmetry, делаем Reset XForm (это в панели Utilites) и конвертируем в Editable Poly. Последние операции с Pivot, я заменяю скриптом «Collapse Selected To Poly At Origin» из бесплатного пакета TIM Scripts. Для этого я помещаю модель центром в нулевую точку и применяю скрипт. Он сбрасывает все скрытые трансформации и преобразует модель в чистенький и готовый к анимации Editable Poly и помечает Pivot в кулевую точку, за один клик.

Кости и скин

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

Теперь применяем модификатор «Skin» и скиним нижнюю челюсть. Помещаем в скин три кости, шейную головную и челюстную. Включаем «Edit Envelopes». Чтобы была возможность работать с точками, в настройках модификатора включаем галку «Vertices». Выбираем енвелоп головы и выделяем все точки. Устанавливаем вес точек на 100%, то есть 1.

Чтобы удобнее было работать с нижней челюстью, сделайте анимацию кадров на 5, это позволит открывать челюсть, не выходя из редактирования енвелопов. Теперь выбираем енвелоп челюсти и выделяем точки, которые будем ему назначать. Это удобнее делать выделением типа Lasso. Грубо выделяем точки района нижней челючти. Так же выделяем точки полости рта внизу и устанавливаем вес =1. Теперь точки нижней челюсти назначены на кость.

При выделении мы захватили точки верхней губы, нужно исключить их из выделения. Для этого выделяем точку посередине верхней губы и увеличиваем область выделения кнопкой Grow. Устанавливаем вес на 0 и точки возвращаются под влияние головной кости.

(Копка Grow, как и ряд других нововведений, появилась в скине сравнительно недавно, и в более ранних версиях макса ее не было. Чтобы, все же иметь возможность увеличивать и уменьшать выделение точек в скине, можно воспользоваться скриптами из пакета TIM Scripts, в нем есть эти инструменты).

А теперь самое интересное. Просто включаем инструмент «Paint Weights» и смягчаем вес точек вокруг рта. (Обратите внимание, галка «Paint Blend Weights» под кнопкой «Paint Weights» должна быть включена).

С косметическими процедурами закончили, теперь, нужно проделать то же самое в полости рта.

После этакого «лифтинга» наш «пациент» выглядит уже намного лучше. Если есть необходимость, можно поднастроить некоторые точки индивидуально. Не забудьте удалить ключевые кадры с кости, когда мы привяжем ее к управляющему объекту, они будут только мешать. Все, с челюстью закончили.

Управляющий объект

Для управления мимикой будем использовать некую внешнюю контрольную панель состоящую из отдельных управляющих объектов. Управляющий объект представляет собой сплайновые объекты, прямоугольник с кругом внутри.

Перемещения круга ограничены стенками прямоугольника. Сделано это при помощи скрипт контроллеров на позиции круга. Управляющий объект, (я буду называть его «Контрол») взят как есть, с DVD Пола Нила (Paul Neale) «Facial Rigging Techniques». Мы не будем строить его, а просто воспользуемся готовым скриптом Пола:

rec=Rectangle length:10 width:10 name:(uniqueName "FaceControl") wireColor:[0,0,200] displayRenderMesh:false
cir=circle radius:1 name:(uniqueName "FaceControlHandle") wireColor:[200,0,0] displayRenderMesh:false
cir.parent=rec
setTransformLockFlags cir #{3..9}
conName=text text:"Control" size:2 wireColor:[0,150,0] pos:[0,5.5,0] alignment:2 displayRenderMesh:false
conName.parent=rec
addModifier conName (meshSelect())
setTransformLockFlags conName #{1..9}
rec.rotation.x_rotation=90

listCon=cir.pos.controller=position_list()
scCon=listCon.available.controller=position_script()

def=attributes clamp
(
      parameters clampP
      (
            l type:#float
            w type:#float
            x type:#float
            y type:#float
      )
)
custAttributes.add scCon def

scCon.l.controller=rec.length.controller=bezier_float()
scCon.l=10
scCon.w.controller=rec.width.controller=bezier_float()
scCon.w=10
scCon.x.controller=listCon[1].x_position.controller=bezier_float()
scCon.y.controller=listCon[1].y_position.controller=bezier_float()

script="
x=0
y=0
w=this.w/2
l=this.l/2
if this.x>w then (x=-this.x+w;this.x=w)
if this.x<-w then (x=-this.x-w;this.x=-w)
if this.y>l then (y=-this.y+l;this.y=l)
if this.y<-l then (y=-this.y-l;this.y=-l)

[x, y, 0]
"
scCon.script=script

Запустив этот скрипт, вы как раз получите готовый контрол, который будет создан в нулевой точке координат.

Обнуление контроллера челюстной кости

Привязку будем осуществлять через Wire Parameters. Но перед тем как делать привязку, кость нужно сначала подготовить. Дело в том, что при привязке кость может получить существенное смещение (кто пользовался Wire Parameters, поймет, о чем я). Для этого мы применим хитрый прием, и условно назовем его обнуление контролера. Не знаю, получится ли у меня объяснить, но смещение кости при привязке на контрол через Wire Parameters будет происходить потому, что кость, в данное время, имеет свое собственное, определенное значение ориентации, при привязке на контрол, это значение стирается, и кости просто передается новое значение которое дает контрол. Чтобы при привязке смещения не происходило нужно применить List контроллер. List контроллер позволяет добавить в список несколько контроллеров, и каждый последующий контроллер в списке будет потомком по отношению к предыдущему. Получается самая что ни на есть обычная иерархия прямо как у костей. Соответственно на первом контроллере у нас останется текущее положение кости, второй контроллер, по отношению к первому будет иметь нулевые координаты, как потомок, к этому контроллеру мы и будем привязываться. То есть текущее значение ориентации кости у нас ни куда не стирается, а остается на первом в списке контроллере, а влияние контрола будет распространяться только на второй контроллер, и значение первого контроллера будет суммироваться со значением контроллера потомка и таким образом мы избегаем непредсказуемой перемены значения при привязке кости на контрол.

Если не понятно, не страшно, перейдем к практике и просто сделаем все то же самое по шагам. Итак, выделяем челюстную кость, и открываем Curve Editor и на Rotation челюстной кости делаем «Assign Controller» и назначаем контроллер Rotation List.

Так у нас получилось, что на Rotation челюстной кости, назначен List Контроллер. Первым и единственным в списке идет контроллер Euler XYZ. Чтобы добавить в список еще один контроллер, выделяем параметр «Available» и назначаем на него еще один Euler XYZ.

Таким образом у нас в списке получилось два контроллера Euler XYZ. Теперь давайте зайдем в панель Motion и для удобства дадим имена этим контроллерам. Первый назовем Zero, а второй Animation.

Если посмотреть ниже, то можно увидеть как раз то, что я пытался объяснить сначала, то есть родительский контролер (Zero) по оси Z имеет значение -101,79, а потомок (Animation), равен 0.

Теперь, если активировать контроллер Animation и задать на него анимацию, то она просто добавится к той, что «зашита» на первом контроллере. (Кстати таким образом можно делать анимацию для различных объектов как бы по слоям, то есть каждый контроллер в списке может иметь абсолютно свой набор ключей анимации).

Ну все, оставляем активным контроллер Animation и переходим непосредственно к привязке.

Привязка челюстной кости к контролу
Наша задача, теперь заключается в том, чтобы заставить челюстную кость перемещаться под влиянием контрола. При перемещении контрола вверх-вниз, то есть по локальному Y, кость должна вращаться по ее локальному Z. Вот и выделяем контрол, заходим в Wire Parameters и находим там параметр позиции контрола по Y.

И привязываем этот параметр к Z вращению кости, вот того самого второго контроллера-потомка «Animation».

При прямой привязке, кость реагирует на перемещения контрола слишком интенсивно, поэтому привязку осуществляем через понижающий множитель, то есть умножаем параметр Y_Position на 0.1

Теперь не закрывая этого окна привязываем X_Position контрола к Y_Rotation кости с тем же множителем.

Нижняя челюсть готова.

Создание и привязка морф-целей для губ

Теперь можно смело приступать к созданию морф-целей. На данном этапе нам нужно создать четыре цели, для управления губами правой половины лица. Для этого просто копируем голову, удаляем с нее все модификаторы. Понадобятся цели с губами «в трубочку», с сильно растянутыми губами, губами выгнутыми вниз и губами выгнутыми вверх.

Первые цели готовы, можно приступать непосредственно к морфингу. Итак, добавляем модификатор Morpher. Но Morpher должен быть ниже модификатора Skin в стеке, то есть, добавляем его сразу после Editable Poly. И тут же заводим туда первые морф-цели.

Дам маленький совет, при настройке морф-целей, нужно постоянно перегружать их в морфере, чтобы увидеть изменения. Чтобы миновать это неудобство, включите галку Automatically Reload Targets. Таким образом в риалтайме вы сможете видеть на модели все изменения производимые с морф-целью.

Сразу же копируем и располагаем контролы возле модели и даем им удобные названия.

Немножко поясню, как работает контрол. В дефолтном положении контрол находится в нулевой точке по локальной оси. Если его смещать вверх, (по Y) то он уйдет в положительную сторону, если вниз, то в отрицательную. Так же, если смещать контрол вправо (по X), он уйдет в полюс, влево, в минус. Соответственно у нас есть четыре морф-цели, которые будут привязываться ко всем трансформациям контрола.

Первым делом привяжем ту цель, которая сводит губы «в трубочку». Выделяем контрол для правой половины губ и идем в Wire Paramrters и находим параметр X позиции.

Тащим связь на модель и привязываемся к первой морф-цели.

Влияние контрола получается очень слабым, поэтому параметр X_Position подключаем через множитель. В данном случае этот множитель 20. В принципе могу объяснить почему. Дело в том, что при создании контрола, его размеры указаны так, что сам управляющий объект – круг, можно смещать на 5 единиц от центра в каждую сторону. Пределы работы морф-цели от 0 до 100, оттуда и этот множитель, то есть 5 единиц умножть на множитель 20, получаем как раз 100 единиц на управление морф-целью.

Не закрывая этого окна привязываем остальные цели. На этот же X_Position привяжем цель которая растягивает губы. То же самое, только учтем, что в этом случае контрол смещается в минус, соответственно знак меняется на отрицательный.

Теперь, точно так же привязываем цель с губами согнутыми вниз. Привязку делаем по оси Y в отрицательную сторону.

И цель с губами вверх, в положительную сторону.

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

Создание и привязка морф-целей для глаз

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

Но нам-то нужно чтобы веко закрывалось по окружности, ну или по крайней мере, чтобы оно огибало выпуклый глаз персонажа. Специально для этого сделаем, морф-цель, полузакрытого века, на самой выпуклой точке. А теперь перечислю какие морфы понадобятся (на картинке с низу вверх): полузакрытое веко (для огибания глазного яблока), закрытое веко, сильно открытое веко, закрытое нижнее веко, сильно открытое нижнее веко и еще две дополнительные цели – смещение век вправо и смещение век влево. Эти две дополнительные цели позволят сделать анимацию глаз более живой, используя движение контрола в стороны.

Назначаем цели морферу и начинаем привязывать их к контролу правого глаза. Тут, пожалуйста повнимательнее, из-за огибания веком глаза нам придется поработать с целью полузакрытого века. По ходу повествования, я обращу на это внимание. Итак выделяем глазной контрол и идем в Wire Paramers.

Так же, как и в прошлые разы, привязываем Y_Position контрола к первой цели, с полузакрытым веком.

Эту цель пропишем позже, а пока просто устанавливаем ее на 100% и пишем Y_Position=100

И связываем остальные цели. На Y_Position вторую цель с закрытым веком.

На Y_Position третью цель с сильно открытым веком.

Вот сейчас внимание, займемся первой целью, с полузакрытым веком. Если сейчас подвигать контрол по Y, то видно, что морфинг работает не правильно. Это потому, что мы установили первую морф-цель (с полузакрытым веком) на 100% и она добавляется к остальным целям. Вот и займемся ею. Вернемся к первой цели и пропишем туда вместо «Y_Position=100» такое выраженьице «if Y_Position >= 0 then (100-Y_Position*20) else (100+Y_Position*20)»

Выраженьице это значит, что если положение контрола по Y больше или равно 0, то значение, которое будет передано на морф цель будет 100% минус положение контрола (от 0 до 5) помноженное на коэфициент 20, иначе (если контрол уйдет вниз), к 100% прибавится значение положения контрола (отрицательное естественно, а значит оно отнимется от 100) помноженное на 20. Например при контроле задранном вверх первая цель будет убрана на 0, а выражение можно понять так: «100%-(5*20)» то есть 0. Или же при контроле опущенном вниз первая цель будет так же убрана на 0, а выражение можно понять так: «100%+(-5*20)» то есть опять же 0. Теперь наши цели будут работать правильно, и глаз будет закрываться корректно, не проходя сквозь глазное яблоко.

Все, заводим остальные цели. Нижнее веко, при опускании контрола, поднимается (коэффициент я поставил не 20, а 15, чтобы веко не поднималось слишком сильно):

Нижнее веко сильно открывается (опускается) при поднятии контрола вверх:

Движение век вправо, при движении контрола вправо (в плюс по X)

Движение век влево при движении контрола влево (в минус по X)

Веки готовы.

Создание и привязка морф-целей для бровей

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

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

Теперь рассмотрим один из узлов более детально. Для примера возьмем цель, которая поднимает центр века вверх. Суть данного приема в следующем: при движении контрола (из нулевой точки) вверх, добавляется морф-цель с поднятой серединой века. Но при движении поднятого контрола в стороны, вес этой цели сходит на ноль. Следовательно, каждая морф-цель века реагирует как на положение контрола по 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, то могу вас поздравить, в ваших жилах течет крепкий бульон! Удачных работ и профессионального роста вам. Пока!

844 0 850 193
88
2009-04-24
мега полезно, спасибо
2009-04-24
абалдеть! 5/5
2009-04-24
Огромное спасибо!
2009-04-24
Красава! 5/5
2009-04-24
Отлично! Спасибо:)
2009-04-24
Очень круто! спасибо!
2009-04-24
жесть, для меня это как полёт на Марс для тараканов... так же нереально. Но тем не менее 5/5
2009-04-25
спасибо тебе) Это класс!
2009-04-25
Классный урок.
2009-04-25
Прочитал урок полностью, впечетляет. Сколько надо было труда все это опробовать, что бы получить результат. Большое спасибо.
2009-04-25
Это то что искал очень долго. Спасибо БОЛЬШОЕ. правда думал все делается проще.
2009-04-25
Спасибо! как раз то что нужно! сейчас пытаюсь углублённо изучать настройку и анимацию персонажей. есть пара вопросов: -на счёт век, не совсем понял зачем скрипт, ведь можно сделать морф с промежуточным значением... или я не о том??? -почему предпочтение отдано полностью Wire Parameters, и не затронуто Reaction Manager? Большое различие? Ограничения? Очень интересно! 5 и 5!
2009-04-25
[b]Anim86[/b] Вот кстати в DVD Пола это и сделано в Reaction Manager, просто мне показалось что с ним немного заморочнее работать, поэтому я выбрал для сесбя Wire. По векам не понял вопроса. Скриптов использовано всего два, один для создания контрола, а второй для отзеркаливания морф-таргетов, остальное собрано на простеньких выражениях, так, чтобы все работало как надо, если внимательно посмотреть урок то все должно быть понятно. К тому же не забывайте, что вы можете придумывать свои приемы используя этот принцип.
2009-04-25
5/5
2009-04-26
Урок конечно большой и картинок много,бесспорно вложено много труда.Но мне,как интересующемуся анимацией всё же не очень понравилось то,что были использованы готовые скрипты,к тому же ещё и с каких то дисков.И некоторые описания крайне скудны, т.е. не описаны мотивации данных действий,многие функции описаны просто "значение такое то,параметр такой то" ну а если мне нужны будут другие параметры,из каких соображений х устанавливать. Но это всё только мой видение,возможно я,как новичок просто не понял ничего,но хотелось бы во всех уроках видеть более подробные разъяснения.
2009-04-26
[b]Evgeny Samsonov[/b], то что я использую готовые скрипты это нормально, все, кто более менее давно занимается используют готовые скрипты. Все то же самое можно сделать и в ручную, конечно, а можно воспользоваться скриптами добрых людей и автоматизировать процесс. Еще надо бы понимать, что анимация мимики это уровень ну совсем не начинающий. Когда у вас будет достаточно опыта, все будет понятно. В конце концов можно просто выполнить пошагово то что я описал в уроке, я описывал абсолютно все не подразумевая, что вы что-то знаете и чего-то не знаете. Да и не в лесу живем, если что то можно спросить, если что не понятно. Так что если вы новичек, пока просто отложите этот урок себе в копилку, потому что этой информации вы нигде не найтете, когда придет время он очень пригодится.
2009-04-26
[quote]этой информации вы нигде не найтете[/quote] Вот это [b]ТОЧНО[/b]! Такого в книжках не печатают! Респект автору!!! Вот до настрою пару персонажиков и за ваш метод возьмусь, обязательно нужно опробовать! =) А скрипты это хорошо!!! так глядишь и сами писать их научимся... а это очень полезно!!! особенно заинтересовал скрипт [i]Зеркальное копирование морф целей[/i] очень интересно! И ещё раз Спасибо автору!!! Ещё секретики будут? =)
2009-04-26
Секретики, конечно будут, даст бог в следующих уроках.
2009-04-26
хороший урок кому интересно подобным образом засетпаплены персонажи в мультфильме Big Buck Bunny, кто не обится блендера - тут можно скачать рабочие сцены и посмотреть много прикольных примеров http://www.bigbuckbunny.org/index.php/download/
2009-04-27
Отличный урок, автор молодец, спасибо! [smile=04] Очень хочется заняться анимацией после таких уроков, но пока отложу в копилку ибо как было сазано такого нигде не найти)) Огромное спасибо за урок, надеюсь последуют продолжения) 5/5!
2009-04-27
По сложности урока, хочу успокоить новичков. То, что многое кажется непонятным, это нормально, потому, что почти все приемы, которые тут используются - новые, и нигде ранее не описанные. То есть этот урок может быть сложноват и для не новичка в общем-то. Что вы хотите, ести я сам изучал данную технику месяца два, с первого раза выполнить урок? Этот урок солжный, я уже говогрил об этом, тут нужно прорабатывать каждый прием в отдельности, и понимать как все работает, благо я описал как устроены все выражения и пояснил, что обозначают все значения. Например прием с обнулением кости вам пригодится много где, не только три анимации мимики, но и при анимации, например механики или взаимосвязанных шестеренок, связанных между собой Wire Parаmeters. И при всем при том, данная работа поможет вам делать анимацию мимики на высочайшем уровне, мне кажется, ради этого стоит собрать мозг в кучу и досконально проработать урок. Когда я искал в сети хоть что-нибудь по мимике, мне так ни разу не не попалось ни одного вразумительного урока, который бы позволил мне делать анимацию не на любительском уровне. Так что, я просто у верен, что данный урок просто клад для персонажника.
2009-04-27
Вопрос к автору: чем будет хуже делать анимацию мимики лица, если прикреплять к лицу персонажа через Xform такие же контроллеры? И не париться со всеми этими скриптами и вайрпараметрами? По-моему результат будет тот же самый :) Спасибо
2009-04-27
[b]Кашин Сергей[/b]. Да, Сергей, так тоже можно. Когда я не умел делать ничего кроме анимированного под музыку динамика, я именно так и поступал.
2009-04-27
ОТЛИЧНЫЙ УРОК!!! Осталось только собрать мозг в кучк!!!:))
2009-04-27
Максим, вы нас балуете!).. Урок просто отличный! Низкий вам поклон до земли:)
2009-04-27
По-моему Вы не ответили на вопрос :)
2009-04-27
Максим, возможно ли данным способом перемещать цель в трех осях системы координат и делать мосштабирование?
2009-04-27
[b]Кашин Сергей[/b], я ответил на ваш вопрос. Если вы выполните урок, то все будет понятно.
2009-04-28
}{арашЁ поРабоТали,маГсим(симсим) Урок прям волшебный))
2009-04-28
[quote=Кашин Сергей] Максим, возможно ли данным способом перемещать цель в трех осях системы координат и делать мосштабирование? [/quote] Ну разумеется можно))) Иерархия там и всё такое, ну...по крайней мере перемещять "втрёХосяХ"...А маштабировать...Тож наверна можна)) З.Ы. Не внятно, проглатывая бкувы, пршУ пРащения за ФЛУд (^_^)
2009-04-28
отличный урок! 5/5! Спасибо
2009-04-29
5/5
2009-04-29
[b]Кашин Сергей[/b], кстати на вопрос о перемещении контрола по трем осям, надо подумать. Вообще, это не предусмотрено и контрол двигается только по X и Y, но если задействовать ось Z, то можно сделать контрол для управления, например, языком по трем осям. Интересная мысля. Подумаем.
2009-04-30
Уважаемый,Максим Поклонов! Большое вам спасибо. Однажды я об этом вам написала, что хочу научиться в 3ds maxe мимику лица. Сегодня ваш урок обрадовала меня. Спасибо что вы есть!
2009-05-02
Максим , спасибо огромное , для себя подчерпнул много полезного для применения в других областях. Таких уроков очень мало ... В основоном на дисках англоязычные. Сам грыз диски , пытаясь понять физику процессов. Поэтому каждый урок такого плана еще больше открывает занавес всех секретов Макса . [b]5\5[/b] добавлю С УДОВОЛЬСТВИЕМ !!!
2009-05-02
Если бы был урок по созданию такой модельки...
2009-05-03
5/5 спасибо большое :-)
2009-05-03
Dankeschön!!!
2009-05-04
Максим, очисть плиз почтовый ящик! Нет возможности писать тебе в личку. Урок отличный.
2009-05-05
5/5 thanks
2009-05-07
[b]классный урок спасибо!!![/b]
2009-05-10
Спасибо! Шикарный урок! Очень актуально. :)
2009-05-13
Плохо что ненаписано. Как этим управлять ))))). Тоесть что бы он реалистично говорил. По шагам? Этож заморочно. Может есть способ записывать шаги в реальном времени?
2009-05-13
Способ есть, кости и мокап )
2009-05-16
[b]Огромное спасибо за такой подробный урок. У меня всё получилось. Потратил полдня и по-тихоньку во всём разобрался. Очень ценны оказались скрипты. Особенно отзеркаливание морф-целей. В два раза сокращается время работы, а результат на профессиональном уровне. И наконец-то получился полноценный скининг, без заломов. К сожалению не во всех учебниках есть грамотное руководство по работе с анимацией мимики. И тем ценнее ваш урок. Буду ждать новых уроков. Ещё раз спасибо и удачи вам![/b]
2009-05-23
Здорово Макс, урок отличный, на твёрдую пятёрку!
2009-05-27
Макс! Ты лучший! Наивысших похва! 5/5
2009-05-28
Хороший урок. Спасибо.
2009-05-29
Урок отличный ПРИГОДИТСЯ!!!
2009-05-29
Молодец! Урок понравился!
2009-05-29
5/5
2009-05-30
Так держать земляк!!! Отличный урок!!! 5/5
2009-05-31
мне даже если не все понятно, я хоть по малому улавливаю, и сделал уже кое что...СПАСИБО! видимо этот урок мне пригодиться еще на всю жизнь....а остольное в максе .. (лично для меня ) особого труда не предоставят, по ходу можно разобраться....для меня мимика самое основное в МАКСЕ , ЕЩЕ РАЗ СПАСИБО...!
2009-05-31
Спасибо за урок!!!
2009-06-25
[quote]выделяем контрол, заходим в Wire Parameters и находим там параметр позиции контрола по Y. И привязываем этот параметр к Z вращению кости, вот того самого второго контроллера-потомка «Animation».[/quote] К какой к какой извените кости вращению привязываем? На этом моменте остановился и не понимаю, что дальше! Плеаз хелп!
2009-06-26
[b]Tosyk[/b], судя по всему тебе надо поупражняться в применении Wire Paramaters, потому что в уроке все понятно рассказано, я попытаюсь объяснить но не уверен что получится понятнее. Короче, управляющий объект (контрол) перемещается по X и по Y, нам надо чтобы челюстная кость вращалась под действием контрола. При перемещении контрола по Y (это когда двигаем его вверх вниз), кость должна вращаться по Z (то есть так же вверх вниз). А при перемещении контрола по X (то есть встороны), челюстная кость должна вращаться по Y (то есть так же в стороны). Вот и привязываем с помощью Wire Parameters, Y контрола с Z кости и X контрола с Y кости. Но внимательно читай урок, не забудь обнулить контроллеры, и привязки делай уже к обнуленному контроллеру (Animation).
2009-07-02
Анимировал мимику своего персонажика Вашим способом и просто в шоке от изящества метода и простоты дальнейшего управления мимикой при анимации. Огромное спасибо за урок!!! Единственный вопрос: где вы в сцене размещаете блок контролов, чтобы не мешали и в то же время были под рукой. Я их разместил далеко от персонажа и нацелил отдельную камеру без фокуса, что позволило крутить контролы в отдельном окне. А как бы посоветовали Вы, Максим?
2009-07-02
За урок 10 из 5
2009-07-02
[b]gelonik[/b], рад, что пригодился урок! Панель управления можно разместить где угодно, это уж как фантазия подскажет, если делаешь мимику прямо в сцене, то можно прилинковать панель прямо к кости головы персонажа и туда же фронтальную камеру. Но персонажные сцены как правило сложные и делать анимацию прямо в сцене не всегда удобно, поэтому я делаю анимацию мимики в отдельном файле с головой а потом через Point Cache применяю ее в сцене. Этот способ я в кратце описывал в [url=http://www.render.ru/books/show_book.php?book_id=745]другом[/url] своем уроке.
2009-08-21
Спасибо Большое Максим!!! Все очень хорошо и понятно написано. Все получилось. Кучу времени для себя сэкономил!
2009-08-26
Респект Паулу...
2009-10-08
ОТЕЦ!!!
2009-11-05
у меня мозг плавится!))))
2009-11-05
Спасибо огромное!!!! Урок замечательный.Просто слов нет чтобы описать мой восторг. Мои персонажи ожили. Правда у меня в процессе возникла проблема с скриптом отзеркаливающим морф цели. Он вроде бы их зеркалит, но при этом существенно искажает сетку. Как будто вырывает полигоны. Я использовала скрипт на нескольких моделях и всё повторяется. Есть положительный момент, чем меньше полигонов в объекте, тем меньше искажается сетка при отзеркаливании. Ну это проверенныя истиная: меньше полигонов, меньше проблем.) Помогите пожалуйста, Максим. Модель настроила как по "инструкции" - pivot, точки и т.д., а сетка всё равно портится.
2009-11-15
Я, конечно, могу сам ошибатбся, но, помоему, в уроке допущена ошибка: [quote]Привязываем оставшиеся две цели. Они смещают бровь влево-вправо. Тут все просто: Цель смещение брови к носу. Выбираем X_Position и вяжем его к цели. Выражение пишем: «Y_Position*20» Цель смещение брови к виску. Выбираем X_Position и вяжем его к цели. Выражение пишем: «-Y_Position*20»[/quote] Почему это мы пишем Игрек позишен, когда мы привязываем его к Иксу? Да и сам Wire ругается, когда ему пишешь Игрек. С Иксом всё работает как нужно. Если я не прав - исправьте меня, если прав - исправьте запись в уроке [smile=04]
2009-11-15
[b]Alexen[/b], да все верно, в уроке есть ошибка. [quote]Привязываем оставшиеся две цели. Они смещают бровь влево-вправо. Тут все просто: Цель смещение брови к носу. Выбираем X_Position и вяжем его к цели. Выражение пишем: [b]«Y_Position*20»[/b] - следует понимать как [b]«X_Position*20»[/b] Цель смещение брови к виску. Выбираем X_Position и вяжем его к цели. Выражение пишем: «-Y_Position*20» - следует понимать как [b]«-X_Position*20»[/b][/quote] Раз находите ошибки, значит урок пригождается... это радует!
2009-11-15
[b]Максим Поклонов[/b], интересно, почему ошибки не заметили ранее читатели. Либо заметили, но не сказали; ну либо так читают..
2009-11-15
Ошибка не критичная, возможно просто не стали обращать внимание. Многие в личку писали вопросы по уроку. Так, что народ в принципе справляется.
2009-11-21
Чем способ с Wire Parameters лучше использования Reaction Manager, где не понадобятся при морфе и риге никаких множителей.Wire Parameters хорош для рига пальцев.Или просто личное предпочтение? [quote]3. Откройте MaxScript Listener, (MaxScript-> MaxScript Listener, по умолчанию F11) и напишите в нем команду которая запускает функцию запоминающую модель: «getMirrorData()» [/quote] Не надо ничего писать, после Ввода скрипта Нила в MaxScript Editor в MaxScript Listener появятся необходимые команды getMirrorData() и mirrorMorph(). Первый как было сказано берет данные вершин выделенного поли-объекта, а второй зеркалит данные одного уже зделанного морфа (например правый край губы приподнят) на другой. Также можно наисать mirrorMorph summetry:true это отзеркалит данные вершин с одной стороны на другую при этом оставив отзеркаливаемую сторону прежней т.е. из (+-) на (++) + это отзеркаливаемая половина, а ранее расмотренный способ будет (+-) на (-+). Это тоже может понадобится при морфе.
2009-11-21
Извеняйте сам ошибся не mirrorMorph summetry:true а mirrorMorph symmetry:true
2009-11-30
Урок классный правда нашёл выход не использовать сриптов при создание контролеров и как подметили использовать Reaction Manager для создания морфа брови!!!
2009-12-05
Здравствуйте, Максим! Урок потрясающий! Всё очень понятно и подробно расписано. Спасибо огромное за ваш труд! 5/5
2009-12-27
Спасибо Максим. Кстати, я заметил глюк, если копировать модель для морфинга с помощью шифта, то потом при движении контроллера вся модель перемещается. Т. е. нужно сначала скопировать, а потом переместить.
2010-01-28
Спасибо огромное за урок, везде искал про этот способ анимации в максе и наконец нашёл, ура!)
2010-01-28
Шикарный урок!!!! Спасибо огромное!!! Мимика всегда была для меня темным лесом.....но теперь все прояснилось.....
2010-02-04
Да... Титанический урок... Спасибо большое, прочитав этот урок я узнал такие приёмы, о которых даже и не догадывался!
2010-03-29
В этом уроке все мне понятно!!! Я не знал что так просто! Спасибо вы гений!!!
2010-08-10
Превосходно!!! Повторил все, все получилось!
2010-09-10
спасибо. переодически орбращаюсь к вашему уроку , по мере надобности
2011-01-15
Супер! Наконец то я понял как делать анимацию лица! Спасибо!!!
2011-01-16
Спасибо! Шикарный урок! Только вот вышла проблемка , я удалял все морф цели , щас че только не пытался, отзеркалить не получается, придется левую половину опять вручную делать )))
2011-01-16
[quote=DeKon] [/quote] Лучше со скриптом разберись, потренируйся на шарике, сэкономишь кучу времени. Обычно проблемы со скриптом бывают когда модель не в порядке, надо двойные точки посклеивать и через symmetry сделать чтобы модель была полностью симметричная.
2011-01-16
Когда я отсиметрил голову , я ее почему то не мог выбрать как морф цель . На нее просто мышкой нажать не мог. ( тоже самое было когда меш смуф был включен )
2011-04-13
Приет Макс ,я запнулся "Создание и привязка морф-целей для губ" удалить все модификаторы это скин? и каким методом делаеться разное положение губ ?без скина и привязки к костям,если можно эту часть поподробней ? Спасибо
2013-10-17
Макс, огромное тебе спасибо за такой урок, очень приятно что всякие тонкости объясняются на родном языке. Жаль что без maxscripts тут не обойтись, код тяжело дается
2013-10-17
Пожалуйста ;) Да тут не столько макс скрипт, сколько математические выражения - плюс, минус, больше меньше. Чужой код всегда тяжело дается это нормально )))
2014-01-21
хороший урок) Хотя это - так сказать "вершина айзберга" - и спасибо за скрипт -обязательно попробую. Для тех у кого скрипт по мирору не работаю( или модель и задумывалась не семетричной) - раскажу как я делаю ( делал) зеркальные морфы- и так - дублируем меш с уже назначеными морфами- дублируем еще раз - но на этот раз убиваем весь стек( просто конверт ту едит поле ( меш) по правой кнопке( назовем меш1 и меш2 -соответсвено) меш1 - мирорим -с помощью миррор тула (если не знаете где кнопка- то можно найти его в закладке едит) после этого к меш2 применяем модифер скинморф - и как цель назначаем меш1 ( если у вас модель семитричная сбрасываем все параметры модифера на минимальные значения) типерь изменяя значения морфа меш1 -мы деформируем меш2 - выставляя вес каждой морфемы меш1 на максимум -делаем снепшот меш2 ( там же в закладке едит) -получаем набор морфтаргетов)
2017-09-01
Спасибо за урок! все получалось пока не начал ставит скрипт ля зеркального отображения, у меня он не открывается почему-то. расшартепожалуйста .me готовый у кого есть!
RENDER.RU