BLENDER MESH OPERATIONS API REFERENCE
Low Level (No Context) PREFERRED python import bpy import bmesh from mathutils import Vector
📚 Референсы 27 блоков кода обновлено 2026-10-02
Primitive Creation
bpy.ops (Context-dependent)
# Requires proper context (view_layer, active object)
bpy.ops.mesh.primitive_cube_add(size=2, location=(0,0,0), rotation=(0,0,0))
bpy.ops.mesh.primitive_uv_sphere_add(radius=1, segments=32, ring_count=16)
bpy.ops.mesh.primitive_ico_sphere_add(radius=1, subdivisions=2)
bpy.ops.mesh.primitive_cylinder_add(radius=1, depth=2, vertices=32, cap_ends=True)
bpy.ops.mesh.primitive_cone_add(radius1=1, radius2=0, depth=2, vertices=32)
bpy.ops.mesh.primitive_torus_add(
major_radius=1, minor_radius=0.3,
major_segments=48, minor_segments=12
)
bpy.ops.mesh.primitive_plane_add(size=2)
bpy.ops.mesh.primitive_grid_add(x_subdivisions=10, y_subdivisions=10, size=2)
bpy.ops.mesh.primitive_monkey_add(size=1) # Suzanne
Low-Level (No Context) - PREFERRED
import bpy
import bmesh
from mathutils import Vector
def create_cube(name="Cube", size=2, location=(0,0,0)):
mesh = bpy.data.meshes.new(name)
obj = bpy.data.objects.new(name, mesh)
bpy.context.collection.objects.link(obj)
obj.location = location
bm = bmesh.new()
bmesh.ops.create_cube(bm, size=size)
bm.to_mesh(mesh)
bm.free()
return obj
def create_uv_sphere(name="Sphere", radius=1, segments=32, ring_count=16):
mesh = bpy.data.meshes.new(name)
obj = bpy.data.objects.new(name, mesh)
bpy.context.collection.objects.link(obj)
bm = bmesh.new()
bmesh.ops.create_uvsphere(bm, radius=radius, u_segments=segments, v_segments=ring_count)
bm.to_mesh(mesh)
bm.free()
return obj
def create_cylinder(name="Cylinder", radius=1, depth=2, vertices=32):
mesh = bpy.data.meshes.new(name)
obj = bpy.data.objects.new(name, mesh)
bpy.context.collection.objects.link(obj)
bm = bmesh.new()
bmesh.ops.create_cone(bm, radius1=radius, radius2=radius, depth=depth, segments=vertices)
bm.to_mesh(mesh)
bm.free()
return obj
BMesh Operations (Edit Mode Equivalent)
Setup
import bmesh
# Object mode BMesh (creates new mesh)
bm = bmesh.new()
# ... operations ...
bm.to_mesh(mesh)
bm.free()
# Edit mode BMesh (modifies existing)
bm = bmesh.from_edit_mesh(obj.data)
# ... operations ...
bmesh.update_edit_mesh(obj.data)
Vertex Operations
# Create vertices
v1 = bm.verts.new((0, 0, 0))
v2 = bm.verts.new((1, 0, 0))
v3 = bm.verts.new((0, 1, 0))
# Select/deselect
v1.select = True
bm.verts.ensure_lookup_table()
# Transform
v1.co = (2, 0, 0)
v1.co += Vector((0.1, 0, 0))
# Delete
bm.verts.remove(v1)
Edge Operations
# Create edge
e = bm.edges.new((v1, v2))
# Edge loops
bmesh.ops.edge_loops(bm, edges=[e])
# Subdivide edges
bmesh.ops.subdivide_edges(bm, edges=bm.edges, cuts=2)
# Bevel edges
bmesh.ops.bevel(bm, geom=bm.edges, offset=0.1, segments=3, profile=0.5)
# Dissolve edges
bmesh.ops.dissolve_edges(bm, edges=[e])
Face Operations
# Create face
f = bm.faces.new((v1, v2, v3)) # Triangle
f = bm.faces.new((v1, v2, v3, v4)) # Quad
# Face properties
f.select = True
f.material_index = 0
f.normal # mathutils.Vector
# Extrude
result = bmesh.ops.extrude_face_region(bm, geom=[f])
extruded_geom = result['geom']
# Move extruded faces
for elem in extruded_geom:
if isinstance(elem, bmesh.types.BMFace):
bmesh.ops.translate(bm, verts=elem.verts, vec=(0, 0, 1))
# Inset
bmesh.ops.inset_region(bm, faces=[f], thickness=0.1, depth=0.1)
# Poke (triangle fan)
bmesh.ops.poke(bm, faces=[f])
# Triangulate
bmesh.ops.triangulate(bm, faces=bm.faces)
# Subdivide faces
bmesh.ops.subdivide_edges(bm, edges=[e for f in bm.faces for e in f.edges], cuts=1)
Selection & Queries
# Select all
for v in bm.verts: v.select = True
for e in bm.edges: e.select = True
for f in bm.faces: f.select = True
# Get selected
selected_verts = [v for v in bm.verts if v.select]
selected_edges = [e for e in bm.edges if e.select]
selected_faces = [f for f in bm.faces if f.select]
# By index
v = bm.verts[0]
e = bm.edges[0]
f = bm.faces[0]
# Lookup tables (required after topology changes)
bm.verts.ensure_lookup_table()
bm.edges.ensure_lookup_table()
bm.faces.ensure_lookup_table()
Mesh Modifiers (BMesh)
# Remesh (voxel)
bmesh.ops.remesh(bm, voxel_size=0.1, adaptivity=0.0)
# Smooth
bmesh.ops.smooth_vert(bm, verts=bm.verts, factor=0.5, iterations=10)
# Decimate
# Not directly in bmesh - use modifier or bpy.ops
# Delete loose
bmesh.ops.delete_loose(bm, dist=0.001)
Mesh Data Access (bpy.data.meshes)
Read Mesh Data
mesh = obj.data
# Vertices
for v in mesh.vertices:
v.co # local coordinates
v.normal # vertex normal
v.groups # vertex groups
v.index # index
# Edges
for e in mesh.edges:
e.vertices # (v1_idx, v2_idx)
e.use_seam # UV seam
e.use_sharp # Sharp edge
e.bevel_weight # Bevel weight
# Polygons (faces)
for poly in mesh.polygons:
poly.vertices # vertex indices
poly.loop_indices # loop indices
poly.normal # face normal
poly.center # face center
poly.area # face area
poly.material_index # material slot index
# Loops (per-vertex-per-face data)
for loop in mesh.loops:
loop.vertex_index # vertex index
loop.normal # loop normal (for smooth shading)
# UV Layers
for uv_layer in mesh.uv_layers:
for uv in uv_layer.data:
uv.uv # Vector (u, v)
# Vertex Colors
for vc_layer in mesh.vertex_colors:
for vc in vc_layer.data:
vc.color # RGBA (0-1)
# Shape Keys
if mesh.shape_keys:
for key in mesh.shape_keys.key_blocks:
key.value = 0.5
Modifiers (via API)
Add Modifier
mod = obj.modifiers.new("Subdivision", 'SUBSURF')
mod.levels = 2
mod.render_levels = 3
mod.subdivision_type = 'CATMULL_CLARK' # 'SIMPLE'
mod = obj.modifiers.new("Bevel", 'BEVEL')
mod.width = 0.02
mod.segments = 3
mod.profile = 0.5
mod.limit_method = 'ANGLE' # 'WEIGHT', 'VGROUP', 'NONE'
mod.angle_limit = 1.0472 # 60 degrees
mod = obj.modifiers.new("Array", 'ARRAY')
mod.count = 5
mod.use_relative_offset = True
mod.relative_offset_displace = (1.5, 0, 0)
mod = obj.modifiers.new("Mirror", 'MIRROR')
mod.use_axis = (True, False, False)
mod.use_bisect_axis = (True, False, False)
mod = obj.modifiers.new("Boolean", 'BOOLEAN')
mod.operation = 'DIFFERENCE' # 'UNION', 'INTERSECT'
mod.object = other_obj
mod.solver = 'EXACT' # 'FAST'
mod = obj.modifiers.new("Solidify", 'SOLIDIFY')
mod.thickness = 0.1
mod.offset = 0 # -1 to 1
mod.use_even_offset = True
mod = obj.modifiers.new("Decimate", 'DECIMATE')
mod.ratio = 0.5 # 0.0-1.0
mod.decimate_type = 'COLLAPSE' # 'UNSUBDIV', 'PLANNAR'
mod = obj.modifiers.new("Remesh", 'REMESH')
mod.mode = 'VOXEL' # 'SMOOTH', 'SHARP'
mod.voxel_size = 0.1
mod.adaptivity = 0.0
Apply Modifier
# Single
bpy.ops.object.modifier_apply(modifier="Subdivision")
# All
for mod in list(obj.modifiers):
bpy.ops.object.modifier_apply(modifier=mod.name)
# Via Python (no context)
bpy.context.view_layer.objects.active = obj
bpy.ops.object.modifier_apply(modifier=mod.name)
Boolean Operations
Using Modifier (Recommended)
def boolean_union(obj_a, obj_b):
mod = obj_a.modifiers.new("Bool", 'BOOLEAN')
mod.operation = 'UNION'
mod.object = obj_b
mod.solver = 'EXACT'
bpy.context.view_layer.objects.active = obj_a
bpy.ops.object.modifier_apply(modifier="Bool")
bpy.data.objects.remove(obj_b, do_unlink=True)
return obj_a
def boolean_difference(obj_a, obj_b):
mod = obj_a.modifiers.new("Bool", 'BOOLEAN')
mod.operation = 'DIFFERENCE'
mod.object = obj_b
mod.solver = 'EXACT'
bpy.context.view_layer.objects.active = obj_a
bpy.ops.object.modifier_apply(modifier="Bool")
bpy.data.objects.remove(obj_b, do_unlink=True)
return obj_a
def boolean_intersect(obj_a, obj_b):
mod = obj_a.modifiers.new("Bool", 'BOOLEAN')
mod.operation = 'INTERSECT'
mod.object = obj_b
mod.solver = 'EXACT'
bpy.context.view_layer.objects.active = obj_a
bpy.ops.object.modifier_apply(modifier="Bool")
bpy.data.objects.remove(obj_b, do_unlink=True)
return obj_a
UV Unwrapping
Basic Unwrap
# Smart UV Project (best for hard surface)
bpy.context.view_layer.objects.active = obj
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.uv.smart_project(angle_limit=1.0472, island_margin=0.02)
bpy.ops.object.mode_set(mode='OBJECT')
# Lightmap Pack (for baking)
bpy.ops.uv.lightmap_pack(PADDING=4, Px_MARGIN=4)
# Cube Projection
bpy.ops.uv.cube_project()
# Sphere Projection
bpy.ops.uv.sphere_project()
Seam-Based Unwrap
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_all(action='DESELECT')
# Mark seams
for e in bmesh.from_edit_mesh(obj.data).edges:
if e.calc_face_angle() > 1.0472: # 60 degrees
e.use_seam = True
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.uv.unwrap(method='ANGLE_BASED', margin=0.001)
bpy.ops.object.mode_set(mode='OBJECT')
UV Manipulation
# Scale UVs
uv_layer = mesh.uv_layers.active
for uv in uv_layer.data:
uv.uv *= 2.0
# Translate UVs
for uv in uv_layer.data:
uv.uv += (0.5, 0.5)
# Rotate UVs
import math
angle = math.pi / 4
for uv in uv_layer.data:
u, v = uv.uv
uv.uv = (u * math.cos(angle) - v * math.sin(angle),
u * math.sin(angle) + v * math.cos(angle))
Vertex Groups / Weights
Create & Assign
vg = obj.vertex_groups.new(name="GroupName")
# Assign vertices with weight
vg.add([0, 1, 2, 3], 1.0, 'REPLACE') # vertex indices, weight, type
# Get weight
weight = vg.weight(vertex_index)
# Remove
vg.remove([0, 1, 2])
Vertex Group Operations
# Normalize all groups for vertex
vg.normalize()
# Clean (remove zero weights)
vg.clean(0.001, 0.0, 0.0)
# Mirror (for symmetrical rigs)
vg.mirror("GroupName.R", "GroupName.L", True)
# Copy
new_vg = obj.vertex_groups.new(name="Copy")
for v in obj.data.vertices:
try:
w = vg.weight(v.index)
new_vg.add([v.index], w, 'REPLACE')
except RuntimeError:
pass # Vertex not in group
Normals & Shading
Auto Smooth
obj.data.use_auto_smooth = True
obj.data.auto_smooth_angle = 1.0472 # 60 degrees
Custom Normals
# Set custom normals
mesh = obj.data
mesh.use_auto_smooth = True
normals = []
for poly in mesh.polygons:
for loop_idx in poly.loop_indices:
normals.append(poly.normal)
mesh.normals_split_custom_set(normals)
mesh.use_auto_smooth = True
# Or from faces
mesh.normals_split_custom_set_from_vertices([v.normal for v in mesh.vertices])
Sharp Edges
# Mark sharp
for e in mesh.edges:
e.use_sharp = True # For auto smooth
# Bevel weight
for e in mesh.edges:
e.bevel_weight = 1.0
Vertex Colors
Paint via Python
# Create layer
vc_layer = mesh.vertex_colors.new(name="Paint")
# Paint by face
for poly in mesh.polygons:
for loop_idx in poly.loop_indices:
loop = mesh.loops[loop_idx]
vc_layer.data[loop_idx].color = (1.0, 0.0, 0.0, 1.0) # Red
# Gradient by height
for poly in mesh.polygons:
for loop_idx in poly.loop_indices:
v = mesh.vertices[mesh.loops[loop_idx].vertex_index]
h = (v.co.z - min_z) / (max_z - min_z)
vc_layer.data[loop_idx].color = (h, h, h, 1.0)
Performance Tips
Batch Operations
# Use foreach for bulk attribute access
co_list = [0.0] * (len(mesh.vertices) * 3)
mesh.vertices.foreach_get("co", co_list)
# Modify
for i in range(0, len(co_list), 3):
co_list[i+2] += 0.1 # Raise Z
# Set back
mesh.vertices.foreach_set("co", co_list)
mesh.update()
Efficient Selection
# Instead of loop:
# for v in bm.verts: v.select = True
# Use:
bm.verts.ensure_lookup_table()
for v in bm.verts:
v.select_set(True) # or v.select = True
Avoid bpy.ops in Loops
# BAD
for obj in objects:
bpy.ops.object.modifier_apply(modifier="Subdivision")
# GOOD - Single context override
with bpy.context.temp_override(selected_objects=objects):
bpy.ops.object.modifier_apply(modifier="Subdivision")
Common Patterns
Create Mesh from Coordinates
def create_mesh_from_vertices(name, vertices, faces):
"""vertices: [(x,y,z), ...], faces: [(v1,v2,v3), ...]"""
mesh = bpy.data.meshes.new(name)
mesh.from_pydata(vertices, [], faces)
mesh.update()
obj = bpy.data.objects.new(name, mesh)
bpy.context.collection.objects.link(obj)
return obj
# Usage
verts = [(0,0,0), (1,0,0), (0,1,0), (1,1,0)]
faces = [(0,1,3,2)] # Quad
obj = create_mesh_from_vertices("Quad", verts, faces)
Duplicate & Separate
# Duplicate object + mesh
new_obj = obj.copy()
new_obj.data = obj.data.copy()
bpy.context.collection.objects.link(new_obj)
# Separate loose parts (Edit mode)
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.separate(type='LOOSE')
bpy.ops.object.mode_set(mode='OBJECT')
Convert to Mesh
# Convert curve/text/meta to mesh
bpy.context.view_layer.objects.active = obj
bpy.ops.object.convert(target='MESH')
🔗 СВЯЗИ
- Прочие в категории «Референсы»: BLENDER MATERIALS API REFERENCE, BLENDER PYTHON API REFERENCE (4.x), BLENDER SCRIPTING PATTERNS - SAFE & EFFECTIVE, BLENDER-MCP - FULL DOCUMENTATION, BLENDER-MCP ADDON - DEEP DIVE
- По темам: INSTALLATION GUIDE - COMPLETE SETUP, MCP ARCHITECTURE - MODEL CONTEXT PROTOCOL FOR BLENDER, MCP SERVER API REFERENCE
- Теги: #api, #blender, #modeling, #reference
🎯 ЦЕЛЬ
Референс категории «Референсы», сложность —.
Связанные материалы
Подобраны по тегам и категории.