# Getting vertex coordinates with applied shape keys

I'm trying to write a function that returns vertex coordinates including their transformation that was a applied by (one or multiple) shape keys. Currently this is how I tried, but I only get vertex coordinates before the shape keys are applied:

def get_vertex_coords():
ob = bpy.data.objects['cc_base_body']
curmode = bpy.context.object.mode
bpy.ops.object.mode_set(mode='OBJECT')
mesh = ob.to_mesh(preserve_all_data_layers=True, depsgraph = bpy.context.evaluated_depsgraph_get())
bm = bmesh.new()
bm.from_mesh(mesh)
coords = []
for vertex in bm.verts:
if vertex.index in poi:
coords.append(vertex.co) # ob.matrix_world @
bpy.ops.object.mode_set(mode=curmode)
return coords


Is there any way to do this?

Thanks to the comments I found a way, see my posted answer.

• What is the difference between your function and New Shape From Mix? Aug 11, 2021 at 12:43
• I'm not sure I know exactly what new shape from mix does. My function is supposed to give me the world coordinates of vertices (filtered with the poi list). New shape from mix adds a new shape key I think. Would that lead to the vertex coordinates being adjusted (in a way accessible to me?) Edit: I just saw this answer: blender.stackexchange.com/questions/5364/… and I will see if I find a way to use that without deleting all my shape keys Aug 11, 2021 at 13:06
• Big question mark re why toggle into edit mode in question code? Feel that bmesh.from_object in OBJECT mode is the go here. Aug 11, 2021 at 13:29
• That is my bad, it was a desperate change, changed back to the correct Object mode. Aug 11, 2021 at 13:31

## 2 Answers

Bmesh.from_object

Would use this method for the modified / deformed coordinates

How do I get a mesh data-block with modifiers and shape keys applied in Blender 2.8? since we are going to load up a bmesh.

Modified and deformed cube shown in edit mode. Test script below, create a modified and deform applied mesh copy, or with cage = True the deformed cage mesh as shown in edit mode above, with modifiers intact.

Instead of printing result, returned mesh as a result and made object copies to visualize result.

import bpy
import bmesh
from bpy import context

def get_modified_mesh(ob, cage=False):
bm = bmesh.new()
bm.from_object(
ob,
context.evaluated_depsgraph_get(),
cage=cage,
)

#bm.transform(ob.matrix_world)
me = bpy.data.meshes.new("Deformed")
bm.to_mesh(me)
return me

context.object.update_from_editmode()
# make a modified and deformed copy
ob = context.object.copy()
me = get_modified_mesh(ob)
ob.modifiers.clear()
ob.data = me
context.collection.objects.link(ob)

# make a deformed copy (keep modifiers)
ob = context.object.copy()
me = get_modified_mesh(ob, cage=True)
ob.data = me
context.collection.objects.link(ob)


Note, if poi is a list of indices then

bm.verts.ensure_lookup_table()
coords = [bm.verts[i].co for i in poi]


looping over all and testing for inclusion is very unoptimal.

• Thanks a lot, both of those work for my application, also thanks for the optimization, poi is indeed a list of indices Aug 15, 2021 at 14:07
• Thankyou, appreciated. See blender.stackexchange.com/a/233823/15543 verts[poi] Aug 15, 2021 at 14:15

Edit: Thanks to Crantisz and this answer How to apply shape keys? I found a way:

I duplicate the object whose vertices I'm looking at, add a new shape key to the duplicated object:

ob.shape_key_add(name="temp", from_mix=True)


and then delete all shape keys from the duplicated object:

for key in ob.data.shape_keys.key_blocks:
ob.shape_key_remove()


I can then get the vertex coordinates and delete the new object:

def get_vertex_coords():
curmode = bpy.context.object.mode
bpy.ops.object.mode_set(mode='OBJECT')
#deselected all then select the object we want to copy (using operators since this seems to be the proper way to do it in blender)
bpy.ops.object.select_all(action='DESELECT')
bpy.data.objects['cc_base_body.001'].select_set(True) #The mesh name should be a parameter here
bpy.ops.object.duplicate()
ob = bpy.context.active_object # This should now give us the duplicated object

#Add the shape key
ob.shape_key_add(name="temp", from_mix=True)
#now remove all shape keys
for key in ob.data.shape_keys.key_blocks:
ob.shape_key_remove()

mesh = ob.to_mesh(preserve_all_data_layers=True, depsgraph = bpy.context.evaluated_depsgraph_get())
bm = bmesh.new()
bm.from_mesh(mesh)
coords = []
for vertex in bm.verts:
if vertex.index in poi:
coords.append(vertex.co) # ob.matrix_world @
bpy.ops.object.delete()
bpy.ops.object.mode_set(mode=curmode)

return coords