Здавалка
Главная | Обратная связь

Загрузка меша из формата .obj



Загрузив меш самостоятельно при помощи собственного загрузчика из формата .obj имеет много преимуществ перед загрузкой меша из формата .x. Вы можете получить полный контроль над процессом загрузки и рендера меша.

Ознакомимся с форматом obj и способом, существующим для его загрузки. Формат obj является по сути дампом вершинного и индексного буфера модели в редакторе. Формат obj текстовый, то есть вы можете любой файл .obj открыть текстовым редактором. Вот типичный пример файла формата obj:

# mtllib ./box2.mtl g # object (null) to come ... # v -1.968504 0.000000 1.968504 v 1.968504 0.000000 1.968504 v -1.968504 0.000000 -1.968504 v 1.968504 0.000000 -1.968504 v -1.968504 3.937008 1.968504 v 1.968504 3.937008 1.968504 v -1.968504 3.937008 -1.968504 v 1.968504 3.937008 -1.968504 # 8 vertices   vt 0.000000 0.000000 0.000000 vt 1.000000 0.000000 0.000000 vt 0.000000 1.000000 0.000000 vt 1.000000 1.000000 0.000000 vt 0.000000 0.000000 0.000000 vt 1.000000 0.000000 0.000000 vt 0.000000 1.000000 0.000000 vt 1.000000 1.000000 0.000000 vt 0.000000 0.000000 0.000000 vt 1.000000 0.000000 0.000000 vt 0.000000 1.000000 0.000000 vt 1.000000 1.000000 0.000000 # 12 texture vertices   vn 0.000000 -2.000000 -0.000000 vn 0.000000 -1.000000 -0.000000 vn 0.000000 -1.000000 -0.000000 vn 0.000000 -2.000000 -0.000000 vn 0.000000 2.000000 -0.000000 vn 0.000000 1.000000 -0.000000 vn 0.000000 1.000000 -0.000000 vn 0.000000 2.000000 -0.000000 # 8 vertex normals   g (null) f 1/10/1 3/12/3 4/11/4 f 4/11/4 2/9/2 1/10/1 f 5/9/5 6/10/6 8/12/8 f 8/12/8 7/11/7 5/9/5 f 1/5/1 2/6/2 6/8/6 f 6/8/6 5/7/5 1/5/1 f 2/1/2 4/2/4 8/4/8 f 8/4/8 6/3/6 2/1/2 f 4/5/4 3/6/3 7/8/7 f 7/8/7 8/7/8 4/5/4 f 3/1/3 1/2/1 5/4/5 f 5/4/5 7/3/7 3/1/3 # 12 faces   g

Разберем формат файла obj. Каждая строка начинается с идентификационного символа. Комментарии # не учитываются. Символы бывают следующие: v, vt, vn, f. Эти символы нам понадобятся больше всего. Символ v обозначает вершину. После этого символа в строке идут координаты этой вершины. Символ vt обозначает текстурные координаты. Так как текстурные координаты имеют только u и v координаты, то третья цифра для них будет всегда равна нулю. Символ vn обозначает нормаль.

При загрузке в программу каждой строке, начинающейся с идентификационного символа v, vt или vn присваивается индекс, так, как если бы сам файл содержал индексы каждой строки, таким образом:

# mtllib ./box2.mtl g # object (null) to come ... # v -1.968504 0.000000 1.968504 [1] v 1.968504 0.000000 1.968504[2] v -1.968504 0.000000 -1.968504 [3] v 1.968504 0.000000 -1.968504 [4] v -1.968504 3.937008 1.968504 [5] v 1.968504 3.937008 1.968504[6] v -1.968504 3.937008 -1.968504 [7] v 1.968504 3.937008 -1.968504 [8] # 8 vertices   vt 0.000000 0.000000 0.000000 [1] vt 1.000000 0.000000 0.000000 [2] vt 0.000000 1.000000 0.000000 [3] vt 1.000000 1.000000 0.000000 [4] vt 0.000000 0.000000 0.000000 [5] vt 1.000000 0.000000 0.000000 [6] vt 0.000000 1.000000 0.000000 [7] vt 1.000000 1.000000 0.000000 [8] vt 0.000000 0.000000 0.000000 [9] vt 1.000000 0.000000 0.000000 [10] vt 0.000000 1.000000 0.000000 [11] vt 1.000000 1.000000 0.000000 [12] # 12 texture vertices   vn 0.000000 -2.000000 -0.000000 [1] vn 0.000000 -1.000000 -0.000000 [2] vn 0.000000 -1.000000 -0.000000 [3] vn 0.000000 -2.000000 -0.000000 [4] vn 0.000000 2.000000 -0.000000 [5] vn 0.000000 1.000000 -0.000000 [6] vn 0.000000 1.000000 -0.000000 [7] vn 0.000000 2.000000 -0.000000 [8] # 8 vertex normals   g (null) f 1/10/1 3/12/3 4/11/4 f 4/11/4 2/9/2 1/10/1 f 5/9/5 6/10/6 8/12/8 f 8/12/8 7/11/7 5/9/5 f 1/5/1 2/6/2 6/8/6 f 6/8/6 5/7/5 1/5/1 f 2/1/2 4/2/4 8/4/8 f 8/4/8 6/3/6 2/1/2 f 4/5/4 3/6/3 7/8/7 f 7/8/7 8/7/8 4/5/4 f 3/1/3 1/2/1 5/4/5 f 5/4/5 7/3/7 3/1/3 # 12 faces   g

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

Каждая тройка чисел в строке f формата obj обозначает следующие: номер вершины v, номер координаты текстуры vt, и номер нормали vn и так три раза. Также обратите внимание, что вершин(8) в нашем примере меньше чем текстурных координат к ним (12). Конечно же для DirectX равенство количества вершин и текстурных координат должно соблюдаться. Таким образом, формат obj содержит только условно дамп индексного буфера. На самом деле, требуется определенный алгоритм, чтобы преобразовать данные из obj в настоящий вершинный и индексный буфер.

Этот алгоритм следующий: Возьмем первые три цифры из первой строки f. Это индексы 1/10/1. Соответственно, возьмем первую строку v, десятую строку vt и первую строку vn.

v -1.968504 0.000000 1.968504 [1] vt 1.000000 0.000000 0.000000 [10] vn 0.000000 -2.000000 -0.000000 [1]

Теперь у нас образовался набор данных, как раз и соответствующих одной вершине для вершинного буфера, а именно: координата, текстурная координата и нормаль. Теперь образуем из этих данных структуру типа VERTEX:

structVERTEX { XMFLOAT3 pos; XMFLOAT3 texcoord; XMFLOAT3 normal; } VERTEX vertices[1024];

У нас существует временный массив для вершинного буфера vertices. Добавим данные вершины 1/10/1 в этот массив. Номер этой вершины массива vertices будет равен 0, так как она первая.

vertices[0]= ... v, vt, vn of 1/10/1 vertex ...

Затем возьмем следующим элемент из строки f. Это будет 3/12/3.

vertices[1]= ... v, vt, vn of 3/12/3 vertex ...

Таким же образом возьмем следующим элемент из строкиf. Это будет 4/11/4.

vertices[2]= ... v, vt, vn of 4/11/4 vertex ...

Одновременно с увеличением индекса новых элементов вершинного буфера – это числа 0, 1, 2 записываем эти индексы в индексный буфер.

indices[count++]=0; indices[count++]=1; indices[count++]=2;

Таким образом, при каждой новой тройке чисел из строки f мы должны собрать новый элемент типа VERTEX и добавить этот элемент в вершинный буфер, если там нет точно такого же элемента. Если во временном вершинном буфере уже содержится элемент с точно такими же координатами, текстурными координатами и нормалью мы не должны его добавлять заново а просто мы должны определить номер этого элемента. Таким образом, индексный буфер будет содержать данные наподобие тех, что на этом листинге:

indices[count++]=0[new]; indices[count++]=1[new]; indices[count++]=2[new]; indices[count++]=3[new]; indices[count++]=2[copy]; indices[count++]=4[new];






©2015 arhivinfo.ru Все права принадлежат авторам размещенных материалов.