I want to use the Python API to create a sequence of absolute shape keys that deform a mesh over time, however I'm having a lot of trouble figuring out the proper way to do that.
Currently I'm trying to mimic how I would do it by hand, i.e. using
bpy.ops, which I'm sure isn't the best way to begin with, but even then I can't get it to work. A minimal sample of what I'm trying to do:
import bpy if __name__ == '__main__': # Create nx*ny points as a starting mesh nx = 11 ny = 11 data = [(x/10., y/10., (x**2+y**2)/200.) \ for x in range(nx) for y in range(ny)] # Create edge loops to define faces faces =  count = 0 for i in range(ny*(nx-1)): if count < ny-1: faces.append((i, i+1, i+ny+1, i+ny)) count += 1 else: count = 0 # Create mesh and object mesh = bpy.data.meshes.new('mesh') obj = bpy.data.objects.new('obj', mesh) obj.location = (0, 0, 0) bpy.context.scene.objects.link(obj) mesh.from_pydata(data, , faces) mesh.update(calc_edges = True) verts = obj.data.vertices # Create a base shape key. This much seems to work. bpy.context.scene.objects.active = obj bpy.ops.object.shape_key_add() bpy.ops.object.shape_key_retime() obj.data.shape_keys.use_relative = False skeys = obj.data.shape_keys skbs = skeys.key_blocks skbs[obj.active_shape_key_index].interpolation = 'KEY_LINEAR' # Create 10 sequential deformations for n in range(10): # Create new shape key bpy.ops.object.shape_key_add() skbs[obj.active_shape_key_index].interpolation = 'KEY_LINEAR' bpy.ops.object.shape_key_move(type='BOTTOM') bpy.ops.object.mode_set(mode='EDIT') # Deform the mesh for i in range(len(verts)): verts[i].co.z *= data[i] mesh.update(calc_edges=True) bpy.ops.object.mode_set(mode='OBJECT')
This does create the shape keys and put them in the correct order, but the mesh deformations aren't linked to the keys (because I'm modifying the vertices directly instead of using the edit-mode tools?), so the mesh always resembles the initial data. If I manually add another shape key after running this script, it magically takes the geometry of the last iteration, but the ones in between still don't seem to do anything.
What is the proper way to implement this (ideally without as much reliance on