Глубокое погружение в FBX

FBX (Filmbox) — формат хранения 3д-контента. Поддерживается всем современным софтом, например: Maya, Blender, 3ds Max, Houdini, Cascadeur. Является стандартом индустрии разработки игр. Этот формат разработала компания Autodesk.

Файлы FBX бывают разных версий: бинарные или ascii.

На практических примерах в Maya и Unreal Engine мы разберём внутреннее устройство ASCII-FBX и подумаем над оптимизацией моделей и анимаций. Как они влияют на производительность и итоговый размер проекта.

(Проблема: бинарный fbx - это черный ящик, и сложно сказать что внутри. Из-за лицензии GPL разработчикам софта не-Autodesk сложно реализовать полную поддержку. FBX из Блендера может не открываться в Майе и наоборот.)

FBX может хранить : геометрию (массивы вершин, нормалей, uv), анимацию (массивы костей и весов костей, блендшейпы), скелеты, настройки материалов, текстуры (jpg/png/tga), камеры, световые источники и многое другое.

## Часть 1: Анатомия FBX. Разбираем файл на примере простой геометрии

Создаем простой кубик в Maya, похожий на дом. Pivot в центре объекта, сам объект в нулевых координатах мира. История трансформации удалена.
Создаем простой кубик в Maya, похожий на дом. Pivot в центре объекта, сам объект в нулевых координатах мира. История трансформации удалена.

ASCII-FBX - это текстовый не сжатый формат. Простые Binary FBX обычно гораздо меньше по размеру, поэтому не нужно использовать ASCII-FBX формат в реальной разработке!

Экспорт из Maya в формате ASCII-FBX 2020
Экспорт из Maya в формате ASCII-FBX 2020

Получился файл SM_CubeLikeHouse.fbx - 19 Kb на жестком диске. Открываем его в текстовом редакторе Notepad++, видим 458 строчек. Файл по структуре чем-то напоминает json или xml.

Сам этот текстовый файл очень большой из-за технической избыточной информации, поэтому проматываем вниз. В разделе Objects была создана полигональная сетка (Geometry), состоящая из массива Вершин, Нормалей, из Материала со свойствами, Оси, Параметры Location, Rotation, Scale сцены и объекта и т.д.

Это наш Статический Меш (в терминологии Unreal Engine).

Глубокое погружение в FBX

Vertices и PolygonVertexIndex - это два массива, по которым собирается модель. Первый квад (4 вертекса соединенных гранями) рисуется по точкам 0, 1, 2, 4, второй квад рисуется по точкам 4, 5, 6, 7 и так далее. Но Анриал у нас рисует треугольниками, а не квадами. Поэтому Анриал будет брать для первого треугольника 0, 1, 2 вертексы, для второго треугольника 3, 4, 5 вертексы и так далее. Отображение полигональной сетки на экране называется Шейдинг.

Не весь софт работает как Майя или Анриал, иногда для отображения треугольников выбирается другой порядок вершин. Например, вы делали модель в Blender, развертку UV в Houdini, а текстурили в Quixel Mixer, возможны ошибки в наложении текстур и шейдинге. Чтобы избежать таких проблем желательно триангулировать модель до экспорта, и хранить 2 исходных версии модели - полигоны квадами и триангулированная.

Импортируем в Анриал 5.7.
Импортируем в Анриал 5.7.

По умолчанию сразу включилась поддержка Нанитов. Автоматически был создан простой материал с настройками из fbx-секции Material. Автоматически как-то была сделана не точная коллизия.

Глубокое погружение в FBX
Пивот в Майе был в центре объекта, поэтому в Анриале мы видим тоже самое.
Пивот в Майе был в центре объекта, поэтому в Анриале мы видим тоже самое.

В момент импорта в Анриал FBX был преобразован в формат UAsset - это бинарный формат Unreal Engine.

В этой полигональной сетке домика - 20 треугольников. В памяти Анриала 70.7 Кб, в то время как исходный ASCII-FBX весил 19 Кб.

