Я пишу сценарий экспорта Python из Blender 2.64. Идея в том, что я пытаюсь экспортировать данные меша удобным для OpenGL VBO способом. Итак, я экспортирую атрибуты вершин в массив макетов структур. Например, для меша с вершинами, нормалями и 1 парой координат текстуры каждый vertexAttribute
в VBO будет 8 последовательными плавающими точками:
vvvnnntt
Все идет нормально. Проблема в том, что когда Blender выполняет UV-отображение, он может фактически назначать разные uv одной и той же вершине.
То есть, скажем, у вас есть куб: у вас есть 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-карте развернутая сетка представляет собой набор смежных граней (представьте, например, форму креста, если бы это был куб, состоящий из 6 граней), и между двумя смежными гранями их общие вершины должны отображаться в одной и той же точке. на уф-карте.
Итак, учитывая вышесказанное, я подумал, что этот подход должен работать:
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]])
Как видите, в приведенном выше коде подразумевается, что я буду посещать вершины более одного раза, потому что я перебираю грани меша (в данном случае треугольники), которые имеют общие вершины. И каждый раз, когда я посещаю вершину, если ей еще не назначены UV-координаты, я назначаю их, просматривая их с помощью 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-текстура явно не отображается правильно.
Есть предположения? Я имею в виду, либо я экспортирую правильно и испортил код рендеринга OpenGL в своем приложении, либо я экспортирую неправильное сопоставление между вершинами и uv-координатами. (или и то, и другое, конечно ... но я предполагаю, что сейчас испортил сценарий экспорта).
И последнее, если я изменю приведенный выше код 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]
И учтите, что в этом примере только один УФ-слой. Итак, очевидно, что Blender присвоил вершине 1 2 uv-координаты.