5
$\begingroup$

I have a mesh with armature modifier. Is there any efficient way to read its vertices coordinates with modifiers accounted in Blender 2.80?

So far the only way I found is to duplicate the object, apply modifier, read vertices and remove duplicated object:

def extract_vertices(my_object):
    # Duplicate object
    for obj in bpy.data.objects: obj.select_set(False)
    my_object.select_set(True)
    bpy.ops.object.duplicate_move()

    # Apply modificators
    duplicated_object = bpy.context.scene.objects[-1]
    bpy.context.view_layer.objects.active = duplicated_object
    duplicated_object.select_set(True)
    bpy.ops.object.modifier_apply(apply_as='DATA', modifier="RIG")

    # Read vertices
    vertices = [v.co for v in duplicated_object.data.vertices]

    # Remove duplicated object
    my_object.select_set(False)
    bpy.ops.object.delete()

    return vertices

It works, but very slow. I need to run this thing thousands of times in the loop, adjusting modifier every iteration.

It seems that Object.to_mesh() described in answer here could be exactly what I need, but it's signature is changed in Blender2.80 and there's no apply_modifiers parameter anymore.

$\endgroup$
4
  • $\begingroup$ Also relevant: blenderartists.org/t/2-80-cheat-sheet-for-updating-add-ons/… $\endgroup$ – Robert Gützkow Aug 28 '19 at 20:32
  • $\begingroup$ @rjg, probably, but not sure. As I newbie I wouldn't immediately figure out how to get vertices coordinates from answers to that question. $\endgroup$ – Andrii Zymohliad Aug 29 '19 at 7:56
  • $\begingroup$ Also the answer here is more complete, IMO. It reminds to do things like bm.verts.ensure_lookup_table() and bm.free(), which I wouldn't know is needed. $\endgroup$ – Andrii Zymohliad Aug 29 '19 at 8:11
  • 1
    $\begingroup$ Sure, no problem lemon's answer is more complete. You don't necessarily need bm.free() (you won't create a memory leak if you don't use it), but it is more efficient because it deallocates the memory right away and not just when there is no reference anymore. It's always a good idea to check the Blender Python API docs (docs.blender.org/api/current/bmesh.html) $\endgroup$ – Robert Gützkow Aug 29 '19 at 12:11
6
$\begingroup$

Using bmesh and the dependencies graph, you can get an evaluated bmesh:

import bpy
import bmesh

depsgraph = bpy.context.evaluated_depsgraph_get()

obj = bpy.data.objects['Cube']

bm = bmesh.new()

bm.from_object( obj, depsgraph )

bm.verts.ensure_lookup_table()

print( "----" )
for v in bm.verts:
    print( v.co )

bm.free()

Edit:

obj.to_mesh should work too (have not tested) but if you don't want to create a mesh, this is not needed.

$\endgroup$
3
  • $\begingroup$ Thanks a lot! I spent hours hitting the wall! Should I call bpy.context.evaluated_depsgraph_get() every time I update modifiers? Or once at initialization is enough? $\endgroup$ – Andrii Zymohliad Aug 28 '19 at 16:44
  • $\begingroup$ @AndriiZymohliad, you should call it each time in my opinion. Untested, but it is logical to think that this is a data structure as another so nothing updates it automatically. Please, add a comment here if you test that (should be simple to do with a modifier, simple deform for instance, and a keyframe on it). $\endgroup$ – lemon Aug 28 '19 at 16:51
  • 1
    $\begingroup$ It seems to work with just a single initialization of depsgraph. I guess the getter just obtains some sort of handle to it and is cheap anyway. $\endgroup$ – Andrii Zymohliad Aug 28 '19 at 16:59

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