Smithery Logo
MCPsSkillsDocsPricing
Login
Smithery Logo

Accelerating the Agent Economy

Resources

DocumentationPrivacy PolicySystem Status

Company

PricingAboutBlog

Connect

© 2026 Smithery. All rights reserved.

    andrew1326

    blender-3d-modeling

    andrew1326/blender-3d-modeling
    Design
    3 installs

    About

    SKILL.md

    Install

    Install via Skills CLI

    or add to your agent
    • Claude Code
      Claude Code
    • Codex
      Codex
    • OpenClaw
      OpenClaw
    • Cursor
      Cursor
    • Amp
      Amp
    • GitHub Copilot
      GitHub Copilot
    • Gemini CLI
      Gemini CLI
    • Kilo Code
      Kilo Code
    • Junie
      Junie
    • Replit
      Replit
    • Windsurf
      Windsurf
    • Cline
      Cline
    • Continue
      Continue
    • OpenCode
      OpenCode
    • OpenHands
      OpenHands
    • Roo Code
      Roo Code
    • Augment
      Augment
    • Goose
      Goose
    • Trae
      Trae
    • Zencoder
      Zencoder
    • Antigravity
      Antigravity
    ├─
    ├─
    └─

    About

    Create 3D models procedurally with Blender Python...

    SKILL.md

    Blender 3D Modeling

    Overview

    Create 3D geometry procedurally using Blender's Python API. Build meshes from vertices and faces, use bmesh for advanced editing, apply modifiers, generate curves, and create parametric or procedural models entirely from code.

    Instructions

    1. Create a mesh from raw vertex data

    import bpy
    
    vertices = [
        (-1, -1, 0), (1, -1, 0), (1, 1, 0), (-1, 1, 0),  # bottom
        (-1, -1, 2), (1, -1, 2), (1, 1, 2), (-1, 1, 2),   # top
    ]
    faces = [
        (0, 1, 2, 3),  # bottom
        (4, 5, 6, 7),  # top
        (0, 1, 5, 4),  # front
        (2, 3, 7, 6),  # back
        (0, 3, 7, 4),  # left
        (1, 2, 6, 5),  # right
    ]
    
    mesh = bpy.data.meshes.new("CustomBox")
    mesh.from_pydata(vertices, [], faces)
    mesh.update()
    
    obj = bpy.data.objects.new("CustomBox", mesh)
    bpy.context.collection.objects.link(obj)
    

    from_pydata(vertices, edges, faces) is the primary way to build meshes. Pass empty lists [] for edges or faces if not needed.

    2. Use bmesh for advanced mesh editing

    import bpy
    import bmesh
    
    # Create from scratch
    bm = bmesh.new()
    
    # Or edit an existing mesh
    obj = bpy.context.active_object
    bm = bmesh.new()
    bm.from_mesh(obj.data)
    
    # Add geometry
    v1 = bm.verts.new((0, 0, 0))
    v2 = bm.verts.new((1, 0, 0))
    v3 = bm.verts.new((1, 1, 0))
    v4 = bm.verts.new((0, 1, 0))
    bm.faces.new((v1, v2, v3, v4))
    
    # Common operations
    bmesh.ops.extrude_face_region(bm, geom=bm.faces[:])
    bmesh.ops.translate(bm, vec=(0, 0, 1), verts=[v for v in bm.verts if v.select])
    bmesh.ops.subdivide_edges(bm, edges=bm.edges[:], cuts=2)
    
    # Write back to mesh
    bm.to_mesh(obj.data)
    bm.free()
    obj.data.update()
    

    Always call bm.free() when done to release memory.

    3. Apply modifiers programmatically

    import bpy
    
    obj = bpy.context.active_object
    
    # Subdivision Surface
    sub = obj.modifiers.new(name="Subdivision", type='SUBSURF')
    sub.levels = 2
    sub.render_levels = 3
    
    # Mirror
    mirror = obj.modifiers.new(name="Mirror", type='MIRROR')
    mirror.use_axis = (True, False, False)
    mirror.use_clip = True
    
    # Array
    array = obj.modifiers.new(name="Array", type='ARRAY')
    array.count = 5
    array.relative_offset_displace = (1.1, 0, 0)
    
    # Boolean
    bool_mod = obj.modifiers.new(name="Boolean", type='BOOLEAN')
    bool_mod.operation = 'DIFFERENCE'
    bool_mod.object = bpy.data.objects["Cutter"]
    
    # Solidify
    solid = obj.modifiers.new(name="Solidify", type='SOLIDIFY')
    solid.thickness = 0.1
    
    # Bevel
    bevel = obj.modifiers.new(name="Bevel", type='BEVEL')
    bevel.width = 0.05
    bevel.segments = 3
    
    # Apply a modifier permanently
    bpy.context.view_layer.objects.active = obj
    bpy.ops.object.modifier_apply(modifier="Subdivision")
    

    4. Create curves and surfaces

    import bpy
    import math
    
    # Create a bezier curve
    curve_data = bpy.data.curves.new("MyCurve", type='CURVE')
    curve_data.dimensions = '3D'
    curve_data.resolution_u = 24
    
    spline = curve_data.splines.new('BEZIER')
    spline.bezier_points.add(3)  # 4 points total (1 default + 3 added)
    
    coords = [(0, 0, 0), (1, 1, 0), (2, 0, 1), (3, 1, 1)]
    for i, (x, y, z) in enumerate(coords):
        pt = spline.bezier_points[i]
        pt.co = (x, y, z)
        pt.handle_type_left = 'AUTO'
        pt.handle_type_right = 'AUTO'
    
    # Add depth to make it a tube
    curve_data.bevel_depth = 0.1
    curve_data.bevel_resolution = 4
    
    obj = bpy.data.objects.new("MyCurve", curve_data)
    bpy.context.collection.objects.link(obj)
    
    # Create a NURBS circle
    bpy.ops.curve.primitive_nurbs_circle_add(radius=2)
    circle = bpy.context.active_object
    circle.data.bevel_depth = 0.05
    

    5. Procedural generation patterns

    Grid of objects:

    import bpy
    
    rows, cols = 10, 10
    spacing = 2.5
    
    for i in range(rows):
        for j in range(cols):
            bpy.ops.mesh.primitive_cube_add(
                size=1,
                location=(i * spacing, j * spacing, 0)
            )
            obj = bpy.context.active_object
            obj.name = f"Grid_{i}_{j}"
    

    Circular array:

    import bpy
    import math
    
    count = 12
    radius = 5
    
    for i in range(count):
        angle = (2 * math.pi * i) / count
        x = radius * math.cos(angle)
        y = radius * math.sin(angle)
        bpy.ops.mesh.primitive_cylinder_add(radius=0.3, depth=2, location=(x, y, 0))
        obj = bpy.context.active_object
        obj.rotation_euler.z = angle
    

    Terrain from heightmap:

    import bpy
    import bmesh
    import math
    import random
    
    size = 20
    res = 50
    
    bm = bmesh.new()
    verts = []
    for i in range(res):
        row = []
        for j in range(res):
            x = (i / res - 0.5) * size
            y = (j / res - 0.5) * size
            z = math.sin(x * 0.5) * math.cos(y * 0.5) * 2 + random.uniform(-0.2, 0.2)
            row.append(bm.verts.new((x, y, z)))
        verts.append(row)
    
    for i in range(res - 1):
        for j in range(res - 1):
            bm.faces.new((verts[i][j], verts[i+1][j], verts[i+1][j+1], verts[i][j+1]))
    
    mesh = bpy.data.meshes.new("Terrain")
    bm.to_mesh(mesh)
    bm.free()
    
    obj = bpy.data.objects.new("Terrain", mesh)
    bpy.context.collection.objects.link(obj)
    
    # Smooth the terrain
    sub = obj.modifiers.new("Smooth", 'SUBSURF')
    sub.levels = 1
    

    6. Assign materials to faces

    import bpy
    import bmesh
    
    obj = bpy.context.active_object
    
    # Create materials
    mat_red = bpy.data.materials.new("Red")
    mat_red.diffuse_color = (1, 0, 0, 1)
    mat_blue = bpy.data.materials.new("Blue")
    mat_blue.diffuse_color = (0, 0, 1, 1)
    
    obj.data.materials.append(mat_red)   # index 0
    obj.data.materials.append(mat_blue)  # index 1
    
    # Assign by face index
    for i, poly in enumerate(obj.data.polygons):
        poly.material_index = 0 if i % 2 == 0 else 1
    

    Examples

    Example 1: Parametric staircase

    User request: "Generate a spiral staircase with 20 steps"

    import bpy
    import math
    
    def create_spiral_staircase(steps=20, radius=3, height=6, step_width=1.5):
        bpy.ops.object.select_all(action='SELECT')
        bpy.ops.object.delete()
    
        step_height = height / steps
        angle_per_step = (2 * math.pi) / steps
    
        for i in range(steps):
            angle = i * angle_per_step
            x = radius * math.cos(angle)
            y = radius * math.sin(angle)
            z = i * step_height
    
            bpy.ops.mesh.primitive_cube_add(
                size=1,
                location=(x, y, z),
                scale=(step_width, 0.4, step_height * 0.8)
            )
            step = bpy.context.active_object
            step.rotation_euler.z = angle
            step.name = f"Step_{i+1:02d}"
    
        # Add central column
        bpy.ops.mesh.primitive_cylinder_add(
            radius=0.2, depth=height, location=(0, 0, height / 2)
        )
        bpy.context.active_object.name = "CentralColumn"
    
    create_spiral_staircase(steps=20)
    bpy.ops.wm.save_as_mainfile(filepath="/tmp/staircase.blend")
    

    Example 2: Honeycomb panel

    User request: "Create a flat honeycomb pattern panel"

    import bpy
    import bmesh
    import math
    
    def create_hexagon(bm, cx, cy, radius):
        verts = []
        for i in range(6):
            angle = math.radians(60 * i + 30)
            x = cx + radius * math.cos(angle)
            y = cy + radius * math.sin(angle)
            verts.append(bm.verts.new((x, y, 0)))
        bm.faces.new(verts)
    
    radius = 0.5
    rows, cols = 8, 10
    bm = bmesh.new()
    
    for row in range(rows):
        for col in range(cols):
            cx = col * radius * 1.75
            cy = row * radius * 1.52
            if col % 2 == 1:
                cy += radius * 0.76
            create_hexagon(bm, cx, cy, radius * 0.9)
    
    mesh = bpy.data.meshes.new("Honeycomb")
    bm.to_mesh(mesh)
    bm.free()
    
    obj = bpy.data.objects.new("Honeycomb", mesh)
    bpy.context.collection.objects.link(obj)
    
    # Add thickness
    solid = obj.modifiers.new("Solidify", 'SOLIDIFY')
    solid.thickness = 0.1
    

    Guidelines

    • Use from_pydata() for simple static meshes. Use bmesh when you need to build geometry with operations like extrude, subdivide, or per-face manipulation.
    • Always call mesh.update() after from_pydata() and bm.free() after bmesh operations.
    • When applying modifiers via bpy.ops.object.modifier_apply(), ensure the object is active and selected.
    • For large procedural meshes (10k+ faces), prefer bmesh over repeated bpy.ops calls — it's significantly faster since operators have per-call overhead.
    • Link new objects to a collection with bpy.context.collection.objects.link(obj) — objects not linked to any collection won't appear in the scene.
    • Blender uses Z-up coordinate system. Keep this in mind when importing from Y-up systems (most game engines).
    • For smooth shading: bpy.ops.object.shade_smooth() or set per-face polygon.use_smooth = True.
    • Test procedural scripts with small counts first, then scale up. A 100x100 grid with subdivision modifiers can freeze Blender.
    Recommended Servers
    Codeinterpreter
    Codeinterpreter
    Gemini
    Gemini
    tldraw
    tldraw
    Repository
    andrew1326/dominations
    Files