1
$\begingroup$

I'm struggling to learn Blender's structures and types and use Python to modify meshes. In trying to sort out image updating, bmesh and mesh data, I copied the following code from the Blender 2.64 API reference (Blender 2.74 installed):

# This example assumes we have a mesh object selected

import bpy
import bmesh

me = bpy.context.object.data

bm = bmesh.new()   # create an empty BMesh

bm.from_mesh(me)   # fill it in from a Mesh

for v in bm.verts:
    v.co.x += 1.0

bm.to_mesh(me)

me.update

(I added the last line as suggested by another question here.)

Using the startup cube, and switching to Edit mode, I tried the script. It fails, pointing to:

bm.to_mesh(me)

What have I missed?

$\endgroup$
3
$\begingroup$

The mesh me must not be in edit-mode when writing the bmesh object bm back to me - like the error message tells you:

ValueError: to_mesh(): Mesh 'Cube' is in editmode

So, either run the code when the mesh is in object mode, respectively change the mode: bpy.ops.object.mode_set(mode='OBJECT')

Or use a wrapped bm, which means to directly manipulate the editmode mesh through the bmesh module:

import bpy
import bmesh

me = bpy.context.object.data

bm = bmesh.from_edit_mesh(me)

for v in bm.verts:
    v.co.x += 1.0

# Update mesh, so we see the changes.
bmesh.update_edit_mesh(me, False, False)

# Because we did not add or remove geometry,
# tessface=False and destructive=False can be used.
# DO NOT DO THIS IF YOU CHANGED GEOMETRY!
# Blender will crash otherwise.

As you see, you can either fill in a mesh, manipulate it (purely in memory, the original mesh is not changed) and write it to a mesh datablock afterwards if desired OR gain access to the editmesh and edit it directly with all changes being applied to the original mesh without copying (the update at the end is required though).

You can chose which way to use based on the current mode to avoid unnecessary mode switches:

import bpy
import bmesh

me = bpy.context.object.data

if me.is_editmode:
    bm = bmesh.from_edit_mesh(me)
else:
    bm = bmesh.new()
    bm.from_mesh(me)

for v in bm.verts:
    v.co.x += 1.0

if bm.is_wrapped:
    bmesh.update_edit_mesh(me, False, False)
else:
    bm.to_mesh(me)
    me.update()

BTW: update is a method of the Mesh type, you need to call it: me.update()

$\endgroup$
  • $\begingroup$ Would not have posted the question if I had seen the error message. However, it is nowhere to be found. What's up with that? $\endgroup$ – Hertfordkc Aug 7 '15 at 22:31
  • $\begingroup$ Got it. Thanks for the thoroughness of your reply. Most helpful. $\endgroup$ – Hertfordkc Aug 7 '15 at 22:43
  • 1
    $\begingroup$ Errors are logged to the system console. How to get it depends on your operating system. Read more here: wiki.blender.org/index.php/User:Fade/Doc:2.6/Manual/Interface/… $\endgroup$ – CoDEmanX Aug 7 '15 at 23:06
  • $\begingroup$ One more hint: if you really want to translate the entire or parts of a mesh by the same value, use bmesh.ops.translate(bm, vec=(1,0,0), verts=bm.verts) (here: translate the entire mesh +1 on X axis). Another example to translate every other vert +0.5 on Z axis: bmesh.ops.translate(bm, vec=(0, 0, 0.5), verts=[v for v in bm.verts if v.index % 2]). Please accept the answer if your problem is solved. $\endgroup$ – CoDEmanX Aug 8 '15 at 13:26

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.