Артефакты при импорте 3D моделей в игровые движки из 3D редакторов на примере Unity3D и Blender

Довольно часто в интернете встречаются вопросы создателей игр, которые в том или ином виде спрашивают: «После импорта 3D модели в Unity3D (Blender, Unreal Engine, Cinema 4D, 3d studio MAX и т.д.) вместо модели отображается не пойми что…», «Почему модель полупрозрачная?», «Мерцают части 3D модели», «Почему отображается только часть модели», «Импортировал модель в Unity, почему ее не видно?», «Почему созданная в 3D-редакторе модель и импортированная в UE4 отображается с какими-то глюками?», «В 3DS MAX модель отображается, а в Unity видна какая-то мешанина…»
А дело здесь, как правило, в направленных внутрь модели нормалях, т.е. модель или часть модели «вывернута наизнанку».

Contents

Проблемы с нормалями. Вывернутые наизнанку нормали 3D модели.

На рисунке слева показан импортированный в Unity5 персонаж с “правильным” направлением нормалей. Справа показана 3D-модель с вывернутыми внутрь модели нормалями. Представленный на данном рисунке персонаж был создан при помощи инструмента для создания трехмерных персонажей Makehuman. Makehuman относится к программному обеспечению с открытым программным кодом, распространяемым под лицензией AGPL3. Модели, созданные и экспортированные при помощи данного инструмента, распространяются под этой же лицензией, либо под лицензией CC0, что прописано в разделе License сайта, посвященного проекту Makehuman.
На рисунке слева показан импортированный в Unity5 персонаж с “правильным” направлением нормалей. Справа показана 3D-модель с вывернутыми внутрь модели нормалями. Представленный на данном рисунке персонаж был создан при помощи инструмента для создания трехмерных персонажей Makehuman. Makehuman относится к программному обеспечению с открытым программным кодом, распространяемым под лицензией AGPL3. Модели, созданные и экспортированные при помощи данного инструмента, распространяются под этой же лицензией, либо под лицензией CC0, что прописано в разделе License сайта, посвященного проекту Makehuman.

Посмотрите на изображение: слева изображена 3D-модель с нормалями, направленными наружу модели, а справа — внутрь нее. Рассматривая правую модель, можно увидеть, что поверхности с вывернутыми внутрь нормалями «тыльные поверхности модели» прозрачны для камер игровых движков, так что у модели справа мы видим зад модели (причем, во всех смыслах «зад»:-) ) сквозь ставшим прозрачным перед. В приведенном выше случае мы видим текстуру зада, пяток, ладоней, т.е. поверхности всех частей модели, находящихся на обратной стороне модели, и всех тех частей, что находятся внутри модели.

Направление нормалей 3D моделей

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

На рисунке оранжевым цветом показана плоскость с нормалями. Зеленым цветом показана область, в которой плоскость (поверхность модели) будет видима камерой игрового движка. В красной области плоскость будет прозрачна для камеры.
На рисунке оранжевым цветом показана плоскость с нормалями. Зеленым цветом показана область, в которой плоскость (поверхность модели) будет видима камерой игрового движка. В красной области плоскость будет прозрачна для камеры.

В отличие от игровых движков в 3D-редакторах, например, том же Blender’е или 3DS MAX’е, поверхности 3D-модели по умолчанию задается двусторонний шейдер, способный отображать как лицевую сторону модели, так и ее изнанку, причем, к примеру, все в том же Blender’е поверхность изнанки несколько темнее, чем лицевая сторона модели.

Слева на рисунке показана 3D-модель в Blender'е с нормалями, направленными наружу. У 3D-модели справа нормали направлены внутрь.
Слева на рисунке показана 3D-модель в Blender’е с нормалями, направленными наружу. У 3D-модели справа нормали направлены внутрь.

 

На этом рисунке показаны все те же две модели в Blender'е с включенным отображением нормалей. Видно, что у модели слева они направлены наружу, в то время как у модели справа нормали направлены внутрь.
На этом рисунке показаны все те же две модели в Blender’е с включенным отображением нормалей. Видно, что у модели слева они направлены наружу, в то время как у модели справа нормали направлены внутрь.

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

На данном рисунке часть нормалей модели слева вывернута внутрь, а часть наружу. У модели справа все нормали вывернуты наружу.
На данном рисунке часть нормалей модели слева вывернута внутрь, а часть наружу. У модели справа все нормали вывернуты наружу.

А вот так эти две модели выглядят в Unity5:

Импортированные модели из Blender в Unity3D. На рисунке вы можете заметить, что часть модели слева после импорта ее в Unity5 стала прозрачной (корпус меха, правая нога и т.д.). Также появились артефакты с нормалями (своеобразные затенения) на выхлопной трубе и дуле орудия.
Импортированные модели из Blender в Unity3D. На рисунке вы можете заметить, что часть модели слева после импорта ее в Unity5 стала прозрачной (корпус меха, правая нога и т.д.). Также появились артефакты с нормалями (своеобразные затенения) на выхлопной трубе и дуле орудия.

Итак, выяснив что именно приводит к появлению подобных артефактов и неправильному отображению моделей в игровых движках, перейдем к решению данной проблемы.
Как было показано выше, в программах для трехмерного моделирования модели по умолчанию отображаются независимо от того, в какую сторону смотрят нормали их поверхностей. Сделано это с той целью, чтобы 3D-художнику/моделлеру было удобно моделировать, поскольку ему при создании модели зачастую необходимо «залезть» внутрь своего творения, особенно в труднодоступные места сложных, например, высокополигональных моделей (high poly моделей), да и низкополигональные модели (low poly models) требуют не меньше внимания к деталям, расположению вершин, а также сетке моделей.

