12

Blender 2.64 から Python エクスポート スクリプトを作成しています。アイデアは、OpenGL VBO に適した方法でメッシュ データをエクスポートしようとしているということです。したがって、構造体レイアウトの配列で頂点属性をエクスポートしています。たとえば、頂点、法線、および 1 組のテクスチャ座標を持つメッシュの場合、vertexAttributeVBO 内のそれぞれは 8 つの連続する float になります。

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 を参照する可能性があります。data.verticesしたがって、フェイスの loop_indices を実際に使用して、オブジェクト ジェネラルとdata.uv_layers[].dataコンテナ内のベクトルと uvCoord の両方を検索する必要があります。

これにより、面ごとに UV マップを適用できます。したがって、各面に異なる UV テクスチャが適用された立方体を作成できます。2 つの隣接する面が頂点を共有している場合でも、頂点は面に応じて異なる UV 座標を持ちます。

それでも、隣接する面にアンラップしているため、メッシュは同じ頂点に対して異なる UV を持つべきではありません。つまり、私の UV マップでは、ラップされていないメッシュは隣接する面のセット (たとえば、6 つの面で構成される立方体の場合は十字形と考えてください) であり、隣接する 2 つの面の間では、それらの共通の頂点が同じポイントにマップされる必要があります。 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]])

ご覧のとおり、上記のコードの意味は、頂点を共有するメッシュの面 (この場合は三角形) を反復処理するために、頂点に複数回アクセスすることです。頂点にアクセスするたびに、まだ 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 マッピングが明らかにめちゃくちゃになります。つまり、モデルは頂点と法線に関しては適切にレンダリングされますが、UV テクスチャは明らかに正しくマッピングされていません。

何かご意見は?つまり、正しくエクスポートしてアプリの OpenGL レンダリング コードを台無しにしているか、頂点と UV 座標間の間違ったマッピングをエクスポートしています。(または両方、確かに..しかし、今のところ、エクスポートスクリプトを台無しにしていると思います)。

最後にもう 1 つ、上記の Python コードを変更して、頂点 1 に対して、UV がまだ割り当てられていない場合にのみ追加するのではなく、頂点に割り当てられた新しい各 UV を追加すると、次のようになります。

[-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 レイヤーが 1 つしかないことに注意してください。明らかに、Blender は 2 つの UV 座標を頂点 1 に割り当てました。

4

1 に答える 1

3

すべてが隣接している場合、頂点ごとに単一の UV になるように、UV を補間または調整/ブレンドする方法があると思います。しかし、その間、誰も代替案を提案しなかったため、異なる UV を使用して頂点を複製し、GL_ELEMENT_ARRAY のエクスポートの試みを中止することになりました。次のコードは、(glDrawArrays を使用して) 単一の VBO でレンダリングする場合に機能します。

def exportMesh(filepath):

    # Only one mesh per scene
    objList = [object for object in bpy.context.scene.objects if object.type == 'MESH']

    if len(objList) == 0:
        return
    elif len(objList) > 1:
        return
    #raise exepction? dialog box?


    # Process the single mesh object:
    mesh = objList[0]

    # File name is same as the mesh's name in Blender
    meshFilePath = filepath[0 : filepath.rindex('/') + 1] + mesh.name + ".mesh"
    file = open(meshFilePath, 'w')

    WorldTransform = Matrix().Identity(4)
    WorldTransform *= Matrix.Rotation(radians(90), 4, "X")
    file.write('World Transform:\n')
    for rcol in WorldTransform_T.row:
        file.write('{:9f} {:9f} {:9f} {:9f}\n'.format(row[0], row[1], row[2], row[3]))
    file.write('\n')

    # Mesh (local) transform matrix
    file.write('Mesh Transform:\n')
    localTransform_T = mesh.matrix_local.copy()
    localTransform_T.transpose()
    for row in localTransform_T.row:
        file.write('{:9f} {:9f} {:9f} {:9f}\n'.format(row[0], row[1], row[2], row[3]))
    file.write('\n')

    vertexAttributeList = []
    for triangle in mesh.data.polygons:
        vertices = list(triangle.vertices)
        i = 0
        for vertex in vertices:
            vertexAttribute = list(mesh.data.vertices[vertex].co)

            if triangle.use_smooth:
                vertexAttribute.extend(list(mesh.data.vertices[vertex].normal))
            else:
                vertexAttribute.extend(list(triangle.normal))

            for uv_layer in mesh.data.uv_layers:
                uvCoord = uv_layer.data[triangle.loop_indices[i]].uv
                vertexAttribute.extend([uvCoord[0], 1 - uvCoord[1]])

            totalVertexWeight = 0
            jointWeights = [group.weight for group in mesh.data.vertices[vertex].groups]
            jointIndices = [group.group for group in mesh.data.vertices[vertex].groups]
            for weight in jointWeights:
                totalVertexWeight += weight

            vgNum = len(mesh.vertex_groups)
            jointWeightsAttribute = []
            jointIndicesAttribute = []
            for vgIndex in range(4):
                if vgIndex < len(jointIndices):
                    jointWeightsAttribute.append(jointWeights[vgIndex] / totalVertexWeight)
                    jointIndicesAttribute.append(jointIndices[vgIndex])
                else:
                    jointWeightsAttribute.append(0)
                    jointIndicesAttribute.append(0)

            vertexAttribute.extend(jointWeightsAttribute)
            vertexAttribute.extend(jointIndicesAttribute)

            vertexAttributeList.append(vertexAttribute)
            i += 1

    # VBO
    vNum = len(vertexAttributeList)
    tNum = len(mesh.data.uv_layers)
    file.write('VBO Length: {:d}\n'.format(vNum))
    for vertexAttribute in vertexAttributeList:
        file.write('{:9f} {:9f} {:9f} {:9f} {:9f} {:9f} {:9f} {:9f} {:9f} {:9f} {:9f} {:9f} {:d} {:d} {:d} {:d}\n'.format(vertexAttribute[0],
                                                                                                                          vertexAttribute[1],
                                                                                                                          vertexAttribute[2],
                                                                                                                          vertexAttribute[3],
                                                                                                                          vertexAttribute[4],
                                                                                                                          vertexAttribute[5],
                                                                                                                          vertexAttribute[6],
                                                                                                                          vertexAttribute[7],
                                                                                                                          vertexAttribute[8],
                                                                                                                          vertexAttribute[9],
                                                                                                                          vertexAttribute[10],
                                                                                                                          vertexAttribute[11],
                                                                                                                          vertexAttribute[12],
                                                                                                                          vertexAttribute[13],
                                                                                                                          vertexAttribute[14],
                                                                                                                          vertexAttribute[15]))
    file.write('\n')


    # Done writing mesh file
    file.close()
于 2012-11-20T06:04:30.060 に答える