3
$\begingroup$

I am trying to create a mesh via a Python script and set a texture for it.

My code so far:

def add_mesh(self, coords, uvs, faces, texture, texHeight, texWidth):
  me = bpy.data.meshes.new("myMesh")
  ob = bpy.data.objects.new("myObject", me)

  me.from_pydata(parsedCoords, [], parsedFaces)
  me.update(calc_edges=True)

  mat = self._make_material("myMaterial", (1,1,1), (1,1,1), 1)
  tex = self._make_texture("myTexture", texture, texWidth, texHeight)
  mTex = mat.texture_slots.add()
  mTex.texture_coods = 'UV'
  mTex.use_map_color_diffuse = True
  mTex.diffuse_color_factor = 1.0
  mTex.blend_type = 'MULTIPLY'

  # Missing: Set the uv-coords for the mesh

  me.materials.append(mat)

I use _make_material and _make_texture which are self-defined. But I think they work.

For the missing part I found using the API-documentation following

uv_layer = me.uv_layers.active.data
for poly in me.polygons:
    for loop_ind in range(poly.loop_start, poly.loop_start+ poly.loop_total):
        vInd = me.loops[loop_index].vertex_index
        uv_layer[loop_index].uv = tuple( uvs[vertex_index] )

The passed uvs is a list uv-coordinates as lists. They are in the same order as the vertices.

My problem now is that the uv_layer = me.uv_layers.active.data does not work. It results in AttributeError: 'NoneType' object has no attribute 'data'

I think my mesh has no uv_layer. How do I add one? Is my code correct if I add a uv_layer to the mesh? I am really unsure about it.

Thank you for your help!

Greetings, Dragonseel

$\endgroup$
3
$\begingroup$

As Dragonseel mentioned: the bmesh is important. http://web.purplefrog.com/~thoth/blender/python-cookbook/barber-pole.html contains a spiralUVs function which assigns UV coordinates to the faces of a cylinder. It demonstrates the mesh.uv_textures.new(name) function for creating a new UV layer.

Here is the function from that page:

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)

    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
        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)
$\endgroup$
1
$\begingroup$

The only way I found for editing the UV-Coordinates of a mesh is via the BMesh module.

This module can be imported in the script via import bmesh.

Assume the code I wrote in the question I will give my solution for the missing part which edits the uv-coords.

bpy.ops.object.mode_set(mode='EDIT')
bm = bmesh.from_edit_mesh(me)

uv_layer = bm.loops.layers.uv.verify()
bm.faces.layers.tex.verify()

for f in bm.faces:
    for l in f.loops:
        luv = l[uv_layer]
        luv.uv = tuple(uvs[l.vert.index])

bmesh.update_edit_mesh(me)
bpy.ops.object.mode_set(mode='OBJECT')

Note that I only tested to set all the uvs to (0,0) since I have another problem with the uv coordinates. But it worked and my mesh was successfully painted red.

Greetings, Dragonseel

$\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.