Внутри дредноута. На рисунке показан пример вида изнутри 3D-модели, когда 3D-артисту требуется получить доступ к труднодоступным местам, например, чтобы выделить несколько ребер для маркирования их в качестве шва uv-развертки модели, или, например, для добавления новых ребер или элементов 3D-модели.
Внутри дредноута. На рисунке показан пример вида изнутри 3D-модели, когда 3D-артисту требуется получить доступ к труднодоступным местам, например, чтобы выделить несколько ребер для маркирования их в качестве шва uv-развертки модели, или, например, для добавления новых ребер или элементов 3D-модели.

Вывернутые не в ту сторону нормали не всегда являются ошибкой в моделировании объекта. Зачастую возникает необходимость создать модель с нормалями, направленными внутрь модели. Примером моделей с вывернутыми внутрь нормалями являются, например, кубы, используемые в качестве скай-боксов (sky-boxes), внутренние поверхности стен комнаты, например, когда такие поверхности смоделированы отдельно от внешних поверхностей стен, фасадов и другие специфичные модели.

На рисунке: слева показана модель мира Саракш (слева), каким его видят герои фантастической повести "Обитаемый остров" братьев Стругацких "Трилогии Каммерера", т.е. вывернутым наизнанку, где материк и океаны расположены на внутренней поверхности сферы. Цитата из книги: "Во-первых, необычайно сильная рефракция непомерно задирала горизонт и спокон века внушала аборигенам, что их земля не плоская и уж во всяком случае не выпуклая – она вогнутая." Здесь для демонстрации мира Саракши материки и океаны взяты земные, хотя на Саракше наличествует лишь один материк. Справа показана наша с вами Земля. Я специально поместил оба "глобуса" чуть ниже плоскости, чтобы мир Саракш лучше воспринимался человеческим глазом в данном его виде.
На рисунке: слева показана модель мира Саракш, каким его видят герои фантастической повести «Обитаемый остров» братьев Стругацких «Трилогии Каммерера», т.е. вывернутым наизнанку, где материк и океаны расположены на внутренней поверхности сферы. Цитата из книги: «Во-первых, необычайно сильная рефракция непомерно задирала горизонт и спокон века внушала аборигенам, что их земля не плоская и уж во всяком случае не выпуклая – она вогнутая.» Здесь для демонстрации мира Саракш материки и океаны взяты земные, хотя на Саракше наличествует лишь один материк. Справа показана наша с вами Земля. Я специально поместил оба «глобуса» чуть ниже плоскости, чтобы мир Саракш лучше воспринимался человеческим глазом в данном его виде.

Под спойлером находится анимированный пример мира Саракш (слева) и нашей Земли (справа).

Саракш против Земли

На некоторых мобильных устройствах не поддерживается GIF-анимация, так что ниже представлено видео анимированного примера мира Саракш (слева) и нашей Земли (справа).

Такой подход оправдан для помещений/игрового окружения, внутри которых находится персонаж/камера, а разработчикам хочется оптимизировать сцену, например, им необходимо скрыть фасад дома, так чтобы видеокарта отрисовывала лишь внутреннее убранство комнаты, вместо того чтобы забивать память видеокарты элементами окружения, находящимися за пределами комнаты. Конечно, практически во всех игровых движках, не попадающие в область видимости камеры модели и модели, «спрятавшиеся» за другими объектами, не отрисовываются (а следовательно и не просчитываются) видеокартой. Однако не все игровые движки, особенно самописные и находящиеся в стадии активной разработки, имеют такое важное решение для отрисовки только видимых камерой объектов, называемое Occlusion Culling. Иногда и профессиональные инструменты для создания игр не поддерживают такую “фичу”, или такой нужный и важный вариант вырезается разработчиками, как, например, в инди-версии Unity 4.6 и ниже. В игровом движке Unity3D версии 4.6 и ниже, чтобы иметь возможность воспользоваться благами Occlusion Culling, необходимо было купить PRO версию движка либо придумывать свои решения, или использовать готовые решения сторонних разработчиков.
Но вернемся к нашим прозрачным и неверно отображаемым импортированным моделям.

Как исправить нормали 3D модели в Unity3D? Как вывернуть нормали? Далее рассматривается несколько способов исправления нормалей моделей.

Одним из способов исправить отображение модели в игровом движке является использование на модели материала c двусторонним шейдером:

 

 

На данном рисунке показан результат применения на отличающихся лишь направлениями нормалей 3D-моделях персонажей стандартного шейдера "Standard" Unity 5 (вверху) и двустороннего шейдера (внизу), код которого приведен выше. Со светом у модели с вывернутыми внутрь нормалями не все складывается хорошо, хотя моделт слева и справа отличаются лишь шейдерами и направлением нормалей, больше ничего не менялось.
На данном рисунке показан результат применения на отличающихся лишь направлениями нормалей 3D-моделях персонажей стандартного шейдера «Standard» Unity 5 (вверху) и двустороннего шейдера (внизу), код которого приведен выше. Со светом у модели с вывернутыми внутрь нормалями не все складывается хорошо, хотя моделт слева и справа отличаются лишь шейдерами и направлением нормалей, больше ничего не менялось.

Исправить отражение света у правой модели с примененным двусторонним шейдером можно, если флипнуть/вывернуть нормали модели через изменение шейдера или скрипт:

На рисунке показана 3D модель персонажа с вывернутыми наружу нормалями при помощи скрипта (справа).
На рисунке показана 3D модель персонажа с вывернутыми наружу нормалями при помощи скрипта (справа).

Такой способ подходит, если вывернуты «не в ту сторону» все нормали 3Д модели. Если же вывернуты нормали только части полигонов, то такой способ не поможет.

Вторым способом решения проблемы с нормалями является использование шейдера для листьев. Подвигав регуляторы/ползунки настроек параметров шейдера, вы сможете добиться более-менее приемлемого результата.

Выглядят модели слева и справа одинаково (можете сами проверить), вот только реалистичность материала хромает. Для рисованного контента, возможно, и сойдет, но не для реалистичных персонажей игр AAA класса. Такой шейдер придется дописывать самому, чтобы текстура стала похожа на настоящую кожу.
Выглядят модели слева и справа одинаково (можете сами проверить), вот только реалистичность материала хромает. Для рисованного контента, возможно, и сойдет, но не для реалистичных персонажей игр AAA класса. Такой шейдер придется дописывать самому, чтобы текстура стала похожа на настоящую кожу.

Следующим способом является изменение параметров Отсечения путем добавления строки “Cull off” в код используемого на модели шейдера, например, в Standard Surface Shader.

 

Вместо параметра off функции Cull можно задать параметры Back или Front. Более подробно об Отсечении и показе «отвернувшихся» от камеры полигонов можно почитать на странице Shader Lab: Culling & Depth Testing сайта Unity3D.

На рисунке показан момент создания Standard Surface Shader’а и результат его применения на моделях с дописанной строкой “Cull off” в код шейдера. Не сложно заметить, что и в этом случае с освещением модели с вывернутыми внутрь нормалями (справа) не все так гладко.
На рисунке показан момент создания Standard Surface Shader’а и результат его применения на моделях с дописанной строкой “Cull off” в код шейдера. Не сложно заметить, что и в этом случае с освещением модели с вывернутыми внутрь нормалями (справа) не все так гладко.

 

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

Исправление/выворачивание нормалей модели в 3D редакторах на примере Blender 3D

Чтобы вывернуть нормали в нужную сторону, в Blender’е достаточно выбрать модель Правой Кнопкой Мыши, перейти в режим редактирования меша, нажав клавишу ‘Tab’, после чего выбрать все вершины модели через нажатие клавиши ‘A’ (один или два раза) и нажать сочетание клавиш Ctrl+N.

На рисунке изображены исходная модель в режиме объекта с вывернутыми внутрь нормалями, модель в режиме редактирования меша и конечный результат (модель в режиме объекта) после выворачивания нормалей наружу.
На рисунке изображены исходная модель в режиме объекта с вывернутыми внутрь нормалями, модель в режиме редактирования меша и конечный результат (модель в режиме объекта) после выворачивания нормалей наружу.

Если описанный способ не помог вывернуть нормали и модель осталась в первоначальном виде, значит стоит попробовать вывернуть нормали ‘внутрь’, также в режиме редактирования меша выбрав все вершины/полигоны вашей модели (клавиша ‘A’) и нажав комбинацию клавиш Ctrl+Shift+N. В некоторых случаях программы 3D-моделирования принимают за лицевую сторону модели совсем не ту поверхность, которую хотелось бы вам. Так, например, для упомянутого выше скай-бокса, который представляет собой куб, Blender посчитает нормали наружу, поскольку он для него — всего лишь куб, а значит согласно алгоритму Blender’а его нормали плоскостей/ребер/вершин должны смотреть наружу. Но ведь у скай-бокса нормали должны быть направлены внутрь него самого, чтобы, находясь внутри него, вы смогли видеть то, что отображается на его внутренних поверхностях (небо, удаленный и недостижимый город и т.д.).

Здесь была рассмотрена модель состоящая из одного меша, монолитная модель. Далее мы рассмотрим, что же делать, если 3D-модель состоит из нескольких объектов или нескольких мешей, объединенных в один объект.

Показанный выше способ был рассмотрен для целостной/монолитной модели, однако очень часто модель (особенно неодушевленные предметы: мебель, роботы, механизмы, автомобили…) бывает разделена на несколько частей, причем существуют два варианта разделения: части объекта разделены на уровне объектов и на уровне мешей.
В первом случае (монолитной модели) при выборе модели в объектном режиме Правой Кнопкой Мыши будет выбрана вся модель целиком, что показано на рисунке ниже.

Модель справа (как вы уже, наверное, догадались, с вывернутыми внутрь нормалями) представляет собой модель, все части которой объединены на уровне мешей (в Blender’e объединение/слияние объектов выполняется посредством последовательного выбора двух и более объектов и нажатия сочетания клавиш Ctrl+J), так что при выборе ее Правой Кнопкой Мыши она ВСЯ будет обведена желтым или оранжевым контуром. У средней модели, состоящей из нескольких объектов, выбраны ноги, а у правой - лишь корпус меха. Оранжевый контур в отличие от желтого контура, которым обводятся модели при их выборе, означает, что вами был осуществлен выбор нескольких моделей.
Модель справа (как вы уже, наверное, догадались, с вывернутыми внутрь нормалями) представляет собой модель, все части которой объединены на уровне мешей (в Blender’e объединение/слияние объектов выполняется посредством последовательного выбора двух и более объектов и нажатия сочетания клавиш Ctrl+J), так что при выборе ее Правой Кнопкой Мыши она ВСЯ будет обведена желтым или оранжевым контуром. У средней модели, состоящей из нескольких объектов, выбраны ноги, а у правой — лишь корпус меха. Оранжевый контур в отличие от желтого контура, которым обводятся модели при их выборе, означает, что вами был осуществлен выбор нескольких моделей.

