чем открыть mesh формат
Чем открыть mesh
Название формата Трехмерная Mesh-модель
Оригинальное название 3D Mesh Model
Разработчик: Medit
Описание расширения
файл 3D-модели, в котором объекты представлены в виде «сетки». Интерпретирует геометрическую моделей с помощью набора областей, формируя таким образом поверхность каждого объекта.
Чем открыть MESH Medit for Windows
Формат mesh, вариант 2:
Название формата Файл сетки DirectX
Оригинальное название DirectX Mesh File
Разработчик: Майкрософт
Описание расширения
Сетка трехмерной модели, используемая приложениями и играми на основе технологии DirectX.
Содержит полигональную сетку модели и часто используется для рендеринга объектов в 3D-играх.
Не нашли описания?
Напишите. Оно обязательно появится на сайте.
Популярные расширения
Распространенный формат для документов старых версий Microsoft Word
Видео, записанное в формате QuickTime (Apple)
Аудио, кодированное без потери качества. Есть поддержка тегов.
Образ CD или DVD диска, служит для создания копий дисков.
Расширение векторного изображения CorelDRAW.
Популярные программы
Простой и многофункциональный видеопроигрыватель
Пожалуй, лучший бесплатный медиа-проигрыватель
Очень удобная программа-просмотрщик графики с огромным набором функций
Наиболее популярный векторный графический пакет
Самый быстрый и один из лучших иинтернет-браузеров
Формат 3d studio mesh, взгляд изнутри
Формат 3d studio mesh, взгляд изнутри.
Или как загружать модели из файлов 3ds в программу.
Я с этого лета изучаю С++ и OpenGl (точнее в С++ я только повышал навыки)). уже столько информации впитал жуть). Причиной тому послужило то, что я пришел к выводу, что нельзя написать нормальную игру, не вникая в процесс программирования полностью. Вообще поначалу сложно было, но сейчас уже стало легче.
Ооочень большой проблемой стало нахождение обучений на русском языке, в Интернете, да и на полках книжных (. И дело не совсем в том, что книг на данную тему нет, они, безусловно, есть, но в целом везде содержание схоже, дается базис. Самой сильной проблемой (как я потом выяснил по форумам, чатам, сайтам) это является загрузка моделей из файлов, в OpenGl нет встроенных команд для этого, все вводится вручную.
Вот, например так описывается куб, состоящий из 6 граней, которые мы и описываем, причем заметьте – только точки, но есть ведь еще столько же – координаты текстур, координаты фейсов (faces coordinats):
А если у нас модель хотя бы на 2000 verticles? 😉
Примечания: в конце урока будет изложено то, как настроить компиляторы C++ на работу с OpenGl, я не привожу эту информацию в начале, так как это не цель урока. Там же приведены ссылки на полезные ресурсы сети, посвященные данной тематике и файлы к уроку.
Цели урока:
Содержание:
Знакомимся с 3ds.
У объекта chunk нелинейная структура, это значит что элементы, находящиеся по структуре внутри других, читаются только после того, как будут прочитаны (будет получен к ним доступ) элементы их содержащие. Структура имеет вид дерева, такую структуру можно наблюдать на локальных дисках компьютера. Конечно же, необязательно читать все объекты, достаточно прочитать только самые важные.
Каждый chunk состоит из 4 записей:
-Identifier: это число, записанное в шестнадцатеричном формате, размером 2 байта, идентифицирующее chunk. С этой информацией мы можем немедленно узнать, нужен ли он нам. Если нам нужен chunk, мы открываем собранную в нем информацию, если нужно, в его child-элементе (элементы, находящиеся по иерархии внутри данного), однако если он бесполезен, мы пропускаем его, используя следующий параметр…
-Lengthofthechunk: еще одно число, на этот раз размером 4 байта, содержит сумму длины chunk’а и его длинны child-элементов.
-Chunkdata: это поле может иметь разную длину. Реально хранимая информация содержится здесь.
В данной таблице представлена зависимость ветвления и размера в объектах chunk:
|
Иерархия и код наиболее полезных chunk’ов в файле:
MAIN CHUNK 0x4D4D
3D EDITOR CHUNK 0x3D3D
OBJECT BLOCK 0x4000
TRIANGULAR MESH 0x4100
VERTICES LIST 0x4110
FACES DESCRIPTION 0x4120
FACES MATERIAL 0x4130
MAPPING COORDINATES LIST 0x4140
SMOOTHING GROUP LIST 0x4150
LOCAL COORDINATES SYSTEM 0x4160
LIGHT 0x4600
SPOTLIGHT 0x4610
CAMERA 0x4700
MATERIAL BLOCK 0xAFFF
MATERIAL NAME 0xA000
AMBIENT COLOR 0xA010
DIFFUSE COLOR 0xA020
SPECULAR COLOR 0xA030
TEXTURE MAP 1 0xA200
BUMP MAP 0xA230
REFLECTION MAP 0xA220
[SUB CHUNKS FOR EACH MAP]
MAPPING FILENAME 0xA300
MAPPING PARAMETERS 0xA351
KEYFRAMER CHUNK 0xB000 — об особенностях и иерархии данной ветви мы поговорим позже
Важно не забывать при чтении определенного chunk’а, нужно вначале прочитать его отцов (элементов стоящих выше по иерархии). Например, для прочтения chunk’а VERTICES LIST мы должны прочитать MAIN CHUNK, 3D EDITOR CHUNK, OBJECT BLOCK и, наконец, TRIANGULAR MESH. Другие объекты, конечно, могут быть пропущены…
Так же хочу отметить, что в том случае если нам надо прочитать более одного объекта, тогда учитывая то, что создание идет через struct, мы прочитать OBJECTBLOCK еще раз и создать новый объект, используя структуру. Ориентироваться в том, что за объект нам выдал chunk можно по имени прочитанного объекта, как только имя повторилось, идем дальше, так же нужно не забывать проверять, что мы читаем, чтобы не прочитать свет, камеры, когда нам нужен mesh. В своем примере я читаю один объект.
Я предлагаю отбросить некоторые объекты в древе и оставить только ветви с информацией: «vertices», «faces», «mapping coordinates», и их отцов по дереву. Эти объекты мы используем в начальном примере:
MAIN CHUNK 0x4D4D
3D EDITOR CHUNK 0x3D3D
OBJECT BLOCK 0x4000
TRIANGULAR MESH 0x4100
VERTICES LIST 0x4110
FACES DESCRIPTION 0x4120
MAPPING COORDINATES LIST 0x4140
Таблица с более подробным описанием каждого chunk’а:
MAIN CHUNK | |
Identifier | 0x4D4D |
Length | 0 + Sub-chunks length |
Chunk father | None |
Sub chunks | 3D EDITOR CHUNK |
Data | None |
3D EDITOR CHUNK | |
Identifier | 0x3D3D |
Length | 0 + sub-chunks length |
Chunk father | MAIN CHUNK |
Sub chunks | OBJECT BLOCK, MATERIAL BLOCK, KEYFRAMER CHUNK |
Data | None |
OBJECT BLOCK | |
Identifier | 0x4000 |
Length | Object name length + sub-chunks length |
Chunk father | 3D EDITOR CHUNK |
Sub chunks | TRIANGULAR MESH, LIGHT, CAMERA |
Data | Object name |
TRIANGULAR MESH | |
Identifier | 0x4100 |
Length | 0 + sub-chunks length |
Chunk father | TRIANGULAR MESH |
Sub chunks | None |
Data | Vertices number (unsigned short) Vertices list: x1,y1,z1,x2,y2,z2 etc. (for each vertex: 3*float) |
FACES DESCRIPTION | |
Identifier | 0x4120 |
Length | varying + sub-chunks length |
Chunk father | TRIANGULAR MESH |
Sub chunks | FACES MATERIAL |
Data | Polygons number (unsigned short) Polygons list: a1,b1,c1,a2,b2,c2 etc. (for each point: 3*unsigned short) Face flag: face options, sides visibility etc. (unsigned short) |
MAPPING COORDINATES LIST | |
Identifier | 0x4140 |
Length | varying + sub-chunks length |
Chunk father | TRIANGULAR MESH |
Sub chunks | SMOOTHING GROUP LIST |
Data | Vertices number (unsigned short) Mapping coordinates list: u1,v1,u2,v2 etc. (for each vertex: 2*float) |
VERTICES LIST | |
Identifier | 0x4110 |
Length | varying |
Chunk father | TRIANGULAR MESH |
Sub chunks | None |
Data | Vertices number (unsigned short) Vertices list: x1,y1,z1,x2,y2,z2 etc. (for each vertex: 3*float) |
Разработка простого приложения.
В моем примере мы сможем считывать только один объект из файла! (то, как это исправить будет описано в следующей главе.
Итак, для начала берем файл – заготовку, содержащий объявление всех структур OpenGl (template01.zip). Я не буду останавливаться на разъяснении устройства программы, это вы сможете понять и по комментариям.
В принципе мы могли бы хранить все типы в главном исходном коде (main.cpp) программы, но лучшим решением будет расположить их в заголовочном файле (header file, main.h).
#define MAX_VERTICES 8000
#define MAX_POLYGONS 8000
Мы должны указать максимальное количество точек и полигонов, которое будит поддерживать наше приложение.
Теперь мы должны создать файл 3dsLoader.cpp (здесь и будет выполняться загрузка модели). Сюда мы вводим:
char Load3DS (obj_type_ptr p_object, char *p_filename)
<
int i;
FILE *l_file;
unsigned short l_chunk_id;
unsigned int l_chunk_length;
unsigned char l_char;
unsigned short l_qty;
unsigned short l_face_flags;
В Load3DS как параметры передаются указатель на объект структуры данных и имя файла, который надо открыть. Возвращает «0» если файл не найден, если файл найден и прочитан то «1». На самом деле для инициализации нам требуется не так уж и много переменных: счетчик i, указатель на файл *l_file и дополнительная переменная l_char для экстраполяции данных в байт формате.
Остальные переменные:
-unsignedshortl_chunk_id: идентификатор chunk’а, шестнадцатеричное значение в 2 байта.
-unsigned int l_chunk_length: длинна chunk’а, 4 байта.
-unsignedshortl_qty: дополнительный параметр, будет полезен для получения информации о параметрах читаемой информации.
-unsignedshortl_face_flags: запоминает некоторую информацию относительно текущего полигона (видим, не видим и прочее), полезен только 3d редакторов сцены, в нашем случае мы не будем с ним работать, но будем его считывать, чтобы переместиться на следующий chunk. Итак, наконец, откроем файл:
FACESDESCRIPTION содержит перечень полигонов объекта. Чтение схоже с предыдущим.
Каждый face содержит дополнительно второе поле, содержащее информацию для 3d редакторов (видимые стороны и прочее). Мы, конечно, читаем и их, но лишь для передвижения далее…
Последним в данном примере мы читаем MAPPING COORDINATES LIST, так же как обычно вначале читаем quantity, затемлист координат, только теперь одна очко будет иметь 2 координаты, так как наложение идет в двумерном пространстве, U и V, припоминается?)
Замечательно! Case – default! Это значит, что на этом рутинная работа закончена, когда у нас на пути chunks, которые нам читать не нужно нам поможет функция fseek, используя информацию из chunk_length, она переводит нас на начало следующего chunk.
default:
fseek(l_file, l_chunk_length-6, SEEK_CUR);
>
>
На этом и конец этого примера. Правда осталась только одна мелочь: давайте закроем файл и возвратим 1!
fclose (l_file); // Closes the file stream
return (1); // Returns ok
>
И вот наша модель из 3дМакса попала в наше приложение!
Весь пример вы можете скачать по ссылке в конце урока. В нем так же в отдельный модуль выделена загрузка текстур, для удобства. (прим.: Данный пример основывается на примере взятом на www.spacesimulator.net)
Подробнее о KEYFRAMER CHUNK.
Эту информацию найти было особенно сложно
…Таблица с подробным описанием каждого chunk’а относящегося к анимации:
Информация далеко не полная, подробнее об этом можно узнать из доков sdk или споcобом, который я опишу немного позже.
Иерархия объектов.
Иерархия объектов схожа с иерархией chunk`ов, то же самое дерево… но не всегда. Каждому объекту в сцене дается номер, чтобы идентифицировать его номер в иерархии. Каждый объект созданный в файле будет и в дереве иерархии. Корневому элементу дается номер «-1»(ffff). При чтении файла сохраняется номер объекта. Если он увеличивается, будет идти работа с дочерним элементом, уменьшится – мы перешли на родительский элемент.
Для примера того, как иерархия представляется, используем файл 50pman.3ds (он есть среди файлов к уроку), его по каким то причинам, по традиции используют для описания этого момента еще с момента появления формата 3ds.
Hierarchy | object name
-1 pelvis
0 chest
1 neck
2 head
1 rt uparm
4 rt lowarm
5 rt hand
1 lft uparm
7 lft lowarm
8 lft hand
0 rt thigh
10 rt shin
11 rt foot
0 lft thigh
13 lft shin
14 lft foot
Schematic View для 50pman.3ds
Для того чтобы понять то почему нумерация имеет именно такой порядок нужно представить саму модель, структура здесь имеет не стандартный вид дерева, потому что главный элемент логически помещен в центр.
Использование иерархии может быть полезно, когда мы должны объединить несколько объектов в структуру, а то как они должны зависеть друг от друга читать из файла.
Как легче узнать какие параметры надо прочитать?
В уроке я не привожу примера с чтением анимации, но взамен (чтобы вы не расстраивались:)) привожу пример, который есть в sdk от autodesk.
Для начала скачайте sdk по ссылке в конце урока. Он подготовлен для работы в MSVC++, но прочитать исходники я думаю, не составит труда тем, у кого ее нет.
Запустим MAKEREL.BAT, это установит пути к директориям sdk. (Чтобы это отменить запустите CLEAN.BAT)
В папке DUMP3DS находится пример, консольное приложение, которое читает 3ds файл и выводит в консоль информацию обо всех chunk`ах, которые подверглись изменению. (Теперь, например мы можем легко узнать какие chunk`и изменяются при добавлении анимации, карт и прочее…) В папке INC содержится заголовочный файл, в котором объявляются все chunk`и, и структуры для их обработки.
Вообще в sdk есть интересные документы, которые еще больше могут углубить ваши знания:
3DSFTK3.DOC – содержит информацию о программе приведенной Autodesk, спецификацию всех функций, структур, переменных. Тут все довольно понятно.
3DSFTK3.DOC – информация о том как устроен формат 3ds. Здесь все довольно непонятно 🙂
3DSFTK3B.DOC – все о анимации. Имеет довольно странную структуру, но полезного тут много.
Как настроить компилятор для работы с OpenGL.
Многие спорят что лучше, компилятор Microsoft или Borland? Мне кажется, это так же глупо, как и спорить на эту тему о 3DMax или Maya… Мне кажется, что важное отличие первого компилятора в том, что для него больше примеров :).
В архиве GL.rar лежит папка GL и Glut32.lib.
Ссылки:
Советую найти OpenGL Red Book (русская версия) – 475 страниц! Это отличный учебник по OpenGL, к сожалению сайт на котором я ее брал уже не работает, но я думаю поиском пользоваться все умеют:)
И еще интересные демки, часто с исходниками, можно найти на сайте NVidia…
Файлы к уроку:
Послесловие.
На этом мой урок подошел завершению, я постарался, как можно полнее изложить тему. Обе цели поставленные вначале урока считаю достигнутыми. Надеюсь, вам было интересно!
Спасибо за внимание, оставляйте свои комментарии и голосуйте. Удачи вам в ваших проектах по 3d графике!
Если оставляете критику, пожалуйста, обосновывайте, мне же важно знать, что не так…
Расширение файла MESH
DirectX Mesh Format
Что такое файл MESH?
Полное имя формата файлов, которые используют расширение MESH: DirectX Mesh Format. Формат DirectX Mesh Format был разработан Microsoft. Формат файла MESH совместим с программным обеспечением, которое может быть установлено на системной платформе Windows. MESH файл относится к категории Файлы изображений 3D так же, как #NUMEXTENSIONS # других расширений файлов, перечисленных в нашей базе данных. Для управления файлами MESH рекомендуется DirectX SDK.
Программы, которые поддерживают MESH расширение файла
Программы, обслуживающие файл MESH
Как открыть файл MESH?
Отсутствие возможности открывать файлы с расширением MESH может иметь различное происхождение. С другой стороны, наиболее часто встречающиеся проблемы, связанные с файлами DirectX Mesh Format, не являются сложными. В большинстве случаев они могут быть решены быстро и эффективно без помощи специалиста. Мы подготовили список, который поможет вам решить ваши проблемы с файлами MESH.
Шаг 1. Получить DirectX SDK
Наиболее распространенной причиной таких проблем является отсутствие соответствующих приложений, поддерживающих файлы MESH, установленные в системе. Чтобы решить эту проблему, перейдите на веб-сайт разработчика DirectX SDK, загрузите инструмент и установите его. Это так просто Полный список программ, сгруппированных по операционным системам, можно найти выше. Если вы хотите загрузить установщик DirectX SDK наиболее безопасным способом, мы рекомендуем вам посетить сайт и загрузить его из официальных репозиториев.
Шаг 2. Обновите DirectX SDK до последней версии
Вы по-прежнему не можете получить доступ к файлам MESH, хотя DirectX SDK установлен в вашей системе? Убедитесь, что программное обеспечение обновлено. Может также случиться, что создатели программного обеспечения, обновляя свои приложения, добавляют совместимость с другими, более новыми форматами файлов. Если у вас установлена более старая версия DirectX SDK, она может не поддерживать формат MESH. Все форматы файлов, которые прекрасно обрабатывались предыдущими версиями данной программы, также должны быть открыты с помощью DirectX SDK.
Шаг 3. Настройте приложение по умолчанию для открытия MESH файлов на DirectX SDK
Если проблема не была решена на предыдущем шаге, вам следует связать MESH файлы с последней версией DirectX SDK, установленной на вашем устройстве. Следующий шаг не должен создавать проблем. Процедура проста и в значительной степени не зависит от системы
Выбор приложения первого выбора в Windows
Выбор приложения первого выбора в Mac OS
Шаг 4. Проверьте MESH на наличие ошибок
Если проблема по-прежнему возникает после выполнения шагов 1-3, проверьте, является ли файл MESH действительным. Проблемы с открытием файла могут возникнуть по разным причинам.
1. Убедитесь, что MESH не заражен компьютерным вирусом
Если файл заражен, вредоносная программа, находящаяся в файле MESH, препятствует попыткам открыть его. Сканируйте файл MESH и ваш компьютер на наличие вредоносных программ или вирусов. Если сканер обнаружил, что файл MESH небезопасен, действуйте в соответствии с инструкциями антивирусной программы для нейтрализации угрозы.
2. Убедитесь, что файл с расширением MESH завершен и не содержит ошибок
Вы получили MESH файл от другого человека? Попросите его / ее отправить еще раз. В процессе копирования файла могут возникнуть ошибки, делающие файл неполным или поврежденным. Это может быть источником проблем с файлом. Это может произойти, если процесс загрузки файла с расширением MESH был прерван и данные файла повреждены. Загрузите файл снова из того же источника.
3. Проверьте, есть ли у вашей учетной записи административные права
Иногда для доступа к файлам пользователю необходимы права администратора. Переключитесь на учетную запись с необходимыми привилегиями и попробуйте снова открыть файл DirectX Mesh Format.
4. Убедитесь, что ваше устройство соответствует требованиям для возможности открытия DirectX SDK
Если в системе недостаточно ресурсов для открытия файлов MESH, попробуйте закрыть все запущенные в данный момент приложения и повторите попытку.
5. Проверьте, есть ли у вас последние обновления операционной системы и драйверов
Регулярно обновляемая система, драйверы и программы обеспечивают безопасность вашего компьютера. Это также может предотвратить проблемы с файлами DirectX Mesh Format. Возможно, файлы MESH работают правильно с обновленным программным обеспечением, которое устраняет некоторые системные ошибки.
Вы хотите помочь?
Если у Вас есть дополнительная информация о расширение файла MESH мы будем признательны, если Вы поделитесь ею с пользователями нашего сайта. Воспользуйтесь формуляром, находящимся здесь и отправьте нам свою информацию о файле MESH.
learnopengl. Уроки 3.1 (Assimp) + 3.2 (класс Mesh)
Assimp
Во всех уроках, мы, в основном, использовали нашего маленького друга — контейнер, но через некоторое время, даже наши лучшие друзья становятся немного скучными. В большом графическом приложении, обычно присутствуют много моделей, на которые намного приятнее смотреть, чем на наш статичный контейнер. Хотя, в отличие от контейнера, нам будет очень сложно, вручную, определить все вершины, нормали и текстурные координаты таких сложных моделей, как например дом или человекоподобные персонажи. Вместо этого, мы будем имортировать модели в наше приложение; модели, которые были тщательно нарисованы, в 3D редакторах, таких как Blender, 3DS MAX или Maya.
В общем, существует много разных форматов, где хранящаяся структура данных отличается. Поэтому, если мы хотим импортировать модель из этих файлов, нам нужно написать импортер самим, для каждого формата, который мы захотим импортировать. Удачно для нас, для этого есть библиотека.
Библиотека для загрузки моделей
Assimp — очень популярная библиотека, для импортирования моделей, которая расшифровывается как Open Asset Import Library. Эта библиотека может импортировать множество различных форматов, содержащие модели, сохраняя данные, которые импортируются, в виде простой иерархической структуры данных. Как только Assimp закончит загрузку моделей, мы сможем получить все нужные нам данные из этой структуры. Без разницы какой формат файлов мы импортируем, обращение к данным в структурах не изменяется, структура остается такой же для всех различных форматов файлов.
При импорте модели, с помощью Assimp, библиотека загружает всю модель в объект сцены (Scene), содержащий все данные импортированной модели. Затем Assimp создает коллекцию узлов, где каждый узел содержит индексы к данным, хранящимся в объекте сцены, каждый узел может иметь потомка. Простая модель структуры Assimp представлена ниже:
В следующих уроках мы создадим наши собственные классы Model и Mesh, которые загружают и хранят импортированные модели, используя только что описанную структуру. Если мы хотим нарисовать модель, то мы выводим ее не целиком, а осуществляем вывод каждой из составляющих модель сеток по-отдельности. До того, как мы сможем имортировать модели, нам нужно сначала включить Assimp в наш проект.
Сборка Assimp
Вы можете скачать Assimp с этой страницы, выбрав соответствующую версию. Во время написания статьи, последняя версия Assimp была 3.1.1. Рекомендуется компилировать библиотеки самостоятельно, так как их, предварительно скомпилированые библиотеки, не работают на большинстве систем. Пересмотрите урок Создание окна, если вы забыли как компилировать библиотеку самим, используя CMake.
Несколько проблем появлялись во время сборки Assimp, так что я отмечу их здесь, с их решениями в случае, если кто-либо из вас получит те же ошибки:
Если вы хотите использовать многопоточность для увеличения производительности, вы можете собрать Assimp с Boost. Полная инструкция находится здесь.
На этом моменте, вы должны были скомпилировать Assimp и внедрить его в ваше приложение.
Класс Mesh
Используя Assimp мы можем загружать множество различных моделей в наше приложение, но после загрузки, данные все ещё хранятся в структуре Assimp. Нам нужно преобразовать эти данные в формат, который понимает OpenGL, чтобы мы смогли отрисовать модель. В предыдущем уроке мы узнали, что полигональная сетка представляет собой одну рисуемую сущность, поэтому давайте начнем с определения собственного класса Mesh.
Давайте подумаем, какой набор данных нам нужен для нашего класса. Полигональная сетка нуждается в наборе вершин, где каждая вершина содержит вектор позиции, вектор нормали и вектор текстурных координат. Полигональная сетка также должна содержать индексы,
для индексированной отрисовки, и данные для материалов.
Теперь, мы можем определить структуру вершины:
Каждая вершина хранится в структуре Vertex, которая может использоваться для индексации каждой вершины. Помимо структуры Vertex, нам также нужно создать структуру, которая хранит текстурные данные.
Она хранит id и тип текстуры (диффузная или бликовая).
Написав структуры, можно начинать писать наш класс:
Как вы можете видеть, класс не очень сложен. Конструктор принимает все нужные нам данные, в методе setupMesh мы инициализируем буферы, в методе Draw мы будем отрисовывать нашу полигональную сетку. Обратите внимание, что функция отрисовки (Draw), принимает объект шейдера, чтобы мы могли установить соответствующие uniform переменные, до отрисовки.
Код конструктора довольно прост, мы просто присваиваем аргументам класса, соответствующие аргуметы. Также мы вызываем функцию setupMesh:
Как видите, ничего необычного здесь не происходит. Далее, переходим к функции setupMesh.
Инициализация
Благодаря конструктору, у нас имеется все нужные нам данные, которые мы можем использовать для отрисовки. Однако, нам сначала нужно настроить соответствующие буферы. К этому моменту у вас не должно быть проблем с этими понятиями, но, возможно, мы вас немного удивим как можно передавать данные в буфер, которые находятся в структуре:
Код не сильно отличается от того, что вы ожидали, но несколько маленьких трюков были использованы с помощью структуры Vertex.
В С++, у структур есть отличное свойство — их память является последовательной. То есть, если бы мы представили структуру как массив данных, то она содержала бы переменные в том порядке, в котором они определены в самой структуре. Например, если мы наполним структуру Vertex, какими нибудь значениями, то их размещение в памяти будет равной:
Благодаря этому свойству, например, если мы применим функцию sizeof к нашей структуре, она вернет размер все аргументов, которые в ней определены. Она должна весить 32 байта
(8 * 4 — размер 1 float). Мы можем это использовать для функции glBufferData:
Также мы используем макрокоманду offsetof, которая в качестве первого аргумента принимает структуру, а в качестве второго — имя переменной структуры. А возвращает она смещение в байтах указанной структуры, до переменной, переданной во втором аргументе. Это идеально подходит для определения последнего параметра функции glVertexAttribPointer:
Смещение теперь определяется с помощью макроса offsetof, который, в данном случае, устанавливает смещение байта для вектора нормали. Обратите также, что мы указываем размер шага равным размеру структуры.
Использование такой структуры не только обеспечивает более читаемый код, но и позволит нам, в будущем, её расширять. Если мы захотим использовать какой нибудь другой вершинный артрибут, мы сможем легко добавить его в нашу структуру и из-за своей гибкости, код не поломается.
Отрисовка
Последняя функция, которую нам следует написать — это Draw. Но перед тем, как отрисовать наши полигоны, сначала нам нужно связать наши текстуры, до вызова функции glDrawElements. Однако, это немного тяжело, т.к. мы не знаем сколько у нас есть текстур (если они вообще есть) и какого они типа. И также, как установить текстурные блоки и текстурных объектов в шейдере?
Чтобы решить эту проблему, мы примем некоторые соглашения об именовании: каждая диффузная текстура называется texture_diffuseN, а каждая бликовая текстурная карта должна называться texture_specularN, где N-любое число, начиная с 1 до максимального количества разрешенных текстур. Допустим у нас есть 3 диффузные текстуры и 2 бликовые текстуры для конкретной полигональной сетки, мы должны определить их так:
Благодаря этому соглашению, мы можем определить столько текстурных объектов, сколько захотим, и если полигональная сетка действительно содержит много текстур, мы знаем, какими будут их имена. Мы можем обрабатывать любое количество текстур на одной полигональной сетке и разработчик может свободно использовать столько текстур, сколько он хочет, просто определяя дополнительные текстурные объекты в шейдере.
Кроме этого решения, есть также много других, и если вам не нравится это, вы можете проявить свою творческую способность и придумать свое собственное решение.
Это не самый красивый код, но отчасти в этом виноват С++, так как, например, в нем нет такого преобразования типов, как int в строку. Мы пробегаемся по N-текстурам и определяем присваиваем их типы строковой переменной, что бы затем мы имели преставление, какой номер конкретного типа текстуры. Далее, мы узнаём номер нашего текстурного объекта, ну и наконец, устанавливаем этому текстурному объекту номер, соответствующий активному текстурному блоку и связываем текстуру. Обратите внимание, что мы собираемся хранить текстурные объекты в структуре Material, как обычно мы и делали.
Обратите внимание, что увеличив диффузные и бликовые счетчики, мы сразу передаем их в stringstream. Правый инкремент в C++ увеличивает значение на 1, но возвращает старое значение.
Вы можете найти полный код класса Mesh здесь.
В следующем уроке, мы создадим класс Model, который работает как контейнер, для объектов класса Mesh и фактически реализует интерфейс загрузки Assimp.