Урок №16. Библиотека импорта 3D-моделей Assimp в OpenGL

  Дмитрий Бушуев  | 

  Обновл. 11 Мар 2023  | 

 15416

 ǀ   8 

До сих пор во всех создаваемых нами сценах присутствовал наш «маленький друг» — деревянный контейнер, но с течением времени уже хочется чего-то большего, правда? Большие графические приложения обычно содержат много сложных и интересных моделей, которые выглядят гораздо красивее, нежели статический контейнер. Однако, если мы в нашей программе захотим использовать более сложные объекты, вроде домов, транспортных средств или человекоподобных персонажей, то столкнемся с проблемой, что, в отличие от объекта-контейнера, мы не сможем задать для них вручную все вершины, нормали и координаты текстур из-за сложности форм вышеназванных объектов. Вместо этого мы можем импортировать в приложение данные о моделях; моделях, которые были старательно разработаны 3D-дизайнерами в таких инструментах, как Blender, 3DS Max или Maya.

Импорт 3D-моделей

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

Нашей задачей является проанализировать экспортированные файлы моделей и извлечь из них всю необходимую информацию, чтобы в дальнейшем представить её в том формате, который будет понятен для OpenGL. Общая проблема заключается в том, что существуют десятки различных форматов файлов моделей, каждый из которых экспортирует данные о модели своим собственным уникальным способом. Например, файл модели формата .obj содержит только данные о модели и незначительную информацию о её материалах, вроде цвета модели и диффузных/зеркальных карт, в то время как файлы моделей формата COLLADA, построенные на использовании стандарта XML, чрезвычайно обширны и содержат информацию о модели, освещении, различных типах используемых материалов, данных анимации, камере, полную информацию о сцене и многое другое.

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

Библиотека загрузки 3D-моделей


Одной из самых популярных библиотек импорта 3D-моделей является Assimp (англ. «Open Asset Import Library» = «Свободная Библиотека Импорта Ресурсов»). Assimp может импортировать информацию из десятка различных файловых форматов (и экспортировать в некоторые из них), загружая все данные о модели в свои собственные обобщенные структуры данных. Как только Assimp загрузит модель, мы сможем получить все необходимые данные из этих структур. Поскольку структура данных в Assimp остается неизменной, независимо от типа импортируемого формата файла, то она абстрагирует нас от всех существующих форматов файлов.

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

Рассмотрим это детально:

   Scene (Сцена) — здесь содержатся все данные сцены/модели, типа материалов и мешей (об этом чуть ниже). Этот объект также хранит внутри себя ссылку на корневой узел сцены.

   Root Node (Корневой узел сцены) — может содержать дочерние узлы (как и все остальные узлы) и может иметь набор индексов, указывающих на данные меша в массиве mMeshes объекта сцены. Массив mMeshes сцены содержит фактические меш-объекты, а значениями массива mMeshes выбранного узла являются индексы для массива meshes объекта сцены.

   Mesh (Меш) — содержит все соответствующие данные, необходимые для рендеринга сцены, например: положение вершин, нормальные векторы, координаты текстуры, грани и материал объекта.

   Face (Грань) — представляет собой примитив визуализации (треугольники, квадраты, точки). Грань содержит индексы вершин, образующих примитив. Поскольку вершины и индексы разделены, то это облегчает нам визуализацию через буфер индексов (см. Урок №4. Рисуем наш первый треугольник в OpenGL).

   Material (Материал) — содержит несколько функций для получения информации о свойствах материала объекта. Чем-то может напоминать цветовые и/или текстурные карты (например, диффузные и зеркальные карты).

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

Примечание о mesh: Когда 3D-дизайнеры в своих программах моделируют какой-нибудь объект, то, обычно, его пытаются сделать не цельным, а составным. Каждая такая модель имеет несколько подмоделей/фигур, из которых она строится. При этом каждая из этих отдельных фигур называется меш (англ. «mesh»). Давайте представим себе человекоподобного персонажа: дизайнеры обычно моделируют голову, конечности, одежду и оружие как отдельные компоненты, и совокупный результат всех этих мешей представляет собой окончательную модель. Один меш — это минимальный набор для того, чтобы отобразить фигуру в OpenGL (данные вершин, индексы и свойства материала). Модель (как правило) состоит из нескольких мешей.

На следующих уроках мы создадим наши собственные классы Model и Mesh, которые загружают и хранят импортированные модели, используя структуру, описанную выше. Затем, если нам нужно будет отобразить модель, мы не будем визуализировать её как единое целое, а будем визуализировать все отдельные меши, из которых состоит модель. Однако, прежде чем мы сможем начать импортировать различные модели, нам сначала нужно подключить Assimp в наш проект.

Собираем Assimp