Во втором случае (составной модели из нескольких моделей/объектов) части модели разделены на несколько частей на уровне объекта, т.е. являются автономными/независимыми моделями (объектами). В этом случае Правой Кнопкой Мыши вы можете выделить конкретную часть модели, например, рюкзак персонажа, манипулятор робота или корпус робота. На рисунке выше корпус самого левого меха представляет собой отдельный объект, не связанный с орудиями, ногами и другими элементами, поэтому желтым контуром выделен только сам корпус. Средняя модель меха ничем не отличается от меха слева (нормали сейчас в расчет не берем), на ней лишь показано, что ноги также являются отдельным объектом.

Как исправить нормали у монолитной/целиковой 3D модели?

Рассмотрим первый случай, когда меши объединены на уровне объектов, так что при выборе модели в объектном режиме выбирается вся модель целиком, а вам необходимо выбрать лишь составной меш модели и, например, изменить для него направление нормалей. Чтобы вывернуть нормали «в нужную сторону» у части такой модели, необходимо в режиме объекта выбрать саму модель Правой Кнопкой Мыши и перейти в режим редактирования меша (клавиша ‘Tab’), после чего отменить выбор всех вершин/полигонов/ребер модели, нажав клавишу ‘A’ (один или несколько раз, в зависимости от того была ли до этого выбрана хотя бы одна вершина меша, или нет). После того как вы отмените выбор всех вершин/полигонов/ребер модели, вы можете выбрать отдельный составляющий модель меш.

На рисунке в режиме редактирования меша показан меш, у которого не выбрано ни одной вершины (слева), и меш со всеми выбранными вершинами (справа). На данном рисунке минимальной единицей редактирования меша является вершина. Однако меш можно редактировать не только в режиме вершин, но и в режиме ребер и поверхностей/полигонов, переключение между которыми осуществляется посредством сочетания клавиш Alt+Tab; после чего в открывшемся меню Режима Выбора Меша можно выбрать режим, в котором вы будете редактировать свой меш. О режиме редактирования меша в режиме поверхностей мы расскажем ближе к концу статьи.
На рисунке в режиме редактирования меша показан меш, у которого не выбрано ни одной вершины (слева), и меш со всеми выбранными вершинами (справа). На данном рисунке минимальной единицей редактирования меша является вершина. Однако меш можно редактировать не только в режиме вершин, но и в режиме ребер и поверхностей/полигонов, переключение между которыми осуществляется посредством сочетания клавиш Alt+Tab; после чего в открывшемся меню Режима Выбора Меша можно выбрать режим, в котором вы будете редактировать свой меш. О режиме редактирования меша в режиме поверхностей мы расскажем ближе к концу статьи.

Стоит отметить, что рассматриваемый случай не относится к монолитным моделям, упомянутым ранее (та же модель человека, если не брать в расчет глаза), когда все вершины модели принадлежат одному мешу. Меш здесь — связанный между собой набор вершин, как ноды одного графа (по сути, меш модели может быть представлен в виде графа, а сама составная модель в виде нескольких графов).
Вернемся к выбору части модели, а точнее, выбору отдельного меша. Теперь необходимо выбрать части модели, направление нормалей которых необходимо подкорректировать. Чтобы выбрать отдельную несвязанную часть модели в Blender’е переместите курсор мыши поверх целевой части модели и нажмите клавишу ‘L’. Теперь осталось лишь вывернуть нормали выбранной части модели — меша — посредством упомянутого сочетания клавиш Ctrl+N (или Ctrl+Shift+N).

На рисунке показан мех без развертки: а) в левой части рисунка корпус меха выбран для исправления нормалей; б) в правой части рисунка показан мех, нормали корпуса которого были вывернуты наружу путем применения пересчета нормалей наружу (Ctrl+N).
На рисунке показан мех без развертки: а) в левой части рисунка корпус меха выбран для исправления нормалей; б) в правой части рисунка показан мех, нормали корпуса которого были вывернуты наружу путем применения пересчета нормалей наружу (Ctrl+N).

На рисунке ниже показан альтернативный способ пересчета нормалей (выворачивания в нужную сторону) без использования ‘горячих клавиш’ в Blender’е.

Чтобы пересчитать нормали наружу или внутрь или инвертировать их, вы можете зайти в меню Mesh,расположенное под окном 3D-вида, выбрать вкладку ‘Normals’ и затем нужное вам в данный момент действие: Пересчитать нормали наружу (Recalculate Outside), Пересчитать нормали внутрь (Recalculate Inside) или Инвертировать нормали (Flip normals).
Чтобы пересчитать нормали наружу или внутрь или инвертировать их, вы можете зайти в меню Mesh,расположенное под окном 3D-вида, выбрать вкладку ‘Normals’ и затем нужное вам в данный момент действие: Пересчитать нормали наружу (Recalculate Outside), Пересчитать нормали внутрь (Recalculate Inside) или Инвертировать нормали (Flip normals).

