In Blender 2.63, with the addition of BMesh, it looks like UV data got obfuscated, and I can’t find where the data got moved to or how to analyze it.
It used to be (2.62) you could go
me = bpy.data.meshes['MyMesh']
uv = me.uv_textures['UVMap']
for j,face in enumerate(me.faces):
face_uv = uv.data[j]
print(face.uv1)
print(face.uv2)
print(face.uv3)
back when all faces had three (or four) points.
Now in 2.62, that “face_uv” object you get is a MeshTexturePoly, and it doesn’t have “uvN” properties, it only seems to have an “image” property. You can still set UV coordinates for meshes in 2.63; so where are they actually being saved?
It does look like the data is there under “uv_layers” rather than “uv_textures” in 2.63, though there’s a few bits of strangeness there:
Starting with a default scene, I UVunwrapped the default cube and then do this in the console:
>>> bpy.data.meshes['Cube'].uv_layers.active
bpy.data.meshes['Cube'].uv_layers["UVMap"]
>>> bpy.data.meshes['Cube'].uv_layers["UVMap"]
Traceback (most recent call last):
File "<blender_console>", line 1, in <module>
KeyError: 'bpy_prop_collection[key]: key "UVMap" not found'
>>> bpy.data.meshes['Cube'].uv_layers.data["UVMap"]
Traceback (most recent call last):
File "<blender_console>", line 1, in <module>
KeyError: 'bpy_struct[key]: key "UVMap" not found'
The element that the console says is returned by the call for the “active” uv_layer can’t actually be called!
The “uv_layers” (bpy_prop_collection) “data” element is actually a reference back to the Mesh type (bpy_types.Mesh), not the collection of UV layers, which appears to make it a broken bpy_prop_collection where you can’t get items by key…?
However, I can grab the return of “active” and it appears to be valid:
the first face ha x vertices, so x uv.co
the second have y vertices, so the uv of the second face are betwen x and x+y
face [(3v),(4v),(7v)]
uv[1,1,1,2,2,2,2,3,3,3,3,3,3,3]
so with 2 loop for you kan easiely have the result
Here’s my little proof of concept script that shows you how the UV, loops, and vertices are linked in Blender 2.62 and higher:
import bpy
if bpy.app.version[0] < 2 or bpy.app.version[1] < 62:
raise Exception("Only for Blender 2.62 and above")
bpy.ops.object.mode_set(mode='OBJECT') # Can't access coordinate data in edit mode currently
me = bpy.data.meshes['Cube']
for f in me.polygons:
print("Polygon", f.index, "from loop index", f.loop_start, "and length", f.loop_total)
for i in f.loop_indices: # <-- python Range object with the proper indices already set
l = me.loops[i] # The loop entry this polygon point refers to
v = me.vertices[l.vertex_index] # The vertex data that loop entry refers to
print(" Loop index", l.index, "points to vertex index", l.vertex_index, \
"at position", v.co)
for j,ul in enumerate(me.uv_layers):
print(" UV Map", j, "has coordinates", ul.data[l.index].uv, \
"for this loop index")
The me.loops object is really a lookup list, and each entry is NOT a loop in and of itself. The “loops” are really polygons and are stored in the me.polygons structure. Using me.polygons, you can slice the me.loops list into chunks.
Running this on the default cube shows that me.polygons has six entries (the six faces of the cube). Each polygon refers to four loop indexes, making the me.loops list 24 entries long.
Every UV layer in me.uv_layers has a “data” attribute that is a list that is the same length as the me.loops list. Every me.loops entry relates to the same index entry in the me.uv_layers[n].data list.
GAH! But the me.uv_layers attribute is readonly! I’m trying to port a mesh importer to 2.63, and the mesh data being imported has UV data; how do I create those coordinates…?
i was having issues with the UV data as well but I got it figured out finally!
import bmesh
me = bmesh.new()
me.from_mesh(object.data) #Your mesh data
for face in me.faces:
uvs = []
for f in face.loops:
uv = f[uv_layer].uv
uvs.extend(uv)
try:
uv1x = uvs[0]
uv1y = 1.0 - uvs[1]
except:
uv1x = 0.0
uv1y = 0.0
try:
uv2x = uvs[2]
uv2y = 1.0 - uvs[3]
except:
uv2x = 0.0
uv2y = 0.0
try:
uv3x = uvs[4]
uv3y = 1.0 - uvs[5]
except:
uv3x = 0.0
uv3y = 0.0
I found i had to add the 1.0 - to the y values. I had to do that last time, but it seems to work fine so, i’m not going to question unless it breaks! Try it out anyways
i have no problems here to change uv coords when mesh is in object mode
and about adding new uv_layer: the tricks seems to be to add a new UV texture uv_textures.new(), which implicitly creates a uv_layer. Then set the .uv properties (seen in import_3ds.py)
Removing UV textures is supposed to also remoev UV layers:
import bpy
for ob in bpy.context.selected_editable_objects:
if ob.type == 'MESH':
for uv_tex in ob.data.uv_textures:
ob.data.uv_textures.remove(uv_tex)
Oh, thank you!
I’ve found another way to remove all UV’s on objects:
import bpy
obj= bpy.context.selected_objects
for ob in obj:
if ob.type == 'MESH':
bpy.context.scene.objects.active = ob
while(len(ob.data.uv_textures)):
bpy.ops.mesh.uv_texture_remove()