So, I have a bunch of vertices and each one of them is in its own vertex group. I also have objects that are constrained to those vertices. I want every one of that objects to have a belonging vertex group (that contains only one vertice) set for vertex group target (CopyLocationConstraint.subtarget).

enter image description here

I was thinking about a script that would set this target vertex group for each object to a vertex group that is the closest to object's origin.

If someone has an idea or has already written that script, I'd be very glad if you could share it.


1 Answer 1


It was not entirely clear how much of the data structures have already been constructed (vertex groups, constraints, etc). You will find techniques for most of it in http://web.purplefrog.com/~thoth/blender/python-cookbook/copy-location-from-vertex-group.html which I include here. Just discard the actions for work that you have already accomplished

import bpy

def index_of_closest_vertex(location, obj):

    verts = obj.data.vertices
    choice = 0
    wLoc = obj.matrix_world * verts[choice].co
    d = (location - wLoc).magnitude
    for i in range(1, len(verts)):
        vLoc = verts[i].co
        wLoc = obj.matrix_world * vLoc
        d2 = (location - wLoc).magnitude
        #print( [ location, wLoc, choice, d, d2])
        if d2<d:
            choice = i
            d = d2
    return choice

def create_per_vertex_vg(obj):

    nVerts = len(obj.data.vertices)
    for i in range(nVerts):
        vgname = "vg %d"%i
        vg = obj.vertex_groups.get(vgname)
        if vg is None:
            vg = obj.vertex_groups.new(vgname)
            vg.add([i], 1.0, 'REPLACE')

            vg.add([i], 1.0, 'REPLACE')
            vg.remove([ j for j in range(nVerts) if j!=i ] )

def find_or_create_clc(obj):
    for cns in obj.constraints:
        if cns.type=="COPY_LOCATION":
            return cns
    return obj.constraints.new('COPY_LOCATION')

def vg_for_i(obj, vertIdx):
    for vg in obj.vertex_groups:
            if (vg.weight(vertIdx)>0):
                return vg
    return None

def set_constraint(src, tgt):
    """ put a copy_location constraint on tgt referencing the vertex group for the closest vertex"""

    i = index_of_closest_vertex(tgt.location, src)

    cns = find_or_create_clc(tgt)
    cns.target = src
    cns.subtarget = vg_for_i(src, i).name


def mission1():

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

    knob = bpy.data.objects['Sphere']

    set_constraint(o1, knob)


  • $\begingroup$ Thank you. It works. I actually did it by hand, but it will surely be useful for some other project or even to someone else. $\endgroup$
    – missy
    Commented Jun 28, 2017 at 17:27

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .