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
    Jun 28, 2017 at 17:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.