Упомянутая в описании рисунка опция Инвертирования нормалей («Флипа» нормалей) отличается от Пересчета нормалей наружу и Пересчета нормалей внутрь тем, что после применения данной опции все нормали пересчитаются в противоположную сторону, т.е. вывернутые наружу нормали пересчитаются внутрь, а вывернутые наружу — внутрь. Пример использования Инвертирования/Обращения нормалей показан на рисунке ниже:

На рисунке: слева показан мех, у которого нормали правой части вывернуты внутрь, а левой части наружу, до использования инструмента 'Flip normals' в Blender'е. Справа показан тот же мех после Инвертирования нормалей меша. Как видно на рисунке 'Flip normals' не всегда спасает, особенно он не спасает в тех случаях, когда у модели часть нормалей подсчитана внутрь 3D-модели, а часть - наружу. "Флип" нормалей обычно используется на меше и оказывается полезен, когда все нормали меша подсчитаны внутрь него или наружу
На рисунке: слева показан мех, у которого нормали правой части вывернуты внутрь, а левой части наружу, до использования инструмента ‘Flip normals’ в Blender’е. Справа показан тот же мех после Инвертирования нормалей меша. Как видно на рисунке ‘Flip normals’ не всегда спасает, особенно он не спасает в тех случаях, когда у модели часть нормалей подсчитана внутрь 3D-модели, а часть — наружу. «Флип» нормалей обычно используется на меше и оказывается полезен, когда все нормали меша подсчитаны внутрь него или наружу

Здесь стоит отметить, что при наличии у модели развертки и выборе части модели посредством клавиши ‘L’, могут выбираться части модели, ограниченные швами (seams) развертки, а не весь меш целиком. Такие части модели называются островами развертки. Остров представляет собой набор вершин/плоскостей лежащих в пределах одного замкнутого шва развертки. Чтобы сменить режим выбора меша, нажмите клавишу ‘T’, чтобы открыть панель инструментов в правой части окна 3D-вида, и выберите меш, нормали которого вы хотите вывернуть/пересчитать. В левой части панели инструментов которую вы только что открыли вы увидите меню Выбора Связанных частей меша (Select Linked), по сути позволяющий выбирать на основании какого типа связи будет происходить выбор частей меша. Выберите ‘Normal’, чтобы выбирать отдельные меши, а не острова развертки, критерием которых выступают швы развертки (Seam).

На рисунке показана ситуация, когда при выборе меша посредством кнопки ‘L’, выбирается остров развертки, а не меш целиком. Решением данного затруднения является выбор кнопки ‘Normal’ в меню Выбора Связанных частей меша (Select Linked) вместо ‘Seam’. Меню Select Linked показывается в меню инструментов, которое вы можете открыть, нажав клавишу 'Tab' или нажав на кнопку с плюсиком в левом верхнем углу окна 3D-вида и переместив мышь вправо.
На рисунке показана ситуация, когда при выборе меша посредством кнопки ‘L’, выбирается остров развертки, а не меш целиком. Решением данного затруднения является выбор кнопки ‘Normal’ в меню Выбора Связанных частей меша (Select Linked) вместо ‘Seam’. Меню Select Linked показывается в меню инструментов, которое вы можете открыть, нажав клавишу ‘Tab’ или нажав на кнопку с плюсиком в левом верхнем углу окна 3D-вида и переместив мышь вправо.

На рисунке показана ситуация, когда при выборе меша посредством кнопки ‘L’, выбирается остров развертки, а не меш целиком. Решением данного затруднения является выбор кнопки ‘Normal’ в меню Выбора Связанных частей меша (Select Linked) вместо ‘Seam’. Меню Select Linked показывается в меню инструментов, которое вы можете открыть, нажав клавишу ‘Tab’ или нажав на кнопку с плюсиком в левом верхнем углу окна 3D-вида и переместив мышь вправо.

Еще одним камнем преткновения являются продублированные вершины модели или ее части целиком, вследствие, например, применения модификатора Edge Split или особенностей импорта/экспорта моделей, что можно решить топорным способом, выделив все вершины/плоскости модели и в открывшемся меню Вершин нажав сочетание клавиш Alt+V, после чего выбрав Remove doubles. Данный инструмент позволяет удалить вершины-дубли и, в частности, нежелательное подразделение модели на несколько мешей. Но будьте осторожны, вы можете слить вершины, которые должны «жить» сами по себе, просто они стоят в одних и тех же координатах или совсем рядом. Более подробно решение данного вопроса мы постараемся рассмотреть в отдельной статье.
Если при помощи клавиши ‘L’ с включенным режимом выбора связанных частей меша ‘Normal’ выбирается вся модель целиком, значит у нее нет составных частей и она создана единым мешем (та самая монолитная модель, с которой мы познакомились выше). В том случае, если нормали модели так и не вывернулись в требуемую сторону, следует проверить наличие в модели паразитных ребер и полигонов, которые могут влиять на то, какую сторону Blender считает лицевой, и избавиться от них. Более подробно мы также постараемся рассмотреть эту проблему в отдельной статье. Если полигонов-паразитов и ребер-паразитов не обнаружено, значит автоматическое назначение направления нормалей обусловлено строением модели и вам придется выбрать необходимые полигоны вручную и вывернуть их нормали в нужную вам сторону. Чтобы выбрать полигоны с «неправильными» нормалями, вы можете выбрать все вершины, составляющие эти полигоны, посредством Правой Кнопки Мыши, либо сразу перейти в режим редактирования полигонов меша и выбрать полигоны с неправильно ориентированными полигонами. Чтобы перейти в режим редактирования полигонов меша, необходимо, находясь в режиме редактирования меша (все та же клавиша ‘Tab’), нажать сочетание клавиш Alt+Tab и в открывшемся меню ‘Mesh Select Mode’ выбрать ‘Face’ (Поверхность).

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

