Я пишу экспорт python script из Blender 2.64. Идея заключается в том, что я пытаюсь экспортировать данные сетки в OpenGL VBO-friendly. Поэтому я экспортирую атрибуты вершин в массив макетов структур. Например, для сетки с вершинами, нормалями и одной парой текстурных координат каждый vertexAttribute
в VBO будет иметь 8 последовательных поплавков:
vvvnnntt
Пока все хорошо. Проблема в том, что, когда Blender выполняет UV-отображение, он может фактически назначить разные uvs одной вершине.
То есть, скажем, у вас есть куб: у вас есть 8 вершин, и у вас есть, скажем, 6 граней (квадраты в этом случае). Я бы ожидал, что грань/многоугольник с индексами 0,1,2,3 подразумевается:
vertex 0, normal 0, uvCoord0
vertex 1, normal 1, uvCoord1
vertex 2, normal 2, uvCoord2
vertex 3, normal 3, uvCoord3
И, следовательно, любое упоминание индекса 0, например, на любой грани всегда будет означать
вершина 0, нормальная 0, uvCoord0 кортеж. Ну, получается в Blender, если я правильно понял, что одно лицо может ссылаться на вершину 0 с uvCoord 0, а другая может ссылаться на одну и ту же вершину 0 с другим uVCoord. Таким образом, лицо loop_indices должно фактически использоваться для поиска как вектора, так и uvCoord в общих объектах контейнеров data.vertices
и data.uv_layers[].data
.
Это позволяет применять uv-карты для лица. Таким образом, у вас может быть куб, в котором каждое лицо имеет другую текстуру uv, и даже если две соседние грани имеют общую вершину, вершина имеет другую координату uv в зависимости от лица.
Тем не менее, моя сетка не должна иметь разные uv для одной вершины, так как я разворачиваюсь на соседние грани. Это означает, что в моей карте UV развернутая сетка представляет собой набор смежных граней (например, например, крестообразную форму, если это куб, состоящий из 6 граней) и между двумя смежными гранями, их общие вершины должны отображаться в одну и ту же точку в карте uv.
Итак, учитывая вышеизложенное, я думал, что этот подход должен работать:
vertexAttributeList = []
for vertex in mesh.data.vertices:
vertexAttribute = list(vertex.co)
vertexAttribute.extend(list(vertex.normal))
vertexAttributeList.append(vertexAttribute)
for triangle in mesh.data.polygons:
for uv_layer in mesh.data.uv_layers:
for i in triangle.loop_indices:
lookupIndex = mesh.data.loops[i].vertex_index
if len(vertexAttributeList[lookupIndex]) == 6:
uvCoord = uv_layer.data[i].uv
vertexAttributeList[lookupIndex].extend([uvCoord[0], 1 - uvCoord[1]])
Как вы можете видеть, импликация в приведенном выше коде заключается в том, что я буду посещать вершины более одного раза, потому что я выполняю итерацию по граням сетки (в этом случае треугольники), которые разделяют вершины. И каждый раз, когда я посещаю вершину, если у нее еще не назначены ее УФ-координаты, я назначаю их, просматривая их с помощью треугольника loop_indices. В конце концов, мое предположение заключалось в том, что у меня есть, в конце концов, уникальные uv-координаты на вершину.
Приведенный выше код дает ему следующий макет, например (я показываю первые 6 атрибутов вершины сетки):
-1.000000 -1.000000 -1.000000 -0.707083 -0.707083 0.000000 0.076381 0.948520
-1.000000 1.000000 -1.000000 -0.707083 0.707083 0.000000 0.454183 0.948519
1.000000 1.000000 -1.000000 0.707083 0.707083 0.000000 0.325162 0.948519
1.000000 -1.000000 -1.000000 0.707083 -0.707083 0.000000 0.205674 0.948519
-1.000000 -1.000000 1.000000 -0.577349 -0.577349 0.577349 0.581634 0.795012
-1.000000 1.000000 1.000000 -0.577349 0.577349 0.577349 0.454183 0.795012
...
Но когда я использую эту информацию плюс грань сетки, которая выглядит так:
4 5 1
5 6 2
6 7 3
7 4 0
...
чтобы отобразить мою модель в моей программе (вроде как двигатель), отображение UV явно перепутано. То есть, модель рендерит тонкие точки с вершинами и нормалями, но текстура uv явно неправильно отображена.
Любые мысли? Я имею в виду, либо я экспортирую право, либо испортил код рендеринга OpenGL в своем приложении, либо я экспортирую неправильное сопоставление между вершинами и координатами uv. (или оба, конечно... но я предполагаю, что теперь я испортил экспорт script).
Последнее, если я изменю приведенный выше код python, чтобы добавить каждый новый uv, который присваивается вершине вместо добавления только в том случае, если uv еще не был назначен, для вершины 1 я получаю:
[-1.0, -1.0, -1.0, -0.7070833444595337, -0.7070833444595337, 0.0, 0.07638061791658401, 0.9485195726156235, 0.5816344618797302, 0.9485194832086563, 0.07638061791658401, 0.9485195726156235]
И в этом примере у вас есть только один слой с uv. Таким образом, Blender присваивал вершинам 1 координаты 2 uv.