понедельник, 5 марта 2012 г.

Экспорт 3d моделей в бинарный формат из COLLADA с использованием Open Asset Import Library.

Некоторые размышления о разработке формата 3d файла, а так же пример экспортера на C#.

Введение.

Вообще существует несколько подходов к транспортировке данных о 3d моделях в свое приложение:
  • Использование существующих форматов. Например, 3ds, SMD, LWO и т.д. К плюсам можно отнести наличие хорошо отлаженных средств экспорта из пакетов моделирования, задача сводится лишь к написанию импортера. Минусы - форматы могут быть очень специфичны, избыточны и просто неудобны. За примерами далеко ходить не надо: 3ds (избыточность, сложность, ограничение на длину имени текстуры в 8 символов) , SMD (вообще текстовый) и т.д. Еще один существенный минус общераспространенных форматов - данные геометрии не годятся для использования с VBO без предварительной обработки. Я не припомню ни одного распространенного формата, данные о геометрии в котором, готовы для заливки в массивы OGL. Хотя, возможно, MD5, но я с ним не разбирался.
  • Написание плагинов\скриптов к пакетам моделирования. К плюсам можно отнести возможность экспорта пользовательских данных, например информации о физических свойствах коллайдеров (так, как я понимаю сделано в Oblivion).
  • Использование данных в формате COLLADA как промежуточных с последующей сборкой интересующих данных в бинарник. Это достаточно интересный подход. Позволяет работать с образом сцены, экспортированной из пакета моделирования с использованием своих любимых инструментов (Delphi, c++, c# ...). Имея толковый парсер XML, разбор производить достаточно просто. Однако, проблема с негодностью данных для использования в VBO актуальна и здесь.
  • Использование данных сцены в формате FBX как промежуточных. Подход похож на предыдущий, за тем лишь исключением, что FBX - закрытый формат. Для его разбора существуют инструменты под c++.
Я в свое время потратил много времени (и некоторое количество сил) на поиски и тестирование различных способов. В конце концов я случайно наткнулся на Assimp - библиотеку импорта данных из разнообразных 3d форматов. Разумеется, никакой привязки к Delphi не обнаружилось, только к D, Python, C# и, разумеется, к C++. Пришлось немного подучить C#, о чем, собственно, не жалею.
Для работы с использованием C# потребуется:
  • Собственно Visual C#. Подойдет и Express версия, которую можно бесплатно скачать у Microsoft.
  • Assimp SDK - исходники библиотеки,  привязки, документация, инструкция по сборке.
  • Assimp.dll - динамически линкуемая библиотека, собранная специально под C# из исходников из SDK.
  • Экспортер\импортер COLLADA для 3ds Max.
Замечание. На самом деле, внутренняя организация данных Assimp очень похожа на таковую в COLLADA, может есть смысл заодно ознакомиться и с этим форматом.
 
Замечание. Транспортировка данных с использованием COLLADA - процесс достаточно длительный по времени. Экспорт сложной модели из 3ds Max с анимацией может занимать пару минут. При обработке сложных моделей COLLADA с использованием Assimp счет тоже может идти на минуты. Это надо учитывать при написании экспортера - логично реализовать пакетную обработку файлов.

Замечание. На самом деле в документации к Assimp обозначается возможность загрузки из родных файлов Blender 3d (*.blend), но я с эти не разбирался.



Минимальные требования к контенту файла модели.


Есть смысл сразу обозначить требования для контента файлов, из которых в движок будут загружаться статические модели и анимированные модели. 


Минимальные требования к содеожимому файла статической модели следующие:

  • Данные о геометрии. В формате, готовом для использования в массивах OpenGL.
  • Информация о материале единичного элемента геометрии (диффузная, нормал, спекуляр карты; коэффициэнты).
Требования к файлу анимированной модели значительно выше. Во-первых надо отметить, что такие модели обязаны нести в себе информацию о иерархии костей скелета. Впрочем файлы статических моделей так же могут обладать данной информацией. Во-вторых, реализовать анимацию ииерархической модели можно несколькими подходами. Первый состоит в использовании скининга. При этом подходе вершины пркрепляются к одной или нескольким костям (обычно счет идет на 2-4 кости). Второй же состоит в том, что к определенной кости модели прикрепляется статическая геометрия. Например к плечевой кости персонажа можно присоеденить геометрию наплечника. Плюс такого подхода в отсутствии необходимости скининга прикрепляемого элемента. Минус же - увеличение количества подобъектов модели. В одной моделе можно комбинировать оба варианта. Итак, минимальные требования к контенту файла анимированной модели:
  • Данные о геометрических подобъектах.
  • Данные о материалах геометрических подобъектов.
  • Данные о иерархии модели.
  • Данные об анимации модели.
В более продвинутых случаях возможно включение дополнительных данных, ориентированных на движок. Например, отдельно обозначенные меши водных поверхностей, коллайдеров, физических свойствах коллайдеров и т.д.


Возможности Assimp.

Open Asset Library предоставляет доступ ко всем данным, описанным в предыдущем разделе, и даже больше. Данные, предоставляемые импортированной с помощью Assimp сцены, можно условно разделить на следующие большие категории:
  • Камеры.
  • Источники освещения.
  • Материалы.
  • Меши.
  • Иерархия.
  • Анимация.
Включение данных о камерах и источниках освещения сцены на мой взгляд обычно не нужно. Хотя иметь такой функционал на будущее и "что бы было" вполне приемлемо.

Материалы. Материалы в Assimp характеризуются следующими параметрами:
  • Имя файла diffuse texture.
  • Имя файла normal texture.
  • Имя файла opacity texture.
  • Имя файла ambient texture.
  • Имя файла emissive texture.
  • Имя файла shininess texture.
  • Имя файла lightmap texture.
  • Имя файла height texture.
  • Цвет ambient.
  • Цвет diffuse.
  • Цвет specular.
  • Цвет emissive.   

Меши. В Assimp реализована возможность инстансинга. Например, если в 3ds max создавать модель замка, имеющего множество одинаковых башенок, можно просто клонировать подобъект башенки и разместить клон в нужной позиции сцены, с нужным шкалированием и разворотами. Другими словами, Assimp импортирует мастер-подобъект, на который потом ссылаются узлы модели. Такой подход может сэкономить некоторое количество видеопамяти и памяти, необходимой для хранения модели на диске (не принципиально).


Мастер-подобъект (aiMesh) содержит следующие основные данные:
  • Имя. Может быть пустым.
  • UV каналы. Текстурные координаты для диффузной карты, карты освещения т.д.
  • Нормали, вершины, тангенты, индексы. Все эти данные почти готовы для эффективного использования в OpenGL.
  • Кости. Узлы модели, которые используются как кости для этого меша. Надо иметь ввиду, что не все узлы являются костями, но любая кость есть узел. Каждая кость содержит список вершин, подверженных ее влиянию, а так же bind-pose матрицу.
  • Индекс материала.
Так же присутствуют данные о раскраске вертексов, однако, ими уже обычно не пользуются.


Иерархия. Иерархия модели в Assimp построена на объектах типа aiNode, содержащих следующие важные данные:
  • Дочерние узлы. Список таких же узлов. Корневым узлом считается узел, не имеющий родительского.
  • Меши. Это как раз ссылки на мастер-меши. Один узел может иметь несколько ссылок на меши.
  • Имя. Предполагается, что имя узла должно быть уникально, однако библиотека не проводит подобной проверки. Реакция на возможное дублирование имен узлов иерархии ложится на плечи разработчика.
  • Матрица трансформации. 

Анимация. В импортированной сцене может содержаться несколько анимаций. За отдельную анимацию отвечает aiAnimation. Стоит обратить внимание, что aiAnimMesh пока не используется. Как я понимаю, это заготовка для хранилища обычной морфинговой анимации.

Анимация характеризуется следующими параметрами:
  • Имя. 
  • Количество тиков в секунду.
  • Продолжительность тика.
  • Каналы анимации.
Наибольший интерес здесь представляют каналы анимации, представленные посредством aiNodeAnim.  Каждый анимационный канал действует на один узел модели. Могут встречаться узлы, на которые не действует ни один канал. Данные о положениях\ротациях\шкалировании узлов в определнный момент времени представлены в виде набора PositionKey, RotationKey, ScalingKey. RotationKey представляет собой структуру типа aiQuatKey. Это кватернион с меткой времени этого ключа от начала анимации.  PositionKey и RotationKey представляет собой вектор с меткой времени от начала анимации. Исходя из этих данных можно восстановить матрицу узла в определенный момент времени относительно родительского узла.

Экспорт.
Сначала я думал привести фрагменты C# кода, но потом передумал. Причина - банальная лень. C# учится  достаточно легко, освоить его на уровне необходимом для написания экспортера дело одного-двух вечеров. После усвоения идеологии Assimp в написании экспортера нет ничего сложного. Надо просто понимать что делать и зачем оно нужно, как потом это использовать. Некоторые сомнения могут возникнуть при принятии решения о том как хранить анимацию - задавать отдельный, вспомогательный формат (как, например *nif и *.kf) или же обойтись одним универсальным. После некоторых раздумий я остановился на едином формате. В файле могут находиться пакеты материалов, мешей, иерархии и анимации, притом какие-то пакеты могут отсутствовать, это задается флагами экспорта, передаваемых экспортеру вместе с именем файла COLLADA. Таким образом, один файл может содержать полную анимированную модель или, например только иерархию. Это может быть полезно при реализации составных моделей, где на готовый скелет крепятся различные части модели в зависимости от ситуации. Пример - переодевание персонажей в RPG, где зачастую имеется один скелет на определенную расу и пол персонажей.

Замечание. В обертке над Assimp под C# имеется ошибка в одном из модулей, отвечающих за анимацию. При встрече с ней необходимо просто поменять private на public в одном из полей класса.


Open Asset Library, Open COLLADA для 3ds max, Демка экспортера.
 

1 комментарий:

  1. Здравствуйте! Выложите пожалуйста демку экспортера, снова а то ссылка уже умерла. Спасибо.

    ОтветитьУдалить