Для того, чтобы выбрать требуемые для пересчета нормалей поверхности нажмите клавишу ‘B’ (которая запускает инструмент прямоугольного выделения) и, удерживая Левую Кнопку Мыши и перемещая мышь, выделите нужные вам полигоны. Отпустив Левую Кнопку Мыши вы подтвердите сделанный вами выбор. Отменить последнее действие в Blender’е вы можете посредством сочетания клавиш Ctrl+Z. Выбрав требуемые полигоны пересчитайте их нормали внутрь или наружу, как было описано выше. Если вы выбрали излишние полигоны, то отменить выбор отдельно взятого полигона вам поможет сочетание клавиши ‘Shift’ и Правой Кнопки Мыши. Если же вы войдете в режим выделения прямоугольной областью (‘B’) и удерживая клавишу ‘Shift’ обведете выделенные полигоны, то вы сможете снять выделение с данных полигонов.

Еще один способ выделения полигонов, ребер или вершин доступен через клавишу ‘C’, которая открывает инструмент выделения окружностью. Нажмите клавишу ‘C’ и, удерживая Левую Кнопку Мыши, проведите курсором мыши поверх полигонов, которые хотите выделить. Размер захватываемой курсором области (окружности вокруг курсора) регулируется колесиком мыши. Чтобы подтвердить выделение, нажмите клавишу ‘Enter’. Обратите внимание, что Shift работает и с этим инструментом выделения.

Выворачиваем нормали/инвертируем направление нормалей модели, состоящей из нескольких 3D объектов

Теперь рассмотрим второй случай, когда модель представлена разрозненными объектами. Здесь никаких отличий от способа выворачивания нормалей, описанного выше, например, для монолитной модели или модели, состоящей из нескольких объединенных в один объект мешей 3D-модели, не наблюдается, поскольку отдельно взятый составной объект является независимым от других. Однако модель, состоящая из нескольких независимых объектов и экспортированная для использования в игровом движке Unity3d (или UE4), обладает рядом особенностей, крайне полезных для механических объектов, например, роботов, или предметов интерьера, таких как шкафы, столы и т.д., а также для создания разрушаемого окружения. Почему? Потому что после импорта таких моделей все независимые объекты остаются независимыми друг от друга объектами, являясь лишь детьми родителя-пустышки.

На рисунке показанный в Иерархии объект ‘robo_47_forLegsExportToEggs_forarticle…’ является объектом-пустышкой и по совместительству родителем, детьми которой являются все составные части показанного меха. Я перетащил объект ‘Cube.002’ на объект ‘Cube.029’, чтобы сделать последнего родителем для ‘Cube.002’. Ребенок сохраняет смещение (offset) и ориентацию относительно родителя, как бы вы не перемещали и не вращали этого самого родителя. На рисунке видно, что я повернул корпус меха (орудия, являясь дочерними к корпусу объектами, поворачивались вместе с корпусом меха), после чего повернул сами орудия, нацелив их в небо. Изменение положения и ориентации (перемещение, вращение) в пространстве дочернего объекта не влияет на объекты, являющимися его родителями, в то же время как операции вращения и перемещения над объектом-родителем передаются всем объектам, являющимися дочерними к нему.
На рисунке показанный в Иерархии объект ‘robo_47_forLegsExportToEggs_forarticle…’ является объектом-пустышкой и по совместительству родителем, детьми которой являются все составные части показанного меха. Я перетащил объект ‘Cube.002’ на объект ‘Cube.029’, чтобы сделать последнего родителем для ‘Cube.002’. Ребенок сохраняет смещение (offset) и ориентацию относительно родителя, как бы вы не перемещали и не вращали этого самого родителя. На рисунке видно, что я повернул корпус меха (орудия, являясь дочерними к корпусу объектами, поворачивались вместе с корпусом меха), после чего повернул сами орудия, нацелив их в небо. Изменение положения и ориентации (перемещение, вращение) в пространстве дочернего объекта не влияет на объекты, являющимися его родителями, в то же время как операции вращения и перемещения над объектом-родителем передаются всем объектам, являющимися дочерними к нему.

Зависимость между родительским и дочерним объектом можно разорвать (как в редакторе Unity3D, так и посредством кода), если возникнет такая необходимость. Но самое главное заключается в том, что эти объекты можно перемещать, вращать посредством transform.position, transform.Translate, transform.rotation, transform.Rotate независимо друг от друга. Их можно делать родителями и детьми друг друга, либо уже упомянутой пустышки, которой в свою очередь также можно манипулировать, причем, как было сказано выше, при манипулировании родителем, дети сохраняют свое смещение/положение и ориентацию относительно родителя. Таким образом можно анимировать не особо сложные составные объекты средствами Unity, в редакторе, посредством кода, не прибегая для этого к анимации, созданной в 3D-редакторе.

На рисунке ниже показан способ анимирования лопастей винтов и дверей посредством арматуры, кости которой назначены винтам и дверям.

