From Blender 2.79 onward the new modifier Surface deform makes this answer obsolete.
This code rigs simulated mesh so there is bone for every edge of mesh, such rig can control high-res version of cloth:

The code:
import bpy
import time
import sys
from mathutils import Matrix, Vector
def new_bone(armature_ob, bone_name, head_loc, tail_vec, parent=None, deform=True, layer=0):
'''Works only in edit mode'''
new_bone = armature_ob.data.edit_bones.new(bone_name)
new_bone.head = head_loc
new_bone.tail = Matrix.Translation((0,0,0)) * Vector(tail_vec) + new_bone.head
new_bone.parent = parent
new_bone.use_deform = deform
new_bone.layers = [i==layer for i in range(32)]
armature_ob.data.layers[layer] = True
return new_bone
def add_constraint(const_type, const_entity, target_obj, sub_target_name):
'''Works only in pose mode'''
constraint = const_entity.constraints.new(const_type)
constraint.target = target_obj
constraint.subtarget = sub_target_name
return constraint
class RigifyMeshPanel(bpy.types.Panel):
bl_label = "Rigify Mesh"
bl_space_type = 'VIEW_3D'
bl_region_type = 'TOOLS'
bl_category = "Rigify Mesh"
def draw(self, context):
layout = self.layout
layout.operator("object.rigify_mesh", icon='OUTLINER_OB_ARMATURE')
class RigifyMesh(bpy.types.Operator):
bl_idname = "object.rigify_mesh"
bl_label = "Rigify Mesh"
bl_description = "Generates a Rig with bones for every edge of active mesh"
@classmethod
def poll(self, context):
try:
active = context.active_object
return active and active.type == 'MESH'
except (AttributeError, KeyError, TypeError):
return False
def execute(self, context):
mesh_ob = context.active_object
progress = ""
start = time.clock()
# Force object mode:
if bpy.context.active_object.mode != 'OBJECT':
bpy.ops.object.mode_set(mode='OBJECT')
# Generate vert groups for each vert:
sys.stdout.write("------------------- RIGIFYING MESH -----------------\n")
sys.stdout.write("Generating Vertex Groups (step 1/4): ")
sys.stdout.flush()
for ivert in [v.index for v in mesh_ob.data.vertices if str(v.index) not in mesh_ob.vertex_groups]:
progress = "Vert %i of %i" % (ivert, len(mesh_ob.data.vertices)-1)
sys.stdout.write(progress+chr(8)*len(progress))
sys.stdout.flush()
mesh_ob.vertex_groups.new(name=str(ivert))
mesh_ob.vertex_groups[str(ivert)].add([ivert], 1.0, 'REPLACE')
# Update mesh data
mesh_ob.update_tag({'DATA'})
sys.stdout.write("DONE IN "+str(round(time.clock()-start, 3))+"s"+" "*(len(progress)-9)+"\n")
sys.stdout.flush()
start = time.clock()
# Get and Reset Armature
sys.stdout.write("Cleaning up Armature (step 2/4): ")
sys.stdout.flush()
if bpy.data.objects.get(mesh_ob.name+'_Rig') is not None:
rig_ob = bpy.data.objects[mesh_ob.name+'_Rig']
context.scene.objects.active = rig_ob
# Clean constraints:
bpy.ops.object.mode_set(mode='POSE')
for id, pbone in enumerate(rig_ob.pose.bones):
for constraint in pbone.constraints:
progress = "cleaning %i of %i" % (id, len(mesh_ob.data.vertices)+3*len(mesh_ob.data.edges)-1)
sys.stdout.write(progress+chr(8)*len(progress))
sys.stdout.flush()
pbone.constraints.remove(constraint)
else:
bpy.ops.object.armature_add(location=mesh_ob.location)
rig_ob = context.active_object
rig_ob.name = mesh_ob.name + '_Rig'
# Clean bones:
bpy.ops.object.mode_set(mode='EDIT')
for bone in rig_ob.data.edit_bones:
rig_ob.data.edit_bones.remove(bone)
sys.stdout.write("DONE IN "+str(round(time.clock()-start, 3))+"s"+" "*(len(progress)-9)+"\n")
sys.stdout.flush()
start = time.clock()
# Add bones:
sys.stdout.write("Generating Bones (step 3/4): ")
sys.stdout.flush()
mesh_ob.data.calc_normals()
for id, vert in enumerate(mesh_ob.data.vertices):
progress = "Bone %i of %i" % (id, len(mesh_ob.data.vertices)+len(mesh_ob.data.edges)-2)
sys.stdout.write(progress+chr(8)*len(progress))
sys.stdout.flush()
new_bone(rig_ob, "vert"+str(id), vert.co, vert.normal/4, None, False, 1)
for id, edge in enumerate(mesh_ob.data.edges):
progress = "Bone %i of %i" % (id+len(mesh_ob.data.vertices), len(mesh_ob.data.vertices)+len(mesh_ob.data.edges)-2)
sys.stdout.write(progress+chr(8)*len(progress))
sys.stdout.flush()
v0 = mesh_ob.data.vertices[edge.vertices[0]]
v1 = mesh_ob.data.vertices[edge.vertices[1]]
new_bone(rig_ob, "edge"+str(id), v0.co, v1.co-v0.co, rig_ob.data.edit_bones[edge.vertices[0]])
sys.stdout.write("DONE IN "+str(round(time.clock()-start, 3))+"s"+" "*(len(progress)-9)+"\n")
sys.stdout.flush()
start = time.clock()
# Add bone constraints:
bpy.ops.object.mode_set(mode='POSE')
pbones = rig_ob.pose.bones
sys.stdout.write("Generating Constraints (step 4/4): ")
sys.stdout.flush()
# Setup vertex bones constraints:
for id, vert in enumerate(mesh_ob.data.vertices):
progress = "Constraint %i of %i" % (id, len(mesh_ob.data.vertices)+3*len(mesh_ob.data.edges)-1)
sys.stdout.write(progress+chr(8)*len(progress))
sys.stdout.flush()
child_of = add_constraint('CHILD_OF', pbones["vert"+str(id)], mesh_ob, str(id))
context_py = context.copy()
context_py["constraint"] = child_of
rig_ob.data.bones.active = pbones["vert"+str(id)].bone
bpy.ops.constraint.childof_set_inverse(context_py, constraint=child_of.name, owner='BONE')
# Setup edge bones constraints:
for id, edge in enumerate(mesh_ob.data.edges):
bone0 = "vert" + str(edge.vertices[0])
bone1 = "vert" + str(edge.vertices[1])
progress = "Constraint %i of %i" % (3*id+len(mesh_ob.data.vertices), len(mesh_ob.data.vertices)+3*len(mesh_ob.data.edges)-1)
sys.stdout.write(progress+chr(8)*len(progress))
sys.stdout.flush()
add_constraint('DAMPED_TRACK', pbones["edge"+str(id)], rig_ob, bone1)
progress = "Constraint %i of %i" % (3*id+1+len(mesh_ob.data.vertices), len(mesh_ob.data.vertices)+3*len(mesh_ob.data.edges)-1)
sys.stdout.write(progress+chr(8)*len(progress))
sys.stdout.flush()
const = add_constraint('COPY_ROTATION', pbones["edge"+str(id)], rig_ob, bone0)
const.use_z = False
const.target_space = 'POSE'
const.owner_space = 'POSE'
progress = "Constraint %i of %i" % (3*id+2+len(mesh_ob.data.vertices), len(mesh_ob.data.vertices)+3*len(mesh_ob.data.edges)-1)
sys.stdout.write(progress+chr(8)*len(progress))
sys.stdout.flush()
add_constraint('STRETCH_TO', pbones["edge"+str(id)], rig_ob, bone1)
# Hide vert bone layer
rig_ob.data.layers[1] = False
sys.stdout.write("DONE IN "+str(round(time.clock()-start, 3))+"s"+" "*(len(progress)-9)+"\n")
sys.stdout.write("----------------------------------------------------\n")
sys.stdout.flush()
return{'FINISHED'}
bpy.utils.register_module(__name__)