что такое меш объект
Что такое service mesh и почему он мне нужен [для облачного приложения с микросервисами]?
Предисловие от переводчика: Эта неделя ознаменовалась выходом Linkerd 1.0, что является отличным поводом рассказать не только об этом продукте, но и о самой категории такого программного обеспечения — service mesh (дословно переводится как «сетка для сервисов» или «сервисная сетка»). Тем более, что авторы Linkerd как раз опубликовали соответствующую статью.
tl;dr: Service mesh — это выделенный слой инфраструктуры для обеспечения безопасного, быстрого и надёжного взаимодействия между сервисами. Если вы создаёте приложение для запуска в облаке (т.е. cloud native), вам нужен service mesh.
За прошедший год service mesh стал критически важным компонентом в облачном стеке. Компании с большим трафиком, такие как PayPal, Lyft, Ticketmaster и Credit Karma, уже добавили service mesh в свои приложения в production, а в январе Linkerd — Open Source-реализация service mesh для облачных приложений — стал официальным проектом фонда Cloud Native Computing Foundation (в этот же фонд недавно передали containerd и rkt, а ещё он известен как минимум по Kubernetes и Prometheus — прим. перев.). Но чем же является service mesh? И почему он стал внезапно необходим?
Что такое service mesh?
Service mesh — это выделенный слой инфраструктуры для обеспечения взаимодействия между сервисами. Он отвечает за надёжную доставку запросов через сложную топологию сервисов, составляющих современное приложение, созданное для работы в облаке. На практике service mesh обычно реализуется как массив легковесных сетевых прокси, которые деплоятся вместе с кодом приложения, без необходимости приложению знать об этом. (Но мы увидим, что у этой идеи есть разные вариации.)
Концепция service mesh как отдельного слоя связана с ростом приложений, создаваемых специально для облачных окружений. В такой облачной модели единое приложение может состоять из сотен сервисов, у каждого сервиса могут быть тысячи экземпляров, и у каждого экземпляра могут быть постоянно изменяющиеся состояния в зависимости от динамического планирования, осуществляемого инструментом для оркестровки вроде Kubernetes. В этом мире взаимодействие сервисов оказывается не просто очень сложным процессом, но и повсеместной, фундаментальной частью поведения исполняемой среды. Управление им очень важно для поддержания производительности и надёжности.
Является ли service mesh сетевой моделью?
Да, service mesh — это сетевая модель, находящаяся на уровне абстракции выше TCP/IP. Подразумевается, что нижележащая сеть L3/L4 представлена и способна передавать байты от точки до точки. (Также подразумевается, что эта сеть, как и все другие аспекты окружения, не является надёжной; service mesh должен обеспечивать обработку сетевых отказов.)
В некоторых смыслах service mesh аналогичен TCP/IP. Как TCP-стек абстрагирует от механики надёжной передачи байтов между конечными сетевыми точками, так и service mesh абстрагирует от механики передачи запросов между сервисами. Как и TCP, service mesh не придаёт значения действующей нагрузке и тому, как она закодирована. У приложения есть задача высокого уровня («отправить что-то из A в B»), и работа service mesh, как и в случае TCP — решить эту задачу, обрабатывая любые встречающиеся по пути проблемы.
В отличие от TCP, у service mesh есть значительная цель помимо «просто заставить что-то работать» — предоставить унифицированную точку входа для всего приложения, обеспечив видимость и контроль его исполняемой среде. Прямая цель service mesh — вынести взаимодействие между сервисами из области невидимой, предполагаемой инфраструктуры, предложив ему роль полноценного участника экосистемы, где всё подлежит мониторингу, управлению, контролю.
Что же service mesh делает?
Надёжная передача запросов в приложении для облачной инфраструктуры может быть очень сложной. И service mesh вроде Linkerd разбирается с этой сложностью с помощью набора действенных техник: предохранения от проблем в работе сети, балансировки нагрузки с учётом задержек, обнаружения сервисов (по модели согласованности в конечном счёте), повторных попыток и дедлайнов. Все эти возможности должны работать совместно, а взаимодействия между ними и среда, в которой они оперируют, могут быть весьма непростыми.
Например, когда делается запрос в сервисе через Linkerd, очень упрощённая последовательность событий выглядит следующим образом:
Важно заметить, что эти возможности предназначены для обеспечения устойчивости и на уровне конечной точки, и на уровне приложения в целом. Распределённые системы больших масштабов вне зависимости от их архитектуры обладают одной определяющей характеристикой: существует много возможностей для того, чтобы малые, локальные падения превратились в катастрофические для всей системы. Поэтому service mesh должен быть спроектирован так, чтобы обеспечить защиту от подобных проблем, снижая нагрузку и быстро падая, когда нижележащие системы достигают своих лимитов.
Почему service mesh нужен?
Service mesh — это, конечно, не предоставление новой функциональности, а скорее сдвиг в том, куда это функциональность помещена. Веб-приложения всегда были вынуждены тянуть ношу взаимодействия между сервисами. Происхождение модели service mesh можно проследить в эволюции этих приложений на протяжении последних 15 лет.
Представьте типичную архитектуру веб-приложения средних размеров в 2000-х: это 3 уровня. В такой модели логика приложения, логика отдачи контента и логика хранилища — отдельные слои. Взаимодействие между этими уровнями является сложным, но ограничено в масштабах — ведь тут всего два транзитных участка. Нет никакой «сетки» (т.е. mesh) — только взаимодействие логики между транзитными участками, осуществляемое в коде каждого слоя.
Когда этот архитектурный подход достиг очень большого масштаба, он начал ломаться. Компании вроде Google, Netflix и Twitter столкнулись с необходимостью обслуживания большого трафика, реализация которой стала предшественником облачного (cloud native) подхода: слой приложения был разбит на множество сервисов (иногда называемых микросервисами), и уровни стали топологией. В этих системах обобщённый слой для взаимодействия быстро стал необходимостью, но обычно принимал форму библиотеки «толстого клиента»: Finagle у Twitter, Hystrix у Netflix, Stubby у Google.
Во многих смыслах эти библиотеки (Finagle, Stubby, Hystrix) стали первыми «сетками для сервисов». Пусть они были заточены для работы в своей специфичной среде и требовали использования конкретных языков и фреймворков, однако уже представляли собой выделенную инфраструктуру для управления взаимодействием между сервисами и (в случае Open Source-библиотек Finagle и Hystrix) применялись не только в компаниях, которые их разработали.
Последовало быстрое движение навстречу современным приложениям, создаваемых для запуска в облаках. Модель cloud native сочетает микросервисный подход из множества маленьких сервисов с двумя дополнительными факторами:
Комбинация сложности и критической важности привела к необходимости выделенного слоя для взаимодействия между сервисами, отделённого от кода приложения и способного справляться с очень динамичной природой нижележащего окружения. Этим слоем и является service mesh.
Будущее service mesh
Пока идёт быстрый рост адаптации service mesh в облачной экосистеме, обширную и захватывающую дорожную карту [дальнейшего развития этой концепции и её реализаций — прим. перев.] ещё только предстоит открыть. Требования, предъявляемые к вычислениям без серверов (например, Amazon Lambda), отлично укладываются в модель service mesh по наименованию и связыванию [компонентов], что формирует естественное расширение его применения в облачной экосистеме. Роли удостоверения служб и политик доступа всё ещё очень молоды в облачных окружениях, и здесь service mesh хорошо подойдёт, чтобы стать фундаментальной составляющей такой потребности. Наконец, service mesh, как и TCP/IP раньше, продолжит своё проникновение в нижележащую инфраструктуру. Как Linkerd эволюционировал из систем вроде Finagle, продолжит свою эволюцию и текущая реализация service mesh как отдельного прокси в пользовательском пространстве, которая может быть добавлена в облачный стек.
Вывод
Service mesh — критически важный компонент стека категории cloud native. Linkerd, появившись чуть более 1 года назад, является частью Cloud Native Computing Foundation и получил растущее сообщество контрибьюторов и пользователей. Его пользователи разнообразны: от стартапов вроде Monzo, разрушающих банковскую индустрию Великобритании [это полностью цифровой банк, предлагающий разработчикам API для доступа к финансовым данным, — прим. перев.], до интернет-компаний больших масштабов вроде PayPal, Ticketmaster и Credit Karma, а также компаний с бизнес-историей в сотни лет вроде Houghton Mifflin Harcourt.
Open Source-сообщество пользователей и контрибьюторов Linkerd ежедневно демонстрируют ценность модели service mesh. Мы преданы созданию отличного продукта и продолжающемуся росту нашего сообщества.
P.S. Автор статьи — William Morgan, один из создателей Linkerd в 2015 году, учредитель и CEO в Buoyant Inc (компания-разработчик, передавшая Linkerd в CNCF).
ОБНОВЛЕНО (20.02.2018): читайте также в нашем блоге обзор нового продукта Buoyant — «Conduit — легковесный service mesh для Kubernetes».
Особенности работы с Mesh в Unity
Компьютерная графика, как известно, является основой игровой индустрии. В процессе создания графического контента мы неизбежно сталкиваемся с трудностями, связанными с разницей его представления в среде создания и в приложении. К этим трудностям прибавляются риски простой человеческой невнимательности. Учитывая масштабы разработки игр, такие проблемы возникают либо часто, либо в больших количествах.
Борьба с подобными трудностями навела нас на мысли об автоматизации и написании статей на эту тему. Большая часть материала коснется работы с Unity 3D, поскольку это основное средство разработки в Plarium Krasnodar. Здесь и далее в качестве графического контента будут рассматриваться 3D-модели и текстуры.
В этой статье мы поговорим об особенностях доступа к данным представления 3D-объектов в Unity. Материал будет полезен в первую очередь новичкам, а также тем разработчикам, которые нечасто взаимодействуют с внутренним представлением таких моделей.
О 3D-моделях в Unity — для самых маленьких
При стандартном подходе в Unity для рендеринга модели используются компоненты MeshFilter и MeshRenderer. MeshFilter ссылается на Mesh — ассет, который представляет модель. Для большинства шейдеров информация о геометрии является обязательной минимальной составляющей для отрисовки модели на экране. Данные же о текстурной развертке и костях анимации могут отсутствовать, если они не задействованы. Каким образом этот класс реализован внутри и как все там хранится, является тайной за энную сумму денег семью печатями.
Снаружи меш как объект предоставляет доступ к следующим наборам данных:
Ядро движка (UnityEngine (native)) изолировано от скриптов разработчика, и обращение к его функционалу реализовано через библиотеку UnityEngine (C#). Фактически она является адаптером, поскольку большинство методов служат прослойкой для получения данных от ядра. При этом ядро и вся остальная часть, в том числе ваши скрипты, крутятся под разными процессами и скриптовая часть знает только список команд. Таким образом, прямой доступ к используемой ядром памяти из скрипта отсутствует.
О доступе к внутренним данным, или Насколько все может быть плохо
Для демонстрации того, насколько все может быть плохо, проанализируем объем очищаемой памяти Garbage Collector’ом на примере из документации. Для простоты профилирования завернем аналогичный код в Update метод.
Мы прогнали данный скрипт со стандартным примитивом — сферой (515 вершин). При помощи инструмента Profiler, во вкладке Memory можно посмотреть, сколько памяти было помечено для очистки сборщиком мусора в каждом из кадров. На нашей рабочей машине это значение составило
Это довольно много даже для нагруженного приложения, а мы здесь запустили сцену с одним объектом, на который навешен простейший скрипт.
Важно упомянуть об особенности компилятора .Net и об оптимизации кода. Пройдясь по цепочке вызовов, можно обнаружить, что обращение к Mesh.vertices влечет за собой вызов extern метода движка. Это не позволяет компилятору оптимизировать код внутри нашего Update() метода, несмотря на то, что DoSomething() пустой и переменные x, y, z по этой причине являются неиспользуемыми.
Теперь закешируем массив позиций на старте.
В среднем 6 Кб. Другое дело!
Такая особенность стала одной из причин, по которой нам пришлось реализовать собственную структуру для хранения и обработки данных меша.
Как это делаем мы
За время работы над крупными проектами возникла идея сделать инструмент для анализа и редактирования импортируемого графического контента. О самих методах анализа и трансформации поговорим в следующих статьях. Сейчас же рассмотрим структуру данных, которую мы решили написать для удобства реализации алгоритмов с учетом особенностей доступа к информации о меше.
Изначально эта структура выглядела так:
Здесь класс CustomMesh представляет, собственно, меш. Отдельно в виде Utility мы реализовали конвертацию из UntiyEngine.Mesh и обратно. Меш определяется своим массивом треугольников. Каждый треугольник содержит ровно три ребра, которые в свою очередь определены двумя вершинами. Мы решили добавить в вершины только ту информацию, которая нам необходима для анализа, а именно: позицию, нормаль, два канала текстурной развертки (uv0 для основной текстуры, uv2 для освещения) и цвет.
Спустя некоторое время возникла необходимость обращения вверх по иерархии. Например, чтобы узнать у треугольника, какому мешу он принадлежит. Помимо этого, обращение вниз из CustomMesh в Vertex выглядело вычурно, а необоснованный и значительный объем дублированных значений действовал на нервы. По этим причинам структуру пришлось переработать.
В CustomMeshPool реализованы методы для удобного управления и доступа ко всем обрабатываемым CustomMesh. За счет поля MeshId в каждой из сущностей имеется доступ к информации всего меша. Такая структура данных удовлетворяет требованиям к первоначальным задачам. Ее несложно расширить, добавив соответствующий набор данных в CustomMesh и необходимые методы — в Vertex.
Стоит отметить, что такой подход не оптимален по производительности. В то же время большинство реализованных нами алгоритмов ориентированы на анализ контента в редакторе Unity, из-за чего не приходится часто задумываться об объемах используемой памяти. По этой причине мы кешируем буквально все что можно. Реализованный алгоритм мы сначала тестируем, а затем рефакторим его методы и в некоторых случаях упрощаем структуры данных для оптимизации времени выполнения.
На этом пока все. В следующей статье мы расскажем о том, как редактировать уже внесенные в проект 3D-модели, и воспользуемся рассмотренной структурой данных.
Глава 11. Mesh-Объекты
К сожалению, на русском языке нет хорошего слова, чтобы обозначить этот объект. Можно перевести это слово как каркас. Можно сказать «сетка», но по-моему, понятнее и узнаваемее будет использовать слово Mesh (меш) без перевода.
В чём состоит удобство? Рассмотрим на примере такого простого объекта, как параллелепипед.
Рис. 11.1. Параллелепипед, все рёбра которого видимы и параллелепипед, некоторые рёбра которого не видимы. |
Начало моделирования
Если сейчас нажать на название одного из этих подъобъектов, то он станет жёлтым и мы перейдём в режим редактирования данных подъобъектов. Когда мы находимся в режиме работы с подобъектами, мы не можем выделять другие объекты, а можем выделять лишь подъобъекты данного типа в пределах того объекта, с которым мы работаем. То есть, если у нас выбран режим работы с вершинами нашего объекта, то работать с вершинами другого объекта мы не можем, пока не выйдем из режима редактирования вершин текущего объекта, не выделим другой объект и не войдём в режим редактирования его вершин.
Они так же желтеют, когда подъобъект выбран, и их можно отключать, тогда режим редактирования подъобъектов заканчивается. В свойствах объекта Editable Mesh даже когда не выбрано никакого режима работы с подъобъектами, уже доступны для нажатия некоторые кнопки и параметры.
После присоединения все части принимают цвет того объекта, к которому мы их присоединяем, опорная точка получившегося объекта совпадает с опорной точкой исходного.
В общем, это не столь интересно, разве что обе кнопки Attach, Remove isolated vertices и то, что касается Align.
Чтобы начать изменять mesh-объект, надо войти в режим работы с каким-либо подъобъектом. Можно выделить все подъобъекты и удалить их. Подъобъекты выделяются так же, как и объекты, при выделении они краснейют. То есть кликать надо по тому подъобъекту, который мы хотим выделить.
Если выделить и удалить все вершины (когда ещё существуют грани), то грани и рёбра тоже удаляться, поскольку без вершин они существовать не могут. И когда мы удаляем вершину, удяляются те подъобъекты, которые на эту вернишу опираются.
Так вот, если удалить все подъобъекты, сам mesh-объект не исчезнет. Если выйти из режима работы с подобъектами и отвыделить наш mesh-объект, то потом его выделить можно будет только при помощи списка.
Но когда объект выбран, можно перейти в режим редактирования его подъобъектов и начать создавать в нём новые подъобъекты. Создать можно тот подъобъект, в режими работы с которым мы находимся.
Элементарное создание подъобъектов
Создать грани можно только если уже имеются вершины. В какой-то версии 3ds MAX была возможность создавать грани без имеющихся заранее вершин, и вершины появлялись по мере надобности сами, но потом её почему-то убрали.
Итак, если в mesh-объекте вообще ничего нет, перво-наперво надо создавать вершины. Они, да и все другие подъобъекты, создаются при нажатой кнопкe Create в группе Edit Geometry. Рёбра не создаются, они являются сторонами вершин.
Вершина появляется сразу после клика мышью, и будет расположена в плоскости координатной сетки текущего вида. После этого её можно пододвинуть в нужное место при помощи кнопки перемещение (move).
Грани и многоугольники создаются в режими работы с ними. Чтобы создать их, надо так же нажать кнопку Create, а потом посделовательно кликнуть мышью по нужным вершинам. Если мы находимся в режими работы с гранями (треугольными), то после того, как указана третья точка, создание заканчивается само собой. То же самое происходит в режими работы с элементами. В режиме работы с многоугольниками, можно указать много вершин подряд, а создание многоугольника завершается если нажать на одну и ту же вершину два раза подряд.
Эффективная работа с подобъектами
Начнём с того, что можно сделать с гранями. Создадим для начала Box, и посмотрим, как из него можно что-либо сотворить, не прибегая к нажатию кнопки Create для подъобъектов. Работать будем в режиме многоугольников, в режиме треугольников всё происходит аналогичным образом.
Как следует создавать симметричные объекты? Чтобы избежать проблем, которые могут возникнуть потом при отражении (конечно, они решаемые, но зачем они нам нужны?), опорная точка объекта должна находиться на плоскости, разделяющий наши половинки.
Поскольку объект будет симметричный, разделим его на две половинки. Можно, конечно, поставить по ширине два сегмента для Box, тогда он как бы и разделится, но мы лучше посмотрим, как работает инструмент Slice Plane. Итак, если вы всё ещё не преобразовали ваш Box в Editable mesh, то сделайте это. И имя надо сменить, назвать его не Box 01, а Dog (собака).
Разрезание осуществляется в режиме работы с рёбрами, поэтому нажмём . И ещё, стоит упомянуть, что разрезка фактически ничего не разрезает, она создаёт шов на поверхности, который представляет собой видимые рёбра. Появление этого шва так же сопровождается появлением новых граней, а иногда и новых вершин. При желании можно включить флажок Split, тогда разрезка будет приводить не только к появлению шва, но и к тому, что фактически в месте разреза поверхность будет разъединена по созданному шву. Пока не будем ставить флажок Split.
В группе Edit Geometry есть кнопка Slice Plane, как только мы её нажмём, у нас появится жёлтая плоскость (рис 11.2).
Рис. 11.2. Режим Slice Plane |
Плоскость расположена горизонтально, а мы хотим сделать вертикальный разрез, поэтому её надо повернуть вдоль оси «y» ровно на 90 градусов. Если вы не расположили Box так, как вам предлагалось ранее, вам придётся самим теперь разбираться, вокруг чего и на сколько градусов надо повернуть плоскость.
После того, как плоскость стала в нужное положение, разделив параллелепипед вдоль на две половинки, нажимайте кнопку Slice. Появится шов красного цвета. Это значит, что создались новые рёбра, и эти рёбра в данный момент выделены.
Рис. 11.3. Режим Slice Plane сразу после нажатия на кнопку Split |
Теперь выключим режим Slice Plane и перейдём в режим работы с многоугольниками .
Надо навести на нужные выделенные грани, и курсор станет похожим на вершину небоскрёба, а затем нажать левую кнопку и тащить. В зависимости от того, куда движется курсор мыши, грани будут либо выезжать, подобно тому, как открывается спичечный коробок, либо наоборот въезжать вовнутрь. В данном случае нам надо их выдвинуть наружу.
При экструзии автоматически создаются и грани, и вершины, и, соответственно, рёбра.
Рис. 11.4. Экструзия |
Рис. 11.5. Bevel |
Кстати, подобъекты можно перемещать, вращать и масштабировать, так же как и просто объекты. Если выделена одна вершина, то смасштабировать или повернуть её не удастся, но если выделана группа вершин, то это можно сделать. А вот грани и многоугольники можно масштабировать и вращать. Мы сейчас смасштабируем наши грани вдоль оси x, чтобы они обе в целом приняли форму квадрата.
Рис. 11.6. Смасшабирование выделенных граней |
Говоря о масштабировании, вращении и перемещении, надо отметить, что для подобъектов тоже можно выбрать тип вспомогательной системы координат, и для граней довольно-таки неплохо работает система Local, в которой ось Z направлена перпендикулярно грани (по нормали). И ещё, масштабирование можно использовать вместо Bevel, хотя в ряде случаев результат будет разным.
Фактически, Bevel меняет форму выделеных граней, если у нас выделено нечто более сложной формы, чем квадрат или прямоугольник. Bevel как бы сжимает или расширяет контур, очерчивающий выделенные грани, а масштабирование меняет размер всей фигуры, сохраняя её пропорции.
Далее не будем рассматривать по шагам, что мы сделаем, а сделаем мы некоторую заготовку для головы при помощи всё тех же Extrude, Bevel и масштабирования и перемещения.
Рис. 11.7. Заготовка головы, сделанная при помощи Extrude, Bevel и масштабирования граней. Повороты не использовались |
Теперь создадим хвост. Для этого повернём вид (не объект, а развернём вид в окне проекции) так, чтобы собака была к нам задом. И перейдём в режим работы с вершинами . Какие-то вершины у нас уже будут выделены, отвыделим их, просто кликнув мышью куда-нибудь мимо, а затем выберем ту, которая находится на том самом месте, где должен быть хвост. В той же группе Edit Geometry находим кнопку Chamfer и нажимаем на неё. Опять же, сюда можно вводить численные параметры, но мы пока будем делать всё вручную. Нажмём на кнопку, наведём курсор на выделенную вершину, нажмём кнопку и будем тащить. Вершина начнёт расползаться, превратившись в грань. На самом деле грань будет седловидной формы, но это не важно. Главное, мы создали место, из которого можно экструзировать хвост.
Рис. 11.8. Chamfer |
Обратите внимание, что по центру проходит линия, разделяющая объект на две половины. Пока мы работали с обеими половинами и они у нас сами собой получались симметричными. А в том месте, где мы применили Chamfer, шва по центру не наблюдается. А он нам нужен, поскольку именно по шву можно разделить наш объект и одну половину выкинуть, поскольку после создания первоначальной заготовки, работать мы будем только с одной половиной, а потом её отразим и прилепим к первой.
Вот как раз предоставился случай познакомится ещё с одной опцией редактирования. Переходим в режим работы с рёбрами. С помощью прямоугольной рамки выделим рёбра вокруг нашей грани, созданной при помощи Chamfer. Сделав это, мы увидим и невидимые рёбра, которые отображаются пунктиром (Рис. 11.9).
Рис. 11.9. Невидимые рёбра |
Итак, мы повернём наше ребро. На месте хвоста получится как бы ямка, иначе и быть не может. Пока нас эта ямка не особо-то и должна волновать, но на примере того, как от неё избавиться, познакомимся ещё с одним инструментом работы с рёбрами. Сделаем наше ребро видимым, чтобы с ним легче было работать.
Рядом с кнопкой Turn (слева) в Edit Geometry есть кнопка Divide (поделить). Если её нажать и кликнуть по ребру, то в месте клика на ребре появится вершина, от которой будут простираться в обе стороны невидимые рёбра. Поэтому, непосредственно сразу после клика мы можем ничего не увидеть, чтобы понять, получилось или нет, надо выключить кнопку Devide и выделить все рёбра в окрестности данной области, либо перейти в режим работы с вершинами. Если мы попали по нужному ребру, вершина появится. Вот тут точно надо работать в режиме Ignore Backfacing или прятать противоположную сторону объекта.
Рис. 11.10. После применения операций Turn и Devide |
Рис. 11.11. Пример хвоста |
Итак, отразим исходную половину, после чего выделим её снова и будем работать с ней дальше. Дальше надо сделать ноги. Но сначала посмотрим ещё раз на рисунки 11.8 и 11.9 (см. копии внизу)
Рис. 11.8 (копия). Chamfer |
Рис. 11.9 (копия). Невидимые рёбра |
Во-первых на рис. 11.8. видно, что прямо посреди рёбер находятся вершины. Это произошло из-за того, что секущая плоскость когда мы делали операцию Slice Plane разрезала невидимые рёбра, которые проходили по диагонали четырёхугольников. Некоторые из этих невидимых рёбер стали видны на рис. 11.9, потому что мы их выделили. Естественно, что теперь невидимых рёбер больше, чем их было до того, как мы выполнили Slice Plane, поскольку им просто пришлось появиться после этой операции, и после того, как мы сделали Chamfer для задней вершины. Ведь каждый многоугольник в конечном счёте состоит из треугольников.
Вообще, обычно невидимые рёбра лучше повернуть при помощи Turn таким образом, чтобы каждое из них было как можно короче.
Рис. 11.12. Рёбра, повёрнутые оптимальным образом. Вид с одной из сторон. |
Здесь мы уже работаем только с одной половиной. Вообще, если наши многоугольники не являются выпуклыми и плоскими, то от того, как проходят невидимые рёбра (ровно как и видимые), будет ощутимо зависить внешний вид конечного объекта. В этом вы можете впоследсвтие убедиться сами. Но когда речь идёт о плоских и выпуклых многоугольниках, или почти плоских выпуклых многоугольниках, лучше рёбра располагать так, чтобы они были как можно короче.
Теперь познакомимся с инструментом Cut, который даже некоторые люди называют волшебным, поскольку этот иснтрумент очень помогает добавлять новые детали на наш объект.
Этот инструмент доступен в режиме работы с рёбрами в группе Edit Geometry, рядом с кнопкой Slice Plane. Соответственно, точно так же, как и в случае Slice Plane, если нажать Split, то на месте шва будет реальный разрез.
Cut (резать) работает так: надо нажать на кнопку, потом выбрать место, с которого начинать шов. Таким местом может быть ребро либо вершина, когда вы наведёте курсор на ребро или вершину, он измениться, и можно кликнуть мышью. После этого за курсором будет тянуться чёрная пунктирная ниточка. Курсор можно вести так, как вы хотите расположить ваш шов и кликать мышью по встречающимся на пути рёбрам. Не обязательно кликать по всем подряд, можно пересечь сразу несколько находящихся на пути рёбер и кликнуть на то, которое находится за ними.
Внимание: Инструмент Cut плохо работает в видах, в которых имеется перспектива, то есть в режиме Perspective, или когда в окне проекции отображается вид через камеру, у которой не включен режим Orthographic Projection. Работать с инструментом рекомендуется либо в видах top, bottom, left, right, front, back, либо в виде User. Удобно по мере надобности переключать в режим User вид Perspective.
Мы разделим туловище собаки на две части, начав наш шов с вершины, расположенной по центру спины, и приведём его к середине живота, где так же должна располагаться вершина. Для этого повернём объект так, чтобы он был виден сверху и сбоку (как на рис. 11.13) и начнём резать (режим Split должен быть выключен).
Рис. 11.13. Рёбра, созданные при помощи инструмента Cut. |
Наш шов кончится на нижнем ребре, поскольку резать по нижней сороны, не видя её, трудно. Правда, до того как резать, можно перейти в режим Wireframe и выбрать во вкладке Display для нашего объекта режим с выключенным Backface Cull, тогда в проволочном режиме отображения нам будут видны все линии нашего объекта, и нам будет видно, как проводить шов и по загороженной от взгляда стороне. Но можно просто прерваться, выключить кнопку Cut, повернуть вид так, чтобы видеть низ и продолжить с той точки, в котрой мы остановились. А может быть так, что и резать-то ничего не понадобится, возможно, невидимое ребро уже создалось между вершиной на середине живота и той точкой, в которой мы остановились. Надо только выбрать его и сделать видимым.
Так вот, если мы выделили вершину при помощи небольшой прямоугольной области и так получилось, что у нас их оказалось в одном месте две или больше, а мы хотим иметь только одну, то можно схлопнуть все выделенные вершины в одну при помощи инструмента Collapse (в группе Edit Geometry). Вообще, Collapse схлопывает не только вершины друг с дружкой, но и рёбра, грани, многоугольники и элементы, при этом всё схлопывается в одну вершину, как коллапс чёрной дыры.
Выделим все рёбра, которые мы только что создали (только видимые) и подвинем их ближе к задней части туловища. Можно, конечно, было бы сразу прорезать шов в том месте, куда мы его передвинули только сейчас, но тогда бы у нас остались лишние вершины на центре спины и живота, и от них пришлось бы избавляться отдельно.
Теперь создадим ноги и уши при помощи операций Extrude. При создании ушей в промежутках можно поворачивать, масштабировать и перемещать многоугольники при помощи инструментов вращения, перемещения и масштабирования, (можно вместо этого оперировать с отдельными рёбрами и вершинами этих многоугольников), чтобы создать нужный наклон для экструзии и нужные размеры промежуточного многоугольника.
Рис. 11.14. Заготовка. |
И вот у нас в итоге получился какой-то монстр (рис. 11. 14). Конечно, для того, чтобы собака приобрела более привлекательный вид, с ней надо работать дальше, придавать форму телу при помощи трансформаций граней, рёбер и вершин, как по отдельности, так и группами, добавляя и убирая детали при помощи описаных здесь методов. Это всего лишь пример, который иллюстрирует методы эффективного моделирования, при котором мы не нуждаемся в том, чтобы создавать подобъекты вручную.
Даже если не создавать новых деталей, а просто подкорректировать уже созданные подобъекты путём перемещения вершин, можно получить такую модель:
Рис. 11.15. Низкополигональная модель собаки. (Здесь файл, 3ds MAX 6) |
Здесь к тому же был выделен весь элемент и поднят вверх так, чтобы лапы стояли на уровне приблизительно z=0.
Такие модели называют низкополигональными, или Лоу-поли (Low-Poly), что означает, что в модели задействовано мало многоугольников. Грань между лоу-поли и не лоу-поли провести довольно трудно, но если угловатость достаточно ощутима, а многоугольники достаточно велики, можно считать модель лоу-поли. Высокополигональные модели High-poly можно получить из относительно простых лоу-поли моделей. Но, следует иметь ввиду, если вы хотите изобразить не игрушку, а модель реального живого существа, то потребуется проработка большего количества деталей. В случае рисования человека надо очень детально проработать лицо. Все бугорки и неровности, которые вы так или иначе хотите отобразить, необходимо прорисовать. Но не стоит добавлять детали специально для предания гладкости. Сделать модель гладкой можно фактически в одно действие и не следует заниматься этим вручную. Подробнее мы об этом узнаем, когда будем рассматривать модификаторы.
Стоит отметить, что часто подобъекты удобно перемещать не по одному, а сразу группами, и при этом удобно работать в разных видах. Например, сделать ноги не такими вытянутыми вдоль туловища было удобно в виде слева, где выделялся сразу весь столбец вершин задней или передней стороны каждой из лап, а потом весь этот массив передвигался в нужном направлении.
Когда мы посчитаем, что создание и редактирование нашей модели завершено, можно будет присоединить одну половинку к другой при помощи Attach. Только учтите, что она не сможет быть присоединена до тех пор, пока является instance илт reference нашей первой половины. Перед присоединением надо сделать её независимой при помощи действия make unique. После того, как мы выполним Attach, надо перейти в режим работы с вершинами, выделить все вершины по центру в месте разреза и сделать для них Weld. Если мы следили во время редактирования, чтобы все вершины на линии разреза имели координату по x строго равную нулю, то значение Weld Treshold (не подписанное поле напротив кнопки Selected в подгруппе Weld) может быть сколь угодно малым. Вообще, если модель достаточно сложна, то его и следует выставлять по минимуму, чтобы у нас случайно не слиплись те вершины, которые мы не хотели бы слеплять.
Вообще, пока не следует этого делать, ведь наша модель ещё далека до совершенства, даже если считать её лоу-поли. К тому же, в версиях 3ds MAX 5 и выше есть более удобный и изящный способ для того, чтобы отразить имеющуюся половинку и создать симметричную модель.
Некоторые вещи для mesh-объектов мы ещё не рассмотрели, но обязательно рассмотрим после того, как ознакомимся со следуюищм типом объектов: Poly (полигональные объекты). Дело в том, что у Mesh и Poly много общего, поэтому нет смысла рассматривать это общее по отдельности. Здесь мы позволим себе рассмотреть ещё группы сглаживания, поскольку они нам скоро уже понадобятся.
Примечание: Ещё раз стоит вспомнить про режим вращения вида , который позволяет вращаться вокруг выделенного подобъекта, то есть точки, грани или ребра. Для того, чтобы такое вращение было возможным, надо находиться в режиме работы с подобъектами, иначе вращение будет происходить вокруг выделенного объекта.
И заканчивая эту главу следует ещё немного сказать про Extrude и Chamfer.
Chamfer работает с вершинами и рёбрами. Как он работает с вершинами мы видели, с рёбрами он работает подобным образом, только многоугольник получается не ромб, а немного более сложная фигура, в общем продолговатый шестиугольник.