На рисунке показана импортированная в Unity3D 3D-модель вертолета с назначенной ей арматурой/скелетом. Записав последовательно анимацию для вращения винтов и открывания люков и экспортировав их одним или несколькими файлами, например, в формате FBX, можно анимировать их в Unity3D с использованием Mecanim или унаследованной системы анимации (Legacy). Для правильной, в данном случае зацикленной, анимации винтов в Unity3D первый и последний кадр созданной в Blender'е анимации должны совпадать, т.е. должно совпадать начальное и конечное положения винтов в первом и последнем кадре анимации. В некоторых случаях, наличие в анимации двух одинаковых кадров для первого и последнего кадра может привести к небольшой задержке в Unity3D, что решаемо путем использования в Mecanim на один-два-три кадра меньше, т.е. можно выбрать диапазон проигрывания импортированной в Unity3D анимации без скачков при переходе из последнего кадра анимации к первому. Если вы не хотите утруждать себя настройкой анимаций в Unity3D, вы можете создать анимацию, в которой бы положение винтов чуть-чуть не доходили бы до стартовой позиции винтов. Другим способом избежать настройки анимаций в Unity3D является возможность ограничить количество кадров анимации в самом Blender'е, чтобы положение винтов в последнем кадре анимации являлось предшествующим положению винтов в первом кадре анимации.
На рисунке показана импортированная в Unity3D 3D-модель вертолета с назначенной ей арматурой/скелетом.

Записав последовательно анимацию для вращения винтов и открывания люков и экспортировав их одним или несколькими файлами, например, в формате FBX, можно анимировать их в Unity3D с использованием Mecanim или унаследованной системы анимации (Legacy). Для правильной, в данном случае зацикленной, анимации винтов в Unity3D первый и последний кадр созданной в Blender’е анимации должны совпадать, т.е. должно совпадать начальное и конечное положения винтов в первом и последнем кадре анимации. В некоторых случаях, наличие в анимации двух одинаковых кадров для первого и последнего кадра может привести к небольшой задержке в Unity3D, что решаемо путем использования в Mecanim на один-два-три кадра меньше, т.е. можно выбрать диапазон проигрывания импортированной в Unity3D анимации без скачков при переходе из последнего кадра анимации к первому. Если вы не хотите утруждать себя настройкой анимаций в Unity3D, вы можете создать анимацию, в которой бы положение винтов чуть-чуть не доходили бы до стартовой позиции винтов. Другим способом избежать настройки анимаций в Unity3D является возможность ограничить количество кадров анимации в самом Blender’е, чтобы положение винтов в последнем кадре анимации являлось предшествующим положению винтов в первом кадре анимации.

На рисунке представлена анимация дверей вертолета, выполненная с использованием арматуры. Анимация создана лишь для открывания дверей. Анимация закрытия дверей реализована средствами Mecanim в Unity путем использования возможности проигрывания анимации в обратную сторону, просто выставив соответствующей анимации значение "-1" в соответствующем шаге аниматора. Система анимации Mecanim, включающая машину состояний для анимации (Animation State Machine), достойна отдельной серии статей, но много чего полезного и важного можно найти в руководстве Unity3D на странице, посвященной Машинам состояния анимаций. 

На рисунке представлена анимация дверей вертолета, выполненная с использованием арматуры. Анимация создана лишь для открывания дверей. Анимация закрытия дверей реализована средствами Mecanim в Unity путем использования возможности проигрывания анимации в обратную сторону, просто выставив соответствующей анимации значение «-1» в соответствующем шаге аниматора. Система анимации Mecanim, включающая машину состояний для анимации (Animation State Machine), достойна отдельной серии статей, но много чего полезного и важного можно найти в руководстве Unity3D на странице, посвященной Машинам состояния анимаций

На этом рисунке анимация лопастей винтов вертолета реализована посредством кода.
На этом рисунке анимация лопастей винтов вертолета реализована посредством кода.

 

Разрушаемые уровни и разрушаемое окружение в Unity3D и Blender 3D

Касательно разрушаемого окружения: вы можете создать и разделить стену на несколько объектов в 3D-редакторе, затем экспортировать их разом, все в том же FBX-формате, после чего импортировать в Unity. У вас получится стена, состоящая из отдельных объектов, которые можно в любой момент времени отделить от родителя (можно это сделать еще при формировании префаба участка стены) и отбросить в сторону, например, при столкновении со стеной автомобиля либо снаряда танка или гранатомета.

На рисунке: слева показана подготовленная секция стены для создания разрушаемого окружения, а справа - разбитая на куски эта же стена, т.е. на отдельные объекты (3D-модели). Поместив на сцену такую модель стены, состоящую из объектов, можно заставить эти куски стены разлетаться согласно вашим задумкам.
На рисунке: слева показана подготовленная секция стены для создания разрушаемого окружения, а справа — разбитая на куски эта же стена, т.е. на отдельные объекты (3D-модели). Поместив на сцену такую модель стены, состоящую из объектов, можно заставить эти куски стены разлетаться согласно вашим задумкам.

Импортировав подобную стену в Unity и добавив каждому независимому объекту коллайдер и Rigidbody, где требуется, вы можете заметно оживить свою игру.

Данный участок стены (или 5-7 ее копий, созданных в Unity3D) отлично разлетаются, если их использовать в стандартных ассетах Unity, где продемонстрированы различные взрывы, и можно, например, разрушить стену из стандартных кубов и т.д.
Данный участок стены (или 5-7 ее копий, созданных в Unity3D) отлично разлетаются, если их использовать в стандартных ассетах Unity, где продемонстрированы различные взрывы, и можно, например, разрушить стену из стандартных кубов и т.д.

Куски стены ведут себя ничуть не хуже стандартных кубиков Unity3D, используемых в упомянутых выше стандартных ассетах Unity3D или в ассете Detonator Explosion Framework

На этом рисунке показан подбитый мех, детали которого я разбросал по сцене вручную, однако ничто не мешает мне сделать то же самое, повесив на каждый объект меха Rigidbody, чтобы каждый кусок подбитого меха падал согласно законам физики. Обратите внимание, что ‘Cube.002’ больше не является дочерним объектом для ‘Cube.029’ Это можно увидеть в окне Иерархии (Hierarchy).
На этом рисунке показан подбитый мех, детали которого я разбросал по сцене вручную, однако ничто не мешает мне сделать то же самое, повесив на каждый объект меха Rigidbody, чтобы каждый кусок подбитого меха падал согласно законам физики. Обратите внимание, что ‘Cube.002’ больше не является дочерним объектом для ‘Cube.029’ Это можно увидеть в окне Иерархии (Hierarchy).

Такой подход отлично подойдет и к управлению танком, как в целом, так и его составными частями: пушкой танка (орудием), башней, гусеницами, люками и чем-нибудь еще.

Также стоит отметить, что подобный подход позволяет использовать для каждого объекта отдельный материал. В этом есть свои плюсы и свои минусы. К минусам можно отнести то, что отдельный материал требует под себя ресурсы, к минусам — то, что у каждого материала могут быть свои характеристики прозрачности, отражения и т.д., так, один объект модели может быть хромированным, второй — деревянным, третий — стеклянным, четвертый — листом дерева и т.д. со своими настройками материала, шейдерами, картами отражений и так далее.
Еще одним недостатком отдельных объектов является то, что у каждого из них существует своя собственная uv-развертка, и, как, правило, своя текстура, что также потребляет ресурсы компьютера. Правда, назвать отдельную развертку для каждой модели совсем уж прям недостатком язык не поворачивается. Также стоит отметить, что каждой такой отдельной развертке модели (и самой модели) соответствует своя текстура, которые могут быть объединены в одну, например, посредством атласа текстур.

Полагаю, что создание вертолета/коптера или танка и управление ими в Unity станет темой одной из следующих статей.

В данной статье говорилось о том, что модели экспортируются из Blender’а и затем импортируются в Unity3D в форматах FBX, однако все выше сказанное подходит и к моделям в форматах OBJ и других. Более подробно про экспорт 3D моделей без ошибок и исправление возникших проблем при импорте 3D моделей в игровые движки класса AAA, такие как Unity3D, Unreal Engine, Amazon Lumberyard и другие, вы можете узнать в статье-уроке Экспорт 3D моделей из Blender в игровые движки Unity3D и Unreal Engine и подготовка моделей к экспорту. Также вы можете импортировать в Unity3D нативные форматы 3D-редакторов: .blend, .max, .mb, .ma и другие, поскольку Unity3D отлично понимает их. Использование нативных форматов в Unity позволяет редактировать модели в 3D-редакторе и практически сразу (конечно, после сохранения в 3D-редакторе) видеть в Unity3D изменения, которые вы внесли в свою модель. Более подробно о форматах, читаемых Unity3D, можно посмотреть на официальном сайте Unity3d в статье руководства 3D-форматы.

Помимо упомянутых в данной статье вопросов неправильного отображения модели и их решения, остались не охваченными вопросы из серии: «Почему нет текстур на модели?», «Почему меня вся модель розовая?» «На модели нет текстуры, она — белая (серая, темная, черная). Где текстура», «Почему у меня текстура наложилась криво?», “Я в Blender’е наложил текстуру, а она не перенеслась вместе с экспортированной, а затем импортированной в Unity3D моделью. Что я делаю не так?” “Как перенести текстуру и материал из Blender’а в Unity?” «Сделал в Blender’е развертку. Экспортировал модель в Unity5, а текстура размножилась на модели. Почему текстура не легла на модель, как нужно?», «Почему созданные материал и текстура в Cycles Blender’а не видны в Unity3D?», «Почему текстура головы модели съехала на ноги?»
Эти вопросы рассмотрены в отдельной статье Ошибки в отображении 3D моделей в Unity 3D. Розовый, черный, белый цвет 3D модели в Unity. Проблемы с материалами, шейдерами, uv разверткой и кешем.

Автор: Максим Голдобин (aka MANMANA)

goldmaxval@gmail.com

2 Comment

  1. Дмитрий says: Ответить

    Огромное спасибо за статью! Всё разжевано и в рот положено, а главное объясняется почему, то есть автор ссылается на основы компьютерной графики. Мне, как новичку, сразу захотелось попробовать все из вышеперечисленных вкусностей-возможностей!

    1. Maxim Goldobin says: Ответить

      Спасибо, Дмитрий, за отзыв, еще один полноценный новый урок по 3D в Blender вы можете посмотреть по данной ссылке Ассет для Unity 3D. Моделирование 3D модели для Unity3D в Blender.
      В этих тринадцати частях урока я постарался показать основы 3D моделирования, а также альтернативные способы создания 3Д моделей для игровых движков, в частности.

Добавить комментарий