My overall goal is to copy the vertex groups from a mesh object to the new object created with that mesh as a bevel object. I have written some python code to help me accomplish this.
Here is a blend file that you can use to test out the code:
Here is how to follow along with my attempt to do this:
- Create a new bezier circle and change the resolution preview to 2. Convert this circle to a mesh and name it "profile"
- In Edit mode, add a subset of the vertices to vertex groups. Here I have created 2 vertex group, "inside" and "outside".
Return to Object mode
Run the following python code:
import bpy
# find indices of inside and outside vertices on the profile
profile = bpy.data.objects["profile"]
vertices_by_group = {}
profile_vert_count = len(profile.data.vertices)
for v in profile.data.vertices:
for g in v.groups:
group_name = profile.vertex_groups[g.group].name
if group_name not in vertices_by_group:
vertices_by_group[group_name] = []
vertices_by_group[group_name].append(v.index)
# create circle object that will be beveled with the profile.
bpy.context.view_layer.objects.active = profile
profile.select_set(True)
bpy.ops.object.convert(target='CURVE')
bpy.ops.curve.primitive_bezier_circle_add(radius=10)
ring = bpy.context.object
ring.name = 'ring'
ring.data.bevel_mode = 'OBJECT'
ring.data.bevel_object = profile
ring.data.resolution_u = 64
# convert to mesh object
bpy.ops.object.convert(target='MESH')
# create new vertex groups on the ring that match those on the profile
mesh_groups = {}
for group_name in vertices_by_group.keys():
mesh_groups[group_name] = bpy.context.active_object.vertex_groups.new(name=group_name)
# Check if new vert index would have been part of original profile groups
for v in ring.data.vertices:
for group_name, group in mesh_groups.items():
if v.index % profile_vert_count in vertices_by_group[group_name]:
group.add([v.index], 1.0, 'ADD')
Note how the vertex groups created on the beveled curve are off by one relative to the vertex groups in the profile object:
The code works by finding the index of the verts in each group on the profile object. It then converts that profile object to a curve, and uses it as a bevel object on a bezier circle. The beveled circle is then converted to a mesh. Then, every vertex on this new mesh is iterated over. If the vertex index modulo the profile vert count matches the index in the original vertex groups, then that vert is added to a group on the new object.
The general idea is that the verts in the new mesh created via beveling the profile will all be nicely ordered and the vert indexes will match up (modulo the original profile vert count). As you can see this almost works, its just that the vertexes are off by one.
If you edit the last line of code to be group.add([v.index-1], 1.0, 'ADD')
then it does appear to work. However this feels somewhat fragile as I am relying on blender's vertex ordering to always follow some rules.
My questions are:
Are there hard and fast rules about the order of verts in objects created this way?
Is it possible to achieve my goal of copying the vertex groups from the profile to the final object in a robust manner?