Created
May 22, 2026 05:02
-
-
Save yunho-c/17cbefb0d18ed94d440f1b72c4cdd008 to your computer and use it in GitHub Desktop.
Blender: 3D rotation arrow
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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