Ways to have one mesh control another? I'm working with Cloth Simulations brought in from another program (Marvelous Designer) via .mdd, applied with the Mesh Cache modifier. No changes can be made to this mesh in Blender without breaking the .mdd. I want to add further details to the cloth in blender, such as thickness, seams, grooves, and other surface detailing that Marvelous Designer doesn't have good tools for. To accomplish this, I want to have my detailed mesh be controlled by the simpler cloth simmed mesh. This isn't much different than if I was doing the cloth sims in Blender, as that is generally done on simple meshes that then control more detailed ones.

My question is, what are my options in Blender for having the simmed mesh control the higher detailed one? From tutorials I've seen from other software (Max and Maya), this is a very common workflow, and they handle it very easily. Does Blender?

I am aware of the following options:

Mesh Deform Modifier:
Take the simmed mesh, solidify it to envelope the high detail mesh, and use a Mesh Deform modifier. This works for very simple meshes, but even at high precision, does not handle complex ones well. It also fails badly when dealing with layers. I can limit it's effect to a vertex group on the target object, but I can't have only a certain vertex group of the parent object exert control. So any place where I would have layers touching each other will get destroyed, as even if I weight paint the solidify very precisely, I can't fully avoid the cage overlapping certain areas.

Bones constrained to the simmed mesh:
Constrain bones to the simmed mesh and have them control the high detail mesh. This is very inefficient and time consuming, even if you have custom scripts to help set it up. It can also lose detail in important areas, and can't really handle things like folds and creases unless you have as many bones as you have vertices. And constraints can often give very strange results. This method has worked so far for things like belts and straps, but that's about it.

Are there any other options? From what I can tell, a combination of the two I've listed is the best choice. But it seems horribly inefficient and obnoxious. This seems like it should be a very common workflow, and there should be better tools for it. Am I missing something?
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 adds panel to 3dView > Toolbar > Rigify Mesh.
The mesh has to have rotation and scale applied.
The vertex count of mesh is recommended below 2000 (timed on i7 4GHz).


300 verts ~ 6s
560 verts ~ 46s
1k verts  ~ 8.2min
2k verts ~ over night

After profiling the code and going through forums the bottleneck is setting constraint properties. Specifically constraint['name'].target and constraint['name'].subtarget. The issue is that blender validates the constraints on every change to all other bones. This may be drastically speeduped with new dependency graph (hopefully). (Same as with duplicating large datasets of objects - before bmesh it took hours, now can be done in seconds.)
If the constaints will be no issue the rig can be improved so the bones rotate along edges nicer (this requires more bones and constraints).
The progress is now also printed in the console:


Known bugs were fixed.


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__)