Вы можете скачать Assimp со страницы GitHub, выбрав соответствующую версию. При написании данной статьи использовался Assimp версии 5.0.1. Рекомендуется компилировать библиотеки самостоятельно, так как их предварительно скомпилированные версии не всегда работают на всех системах. Если вы забыли, как самостоятельно скомпилировать библиотеку с помощью CMake, то перечитайте Урок №2. Подготовка к первому проекту OpenGL: настройка GLFW, CMake и GLAD.

Сборка Assimp под Windows

Исходные данные: Windows 10 версии 1909 + MS Visual Studio 2019 версии 16.6.0.

Сначала нам нужно распаковать архив assimp-5.0.1.zip в какую-нибудь папку. У меня это — C:\OpenGL:

Затем переходим в распакованную папку C:\OpenGL\assimp-5.0.1\ и создаем новую папку, например, build:

Запускаем CMake-GUI. В окне программы указываем путь к исходникам Assimp и папку, в которой будет сохранен результат работы CMake. После этого нажимаем кнопку "Configure":

В появившемся окне выбираем платформу, под которую CMake будет собирать проект. После этого нажимаем кнопку "Finish":

В результате мы получим следующее окно с красным фоном. Нажимаем кнопку "Configure" еще раз:

После этого красный фон исчезнет. И мы нажимаем кнопку "Generate", чтобы сгенерировать файлы проекта:

В результате данных действий CMake должен вывести нам следующие строки:

А в папке C:\OpenGL\assimp-5.0.1\build\ должны появиться новые файлы, среди которых будет файл решения Assimp.sln:

Открываем его, запустится Visual Studio. Далее щелкаем ПКМ в обозревателе решений по строке ALL_BUILD и в появившемся меню выбираем пункт "Собрать". Начнется процесс компиляции проекта:

Забегая вперед, скажу, что на моей системе с процессором AMD FX8320 3.5GHz процесс сборки шел около 4 минут при 100% загрузке всех ядер. Результатом должно быть следующее:

Теперь в папке C:\OpenGL\assimp-5.0.1\build\code\Debug\ мы должны увидеть следующие файлы:

Копируем файл C:\OpenGL\assimp-5.0.1\build\code\Debug\assimp-vc142-mtd.lib в папку C:\OpenGL\Lib к остальным нашим файлам OpenGL-библиотек:

Копируем папки C:\OpenGL\assimp-5.0.1\assimp-5.0.1\include\assimp и C:\OpenGL\assimp-5.0.1\build\include\assimp в C:\OpenGL\Include. На вопрос о слиянии двух папок отвечаем "Да":

И также в Visual Studio подключаем к проекту нашу библиотеку. Для этого открываем рабочий проект, выбираем из верхнего меню "Проект" > "Свойства" и в появившемся окне задаем следующие параметры:

Добавим еще каталоги:

Готово! Мы только что подключили библиотеку Assimp к нашему проекту. На следующих уроках мы будем работать уже с импортированными моделями. При этом, во время запуска исполняемого файла проекта может появиться следующее сообщение об ошибке:

Для решения данной проблемы скопируем файл C:\OpenGL\assimp-5.0.1\build\code\Debug\assimp-vc142-mtd.dll в Debug-папку с исполняемым файлом нашего проекта. В моем случае эта папка находится здесь: C:\Users\Имя_Пользователя\source\repos\Advanced OpenGL\x64\Debug\:

И окно с ошибкой не будет больше нам докучать.

Сборка Assimp под Linux

Исходные данные: Debian + CodeBlocks.

К сожалению, под данную платформу мне не удалось заставить стабильно работать собранную из исходников библиотеку Assimp. С ней постоянно возникали какие-то проблемы. При этом проект урока с подключенной библиотекой успешно компилировался, запускалось окно программы, подгружалась модель. Но при попытке осмотреться мышкой внутри сцены, изображение модели внутри окна полностью пропадало. Поэтому пока пользователям Linux приходится рассчитывать только на свои собственные силы. Увы…

Проблемы при построении проекта с Assimp


При построении проекта с использованием Assimp могут появляться некоторые проблемы.

Проблема №1: CMake постоянно выдает ошибки при получении списка конфигурации о пропавших библиотеках DirectX, сообщение об ошибке следующее:

Решение заключается в том, что вам нужно установить DirectX SDK, если вы этого еще не сделали.

Проблема №2: При установке DirectX SDK может появиться код ошибки s1023. В этом случае перед установкой DirectX SDK вам необходимо будет удалить пакеты Visual C++ Redistributable Packages.

Оценить статью:

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (18 оценок, среднее: 4,78 из 5)
Загрузка...

Комментариев: 8

  1. Кетчуп:

    У меня получилось собрать библиотеку под Linux! Но не под Windows 🙁

    У меня:
    Intel Core2 Duo E7500 2.93GHz
    KDE neon 5.21 User Edition
    gcc 9.3.0
    g++ 9.3.0
    make 4.2.1
    cmake 3.16.3

    Скачал zip архив с исходым кодом отсюда: https://github.com/assimp/assimp/releases/tag/v5.0.1
    Извлёк его сюда: /home/anton/Libraries/temp/
    В /home/anton/Libraries/temp/ появилася папка assimp-5.0.1

    Запустил cmake-gui:

    Where is the source code: /home/anton/Libraries/temp/assimp-5.0.1
    Where to build the binaries: /home/anton/Libraries/temp/assimp-5.0.1/build

    Нажал на Configure
    Запросило создать папку /home/anton/Libraries/temp/assimp-5.0.1/build, я согласился

    Specify the generator for this project: Unix Makefiles
    Use default native compilers

    Снял галочку с ASSIMP_BUILD_ASSIMP_TOOLS (Почему — не знаю)
    CMAKE_INSTALL_PREFIX: /home/anton/Libraries/packages/assimp
    В эту директорию установится библиотека

    Нажал на Configure
    Нажал на Generate

    Потом в терминале:

    cd /home/anton/Libraries/temp/assimp-5.0.1/build
    cmake —build .
    cmake —install .

    (Собрал и установил библиотеку)

    Собиралось у меня очень долго 🙁

    Теперь в папке /home/anton/Libraries/packages/assimp находится готовая библиотека

    Я использую CLion и мой CMakeLists.txt выглядит так:

    cmake_minimum_required(VERSION 3.17)

    project(AssimpTest)
    set(CMAKE_CXX_STANDARD 14)
    set(EXECUTABLE_OUTPUT_PATH ./../Executable)

    set(GLAD /home/anton/Libraries/files/glad.c)
    add_executable(AssimpTest main.cpp ${GLAD})

    include_directories(/home/anton/Libraries/include)

    find_package(glfw3 REQUIRED PATHS /home/anton/Libraries/packages/glfw/)
    target_link_libraries(AssimpTest glfw)

    find_package(assimp REQUIRED PATHS /home/anton/Libraries/packages/assimp/)

    include_directories(${ASSIMP_INCLUDE_DIRS})
    target_link_libraries (AssimpTest ${ASSIMP_LIBRARY_DIRS}/${ASSIMP_LIBRARIES})

    Работает у меня всё просто отлично 🙂

  2. Фанат:

    Классный сайт! Много полезной и нужной информации, продолжайте в том же духе!

    1. Фото аватара Дмитрий Бушуев:

      Спасибо большое 🙂

  3. noname:

    Привет. Сделайте пожалуйста инструкцию по сборке на CodeBlocks MinGW. Когда я пытался установить assimp5.0.1(новая версия) у меня CMake ругался на старый MinGW, пришлось ставить assimp4.0.1. Однако далее при попытке собрать это дело в codeblocks возникло несколько ошибок:
    1) unrecognized option `-mbig-obj'
    2) code\CMakeFiles\assimp.dir\build.make|1686|recipe for target 'code/CMakeFiles/assimp.dir/IFCReaderGen1.cpp.obj' failed
    3) CMakeFiles\Makefile2|325|recipe for target 'code/CMakeFiles/assimp.dir/all' failed
    4) assimp-4.0.1\build\Makefile|128|recipe for target 'all' failed

    Помогите пожалуйста (VS не перевариваю)

      1. Фото аватара Дмитрий Бушуев:

        Я пробовал собирать Assimp с помощью CodeBlocks как в Linux, так и в Windows10.
        Самый большой прогресс был в варианте с Linux — библиотека Assimp компилировалась, соединялась с проектом, даже загружала модель в сцену. Но при этом был баг — стоило чуть двинуть мышкой (чтобы осмотреться вокруг сцены), как поворот камеры происходил с какой-то чудовищной скоростью. Хотя реакция на кнопки WASD была нормальная.

        Хуже всего обстояли дела в варианте CodeBlocks + Windows10. В данном случае библиотека Assimp вообще не захотела собраться, кидаясь на выходе различными ошибками компиляции (их было около 50 штук).

        Судя по вашему комментарию со ссылкой на тикет, разработчики Assimp признали (месяц назад) проблему и попытаются что-то сделать к выходу версии 5.1. Так что как-то так…

        1. noname:

          У меня получилось собрать assimp 4.0.1 для mingw-w64 (только пришлось убрать некоторые странные импортеры в которых возникали ошибки). В итоге assimp у меня распознаёт .obj, но, когда я пытаюсь загрузить сцену с обычным кубом из блендера (в .obj), объект не отображается (он точно не чёрный, текстуры загружаются без ошибок), его просто нет. (Я пробовал с разными модельками из интернета). Пробовал выводить отладочную информацию (количество мешей, нодов) — вроде как всё правильно. Может быть assimp криво стоит, такое может быть?

        2. Иван:

          Если ваш Линух был на виртуалке, то попробуйте отключить захват мыши виртуалкой

Добавить комментарий для noname Отменить ответ

Ваш E-mail не будет опубликован. Обязательные поля помечены *