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.

up vote 1 down vote accepted

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')
        else:

            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:
        try:
            if (vg.weight(vertIdx)>0):
                return vg
        except:
            pass
    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']
    create_per_vertex_vg(o1)

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

    set_constraint(o1, knob)

#
#
#

mission1()
  • 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. – martinsifrar Jun 28 '17 at 17:27

Your Answer

 
discard

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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