1
$\begingroup$

I have a cuboidal structure. I have it uv unwrapped. Now, I need to apply a same seamless texture to all the sides. In effect, I need the uv faces one over the other. The code snippet below shows my approach in selecting the faces and placing them over each other,

bpy.context.area.type = 'IMAGE_EDITOR'
//Translating the faces, to place them one above the other
bpy.ops.uv.select(extend=False, location=(0.0, 0.0))
bpy.ops.transform.translate(value=(0.378906, 0, 0)) 

bpy.ops.uv.select(extend=False, location=(0.25, 0.0))
bpy.ops.transform.translate(value=(0.135343, 0, 0))

bpy.ops.uv.select(extend=False, location=(0.75, 0.0))
bpy.ops.transform.translate(value=(-0.351892, 0, 0))

bpy.ops.uv.select(extend=False, location=(0.6, 0.0))
bpy.ops.transform.translate(value=(-0.108398, 0, 0))    

While I achieved as much as that, the next step requires me to scale them, so as to apply the image texture properly. So, once again I started selecting the same faces using the same method above. The only change was that "extend" was set to "true", in order to extend the selection. Well, simple as it felt, it didn't work. Then I realized, it selects based on the location and now all the faces have been translated to the same location.

It meant, I can't use this same selection statement. But this is the only method I know and I am still new to blender python.

My question. Is there an effective and easier way to select the uv faces, say like faces[0]? If so, please share.

New Edit:

Now this is the sequence of operations which I executed in the console,

>>> import bmesh
>>> bm = bmesh.new()
>>> obj = bpy.context.active_object
>>> bm.from_mesh(obj) 
>>> bm.faces.
             active
             ensure_lookup_table(
             get(
             index_update(
             layers
             new(
             remove(
             sort(

As you can see, bm.faces does not have any attribute named loop.

$\endgroup$
2
$\begingroup$

Manipulating the UV coordinates of a face is usually done via the bmesh API. Here is an example extracted from http://web.purplefrog.com/~thoth/blender/python-cookbook/barber-pole.html

def spiralUVs(mesh, xPlus):
    # add a UV layer called "spiral" and make it slanted.
    mesh.uv_textures.new("spiral")
    bm = bmesh.new()
    bm.from_mesh(mesh)

    bm.faces.ensure_lookup_table()

    uv_layer = bm.loops.layers.uv[0]

    nFaces = len(bm.faces)
    for fi in range(nFaces):
        x0 = fi*2/nFaces
        x1 = (fi+1)*2/nFaces
        # assume a quad; 0..3
        bm.faces[fi].loops[0][uv_layer].uv = (x0, 0)
        bm.faces[fi].loops[1][uv_layer].uv = (x1, 0)
        bm.faces[fi].loops[2][uv_layer].uv = (xPlus+x1, 1)
        bm.faces[fi].loops[3][uv_layer].uv = (xPlus+x0, 1)
    bm.to_mesh(mesh)

Other examples that manipulate UV maps include http://web.purplefrog.com/~thoth/blender/python-cookbook/expand-uv-to-fit.html and http://web.purplefrog.com/~thoth/blender/python-cookbook/uv-from-geometry-cubic.html

$\endgroup$
  • $\begingroup$ Sorry, doesn't seem to work. Can you tell me some method just to select multiple uv unwrapped faces? $\endgroup$ – Gabriel Mar 12 '16 at 13:21
  • $\begingroup$ I have the feeling, the code you posted is wrong. I can't find any "loops" attribute under bm.faces. I checked in the console. And perhaps that is the reason, I get the error " no attribute named loops". Please help me out. $\endgroup$ – Gabriel Mar 12 '16 at 13:39
  • $\begingroup$ That is strange. I just fired up a copy of Blender 2.76 and ran my barber-pole.py script and it worked fine. Maybe if you use <kbd>ctrl-space</kbd> to do completion on the faces[fi] reference in the console and post the resulting completion options to pasteall it will help us figure out what is going wrong. $\endgroup$ – Mutant Bob Mar 12 '16 at 15:31
  • $\begingroup$ I have edited my question and have pasted the auto complete options. As seen, bm,faces does not have any loop attribute. $\endgroup$ – Gabriel Mar 12 '16 at 16:33
  • $\begingroup$ yes, but I bet that faces[0] has a loop attribute. faces is the list. faces[0] is the first face. $\endgroup$ – Mutant Bob Mar 12 '16 at 16:45
0
$\begingroup$

I had a similar issue. I needed to iterate through each face in the UV map and find out if a vertex of the mesh is mapped more than once to the UV map.

This was quite useful: https://blenderartists.org/forum/archive/index.php/t-254004.html

Especially this

for polygon in mesh.polygons:

print("Polygon", polygon.index, \
      "from loop index", polygon.loop_start, \
      "and length", polygon.loop_total)

for loop_index in polygon.loop_indices: # <-- python Range object with the proper indices already set

    loop_entry = mesh.loops[loop_index] # The loop entry this polygon point refers to
    vertex = mesh.vertices[loop_entry.vertex_index] # The vertex data that loop entry refers to

    print("\tLoop index", loop_entry.index, \
          "points to vertex index", loop_entry.vertex_index, \
          "at position", vertex.co)

    for j, ul in enumerate(mesh.uv_layers):
        print("\t\tUV Map", j, \
              "has coordinates", ul.data[loop_entry.index].uv, \
              "for this loop index")

See answer of midnight426 for more detail, it is basically his code, i just changed some variable names. Hope it helps.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.