scenario-zbrush-hard-surface について
ZBrushでのハードサーフェス制作を支援するスキルです。再現可能な操作でブーリアン、エッジ、パネルや金具を組み立て、用途とカメラに応じた検査工程を設けます。
主な機能
- 01パーツ作成とブーリアンのスクリプト化
- 02ポリグループによるクリース設計
- 03ダイナミックサブディビジョンとベベル調整
- 04配列によるカットと金具の配置
- 05段階的なモデルと書き出しの検査
活用シーン
- 01ゲーム用小道具のハイポリ制作
- 02開口部、パネル、継ぎ目の設計
- 03ボルトや通気口の反復配置
- 04ベイク工程へのモデル引き渡し
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ scenario-labs/ skills --skill scenario-zbrush-hard-surfaceインストール後、Claude Code で/scenario-zbrush-hard-surfaceを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/critique.mdexpert-notes.mdgui-paths.mdprocedures.mdsources.mdscripts/zb_hardsurface.py詳細
ZBrush ハードサーフェス
ハードサーフェスの良し悪しは、仕上がりで判断されます。すべてのエッジが明確に直線または曲線として読め、平面に均一なハイライトが出て、エッジが光を受けるのに十分な幅を持ち、各パーツが実際に製造できそうであれば、工業製品らしく見えます(Plouffe、Klimer)。エージェントは、決定論的な操作(プリミティブ、Live Boolean スタック、クリースプランとしてのポリグループ、Dynamic Subdivision の数値、ArrayMesh、Panel Loops)を使ってその表現を作り、ほかに手段がない場合にだけクリックやストロークを使います。ここで挙げた関連スキルが利用可能なスキルにない場合は、ユーザーにインストールを依頼してください
(npx skills add scenario-labs/skills --skill <name>)。無人で作業する場合は、ツールのスキーマに基づいて進め、不足している点を明示してください。
必須の事前知識: scenario-zbrush-expert(ブリッジ、ストロークエンジン、レビューの反復、2026 年の注意点)。
ツールキット:scripts/zb_hardsurface.py
(import sys; sys.path.insert(0, "<this skill>/scripts"); import zb_hardsurface as hs の後、
hs.hs_call("new_part", "cube") を実行)。リードの zb_ops、zb_review、zb_audit、zb_stroke を基盤としています。まだ ZBrush では実行されていません。
基本方針(エキスパート向けの追加事項)
- ポリグループがクリースプランです。 45 度で Groups By Normals を適用します(33 度では柔らかい平面も拾い、60 度ではエッジを拾い損ねます)。Mirror And Weld、UnCreaseAll、Crease PG の順に実行します(Pavlovich、Plouffe)。まずクリースを適用し、減衰範囲を局所的にする必要がある場合に限ってループを追加します。後から Crease PG を適用すると、意図的に柔らかくした境界にも再度クリースが付きます。グループを分け直すか、角度に基づいてクリースを適用してください。
- SmoothSubdiv と CreaseLvl の差がエッジ幅を決めます。 差が 0 だとカミソリのように見え、「CG らしさ」が強くなります。CreaseLvl が SmoothSubdiv に近いほどエッジは鋭くなります。そのため、4/3 は 4/2 より鋭くなります
(
hs.edge_width)。Pavlovich は 3/2 で作業し、4/2 でベイクします。Plouffe はカミソリのように鋭い 4 に対して CreaseLvl 3 を維持し、2 は柔らかすぎるとしています。判断基準は、両方を金属素材でレンダリングし、計画的に見える範囲で最も幅の広いエッジを選ぶことです。 - QGrid は箱型のブロック向けです(円弧にファセットが出ます)。曲線部分には Smooth Subdiv と Crease Tolerance を使い、部分ごとに調整します。Pavlovich のアーチは 22 で維持できました。値が低すぎると、円弧の小さな角にクリースが付きます。
- ブーリアンにはクリーンな入力が必要です(Live Boolean のドキュメント、Pavlovich)。水密で、共面の面がなく、密度が近く、Dynamic レベルが低く、一部が隠れていないことが条件です。DSDiv をオンにし、パーツごとに Start グループを 1 つ設定してから、ZRemesher の Detect Edges を Half にします。ブーリアン処理ではクリース、UV、レベル、レイヤーは失われますが、ポリグループは保持されます。
- カットと複製はライブのまま維持します。 結果ではなく、カッターに ArrayMesh を適用します。インスタンス化したファスナー(NanoMesh、ArrayMesh)なら、後から Edit Mesh を 1 回切り替えるだけで「プラスではなくマイナス」に変更できます。座席ごとにインポートすると、座席ごとに 1 回ずつ呼び出しが必要になります。
- 直線か曲線かを明確にし、中間にはしません(Plouffe)。平面を磨き、次にエッジ、最後に角の柔らかさを整えます。鋭いエッジから滑らかなエッジへとつなげます。近接する鋭いエッジと丸いエッジを混在させないでください。境界に沿ってキャビティを 1 つ設けると、独立したプレートらしさが出ます。
- 機能とカメラがディテールを決めます(Klimer)。製造方法、電力の流れ、ファスナーの系統を 1 つに統一すること、繰り返される角度を同じにすることが基準です。エンジンで 2 回検証します。まずリグを使い、500~40k ポリゴンのブロックを確認します。次に、1M ポイント未満にデシメートしたハイポリを確認します。見えない内部や下面は、塗りつぶすか簡素にし、暗い AO で存在感を出します(Pavlovich)。
- 微細なディテールは承認後に 3D レイヤーで追加します(Klimer)。負の強度は内側に彫り込み、複製すると効果が二重になり、トポロジーを変更するとレイヤーが失われます。そのため、ブーリアン、リメッシュ、Apply [added] の最後の処理が終わってからレイヤーを追加します。
- Mirror And Weld は常に負の X 側を正の X 側にコピーします。 正の X 側を良い半分として使う場合は、最初に Deformation Mirror を実行します(Pavlovich、Plouffe)。Slice、Trim、BRadius は対称編集を無視するため、片側だけの編集は必ずここで反映します。
エージェントがここでできることとできないこと
| 決定的に実行可能(スクリプト化する) | クリックまたはストローク[要検証] | GUI のみ、または代替手段 |
|---|---|---|
プリミティブ、Unify、配置(new_part、place、import_part);Live Boolean の役割(set_roles、roles_from_groups)、DSDiv、Make Boolean Mesh、Show Coplanar、Show Issues | ZModeler:アクションとクリースオプションを保持した保存済みブラシまたは 2026 プリセット、click_target での 1 回の canvas_action(初回はドラッグ、タップで再生) | Clip、Trim、Slice、Knife(Ctrl+Shift ドラッグ。press_key は動作しません):ブーリアンカッター、fitted_split_groups、グループの輪郭上の DynaMesh Groups、ZScript の IKeyPress ラッパー(scenario-zbrush-automation) |
| Dynamic Subdiv、CreaseLvl、CTolerance、Crease PG、Crease Bevel、Apply | NanoMesh の挿入:対象グループの面、または正面を向いた平面を 1 回クリック(付属マクロのルーチン) | Gizmo 変形ツール:軸に沿って配置されたパーツ上の Deformation スライダー |
Groups By Normals、Mirror And Weld、Panel Loops、GroupsLoops、ArrayMesh、NanoMesh スライダー、MeshFromBrush(fastener_from_brush)、マスク(mask_fillet)、ZRemesher、DynaMesh、Decimation | IMM:合成した Dots ストローク、またはスクリプト曲線での Curve Mode。最初に imm_ready を実行します | Retopo ブラシ、Mask By Polypaint ダイアログ、フリーハンドマスク、hPolish による平面化(弱いストローク) |
最初に決めること
| 入力 | 変更点 | 何も指定がない場合のデフォルト |
|---|---|---|
| 用途 | ゲーム(ローポリゴンにベイク)、映像、印刷用コレクタブル、コンセプトの読み取り | 1 枚の 2048 マップにベイクしたゲームアセット(Pavlovich のピストル) |
| カメラ | 一人称視点と ADS、三人称視点、ターンテーブル、印刷用フレーミング | 三人称視点。ディテールのサイズは、その視点で認識できる大きさにします |
| 予算 | ローポリゴンの三角形数、マップサイズ、ハイポリゴンの上限 | 数を報告して確認します。予算を決してでっち上げません |
| 機能仕様書 | 開閉方法、通気口、電源、製造方法、留め具の種類 | ブロックアウトの前に作成します(Klimer) |
| スケール | リグあり:ブロックアウトで実寸。コンセプト:比率 | Unify(約 2 ユニット)、Z 軸を前方、パースをオフ(Chervenka)。mm 指定のブリーフでは to_tool_units を使用 |
| 可動パーツ | ヒンジ付きバイザーは別パーツかつ Start グループにする | 別パーツ |
| Painter への引き継ぎ | Substance Bridge、または OBJ と外部ベイク | 確認します。どちらも以下に記載されています |
ワークフロー
- セットアップ。 SubTool としてプロキシまたはコンセプトを用意します。Unify、Z 軸方向に前面を向け、X 対称を設定します。すべてのブーリアン、DynaMesh、ZRemesher、Apply の前に、バージョン付きの ZTL を保存します(Python からは元に戻せません)。ゲート:バウンディングボックスの最長辺が約 2 であること。ZTL がディスク上に保存されていること。
- ブロックアウト。
new_partとplaceを使うか、DCC のブロックアウトからimport_partを使います。ボディを先に作り、カッターは下に配置します。ゲート:コンセプトと照らし合わせたフォームシート(zb_review.review)。リグ付きアセットは、ディテール追加前に、リグとともにエンジン内でブロックアウト OBJ を確認します。 - シェル。 プリミティブに変形スライダーを適用し、開口部には減算ボックスを使います。Make Boolean Mesh を実行し、
zremesh_recipe("after_boolean")を使います。スカルプトの手順(DynaMesh 128~176、hPolish、TrimDynamic)はコンセプトのみです。ゲート:hygiene(obj)が問題なしであること(結果をノート経由で報告する Check Mesh の代わりに使います)。PolyFrame で均一な四角形が表示されること。 - クリースの計画。
crease_by_groups(45)、dynamic_subdiv(intent="working")を使い、アークにはスパンごとに調整したcrease_by_angleを使います。ZModeler で作成するループとインセットには、作成時にクリースを設定します(zmodeler_plan:Insert EdgeLoop は「Crease」、Inset はシャープにする場合「Crease New Edges」、丸みをつける場合「Crease Inner Poly」。デフォルトは「Do Not Crease」です)。ゲート:check_crease。金属シート(review_sheets)で、スキャロップのない、光を柔らかく受けるエッジと、対称なポリグループが確認できること。 - カットとベント。 サーフェスを貫通するようにカッター
new_part(..., op="sub")を配置し、面一にはしません。Smooth 3 / CreaseLvl 2 に加えて、角度によるクリースを設定します。カッターにはarray_meshを使います。事前ゲート:stack_report()["problems"]が空であること、coplanar_reportに問題がないこと、Show Coplanar のスナップショットに赤がないこと、array_planの壁面に問題がないこと。その後、make_boolean_meshを実行します(タイムアウトは短めに設定)。事後ゲート:UMesh SubTool の Start グループが一致すること。Show Issues のスナップショットに問題がないこと。再度クリースを設定します(意図的に境界を滑らかにした場合を除き、Crease PG を使います)。ZRemesher の前にhygieneを実行します。片側だけを編集した場合は、mirror_report、mirror_weld(keep=...)を実行し、エクスポート前後にmirror_checkを行います。 - パネルと嵌合パーツ。 まずパネルをポリグループとして計画します。実際に分離する場合は、Plouffe の手順で Panel Loops を使います(
panel_loops)。開口部に嵌合するバイザーやハッチには、1つのカッターを2回使う方法(fitted_split_groups:一方の Start グループでは Intersect、もう一方では Subtract)か、グループの輪郭に DynaMesh Groups を使います。縫い目には、border_polylinesとcurve_meshを使った薄い減算カッターを使います[要確認]。マスクにはmask_fillet(Klimer のブラー、反転、繰り返し)を使います。ゲート:split_copy("groups")でパネル数を確認します。シート上の隙間が一定であること。 - ハードウェア。 1つのファミリーに統一します。列には ArrayMesh を使います。放射状のセットは、ArrayMesh Rotate 360 の後、ZRVar の変化を加えて
array_commit("nano")を使います(Chervenka)。ドラッグ操作なしで IMM からパーツを作るにはfastener_from_brushを使います。ボルト位置に面がない場合は、補助平面を使います。縫い目をまたぐポートにはseam_port_groups(Pavlovich)を使います。正確な配置にはspaced_pointsを使います。ゲート:シート上のどこでも、数、向き、ファスナーが同じであること。 - ハイポリの確定。
bake_split()を使います。コピーに対して 4/2 で Apply を実行し、元のモデルでは Dynamic をオフにします。正確な面取り幅には、Crease Bevel の幅またはブーリアンの面取りを使います。Polish で得られるのは最小値のみです(Polycount)。ゲート:レベルが 1 + Flat + Smooth であること。edge_languageに曖昧な線がないこと。plane_flatnessに揺らぎのあるグループがないこと。pinch_reportが何も検出しないこと。 - マイクロディテール(承認後)。領域ごとにレイヤーを作成します(Tool:Layers:New、手順 P15)。ゲート:各パスの前後に
layer_safe(recorded, zb_ops.stats())を実行します。 - ローポリと引き渡し。 Dynamic をオフにしたケージを用意します。パーツごとに ZRemesher を実行します(
zremesh_recipe("part"))。簡易的な静的プロップには、dynamesh_visible(res)の後にdecimate_percentを1回実行するか、Maya または Blender を使います。Klimer の ZRemesher と自動リダクションでは、「今まで出荷した中で最悪のメッシュ」ができました。Painter の手順(scenario-zbrush-retopology-export が実行します)には、Substance Bridge Low & High と Auto-Bake と Send PolyPaint の組み合わせ(bridge_preflight)、またはクリースのシームを使ったネイティブ Unwrap(unwrap_creases)の後に OBJ を使う方法があります。ゲート:zb_audit.verdict(..., "game")。アニメーションするパーツは分離します。
数値
| 値 | 用途 | 出典 |
|---|---|---|
| 法線によるグループ分け 45(33は滑らか、60は失敗) | クリース計画 | Pavlovich; Plouffe |
| Smooth/Crease 3/2は作業用、4/2はベイク用、4/3は厳密、4/1はソフト | エッジ幅 | Pavlovich; Plouffe |
| クリースの許容角度 45(片側のアーチでは22) | 角度によるクリース | Pavlovich |
| QGridごとに面をx4、FlatまたはSmoothステップ;レベル1 + Flat + Smoothを適用 | 予算 | DSUB doc |
| カッターの円柱は8、12、16、24または32辺;DynaMeshベイク前は36~140辺 | カッター | Pavlovich; Polycount |
| ArrayMeshの繰り返し回数は4~5 | 通気口 | Pavlovich |
| Panel Loops:Loops 1、Polish 0、Bevel 0、Elevation -100、Double、Ignore Groups | プレート | Plouffe |
| ZRemesher Half + Detect Edges + Adaptive 0 | カット対応ベース | Pavlovich |
| Keep Groups、Smooth Groups 0、AdaptiveSize 25 | パーツのリトポロジー | Chervenka |
| パネルベースあたり約3つ星 | ピンチの予算 | Plouffe |
| LazyStep 2は接触(本人の推測)、リベットは2.5;Curve Step 1は接触 | IMMの実行 | Pavlovich; IMM doc |
| DynaMeshの探索用は176;ゲーム用シェルは1000 | 解像度 | Pavlovich |
| 1.671Mのうち25k = 1.4~1.5パーセント | 1回のデシメーション処理 | Pavlovich |
| SubToolあたり10Mポリゴン | ハイポリ上限 | Plouffe |
| ブロックは500~40kポリゴン;レビュー時は100万ポイント未満に抑える | エンジンチェック | Klimer |
| 2048ベイク、4 pxパディング | マップ | Pavlovich |
品質ゲート
- コード:
stack_reportとcoplanar_reportがクリーンであること;make_boolean_mesh()["ok"];hygiene;check_crease;mirror_check;edge_language(ambiguousがないこと);plane_flatness(obj)["wobbly"]が空であること;pinch_report;layer_safe;bridge_preflight;zb_audit.verdict。 - ビジュアル:
review_sheets:フォームには5つのビューからのMatCap Gray;平面とエッジ幅にはメタル表示、正面および30度の浅い角度からのビュー; グループと点線のクリースにはPolyFrameを使用します。各ブーリアン処理の前にCoplanarを表示し、後にIssuesを表示します。ピンチは、暗いポリペイントと低メタルのMatCapを使った低レベルで確認します。references/critique.mdに従って評価してください。
よくある間違い
| 間違い | 起こること | 修正方法 |
|---|---|---|
| CreaseLvl >= SmoothSubdiv | CG のエッジが鋭利になる | dynamic_subdiv(intent="bake") |
| 曲面シェルに QGrid を適用する | 円弧がファセット状になる | QGrid 0、Smooth と crease_by_angle を適用する |
| カッターをボディと面一にする | コプラナーな注記ブロック、穴ができる | 貫通させる。coplanar_report を実行する |
| Start グループがない、または DSDiv がオフ | パーツがボディに縫い付けられる。UMesh がファセット状になる | set_roles(... start=True) を設定する。dsdiv=True を指定する |
| Mirror And Weld で +X 側の半分を保持する | 編集内容が消える | mirror_weld(keep="pos")、mirror_check を実行する |
| 境界をソフト化した後に PG を Crease する | ソフト化したエッジが再び鋭利になる | 角度でクリースするか、先にグループを結合する |
| カット後に残骸がある | ZRemesher が失敗する | hygiene を実行し、残骸を非表示にして Del Hidden を実行する |
| レベルがある SubTool で IMM を使う | 挿入が拒否される | imm_ready を実行する。レベルのないプレースホルダー SubTool を使う |
| トポロジー変更前にレイヤーを作成する | レイヤーが適用されなくなる | 最後のブーリアン処理後、または Apply の後にレイヤーを作成する |
| Force UV Auto-Unwrap をオンにする | すべての SubTool の UV が失われる | bridge_preflight を実行する。オフにする |
引き継ぎ
- 受け取るもの: ユーザーからのコンセプトとブリーフ、scenario-3d の AI メッシュ、scenario-maya-modeling または scenario-blender-hard-surface の DCC ブロック(OBJ、四角形ポリゴンと三角形ポリゴン)、scenario-zbrush-sculpting のフォーム作成パス。
- 引き渡すもの: バージョン管理された ZTL(SubTool は高解像度、ケージは Dynamic オフ)、パーツごとの OBJ(高解像度版と低解像度版で名前を一致させる)、
stack_reportと最後のシート。UV 用に scenario-zbrush-retopology-export へ引き渡します(クリースシームを使った Unwrap、UV Master)。ベイクには Substance Bridge または Multi Map Exporter を使います(ポリペイント ID は Send PolyPaint または MME の Texture From Polypaint マップで引き継ぎます。OBJ の頂点カラーは確立されていません)。また、ゲーム用ローポリも引き渡します。2026.1 の Retopo ブラシは、そこでの GUI 作業手順です。手作業で作成するローポリは scenario-maya-modeling、scenario-maya-retopology-uv、scenario-blender-retopology または scenario-blender-uv-baking へ引き渡します。ポリペイント ID は scenario-zbrush-paint-render へ、印刷用パーツは scenario-zbrush-pose-print へ引き渡します。
ZBrush 2026 の注意事項
- Knife(2021.7 から 2022)と Split To Parts(2024)の組み合わせにより、Slice と Trim の手順の大半が置き換えられます。Knife では穴をカットできません。
- ZModeler 2026.0 では、作成時(Insert EdgeLoop、Inset)にクリースを設定できます。2026.2.1 では Bevel All、Outer Edges、Inner Edges が追加され、Extrude の代わりに QMesh が既定で実行される問題が修正されました。
- Substance Bridge(2026.2.0):Low & High、Auto-Bake、Send PolyPaint に対応しています。Force UV Auto-Unwrap はグローバル設定で、送信するたびに新しい Painter プロジェクトが作成されます。
- 2026.2.1 では Live Boolean のレンダリングと Apply のクラッシュが修正されています。ZRepeat It は同梱されていません。Python で SubTool をループ処理してください。
- 処理を妨げる注意事項(2026.2.1 の UI 表記):コプラナーな Make Boolean Mesh、Mirror And Weld の床面 Elv、インポート時の n-gon、レベルがある状態での DynaMesh、Check Mesh Integrity の結果[要確認]、現在のブラシがすでに挿入ブラシの場合に表示される Create InsertMesh の Append-or-New プロンプト、同梱の Create Instance Subtool マクロが注記で終わる問題。
- 接頭辞付きラベル:
s.SmoothSubdiv、P.Panel Loops、a.Repeat、m.Width。Tool > Geometry の各セクションではパス階層が追加されません。macOS では Cmd+W で ZBrush を終了します。Control+W ではグループ化します。
参考資料
references/expert-notes.md:専門家による原則、タイムスタンプ、判断条件が記載されています。計画時に読み込んでください。references/procedures.md:ブリッジの手順全体が記載されています。コードを書く前に読み込んでください。references/critique.md:評価基準が記載されています。各ゲートで読み込んでください。references/gui-paths.md:パレット、ホットキー、ブラシが記載されています。GUI でしか実行できないステップがある場合に読み込んでください。references/sources.md:すべてのソース、認証情報、URL、タイムスタンプが記載されています。