Когда вы будете собирать (Build) проект, то все ассеты будут переупакованы в процессе подготовки ассетов Cooking (Кукинг, не переводится).

Глубокое погружение в FBX

Когда мы назначим материал, размер модели вырастет до 1.8 Мб.

Глубокое погружение в FBX

ASCII-FBX - 19 Кб
UAsset - 70.7 Кб

## Часть 2: Усложняем геометрию. Материалы, Vertex Color, Transform

Добавлены 3 материала - Body, Roof, Basement. Pivot НЕ в центре объекта, сам объект сдвинут относительно координат мира. История трансформации НЕ удалена. Добавлены Vertex Color на переднюю часть дома. 
Добавлены 3 материала - Body, Roof, Basement. Pivot НЕ в центре объекта, сам объект сдвинут относительно координат мира. История трансформации НЕ удалена. Добавлены Vertex Color на переднюю часть дома. 

Получился файл SM_CubeLikeHouse2.fbx размером 24 Кб. Если открыть его в текстовом редакторе, то обнаружим 412 строк.

Количество вершин увеличилось, и они все лежат одним массивом, потому что вся модель - единый неразрывный контур. Если бы части модели были отдельными мешами, то было бы несколько массивов и несколько секций Geometry.
Количество вершин увеличилось, и они все лежат одним массивом, потому что вся модель - единый неразрывный контур. Если бы части модели были отдельными мешами, то было бы несколько массивов и несколько секций Geometry.
Vertex Color находится в секции LayerElementColor. В одном массиве цвета, в другом массиве индексы вершин. Эта информация используется в шейдерах/материалах Анриала.
Vertex Color находится в секции LayerElementColor. В одном массиве цвета, в другом массиве индексы вершин. Эта информация используется в шейдерах/материалах Анриала.
В разделе Connections мы видим что материалы назначены на определенную полигональную сетку. Цвета из Майи тоже перенесутся.
В разделе Connections мы видим что материалы назначены на определенную полигональную сетку. Цвета из Майи тоже перенесутся.
При импорте в Анриал автоматически создались 3 материала, и вставились в Слоты Материала для нашего Статик Меша.
При импорте в Анриал автоматически создались 3 материала, и вставились в Слоты Материала для нашего Статик Меша.
Автоматически включились Наниты и сгенерирована Simple Collision физика.
Автоматически включились Наниты и сгенерирована Simple Collision физика.
Модель на сцене не удобно размещать из-за сдвинутого Пивота.
Модель на сцене не удобно размещать из-за сдвинутого Пивота.

ASCII-FBX - 24 Кб
UAsset - 78.7 Кб

## Часть 3: Физика в FBX. UBX (Collision) и сокеты (Socket)

Добавляем к этой модели UBX и UCX коллизию, и 3 именованных сокета.
Добавляем к этой модели UBX и UCX коллизию, и 3 именованных сокета.

Сокеты в Статик Меши можно добавить через любой легковесный объект, например, Локатор (Locator, иконка - снежинка). Разместить эти локаторы в 3д пространстве и сделать Пэрентами основного меша.

Эти объекты должны называться SOCKET_Какое-тоНазваниеСокета. И конечно же никакого русского языка и никаких спец-символов.

Simple Collision в Статик Меши так же вручную можно смоделировать и добавить. Иногда это проще, чем создавать коллизию в Анриале. Я использовал Box-форму и Convex-форму для сложного замкнутого контура крыши. Этим мешам желательно удалить UV.
Такие меши Должны называться UBX_ОригинальныйМеш_01, UBX_ОригинальныйМеш_02, UCX_ОригинальныйМеш_03. Теперь Анриал сможет автоматически загрузить эту коллизию.
Более детально можно прочитать в официальной документации:

Получился файл SM_CubeLikeHouse3.fbx размером 32 Кб.

В файле несколько разделов Geometry и теперь сложно разобраться, где какой меш.
В файле несколько разделов Geometry и теперь сложно разобраться, где какой меш.
В разделе Model мы видим как соотносятся идентификаторы полигональных сеток, их название и трансформация.
В разделе Model мы видим как соотносятся идентификаторы полигональных сеток, их название и трансформация.
Импорт в Анриал.
Импорт в Анриал.
Сокеты и коллизия автоматически импортировались.
Сокеты и коллизия автоматически импортировались.
Глубокое погружение в FBX

