4
$\begingroup$

I've only just started studying the Blender Python API. I'm writing a script (see below) to automate something I've done by hand : joining two adjacent cubes and cleaning up the resulting mesh.

After joining and removing doubles, I expect to have 12 vertices instead of 16 in the resulting object. In the Info header, this seems to be the case, but when I print to the windows terminal I still see 16. Also I do see the output from remove_double(), here's a screenshot :

Info header and Windows console screenshot

So what's wrong here ? What is the right way to access an object's mesh, and count its vertices ?

Joao

import bpy

# Create two adjacent cubes and join them
bpy.ops.mesh.primitive_cube_add(location=(1,0,0))
ob = bpy.context.object
bpy.ops.mesh.primitive_cube_add(location=(3,0,0))
ob.select = True
bpy.ops.object.join()

# Expect 16 vertices, 24 edges, 12 faces
result = bpy.context.object
print(str(len(result.data.vertices)))

# Go to edit mode, remove double vertices
bpy.ops.object.mode_set(mode = 'EDIT')
bpy.ops.mesh.remove_doubles()

# Expect 12 vertices, 20 edges, 11 faces
result = bpy.context.object
print(str(len(result.data.vertices)))
$\endgroup$
2
$\begingroup$

This is the correct way, however blender is not updating the data. Exit edit mode, (bpy.ops.object.mode_set(mode='OBJECT')) and the correct result appears. Oddly enough, blender displays the correct number of vertices in the header, I'm not sure why the python api doesn't.

$\endgroup$
4
$\begingroup$

With the standard API (bpy), the editmesh is flushed to mesh when you change mode. What you access is the mesh, which is still in the old state as it was when you entered editmode. What you want is the editmesh's vertex count, but you can't directly access it with bpy.

You could change mode to flush changes, but there's actually a better way in recent Blender versions:

# Load the objects edit-mode data into the object data
bpy.context.object.update_from_editmode()

If you work with the BMesh Module (bmesh) and a wrapped bmesh, the number of vertices will be immediately updated - but you may still need to flush changes from bmesh to mesh after adding/removing geometry or Blender will crash:

import bpy
import bmesh

me = bpy.context.object.data
bm = bmesh.from_edit_mesh(me)

print(len(bm.verts)) # 8 (in case of cube)

bm.verts.remove(bm.verts[0])

print(len(bm.verts)) # 7

bmesh.update_edit_mesh(me)
$\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.