Skip to content

Instantly share code, notes, and snippets.

@yunho-c
Created May 22, 2026 05:02
Show Gist options
  • Select an option

  • Save yunho-c/17cbefb0d18ed94d440f1b72c4cdd008 to your computer and use it in GitHub Desktop.

Select an option

Save yunho-c/17cbefb0d18ed94d440f1b72c4cdd008 to your computer and use it in GitHub Desktop.
Blender: 3D rotation arrow
import bpy
import math
def create_3d_rotation_arrow():
# Parameters to tweak the look of your arrow
radius = 2.0 # Radius of the overall circle
thickness = 0.2 # Thickness of the curved pipe
arrow_radius = 0.5 # Width of the arrowhead
arrow_length = 1.0 # Length of the arrowhead
start_angle = 0.0
end_angle = math.radians(280) # 280-degree sweep leaves a nice gap
segments = 32
# 1. Create the curved body (NURBS path)
curve_data = bpy.data.curves.new(name='RotationCurveData', type='CURVE')
curve_data.dimensions = '3D'
curve_data.bevel_depth = thickness
curve_data.bevel_resolution = 6
curve_data.fill_mode = 'FULL'
spline = curve_data.splines.new(type='NURBS')
spline.points.add(segments - 1)
for i in range(segments):
factor = i / (segments - 1)
angle = start_angle + (end_angle - start_angle) * factor
# Calculate X/Y along a circle
x = radius * math.cos(angle)
y = radius * math.sin(angle)
# Set point coordinates (x, y, z, weight)
spline.points[i].co = (x, y, 0, 1.0)
spline.use_endpoint_u = True
# Link curve to the scene
curve_obj = bpy.data.objects.new('RotationArrow_Body', curve_data)
bpy.context.collection.objects.link(curve_obj)
# 2. Create the Arrowhead (Cone)
bpy.ops.mesh.primitive_cone_add(
vertices=32,
radius1=arrow_radius,
depth=arrow_length,
location=(0, 0, 0)
)
arrowhead = bpy.context.active_object
arrowhead.name = 'RotationArrow_Head'
# 3. Position and Rotate the Arrowhead
# Calculate tangent vector at the end of the curve
tangent_angle = end_angle + math.pi / 2
# Calculate exactly where the curve ends
end_x = radius * math.cos(end_angle)
end_y = radius * math.sin(end_angle)
# Offset the cone so its flat base sits flush against the end of the curve
# (Since a cone's origin is at its center, we move it forward by half its length)
offset_x = (arrow_length / 2.0) * math.cos(tangent_angle)
offset_y = (arrow_length / 2.0) * math.sin(tangent_angle)
arrowhead.location = (end_x + offset_x, end_y + offset_y, 0)
# Rotate cone to follow tangent.
# Default cone points Z UP. We rotate Y by 90 to lay it flat, then Z by the tangent angle.
arrowhead.rotation_euler = (0, math.pi / 2, tangent_angle)
# 4. Create and Apply the Blue Material
mat = bpy.data.materials.new(name="RotationBlue")
mat.use_nodes = True
bsdf = mat.node_tree.nodes.get("Principled BSDF")
if bsdf:
# Hex translation of the bright blue UI color
bsdf.inputs['Base Color'].default_value = (0.05, 0.45, 1.0, 1.0)
bsdf.inputs['Roughness'].default_value = 0.3
curve_obj.data.materials.append(mat)
arrowhead.data.materials.append(mat)
# Smooth out the arrowhead's shading
bpy.ops.object.shade_smooth()
# Parent the arrowhead to the curve so you only have to move one object around
arrowhead.parent = curve_obj
# Make the final group active and selected
bpy.context.view_layer.objects.active = curve_obj
curve_obj.select_set(True)
# Run the function
create_3d_rotation_arrow()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment