Синтаксический анализ формата файла wavefront obj

Я хотел бы импортировать модели obj в мою программу opengl. У меня есть класс / формат данных, который я использую для передачи данных атрибутов в шейдеры:

class CustomVertex : public IVtxFmt
{
public:
  float m_Position[3];      // x, y, z      offset 0, size = 3*sizeof(float)    
  float m_Normal[3];        // nx, ny, nz;  offset 3
  float m_TexCoords[2];     // u, v         offset 6
  float m_Colour[4];        // r, g, b, a   offset 8
  float m_Tangent[3];       // r, g, b      offset 12
  float m_Bitangent[3];     // r, g, b      offset 15
};

Поэтому я работаю с моделью бревенчатой ​​хижины, которую я скачал из Интернета.

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

Так что мой первый инстинкт был разобрать файл obj и в итоге

vector<vertex>
vector<Normal>
vector<TexCoord>

Это не просто перевести в мой формат CustomVertex, поскольку в файле может быть 210 вершин, 100 текстовых координат и 80 нормалей.

После списка ~390 лиц в этом формате:

f 83/42/1 67/46/1 210/42/1 

Я сталкиваюсь со следующим в файле:

#
# object tile00
#

с последующим определением вершин.

Итак, из этого я сделал вывод, что модель может состоять из нескольких подобъектов, каждый из которых определяется числом граней; каждая грань определяется 3-мя значениями вершин / нормалей / текстовых координат.

Поэтому, чтобы получить вектор CustomVertex, я думаю, что мне нужно сделать следующее:

создать и заполнить:

vector <vertex>
vector <normal>
vector <texcoord>

vector <indices>

Мне нужно создать CustomVertex для каждой уникальной тройки v/vn/vt в определениях лица.

Итак, я подумал о создании карты:

std::vector<CustomVertex> and
std::map< nHashId, CustomVertex_index >

Таким образом, моя идея состоит в том, что для каждого v/vn/vt, с которым я сталкиваюсь, я создаю хэш этой строки, например, nHashId = hash("80/50/1")* и ищу хэш на карте. Если ничего не существует, я создаю CustomVertex и добавляю его в вектор, затем добавляю вновь созданный хэш и CustomVertex_index в карту.

*: Создавая хэш строки v/vn/vt, я создаю уникальное числовое значение, соответствующее этой строке, которое, я надеюсь, быстрее будет искать / сравнивать на карте, чем эквивалентный текст.

Если я сталкиваюсь с соответствием хешу, я считаю, что customvertex уже существует, и вместо создания нового CustomVertex я просто добавляю запись CustomVertex_index в вектор индексов и продолжаю.

Поскольку это кажется вычислительно дорогостоящим упражнением, я предполагаю, что буду выгружать свои массивы CustomVertex (и соответствующие массивы индексов) на диск для последующего извлечения, а не анализировать каждый раз файл obj.

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

Итак, на мои вопросы: 1. Мой метод кажется правильным или сумасшедшим? Если сумасшедший, пожалуйста, укажите, где я иду не так.

  1. Можете ли вы определить возможные проблемы?

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

2 ответа

Можете ли вы определить возможные проблемы?

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

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

Есть гораздо более простой способ: просто сравнивайте индексы и не используйте хэши.

Вместо создания строкового хеша "v/vn/vt", идея состоит в том, чтобы хэшировать только v как целое число. После этого вы получаете корзину, которая содержит все комбинации "v/vn/vt", которые имеют один и тот же индекс v.

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

Другие вопросы по тегам