ASCII-FBX - 32 Кб
UAsset - 88.7 Кб

## Часть 4: Embed media

У модели 3 материала как и раньше. В 2 материала я добавил текстуры котиков. При экспорте из Майи я поставил галку на Embed Media. Текстуры теперь будут храниться в FBX контейнере.
У модели 3 материала как и раньше. В 2 материала я добавил текстуры котиков. При экспорте из Майи я поставил галку на Embed Media. Текстуры теперь будут храниться в FBX контейнере.

Получился файл SM_CubeLikeHouse4.fbx размером 164 Кб. В этом файлике всего 562 строчки, но появился блок с упакованными картинками.

Блок с текстурами называется Video - Clip =)
Блок с текстурами называется Video - Clip =)
При импорте в Анриал, текстуры импортировались из FBX-файла. На финальный размер модели внутри Анриала это никак повлияло. Отдельно модель и отдельно текстуры.
При импорте в Анриал, текстуры импортировались из FBX-файла. На финальный размер модели внутри Анриала это никак повлияло. Отдельно модель и отдельно текстуры.

Иногда удобны Embed Media встроенные в FBX. Например, в тех случаях, когда эту модель больше не нужно редактировать. Удобно такую модель загрузить на сайт Mixamo для поиска подходящих анимаций.

Иногда это не удобно, когда модель нужно доработать, перескинить, переделать Morph Target, или что-то еще.

## Часть 5: Скелет и анимация

Кости скелета управляют вершинами полигональной сетки - это скелетная анимация.

Скининг (Skinning, не переводится) - это процесс назначения костям (Bones) относительных весов (Weight) для трансформации вершин (Vertex).
Главная кость скелета обычно называется root (рут, не переводится).

Риг - это управляющая конструкция для скелета. Что-то вроде дополнительного упрощенного скелета, которым пользуются аниматоры. Риггинг (Rigging, не переводится) это процесс разработки управляющей конструкции.

Физические ассеты сейчас не переносятся из Майи в Анриал. Риги обычно остаются в программе моделирования и не экспортируются, а в Анриале создаются свои собственные риги.

Из Майи экспортирую 2 объекта - скелетную сетку (меш) и скелет (root - Body - Head). Экспорт со включенной галочкой Export Animations, иначе скелет не экспортируется.
Из Майи экспортирую 2 объекта - скелетную сетку (меш) и скелет (root - Body - Head). Экспорт со включенной галочкой Export Animations, иначе скелет не экспортируется.

SK_AnimatedCubeLikeHouse.fbx размером 28 Кб.

При импорте автоматически создался Physical Asset, Skeleton и Skeletal Mesh. 
При импорте автоматически создался Physical Asset, Skeleton и Skeletal Mesh. 

Мы можем вместе с моделью в одном FBX-файле хранить не только меш, скелет, но и анимацию, и даже десятки анимаций. Но лучше отдельно под каждую анимацию создавать отдельный FBX, без меша. Во-первых, это экономия места на диске, во-вторых, удобнее работать в командной разработке игры, в-третьих, редактирование 1 анимации в контейнере состоящем из 50 анимаций и меша - это адское мучение.

1 анимация = 1 файл.

Открываем FBX в текстовом редакторе.

Видим, что после описание вершин модели, появилась информация о Костях (LimbNode), Позе (Pose), Скининге (Deformer - Skin, Cluster).
Видим, что после описание вершин модели, появилась информация о Костях (LimbNode), Позе (Pose), Скининге (Deformer - Skin, Cluster).
<b>Для КАЖДОЙ кости</b> записана информация о весах (Weight) для определенных Индексов (Вершин)
Для КАЖДОЙ кости записана информация о весах (Weight) для определенных Индексов (Вершин)

В разделе Connections мы видим все объекты FBX-файла, и как они друг с другом связаны

