Blender 2.6 JSON导出器,纹理坐标麻烦

Posted

技术标签:

【中文标题】Blender 2.6 JSON导出器,纹理坐标麻烦【英文标题】:Blender 2.6 JSON exporter, texture coordinates trouble 【发布时间】:2012-11-23 19:43:16 【问题描述】:

我正在尝试为 Blender 2.6x 编写一个简单的 JSON 导出器,因为我能找到的唯一一个 (http://code.google.com/p/blender-machete/) 不适用于 2.6。我从搅拌机中获取顶点、法线和索引没有任何问题,但尽我所能,我似乎无法弄清楚为什么纹理坐标出现错误。纹理似乎在一个简单的立方体的表面上对角倾斜,并且拉伸......真的很丑而且错误。我一直在网上寻找一些官方出口商的来源,但我仍然无法弄清楚,所以我希望有人能给我一些提示或解决方案。

我用来访问纹理坐标的代码如下:

    # add texture coordinates to scene_data structure
    m = bpy.context.active_object.to_mesh(bpy.context.scene, True, 'PREVIEW')
    for j in range(len(m.tessfaces)):
        if len(m.tessface_uv_textures) > 0:
            scene_data[mesh_number]["tex_coords"].append( m.tessface_uv_textures.active.data[j].uv1.x )
            scene_data[mesh_number]["tex_coords"].append( m.tessface_uv_textures.active.data[j].uv1.y )
            scene_data[mesh_number]["tex_coords"].append( m.tessface_uv_textures.active.data[j].uv2.x )
            scene_data[mesh_number]["tex_coords"].append( m.tessface_uv_textures.active.data[j].uv2.y )
            scene_data[mesh_number]["tex_coords"].append( m.tessface_uv_textures.active.data[j].uv3.x )
            scene_data[mesh_number]["tex_coords"].append( m.tessface_uv_textures.active.data[j].uv3.y )

这给了我一个纹理坐标列表,但不知何故我做错了,因为我上面解释的纹理外观不正确。

除了显示代码,我不知道还能做什么,因为我已经尝试以我能想到的各种方式对其进行更改,所以这是上面的 sn-p 代码所在的函数:

def get_json(objects, scene):
    """ Currently only supports one scene. 
        Exports with -Z forward, Y up. """

    scene_data = []
    mesh_number = -1

    # iterate over each mesh
    for i in range(len(bpy.data.objects)):
        if bpy.data.objects[i].type == 'MESH':

            mesh_number += 1

            bpy.ops.object.mode_set(mode='OBJECT')

            # convert all the mesh's faces to triangles
            bpy.data.objects[i].select = True
            bpy.context.scene.objects.active = bpy.data.objects[i]

            bpy.ops.object.mode_set(mode='EDIT')

            bpy.ops.mesh.select_all(action='SELECT')
            bpy.ops.mesh.quads_convert_to_tris()
            bpy.context.scene.update()

            bpy.ops.object.mode_set(mode='OBJECT')

            bpy.data.objects[i].select = False

            # add data to scene_data structure
            scene_data.append(
                "name"          : bpy.data.objects[i].name,
                "vertices"      : [],
                "indices"       : [],
                "normals"       : [],
                "tex_coords"    : []
            )

            # iterate over all the vertices in the mesh
            for j in range(len(bpy.data.objects[i].data.vertices)):
                # add vertex to scene_data structure
                scene_data[mesh_number]["vertices"].append( bpy.data.objects[i].data.vertices[j].co.x + bpy.data.objects[i].location.x )
                scene_data[mesh_number]["vertices"].append( bpy.data.objects[i].data.vertices[j].co.z + bpy.data.objects[i].location.z )
                scene_data[mesh_number]["vertices"].append( -(bpy.data.objects[i].data.vertices[j].co.y + bpy.data.objects[i].location.y) )

                # add vertex normal to scene_data structure
                scene_data[mesh_number]["normals"].append( bpy.data.objects[i].data.vertices[j].normal.x )
                scene_data[mesh_number]["normals"].append( bpy.data.objects[i].data.vertices[j].normal.z )
                scene_data[mesh_number]["normals"].append( -(bpy.data.objects[i].data.vertices[j].normal.y) )

            # iterate over each face in the mesh
            for j in range(len(bpy.data.objects[i].data.polygons)):
                verts_in_face = bpy.data.objects[i].data.polygons[j].vertices[:]

                # iterate over each vertex in the face
                for k in range(len(verts_in_face)):

                    # twiddle index for -Z forward, Y up
                    index = k
                    if index == 1: index = 2
                    elif index == 2: index = 1

                    # twiddle index so we draw triangles counter-clockwise
                    if index == 0:  index = 2
                    elif index == 2: index = 0

                    # add index to scene_data structure
                    scene_data[mesh_number]["indices"].append( verts_in_face[index] )

            # add texture coordinates to scene_data structure
            m = bpy.context.active_object.to_mesh(bpy.context.scene, True, 'PREVIEW')
            for j in range(len(m.tessfaces)):
                if len(m.tessface_uv_textures) > 0:
                    scene_data[mesh_number]["tex_coords"].append( m.tessface_uv_textures.active.data[j].uv1.x )
                    scene_data[mesh_number]["tex_coords"].append( m.tessface_uv_textures.active.data[j].uv1.y )
                    scene_data[mesh_number]["tex_coords"].append( m.tessface_uv_textures.active.data[j].uv2.x )
                    scene_data[mesh_number]["tex_coords"].append( m.tessface_uv_textures.active.data[j].uv2.y )
                    scene_data[mesh_number]["tex_coords"].append( m.tessface_uv_textures.active.data[j].uv3.x )
                    scene_data[mesh_number]["tex_coords"].append( m.tessface_uv_textures.active.data[j].uv3.y )

    return json.dumps(scene_data, indent=4)

有人能告诉我我做错了什么吗?我已经在这几天了,没有任何进展。

【问题讨论】:

【参考方案1】:

经过进一步研究,我想我可能知道问题所在,但我不确定...

从这里: http://www.gamedev.net/topic/602169-opengl-drawing-cube-using-gldrawelements-and-gltexcoordpointer/page_p_4811454#entry4811454

这是不能使用共享顶点的经典示例。一旦引入除位置以外的顶点属性,立方体就需要有 24 个顶点,而不是 8 个。立方体的角不是共享顶点,因为它们没有相同的纹理坐标。

例如,前两个三角形由索引 [0, 1, 2, 0, 2, 3],如果你引用顶点和纹理坐标 阵列,那张脸很好。后两个三角形由 索引 [0, 4, 5, 0, 5, 1],同时引用顶点数组 正确制作立方体的第二个面,得到的纹理 坐标完全坏了。

我认为这是我的问题是对的,还是我错了?

编辑: 通过使用更多顶点位置几乎可以使纹理工作。现在唯一的问题是一个简单立方体的一个面将被扭曲并倾斜到它的正确位置。所有其他面孔看起来都很好。

这是几乎可以工作的功能:

def get_json(objects, scene):
    """ Currently only supports one scene. 
        Exports with -Z forward, Y up. """

    object_number = -1
    scene_data = []

    # for every object in the scene
    for object in bpy.context.scene.objects:

        # if the object is a mesh       
        if object.type == 'MESH':

            object_number += 1

            # convert all the mesh's faces to triangles
            bpy.ops.object.mode_set(mode='OBJECT')
            object.select = True
            bpy.context.scene.objects.active = object

            # triangulate using new Blender 2.65 Triangulate modifier
            bpy.ops.object.modifier_add(type='TRIANGULATE')
            object.modifiers["Triangulate"].use_beauty = False
            bpy.ops.object.modifier_apply(apply_as="DATA", modifier="Triangulate")

            bpy.ops.object.mode_set(mode='OBJECT')

            object.select = False

            # add data to scene_data structure
            scene_data.append(
                "name"          : object.name,
                "vertices"      : [],
                "indices"       : [],
                "normals"       : [],
                "tex_coords"    : []
            )

            vertex_number = -1

            # for each face in the object
            for face in object.data.polygons:
                vertices_in_face = face.vertices[:]

                # for each vertex in the face
                for vertex in vertices_in_face:

                    vertex_number += 1

                    # store vertices in scene_data structure
                    scene_data[object_number]["vertices"].append( object.data.vertices[vertex].co.x + object.location.x )
                    scene_data[object_number]["vertices"].append( object.data.vertices[vertex].co.z + object.location.z )
                    scene_data[object_number]["vertices"].append( -(object.data.vertices[vertex].co.y + object.location.y) )

                    # store normals in scene_data structure
                    scene_data[object_number]["normals"].append( object.data.vertices[vertex].normal.x )
                    scene_data[object_number]["normals"].append( object.data.vertices[vertex].normal.z )
                    scene_data[object_number]["normals"].append( -(object.data.vertices[vertex].normal.y) )

                    # store indices in scene_data structure
                    scene_data[object_number]["indices"].append(vertex_number)

            # texture coordinates
            #   bug: for a simple cube, one face's texture is warped
            mesh = object.to_mesh(bpy.context.scene, True, 'PREVIEW')
            if len(mesh.tessface_uv_textures) > 0:
                for data in mesh.tessface_uv_textures.active.data:
                    scene_data[object_number]["tex_coords"].append( data.uv1.x )
                    scene_data[object_number]["tex_coords"].append( data.uv1.y )
                    scene_data[object_number]["tex_coords"].append( data.uv2.x )
                    scene_data[object_number]["tex_coords"].append( data.uv2.y )
                    scene_data[object_number]["tex_coords"].append( data.uv3.x )
                    scene_data[object_number]["tex_coords"].append( data.uv3.y )

    return json.dumps(scene_data, indent=4)

我想知道只有一张脸的纹理扭曲的原因是什么?我快到了,但似乎无法弄清楚这一点。

【讨论】:

以上是关于Blender 2.6 JSON导出器,纹理坐标麻烦的主要内容,如果未能解决你的问题,请参考以下文章

创建一个弹出菜单来调用自定义导出器(Blender 2.6 API)?

Three.js 导出没有纹理的 Blender 模型

如何在 Blender 导出脚本中导出每个顶点的 UV 坐标

如何从Blender导出fbx纹理以用于Monogame

搅拌机可以按顶点 UV 坐标导出吗?

Blender 导出器 (v70) 到 json three.js 蒙皮动画