Following code works now as I wanted. The mesh has been folded on the inner side of the rope during bending. Including Vertex Groups, which do not overlap and bbones solved this problem. Large parts of the code is from various sources in the internet.
(The rope mesh is not created in the sript. I import a obj-file here containing the test rope mesh.)
import bpy, bmesh
import math
from bpy.props import *
# #####################################
# parameter
# #####################################
MY_SCALE = 0.1
DV_Rope_Diameter = 10.5 # [mm]
DV_Rope_Length = 10.5 # [mm]
DV_Rope_Segments = 10 # [mm]
DV_Bbone_Segments = 25
DV_Bone_Envelope_Distance = 6.3 # dummy
DV_Bone_Head_Radius = 5 # dummy
DV_Bone_Tail_Radius = 5 # dummy
DV_Bone_Envelope_Weight = 1.0 # dummy
DV_Bone_Bbone_In = 1.0
DV_Bone_Bbone_Out = 1.0
DV_Name_Armarture = 'Armature' # name of armature, given by blender
DV_Name_Rope_Mesh = 'Group64191' # name of rope mesh from import file (.obj)
DV_File_Rope_Mesh = "C:\Temp\Data\Rope_1.obj" # name of rope mesh file
DV_File_Rope_Data = "C:\Temp\Data\MEA_ROPE_" # ascii data files -> MEA_ROPE_001.tab
# #####################################
# Clean the scene
# #####################################
bpy.ops.object.select_by_type(type='MESH')
bpy.ops.object.delete()
bpy.ops.object.select_by_type(type='EMPTY')
bpy.ops.object.delete()
bpy.context.scene.render.engine = 'CYCLES'
#bpy.context.scene.unit_settings.system='METRIC'
#scale = bpy.context.scene.unit_settings.scale_length = 1.0
#bpy.context.space_data.grid_scale = 0.01
bpy.context.scene.cursor_location = (0.0, 0.0, 0.0)
# #####################################
# create cylinders
# #####################################
for counter in range(0, DV_Rope_Segments):
bpy.ops.mesh.primitive_cylinder_add(radius=(DV_Rope_Diameter*MY_SCALE)/2.0, depth=(DV_Rope_Length*MY_SCALE), view_align=False, enter_editmode=False, location=(0.0, 0.0, 0.0), layers=(False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False))
bpy.ops.object.mode_set(mode='EDIT')
bpy.context.active_object.location = ((DV_Rope_Length*MY_SCALE)/2+counter*(DV_Rope_Length*MY_SCALE), 0.0, 0.0) # accepts tupples, use Vector if you are going to do calcs.
bpy.context.active_object.rotation_axis_angle = (math.pi/2.0, 0.0, 1.0, 0.0)
bpy.ops.object.mode_set(mode='OBJECT')
bpy.context.object.hide_render = True
obj = bpy.data.objects['Cylinder']
obj.name = "Cylinder.000"
# #####################################
# Create armature
# #####################################
# http://wiki.blender.org/index.php/Dev:2.5/Py/Scripts/Cookbook/Rigging/Add_armature
bpy.ops.object.armature_add()
ob = bpy.context.scene.objects.active
#ob.name ="give me a good name!"
arm = ob.data
bpy.ops.object.mode_set(mode='EDIT')
for i in range(DV_Rope_Segments-1):
bpy.ops.armature.extrude()
bpy.ops.transform.translate(value=(1.0, 0.0, 0.0))
for i in range(len(arm.edit_bones)):
eb = arm.edit_bones[i]
eb.bbone_segments = DV_Bbone_Segments
eb.head = ((DV_Rope_Length*MY_SCALE)*i,0,0)
eb.tail = ((DV_Rope_Length*MY_SCALE)*(i+1),0,0)
eb.use_inherit_scale = False
eb.use_inherit_rotation = False
eb.envelope_distance = DV_Bone_Envelope_Distance*MY_SCALE
eb.head_radius = DV_Bone_Head_Radius*MY_SCALE
eb.tail_radius = DV_Bone_Tail_Radius*MY_SCALE
eb.envelope_weight = DV_Bone_Envelope_Weight
eb.bbone_in = DV_Bone_Bbone_In
eb.bbone_out = DV_Bone_Bbone_Out
# #####################################
# Bone constraints. Armature must be in pose mode.
# #####################################
for i in range(len(arm.edit_bones)):
bpy.ops.object.mode_set(mode='POSE')
# Copy Location constraints
cns = ob.pose.bones[i].constraints.new('COPY_LOCATION')
cns.name = 'Copy_Location'
cns.target = bpy.data.objects["Cylinder." + str(i).zfill(3)]
cns.subtarget = ""
cns.owner_space = 'WORLD'
cns.target_space = 'WORLD'
# Copy rotation constraints
cns = ob.pose.bones[i].constraints.new('COPY_ROTATION')
cns.name = 'Copy_Rotation'
cns.target = bpy.data.objects["Cylinder." + str(i).zfill(3)]
cns.subtarget = ""
cns.owner_space = 'WORLD'
cns.target_space = 'WORLD'
cns.use_offset = True
bpy.ops.object.mode_set(mode='OBJECT')
# #####################################
# Create cylinder motion from ASCII file
# #####################################
for n in range(0, DV_Rope_Segments):
filename= DV_File_Rope_Data + "%i.tab" % (n+1)
x=0
for line in open(filename):
line=line.rstrip("
")
temp=line.split()
cylindername = "Cylinder.%03i" % n
knob = bpy.data.objects[cylindername]
knob.rotation_mode = 'XYZ'
knob.location = ( float(temp[1])*MY_SCALE,-float(temp[3])*MY_SCALE,float(temp[2])*MY_SCALE )
knob.rotation_euler = ( float(temp[4])*math.pi/180.0,
float(temp[5])*math.pi/180.0,
float(temp[6])*math.pi/180.0 )
# set the keyframe at frame
x=x+1
knob.keyframe_insert(data_path="location", frame=x)
knob.keyframe_insert(data_path="rotation_euler", frame=x)
# #####################################
# Import Rope Mesh
# #####################################
bpy.ops.import_scene.obj(filepath=DV_File_Rope_Mesh)
#bpy.context.object.name = 'Rope'
bpy.data.objects[DV_Name_Rope_Mesh].select = True
bpy.data.objects[DV_Name_Armarture].select = True
bpy.ops.object.parent_set(type='ARMATURE_ENVELOPE')
# #####################################
# Define new Vertex Groups
# #####################################
bpy.ops.object.select_all(action='DESELECT')
bpy.data.objects[DV_Name_Armarture].select = False
bpy.data.objects[DV_Name_Rope_Mesh].select = True
#ob = bpy.context.active_object
ob = bpy.data.objects[DV_Name_Rope_Mesh]
me = ob.data
#Let's get the bmesh data
bm = bmesh.new()
bm.from_mesh(me)
for n in range(0, DV_Rope_Segments):
if n == 0:
groupName = "Bone"
else:
groupName = "Bone.%03i" % n
# Try to retrieve the vertex group, and if we can't make a new one
try:
group_index = ob.vertex_groups[groupName].index
except:
group = ob.vertex_groups.new(groupName)
group_index = group.index
# Now here's something new... we have to get the custom data layer
# The vertex groups are all in the deform layer (there is always just one, which we retrieve as the active one)
deform_layer = bm.verts.layers.deform.active
if deform_layer is None: deform_layer = bm.verts.layers.deform.new()
#verts = [vert.co for vert in bm.verts]
#plain_verts = [vert.to_tuple() for vert in verts]
for vert in bm.verts:
if ( (vert.co[0] > (DV_Rope_Length*MY_SCALE)*n) and (vert.co[0] < (DV_Rope_Length*MY_SCALE)*(n+1) ) ):
vert[deform_layer][group_index] = 1.0
else:
vert[deform_layer][group_index] = 0.0
if n == 0:
if ( vert.co[0] < 0 ):
vert[deform_layer][group_index] = 1.0
if n == (DV_Rope_Segments-1):
if ( vert.co[0] > (DV_Rope_Length*MY_SCALE*DV_Rope_Segments) ):
vert[deform_layer][group_index] = 1.0
bpy.ops.object.mode_set(mode='OBJECT')
# That's it... we're done... so we put the bmesh back in the object
bm.to_mesh(me)
bm.free()