wireframe-to-3d について
wireframe-to-3dは、正投影のワイヤーフレーム画像からパラメトリックなBlenderモデルを作り、GLBとして出力するスキルです。画像解析、カーブによるモデリング、出力検証を組み合わせ、3Dアセットの作成を支援します。
主な機能
- 01ワイヤーフレーム輪郭の解析
- 02パラメトリックBezierカーブの生成
- 03Blenderでのモデリングコード実行
- 04メッシュ変換とPBRマテリアル設定
- 05検証とGLB出力
活用シーン
- 01ワイヤーフレーム図からモデルを作成
- 02プレビューまたは本番向け詳細度の選択
- 03トポロジーと出力ファイルサイズの確認
MCP 対応
Blender MCPを使い、シーンの確認、Blender Pythonコードの実行、オブジェクト情報の取得を行います。MCPを介してモデリングと検証をBlenderに接続します。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ roble3/ cc-blender-skill --skill wireframe-to-3dインストール後、Claude Code で/wireframe-to-3dを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
evals/evals.jsonreferences/algorithms.mdbest-practices.mdblender-patterns.mdscripts/wireframe_analyzer.py詳細
ワイヤーフレームから3Dへの変換
2Dの正投影ワイヤーフレーム画像をパラメトリックな3D Blenderモデルに変換し、glTF 2.0バイナリ(.glb)としてエクスポートします。
概要
このスキルでは、次の4段階のパイプラインを実行します。
scripts/wireframe_analyzer.pyを使ってワイヤーフレーム画像をローカルで解析します(OpenCV → JSON形式のベジェ制御点)。- 輪郭をパラメトリックなベジェ曲線として再現するBlender Pythonコードを生成します。
mcp__blender__execute_blender_code経由でコードをBlender上で実行し、曲線をPBRマテリアル付きメッシュに変換します。- 最適化されたGLBとしてエクスポートし、サイズとトポロジーを検証します(≤ 15 MB)。
あなた(Claude)がオーケストレーターです。scripts/ディレクトリにある単独で実行できるコードはwireframe_analyzer.pyのみです。それ以外は、MCP経由で生成して実行するパターンです。
前提条件 — 最初に確認
ワイヤーフレームの作業を始める前に、環境を確認します。
-
Blender MCPに接続できること。
mcp__blender__get_scene_infoを呼び出します。「Could not connect to Blender」というエラーが発生した場合は、作業を中止してユーザーに次のように伝えます。「BlenderのMCPアドオンが起動していません。Blenderを起動し、BlenderMCPアドオン(ポート9876)を有効にしてから、もう一度実行してください。」
-
アナライザー用のPython依存関係。次を実行します。
python3 -c "import cv2, numpy, scipy" 2>&1エラーが発生した場合は、
pip install opencv-python numpy scipy Pillowを実行するか、ユーザーに実行するよう案内します。 -
画像入力。ユーザーからPNGが1つ以上提供されていることを確認します。適切なサイズの目安は400×400 px以上で、黒地に白、または白地に黒の線画です。
判断フロー
Q1:ビューはいくつですか?
- 1つのビュー → 平坦な2D押し出しのみです(ユーザーに警告してください。奥行きは指定するか、仮定する必要があります)。
- 正面+側面 → 3D全体を再構成します(シルエット × 奥行きプロファイル)。
- 正面+側面+背面 → 対称性の検証に背面ビューを使用します。
Q2:詳細レベルはどれくらいですか?
preview— RDPイプシロン = 4.0、目標は約1~2k tris、GLBは1 MB未満です。production— RDPイプシロン = 2.0、目標は約5~8k tris、GLBは2~4 MBです。デフォルト。high— RDPイプシロン = 1.0、目標は約10~20k trisです。15 MB未満に収めるため、Decimateが必要になる場合があります。
Q3:ジオメトリの種類はどれですか?
wires— フレーム、アーム、ヒンジ。曲線にbevel_depthを使用します。surfaces— レンズ、ドーム。プロファイルのロフト、またはキャップのフィルを使用します。hybrid— 両方。メガネのようなオブジェクトではデフォルトです。
Q4:実際のスケールはどれくらいですか?
- ユーザーが寸法を指定した場合(例:「メガネの幅は140 mm」)は、その寸法を使用します。
- それ以外の場合は、ワイヤーフレームの縦横比から推定し、妥当なデフォルト値(メガネの幅は140 mm、ヘルメットは180 mmなど)を想定します。明確でない場合はユーザーに確認してください。
参照画像/テクスチャを基にした対象物の必須修正ループ
ユーザーから参照画像/テクスチャと一致していないというフィードバックがあった場合、通常の「プリミティブから生成する」ループを中断し、参照画像に固定したモデリングに切り替えてください。
- モデリングの前に、提供されたテクスチャ/ワイヤーフレームから見えるデザインパーツの数をまず数え、その数を標準出力/メモに記録してください。対称性から放射状または反復パーツの数を推測しないでください。ソースマニフェストに記載されたビジュアルデザイン上の数が基準です。
- 正面図を基準にします。 検証に使う同じ正投影カメラの正面ビューに、画像が空の平面/参照画像オーバーレイを作成します。奥行きを追加する前に、スケール、中心線、外接円を合わせてください。
- まず正面ビューの X/Z で 2D シルエットをトレースまたは定義します。 そのシルエットからメッシュの表面を作成してください。汎用的な楕円を配置してからテクスチャを貼ろうとしないでください。
- 正面投影を固定します。 正面シルエットが一致した後にのみ、ビュー軸方向へ奥行きを追加してください。側面図/背面図では厚みや重なりを調整しますが、正面の輪郭を変えてはいけません。
- 正面の描画に合わせるテクスチャには、ビューから投影する方式の UV を使用してください。正面を向いた表面を 1 つ、対応するテクスチャの切り抜きに 1:1 でマッピングしてください。
- オーバーレイ検証をレンダリングします。 参照画像/ワイヤーフレームをモデルの背後または前面に表示し、期待される数、実際のオブジェクト数、前面の位置、外形シルエットの境界、側面/背面の奥行きを記載したチェックリストも表示してください。
- 同じエラーを 2 回繰り返した場合は、
references/best-practices.mdを参照し、次の試行の前に後からも使える短いメモを追加してください。
反復モチーフの対象物では、ソースマニフェストで宣言された主要な構成要素を正確に作成してください。ソース上で見える位置または意味的な役割に基づいて名前を付け、エクスポート前に数を検証してください。
ステージ 1 — アナライザーを実行する
ビューごとに、付属のアナライザーを 1 回実行します。
python3 ${CLAUDE_SKILL_DIR}/scripts/wireframe_analyzer.py <input.png> <output.json>
スクリプトは次の形式の JSON を出力します。
{
"metadata": {"image_size": [W, H], "num_contours": N, "parameters": {...}},
"contours": [[[x, y], ...], ...],
"bezier_curves": [[[[P0], [P1], [P2], [P3]], ...], ...]
}
RDP イプシロンの調整(デフォルト設定でうまくいかない場合のみ):
- 出力の輪郭が少なすぎる/ギザギザしている → イプシロンを 1.0~1.5 に下げます。
- 出力のノイズの多い点が多すぎる → イプシロンを 3.0~4.0 に上げます。
--rdp-epsilonで渡してください(またはスクリプト内の呼び出しを編集してください)。
Read で JSON を読み取ってください。巨大な JSON データを Blender に渡さず、まず必要な情報を抽出してください。
ステージ 2 — Blender コードを生成する
コードは小さく自己完結したチャンクに分けて作成してください(execute_blender_code の各呼び出しでは新しい Python 名前空間が使われ、呼び出しをまたいで保持されるのは bpy.data のみです)。必要なものは毎回再インポートしてください。
パターン:制御点からベジェ曲線を作成する
import bpy
# Identify by stable name; bpy.data persists between calls.
name = 'GEO-lens-right'
curve_data = bpy.data.curves.new(name=name, type='CURVE')
curve_data.dimensions = '3D'
curve_data.resolution_u = 16 # tessellation resolution
curve_data.bevel_depth = 0.001 # 1 mm wire thickness (adjust for surfaces)
curve_data.use_fill_caps = True
obj = bpy.data.objects.new(name, curve_data)
bpy.context.collection.objects.link(obj)
# Control points come from the analyzer JSON (px → mm scaling done client-side).
control_points = [(0.0, 0.0, 0.0), (0.5, 1.0, 0.0), (1.5, 1.0, 0.0), (2.0, 0.0, 0.0)]
spline = curve_data.splines.new(type='BEZIER')
spline.bezier_points.add(len(control_points) - 1)
for i, (x, y, z) in enumerate(control_points):
pt = spline.bezier_points[i]
pt.co = (x, y, z)
pt.handle_left_type = 'ALIGNED' # C¹ smooth
pt.handle_right_type = 'ALIGNED'
print(f"created:{name}") # signal back via stdout
ピクセルからワールド座標への変換(Blender に送信する前に、生成するコード内で行ってください):
norm_x = px_x / img_width
norm_y = 1.0 - (px_y / img_height) # flip Y; image origin is top-left
x_world = (norm_x - 0.5) * world_width_mm / 1000.0 # to metres
y_world = (norm_y - 0.5) * world_height_mm / 1000.0
パターン:曲線をメッシュに変換してクリーンアップする
import bpy
name = 'GEO-lens-right'
obj = bpy.data.objects[name]
bpy.context.view_layer.objects.active = obj
bpy.ops.object.convert(target='MESH')
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.remove_doubles(threshold=0.0001)
bpy.ops.mesh.normals_make_consistent(inside=False)
bpy.ops.object.mode_set(mode='OBJECT')
bpy.ops.object.shade_smooth()
mesh = obj.data
print(f"mesh:{name} verts:{len(mesh.vertices)} polys:{len(mesh.polygons)}")
パターン:PBR マテリアル(Principled BSDF — glTF がクリーンにエクスポートできる唯一のシェーダー)
import bpy
mat = bpy.data.materials.get('MAT-frame-metal') or bpy.data.materials.new('MAT-frame-metal')
mat.use_nodes = True
bsdf = mat.node_tree.nodes['Principled BSDF']
bsdf.inputs['Base Color'].default_value = (0.08, 0.08, 0.10, 1.0)
bsdf.inputs['Metallic'].default_value = 1.0
bsdf.inputs['Roughness'].default_value = 0.25
obj = bpy.data.objects['GEO-frame']
if obj.data.materials:
obj.data.materials[0] = mat
else:
obj.data.materials.append(mat)
print('material:assigned')
マテリアルのプリセット(ユーザーから指定がない限り、以下を使用してください):
MAT-frame-metal— ベース(0.08, 0.08, 0.10)、metallic=1.0、roughness=0.25(ブラッシュドスチール)MAT-lens-mirror— ベース(0.05, 0.08, 0.15)、metallic=0.8、roughness=0.05、IOR=1.5(鏡面ガラス)MAT-pad-silicone— ベース(0.65, 0.63, 0.60)、metallic=0.0、roughness=0.7(マットシリコーン)
パターン:GLB にエクスポートする
import bpy, os
filepath = '/tmp/wireframe_output.glb'
bpy.ops.export_scene.gltf(
filepath=filepath,
export_format='GLB',
export_materials='EXPORT',
export_uv=True,
export_normals=True,
export_animations=False,
export_yup=True,
)
size_mb = os.path.getsize(filepath) / (1024 * 1024)
print(f"export:{filepath} size_mb:{size_mb:.2f}")
size_mb > 15 の場合は、Decimate を適用して再エクスポートしてください(エラー復旧を参照)。
ステージ 3 — 検証する
パイプライン全体の完了後、成功を宣言する前に検証してください。
mcp__blender__get_scene_info— 想定されるオブジェクトが存在することを確認します。- 対になったパーツ(左右のレンズ)については、それぞれに対して
mcp__blender__get_object_infoを呼び出し、バウンディングボックスの幅を比較します。許容差:1 mm。 - 三角形数:
get_object_infoで取得します。パーツが上限を超える場合は、Decimate を計画してください。 - ファイルサイズ:上限は 15 MB、理想は 8 MB 以下です。
エラーからの復旧
| 症状 | 考えられる原因 | 対処方法 |
|---|---|---|
MCP から Code execution error: ... が返される | 生成されたコードに不正な Python が含まれている | コードを小さな単位に分けて再出力し、エラーメッセージに示された行を追跡します |
Could not connect to Blender | アドオンが実行されていない | Blender とアドオンを起動するようユーザーに伝えます |
Timeout waiting for Blender response | コードのまとまりが大きすぎる、または処理が遅い | execute_blender_code の呼び出しを小分けにします |
| 呼び出し間で変数が未定義になる | 呼び出しごとに新しい名前空間が使われる | モジュールを再インポートし、bpy.data.objects['name'] でオブジェクトを参照します |
| アナライザーの輪郭数が 0 | 画像のコントラストが低すぎる | --gaussian-kernel 7 --canny-t1 30 を指定して再実行します |
| レンズが非対称 | 元の図面が非対称、または輪郭検出に一貫性がない | ユーザーに警告し、依頼されない限り自動でミラーリングしません |
| GLB のサイズが大きすぎる | ポリゴン数が多い、またはテクスチャが埋め込まれている | 比率を 0.6~0.8 に設定した DECIMATE モディファイアを適用し、再エクスポートします |
| メッシュに穴がある | カーブの解像度が低すぎる | curve_data.resolution_u を 24 または 32 に上げ、再変換します |
| GLB にマテリアルがない | Principled BSDF 以外のノードを使用した | Principled BSDF のみを使ってマテリアルを再構築します |
Decimate のコードパターン(GLB が 15 MB を超える場合)
import bpy
obj = bpy.data.objects['GEO-frame']
bpy.context.view_layer.objects.active = obj
mod = obj.modifiers.new(name='Decimate', type='DECIMATE')
mod.ratio = 0.7
mod.use_collapse_degenerate = True
bpy.ops.object.modifier_apply(modifier=mod.name)
print(f"decimated:{obj.name} verts:{len(obj.data.vertices)}")
ユーザーへの出力
完了したら、次の内容を報告します。
- GLB ファイルの出力パス
- ファイルサイズ(MB、15 MB の上限との比較)
- パーツごとの三角形数(30 000 の上限との比較)
- 割り当てたマテリアルスロット
- 警告(非対称、デシメーションの適用、フォールバックの使用)
例:
✓
/tmp/wireframe_output.glbにエクスポートしました(2.4 MB)
三角形数:5 200(3 パーツ:GEO-frame、GEO-lens-right、GEO-lens-left)
マテリアル:MAT-frame-metal、MAT-lens-mirror
警告:なし
詳細なリファレンスを読み込むタイミング
上記の本文で、よくあるケースの 80% をカバーできます。まれなケースに対応するには、必要に応じて次のリファレンスを読み込みます。
references/algorithms.md— 画像処理パイプラインの理論(Canny、RDP、最小二乗法によるベジェフィッティング)、2D から 3D への再構築原則、ISO 128 の正投影規格。アナライザーの出力が適切でなく、パラメーターの調整が必要な場合に読み込みます。references/blender-patterns.md— Blender Python のパターンを網羅(ロフト、曲面回転、カスタムモディファイアースタック)。ユーザーから標準外のジオメトリ(曲面、複雑なブリッジ、可動パーツ)を求められた場合に読み込みます。references/best-practices.md— パフォーマンス最適化(foreach_set、一括操作、コンテキストキャッシュ)、命名規則(Blender Studio 標準)、モディファイアースタックの順序。ビルドが遅い場合や出力トポロジーの品質が低い場合に読み込みます。
制約事項
- Blender ≥ 4.0(5.x を推奨)。Principled BSDF ノードと glTF エクスポーターは、これらのバージョン間で安定しています。
- glTF は埋め込み形式のみ(
.binとテクスチャのサイドカーは不可。KTX2/Draco 圧縮も不可。Three.js で追加のローダーが必要になりますが、こちらでは同梱していません)。 - PNG テクスチャのみ(最大 1024×1024)。フラットな PBR カラーを優先し、テクスチャは不可欠な場合のみ使用します。
- GLB にボーンアニメーションを含めないでください。アイドル時の動きは、利用側のサイトで JS によって制御されます。
ヒント
ユーザーが「このワイヤーフレームを変換して」とだけ言った場合は、デフォルトで view_type=auto-detect、detail_level=production、geometry_type=hybrid、world_width_mm=auto を使用します。複数の解釈が考えられる場合にのみ、確認を求めます。
スコープの境界 — wireframe-to-3dで生成するものと、生成しないもの
このスキルが生成するのは、2Dアウトラインをなぞって薄い曲線に押し出したものです。入力された図面を平面上に表現したワイヤーフレームです。以下は生成しません。
- 塗りつぶされたサーフェス(例:リムのアウトライン間にあるレンズのガラス)
- 単一視点からの実際の3D奥行き(出力はY方向に平坦です)
- 複数視点からの3D再構築(正面図と側面図を組み合わせた立体的な再構築)
- 入力線に含まれていないサブフィーチャー(ノーズパッド、可動式ヒンジなど)
- プロダクション品質のマテリアル(プレースホルダーのみです。実際のマテリアルには
blender-materialsを使用します)
「完成した、レンダリングとテクスチャ設定済みのX」(例:ワイヤーフレームから作るRay-Ban Aviator)が必要な場合は、このスキルをほかのスキルと組み合わせてください。
| 手順 | スキル | 追加されるもの |
|---|---|---|
| 1 | wireframe-to-3d | フレームのアウトラインを3D曲線にします — 基礎となるものであり、成果物ではありません |
| 2 | blender-modeling | 塗りつぶされたレンズディスク(UV球をレンズの寸法に合わせてスケーリング)、テンプルアーム(Y方向の後方へ伸びるベジェ曲線)、ワイヤーフレームにない3Dディテール |
| 3 | blender-materials | ゴールド/シルバーのメタルフレーム、Metallic=0.9, Roughness=0.04のミラーレンズマテリアルなど |
| 4 | blender-lighting | 製品写真向けのライティングにsubject_class='metal'を使用 |
| 5 | blender-cameras | ヒーロー製品写真に85-100mmの焦点距離と浅い被写界深度 |
| 6 | blender-rendering | Cyclesで256以上のサンプル数、ノイズ除去、AgXビュー変換 |
wireframe-to-3d単体で生成されるもの(平坦なアウトラインのトレース)はtext-to-blender/assets/v0.9.0-validation/03_aviator_wireframe_to_3d.webpを、スキルを連携して生成されるもの(Ray-Ban風のヒーローレンダー)は04_aviator_chained_upgrade.webpを参照してください。
ワイヤーフレームから「Xのモデル」を求められた場合、オーケストレーター(text-to-blender)は常にスキルの連携を計画する必要があります。