Экспортер JSON в Blender 2.6, проблема с текстурой
Я пытаюсь написать простой экспортер JSON для Blender 2.6x, потому что единственный, который я смог найти ( http://code.google.com/p/blender-machete/), не работает с 2.6. У меня не было никаких проблем с получением вершин, нормалей и индексов из Blender, но, как бы я ни пытался, я просто не могу понять, почему координаты текстуры выходят из строя. Текстуры кажутся наклоненными по диагонали к лицу простого куба и растянутыми... действительно уродливыми и неправильными. Я искал в Интернете и через источник для некоторых официальных экспортеров, но я все еще не могу понять это, поэтому я надеялся, что кто-то может дать мне несколько советов или решений.
Кусок кода, который я использую для доступа к координатам текстуры, выглядит так:
# 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 )
Это дает мне список координат текстуры, но почему-то я делаю это неправильно, из-за неправильного внешнего вида текстуры, как я объяснил выше.
Я не знаю, что еще делать, но покажу код, так как я пытался изменить его всеми возможными способами, поэтому вот функция, где приведен фрагмент кода выше:
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 ответ
После дальнейших исследований, я думаю, что, возможно, знаю проблему, но я не уверен в этом...
Это классический пример, когда вы не можете использовать общие вершины. Как только вы вводите атрибут вершины, отличный от позиции, у куба должно быть 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)
Мне интересно, что может быть причиной искажения текстуры только одного лица? Я почти там, но не могу понять это.