I have the following code which creates two Bezier curves which share a control point:

Two curves created programmatically

import bpy

def CreateBezier(cp1, cp2):
    bpy.ops.curve.primitive_bezier_curve_add(enter_editmode=True, align='WORLD', location=(0, 0, 0), scale=(1, 1, 1))
    bpy.context.object.data.resolution_u = 10
    bpy.context.object.data.bevel_resolution = 0
    bpy.context.object.data.bevel_depth = 0.06
    points = bpy.context.active_object.data.splines[0].bezier_points
    SetBezierSplinePoint(points[0], cp1)
    SetBezierSplinePoint(points[1], cp2)

def SetBezierSplinePoint(point, cp):
    point.co = cp["co"]
    point.handle_left = cp["handle_left"]
    point.handle_right = cp["handle_right"]
    point.tilt = cp["tilt"]

cp1 = {"co" : (0,0,0), "handle_left" : (-.5,0,0), "handle_right" :  (.5,0,0),  "tilt" : 0}
cp2 = {"co" : (1,1,.5),"handle_left" : (1,.5,0),   "handle_right" :  (1,1.5,0),"tilt" : 0}
cp3 = {"co" : (2,.5,0.5),"handle_left" : (2,2.1,.4),"handle_right" :  (2,1.9,.6),"tilt" : 0}

CreateBezier(cp1, cp2)
CreateBezier(cp2, cp3)

The problem is where both bezier curves meet - the "tilt" is different between them:

Curve join points

Is it possible to programmatically match the tilt of the first curve when creating the second?

  • $\begingroup$ Not exactly sure why or how to calculate it, but setting the second control point's turn=-25.6° on the second curve fixes it: CreateBezier(cp1, cp2) cp2['tilt']=-0.446879 CreateBezier(cp2, cp3) $\endgroup$
    – Ron Jensen
    Oct 7, 2021 at 14:09
  • $\begingroup$ It may or may not help you in your use-case, but setting: bpy.context.object.data.twist_mode = 'Z_UP' will fix (or mask) the problem. $\endgroup$
    – Ron Jensen
    Oct 7, 2021 at 14:30
  • $\begingroup$ @RonJensen - many thanks, that solution is good enough for me. Would you like to answer it officially so I can mark it as an answer? $\endgroup$
    – FredL
    Oct 7, 2021 at 14:39
  • $\begingroup$ I'm going to do some more research today to see if I can come up with a better/more complete answer. I'll create an answer later (unless @batFinger beats me to it!) $\endgroup$
    – Ron Jensen
    Oct 7, 2021 at 14:41
  • 1
    $\begingroup$ @MartyFouts I'm using multiple separate curves rather than a single curve with multiple control points as I'm creating a tree generator, which would have multiple branches merging into other branches. As far as I'm aware this can't be achieved with single bezier curves (I could be wrong!) $\endgroup$
    – FredL
    Oct 8, 2021 at 12:27

1 Answer 1


As pointed out by @MartyFouts, this answer discusses the three different ways Blender calculates the normal (up direction) on a spline curve. The default way is "minimize" which requires recursive calculation along the spline curve. I don't know a simple way to find the normal direction from Python, but if you do find it, you can enter it as the "Tilt" value for the next spline. I estimated a value of -26° or -0.446879 radians for the OP question.

Another "Twist Method" is Z-Up. With this method the normal always (tries) to point in the positive Z direction. This method can be set in Python with:

bpy.context.object.data.twist_mode = 'Z_UP' 

This will solve the alignment problem at the expense of losing the curve's twist functionality.

  • $\begingroup$ This works perfectly, thank you! $\endgroup$
    – FredL
    Oct 8, 2021 at 12:23

You must log in to answer this question.

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