我正在编写一个来自Blender2.64的python导出脚本。我的想法是尝试以一种OpenGL VBO友好的方式导出网格数据。所以我正在导出结构布局数组中的顶点属性。例如,对于具有顶点、法线和一对纹理坐标的网格,VBO中的每个vertexAttribute
将是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中,如果我理解正确,一个面可以用uvCoord 0引用顶点0,而另一个面可以用不同的uvCoord引用相同的顶点0。因此,面的循环索引实际上必须用于查找objets常规data.vertices
和data.uv_layers[].data
容器中的向量和uvCoord。
这允许对每个面应用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_索引查找它们来指定它们。毕竟,我的假设是,在一天结束的时候,每个顶点都有唯一的紫外坐标。
上面的代码给出了以下布局,例如(我将显示网格的前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坐标之间的映射。(或者两者都可以。。但我现在假设我弄乱了导出脚本)。
最后一件事,如果我更改上面的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,以便在所有东西都相邻的情况下每个顶点都有一个UV。但与此同时,由于没有人提出替代方案,我最终用不同的uv复制了顶点,并放弃了导出GL_ELEMENT_数组的尝试。如果使用单个VBO(使用glDrawArrays)进行渲染,则以下代码有效:
相关问题 更多 >
编程相关推荐