5
$\begingroup$

I'm currently working on my custom format exporter form blender and have hit some kind of a speed bump... Through tons of experimentation I have finally found that UV data is stored in:

mesh.uv_layers[layer].data

But I don't think that the internal blender data format agrees with the way I'm going about exporting. First off, my exporter assumes that all faces are either triangles or quads. If a face is a quad then it outputs it as two triangles:

t1 = 0 1 2
t2 = 2 3 0

Now, my exporter just iterates over mesh.polygons and outputs per vertex per triangle, but uv_layers.data obviously doesn't store it this way. So how could I go about exporting it? I need a way to lookup the uv coordinates for a specific vertex and output it in the same way as I do this:

for vert in fac.vertices:
     file.write("+v %g %g %g\n" % (obj.vertices[vert].co.x, obj.vertices[vert].co.y, obj.vertices[vert].co.z))

But using the vertex's UV instead.

Any suggestions are greatly appreciated! Thanks guys!!!

EDIT:

For anyone who runs into a similar problem, here is my working code:

    for fac in obj.polygons:
        if len(fac.vertices) == 3:
            for li in fac.loop_indices:
                file.write("+t %g %g\n" % (uv_layer[li].uv.x, uv_layer[li].uv.y))
        if len(fac.vertices) == 4:
            file.write("+t %g %g\n" % (uv_layer[fac.loop_indices[0]].uv.x, uv_layer[fac.loop_indices[0]].uv.y))
            file.write("+t %g %g\n" % (uv_layer[fac.loop_indices[1]].uv.x, uv_layer[fac.loop_indices[1]].uv.y))
            file.write("+t %g %g\n" % (uv_layer[fac.loop_indices[2]].uv.x, uv_layer[fac.loop_indices[2]].uv.y))
            file.write("+t %g %g\n" % (uv_layer[fac.loop_indices[2]].uv.x, uv_layer[fac.loop_indices[2]].uv.y))
            file.write("+t %g %g\n" % (uv_layer[fac.loop_indices[3]].uv.x, uv_layer[fac.loop_indices[3]].uv.y))
            file.write("+t %g %g\n" % (uv_layer[fac.loop_indices[0]].uv.x, uv_layer[fac.loop_indices[0]].uv.y))

This code will export the uv coordinates for any triangle or quad in the mesh (Quads are broken down into two triangles). The result is a list of the vertex uv coordinates in order of the vertices. So every 3 lines represents a triangle.

obj is the mesh data of the current mesh, which is accessed by bpy.data.meshes['NameOfMesh'].

$\endgroup$
1
  • $\begingroup$ You shouldn't have to guess this or do a lot of experimenting, blender comes with exporters that write out UV's (OBJ, PLY, FBX, 3DS) you can see how they do it. $\endgroup$
    – ideasman42
    Feb 26, 2014 at 8:04

1 Answer 1

4
$\begingroup$

UV's aren't per vertex in Blender, but per loop (which means per face-vertex). Also see here and here.

For triangle export, use the tessellated faces and split the quads into triangles or triangulate using the bmesh operator. Export the faces together with the UV coordinates. If UVs are the same for a shared vertex, you could simply pick the first loop, otherwise interpolate? (may give weird results...)

Print loop and vertex indices per polygon together with UV coordinate (uv index equals loop index):

import bpy

me = bpy.context.object.data
uv_layer = me.uv_layers.active.data

for poly in me.polygons:
    print("Polygon", poly.index)
    for li in poly.loop_indices:
        vi = me.loops[li].vertex_index
        uv = uv_layer[li].uv
        print("    Loop index %i (Vertex %i) - UV %f %f" % (li, vi, uv.x, uv.y))
$\endgroup$
7
  • $\begingroup$ Okay, this helped a little, but I'm still confused. Is the data stored similar to polygons? Could I access it by going layer.data[vert]? Thanks. $\endgroup$
    – user2270
    Feb 26, 2014 at 7:42
  • $\begingroup$ No, you can't access it via vertex (index), it uses loop indices. It is like UVLayer[Polygon[#].loop_indices[#]].uv. Added example to loop over all polygons and print loop / vertex indices together with UV coordiante to my answer. $\endgroup$
    – CodeManX
    Feb 26, 2014 at 9:13
  • $\begingroup$ This gives me errors. It doesn't tell me what though. But it doesn't complain if I comment out uv = uv_layer[li].uv. I made sure that all of the variables connect properly to my variables. And it doesn't look like uv_layer is iterable. Is it supposed to be uv_layer.data[li]? I tried that and it still fails. $\endgroup$
    – user2270
    Feb 26, 2014 at 21:21
  • $\begingroup$ Works fine, the object needs a UV map of course (above script prints active UV map only, but you can adapt that to your liking): me.uv_layers[LAYER_NAME_OR_INDEX].data[LOOP_INDEX]. You need to check the System console, python errors will usually not show in the error popup or built-in python console. $\endgroup$
    – CodeManX
    Feb 26, 2014 at 22:16
  • $\begingroup$ Okay, I've played around with it a bit, and it isn't throwing any errors and it outputs the correct number of coordinates. I am going to test it a little bit to make sure that the values correspond correctly. But otherwise, thanks for the help! I'll mark your answer as correct and post what worked for me once I decide all is perfect! $\endgroup$
    – user2270
    Feb 26, 2014 at 22:57

You must log in to answer this question.