mcpField
B
blender-3d-modeling

blender-3d-modeling

github.com/andrew1326クリエイティブ・メディア3159 回インストール4 週間前に更新
リポジトリ

blender-3d-modeling について

BlenderのPython APIでプロシージャルな3D形状を作成するスキルです。メッシュ構築、bmesh編集、モディファイア、カーブなどを扱い、コードからモデルを作る制作者や技術者向けです。

主な機能

  1. 01頂点と面のデータからメッシュを構築
  2. 02bmeshによる形状編集
  3. 03Pythonでモディファイアを適用
  4. 04カーブとサーフェスの生成
  5. 05パラメトリックパターンや地形の作成
  6. 06メッシュ面へのマテリアル割り当て

活用シーン

  1. 01パラメトリックな階段の生成
  2. 02ハニカムパネルの作成
  3. 03グリッドや円形のオブジェクト配列を構築
  4. 04高さマップから地形を生成

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/andrew1326/dominations --skill blender-3d-modeling

インストール後、Claude Code で/blender-3d-modelingを入力して読み込まれたか確認します。

詳細

Blender 3D モデリング

概要

Blender の Python API を使用して 3D ジオメトリをプロシージャルに作成します。頂点と面からメッシュを構築し、高度な編集には bmesh を使用し、モディファイアを適用し、カーブを生成し、パラメトリックまたはプロシージャルなモデルを完全にコードから作成します。

手順

1. 生の頂点データからメッシュを作成する
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) はメッシュを構築する主要な方法です。エッジや面が不要な場合は空のリスト [] を渡してください。

2. 高度なメッシュ編集には bmesh を使用する
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()

終了時には必ず bm.free() を呼び出してメモリを解放してください。

3. モディファイアをプログラムで適用する
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. カーブとサーフェスを作成する
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. プロシージャル生成のパターン

オブジェクトのグリッド:

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}"

円形配列:

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

ハイトマップからの地形:

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. 面にマテリアルを割り当てる
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

例

例 1: パラメトリックな階段

ユーザーのリクエスト: 「20 段の螺旋階段を生成して」

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")
例 2: ハニカムパネル

ユーザーのリクエスト: 「平らなハニカムパターンのパネルを作成して」

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

ガイドライン

  • シンプルな静的メッシュには from_pydata() を使用してください。押し出し、細分化、面ごとの操作などの操作でジオメトリを構築する必要がある場合は bmesh を使用してください。
  • from_pydata() の後には必ず mesh.update() を、bmesh 操作の後には bm.free() を呼び出してください。
  • bpy.ops.object.modifier_apply() でモディファイアを適用する際は、オブジェクトがアクティブかつ選択されていることを確認してください。
  • 大規模なプロシージャルメッシュ(1 万面以上)では、bpy.ops の繰り返し呼び出しよりも bmesh を優先してください。オペレーターには呼び出しごとのオーバーヘッドがあるため、bmesh の方が大幅に高速です。
  • 新しいオブジェクトは bpy.context.collection.objects.link(obj) でコレクションにリンクしてください。どのコレクションにもリンクされていないオブジェクトはシーンに表示されません。
  • Blender は Z アップ座標系を使用します。Y アップ座標系(ほとんどのゲームエンジン)からインポートする際はこの点に注意してください。
  • スムーズシェーディングの場合: bpy.ops.object.shade_smooth() を使用するか、面ごとに polygon.use_smooth = True を設定してください。
  • プロシージャルスクリプトはまず少ない数でテストし、その後スケールアップしてください。細分化モディファイアを適用した 100x100 のグリッドは Blender をフリーズさせる可能性があります。

コメント