Глубокое погружение в FBX

ASCII-FBX - 28 Кб
UAsset SKM - 98.8 Кб
UAsset Skeleton (3 кости) - 6.6 Кб

## Часть 6: Стандартный скелет Unreal Engine

Персонаж <b>Mannequin UE4</b> из проекта Game Animation Sample (Unreal Engine 5.7.3)
Персонаж Mannequin UE4 из проекта Game Animation Sample (Unreal Engine 5.7.3)

FBX -1 Мб
UAsset (меш) - 8.1 Мб
UAsset (68 костей) - 23.5 Кб

Меш с назначенным материалом и подключенным скелетом - Disk Size 16.4 Мб, Memory Size 11.6 Мб
Меш с назначенным материалом и подключенным скелетом - Disk Size 16.4 Мб, Memory Size 11.6 Мб
Второй стандартный персонаж - <b>Manny</b>
Второй стандартный персонаж - Manny

FBX - 3.2 Мб
UAsset (меш) - 18.9 Мб
UAsset (161 кость) - 215.2 Кб

Меш с назначенным материалом и подключенным скелетом - Disk Size 155.3 Мб, Memory Size 65.6 Мб
Меш с назначенным материалом и подключенным скелетом - Disk Size 155.3 Мб, Memory Size 65.6 Мб
Третий стандартный персонаж - <b>UEFN Mannequin</b>
Третий стандартный персонаж - UEFN Mannequin

FBX - 519 Кб
UAsset (меш) - 2.3 Мб
UAsset (88 костей) - 101.2 Кб

Меш с назначенным материалом и подключенным скелетом - Disk Size 7.1 Мб, Memory Size 9.2 Мб
Меш с назначенным материалом и подключенным скелетом - Disk Size 7.1 Мб, Memory Size 9.2 Мб

Сравним персонажей:
Персонаж - Mannequin - UEFN - Manny
Костей - 68 - 88 - 161
UAsset - 8.1 Мб - 2.3 Мб - 18.9 Мб
Memory - 11.6 Мб - 9.2 Мб - 65.6 Мб

В трипл-эй студиях, например, Epic Games или CD Project Red, могут себе позволить использовать высокополигональные меши. Например, вот персонаж Twin Blast из игры Paragon. В этом персонаже 204 кости, около 100к полигонов, и 15 слотов Материалов. Paragon - сетевая игра для консоли Play Station 4. Одновременно в этой игре было 10 таких высокодетализированных персонажей и эта игра не тормозила на старой консоли. Инди-разработчикам не всегда удается добиться такой оптимизации.

Глубокое погружение в FBX

## Часть 7: Анимация

Экспортирую из Анриала анимацию Slide для скелета UEFN

Глубокое погружение в FBX

FBX - 2.1 Мб
UAsset - 2.5 Мб
Frames - 300
Length = 10s
Frame Rate = 30

Disk Size = 2.6 Мб, Memory Size = 59.2 Кб
Disk Size = 2.6 Мб, Memory Size = 59.2 Кб
Анимация Slide открыта в Майе в редакторе Graph Editor
Анимация Slide открыта в Майе в редакторе Graph Editor

Выполняю упрощение кривых, удаление лишних ключей.

Импортирую анимацию обратно
Импортирую анимацию обратно
Disk Size = 2.1 Мб, Memory Size = 25.2 Кб
Disk Size = 2.1 Мб, Memory Size = 25.2 Кб

Это простой пример оптимизации уже оптимизированной анимации. Но если использовать Мокап-анимации, или анимации из Маркет-Плейсов, то могут быть сильно не-оптимизированные, не синхронизированные по FPS анимации.

Итак, представим ситуацию, что вы разрабатываете игру, берете ассеты Мегасканс с миллионами полигонов, берете текстуры 8к, чтобы было красивее, и берете мокап-анимации для анимации моделей. Можно ли уложиться в целевой размер билда игры 40 Гб? Да, можно, только это сложно.

Меня на эту статью подтолкнуло видео от Sandfall Interactive на канале Unreal Engine:

14
22 комментария