mcpField
M
machine

machine

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

machine について

machine は、機械の構造や動作原理を示す 3D 表示と映像を作るスキルです。1 行の説明から実寸の部品と物理計算を含む自立型 HTML ページを構成し、映像も出力します。

主な機能

  1. 01自立型 three.js ページの生成
  2. 02実寸に基づく部品の構築
  3. 03断面・分解・X 線表示
  4. 04方程式による数値と動作の計算
  5. 05規定構成の機械映像の作成

活用シーン

  1. 01ターボファンのインタラクティブな展示
  2. 02内部構造と部品の組み立ての表示
  3. 03スライダー入力による動作変化の提示
  4. 04故障と計算された影響の表現

インストール

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

$npx skills add https://github.com/airsuphq/machine-skill --skill machine

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

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

README.md
LICENSE
CHANGELOG.md
.gitignore
CONTRIBUTING.md
LAUNCH.md
V2-IDEAS.md
package.json
.github/
REPO.md
evals/
evals.json
examples/
compressor.html
rocket-engine.html
turbofan.html
refinery-pump.html
film/
README.md
reply.html
launch.html
kit/
template.html
lab-kit.js
references/
solvers.md
scripts/
inline.mjs
shot.mjs
record.mjs
pinkscan.mjs
scripts/lib/
browser.mjs
guard.mjs
serve.mjs
png.mjs

詳細

Machine Skill

製品スタジオが撮影し、エンジニアが説明するように機械を作ります。実物を実物大で、実際の素材を使い、整ったスタジオセットに置き、実際の方程式で動かします。1 行入力すれば、HTML ファイル 1 つと動画が 1 つのコマンドで出力されます。

出力は常に次のとおりです。

  1. <name>.html:単体で完結する 1 ページ(jsDelivr の three.js 0.170、キットをインライン化)。ディスク上、任意の静的ホスト、または iframe 内で開けます。
  2. 動画:node scripts/record.mjs <name>.html out/<name>.mp4 --music freepd:<Category>/<Name>。

まず examples/ を開いてください。すべての例は、ページ冒頭の 1 行から作られています。examples/turbofan.html がリファレンスです。何か書き始める前に、最初から最後まで読んでください。

求める水準

始める前に、視聴者が 3 秒後に目にするフレームを思い描いてください。実物の機械を撮影したスタジオ製品写真のように、最初から見える必要があります。正しいシルエットとプロポーション、金属らしく見える金属、紙の床に落ちる柔らかな影、浮いているものも、クリッピングしているものも、仮のものもない状態です。その後、機械が動き、画面上の数値はすべて計算されます。

次のいずれかに当てはまる間は、完成ではありません。

  • 整備士があるはずだと思う部品が欠けている(燃焼器に燃料ノズルがない、時計に脱進機がない、エンジンにバルブがない)
  • 何かが浮いている、交差している、または接合部に目立つ継ぎ目や隙間がある
  • 金属であるべき素材がプラスチックのように見える、またはすべてが同じグレーに見える
  • 画面上の数値がソルバーで計算されず、手入力されている
  • カットアウェイが中身の詰まっていない殻だけを見せており、断面が実体として描かれていない
  • 動画の最初のフレームが美しくない

ワークフロー

1. 実際の機械を調べる(5 分、コードなし)

機械のスクリプトの先頭にあるコメントブロックに、知っていること(可能であればウェブで調べた情報も)を書き留めます。

  • 実際の寸法:シルエットを決める 5~10 個の部品について、単位はメートル(ターボファン:ファン直径 2.85 m、全長 4.9 m、ナセル最大直径 3.44 m)。
  • 部品一覧:組み立て順に、それぞれの素材も記載します。部品名は 15~40 個を目安にします。繰り返し使われる部品(ブレード、歯、ボルト、コイル)も個別に数えます。
  • 物理:機械が動く仕組みを、実際に計算する 3~6 個の方程式として記述します。実際の定数と運転点も含めます(ターボファン:ブレイトンサイクル、離陸時 N1 100%、OPR 42、T4 1,750 K、約 330 kN)。
  • 1 つの数値:視聴者が気にする主役の数値です(推力、トルク、1 時間あたりの拍数、流量、出力)。大きなセリフ体の数値表示と細いバーで示します。
  • 入力:視聴者が操作したい入力です。スライダーを 1 つ用意します(スロットル、風速、rpm、ポンプ速度、挽き目)。
  • 故障:エンジニアが懸念する故障と、ソルバーが予測する結果です(ファンブレードの脱落による不釣り合い荷重、レッドラインを超えたときのバルブフロート、ポンプのストール、過圧)。アニメーションではなく、計算された結果でなければなりません。
2. テンプレートからページを作成する

kit/template.html を <name>.html にコピーします。このテンプレートには、インポートマップ(バージョンが [email protected] に固定されています)、フォント、キットを配置する目印付きブロック、そして記入する 4 つのセクションがあります。

const { THREE, Lab, MAT, GEO, heatGlow, clamp, lerp, approach, fmt } = window.LabKit
const lab = new Lab({ prompt, no, title, sub, size, view, cut })   // 1. the lab
// 2. the parts      lab.mesh(GEO..., MAT..., { name, pos, explode, xray, count })
// 3. the solver     lab.hero(...); lab.slider(...); lab.onTick((dt, lab) => { ... lab.setHero(...) })
// 4. break, explain, film      lab.breakIt(...); lab.how(...); lab.autoFilm(...); lab.start()

コピーしたらすぐに、node <skill dir>/scripts/inline.mjs <name>.html を実行します。これにより、キットが目印付きブロックに貼り付けられ、ページは保存場所にかかわらず単体で完結するファイルになります(テンプレート内の src="../kit/lab-kit.js" は、このリポジトリ内でのみ解決されます)。その後、2 つ目のスクリプトブロックに機械のコードを書きます。

3. ジオメトリ:実寸の実体部品

機械固有の座標系でメートル単位を使い、Y 軸を上向きにします。ground を設定しない場合、床は y = 0 です。size には実際の最長寸法を設定します。キットが表示スケールを調整して、すべての機械がセット上で同じサイズになるようにし、スケールバーには実寸が表示されます。

  • 回転部品(シャフト、ディスク、ケーシング、ノズル、コーン、スピナー、ピストン、ベゼル):閉じたプロファイルで GEO.lathe([[r, y], ...]) を使います。壁には GEO.shell(profile, thickness)、チューブには GEO.tube(rOut, rIn, h)、面取りディスクには GEO.disc(r, h) を使います。角はシャープなまま保たれ、曲面には自動でスムーズシェーディングが適用されます。
  • ブレードとベーン:GEO.rotor({ count, axis, r0, r1, chord, thick, camber, twist, pitch, sweep }) は、実際のキャンバーとねじりを備えた翼型(NACA 厚さ)の閉じた立体を生成し、円周上に配置します。chord、thick、camber には [root, tip] 配列を使います。
  • ギア:GEO.gear({ teeth, module, width, bore, helix, spokes, rim }) を使います。2 つのギアは、中心距離 (z1 + z2) * module / 2 でかみ合わせ、歯数比の逆比で回転させ、半歯分ずらします。
  • パイプ、ホース、ワイヤー:GEO.pipe(points, r)(閉じており、両端にキャップ付き)を使います。構造に沿ってポート間に配線し、部品を貫通させないでください。
  • 締結具:すべてのフランジに GEO.bolts(n, R, size, h) を使います。スプリングには GEO.spring(R, wire, turns, len)、ボックスには GEO.rbox(w, h, d, r)(常に丸みを付け、角を鋭くしない)を使います。穴のあるプレートには GEO.extrude(shape, depth) を使います。
  • 質量と慣性はジオメトリから求められます。GEO.volume(geo) で体積と重心を取得し、実際の密度を掛けてください。

きれいに仕上げるためのルール:

  • すべての部品を閉じた立体にします(lathe のプロファイルは閉じ、シェルには厚みを付け、パイプにはキャップを付けます)。これにより、断面表示で切断面が立体として描画されます。開いたサーフェスは切断時に中空に見えます。
  • 目に見える交差も、浮いている部品もなくします。 各部品を支持部に接触させます(フランジは面に接し、シャフトはベアリング内を通り、支柱は床まで届くようにします)。接合部は拡大表示で確認してください。
  • 視線が集まる箇所を細かく作り込みます:フランジのボルト円、面取り、リップ、銘板、燃料ライン、ハーネスなどを追加します。大きな平面には、継ぎ目、パネルライン、またはテクスチャ仕上げを加えます。
  • 機械にベースを付けます:床に脚が接するスタンド、クレードル、台座、ベンチ、またはマウントを用意します。実際の機械が宙に浮いていることはほとんどありません。
  • 予算:三角形は最大約 70 万、メッシュは最大 200 個です。繰り返しの静的部品は GEO.merge / GEO.ring で結合し、可動グループは分離したままにします。
4. マテリアル:単一のグレーにしない

MAT.* プリセットを使います。これらには実測された反射率が設定されており、鋼、チタン、アルミニウム、真鍮、銅の違いが並べたときにも分かります。各プリセットでは、オーバーライド(color、roughness、clearcoat、その他すべての MeshPhysicalMaterial フィールド)と finish(微細な粗さのテクスチャ:lathe 部品の turned リング、brushed の筋目、cast の斑点、smudge、knurl)を指定できます。

用途プリセット
シャフト、ディスク、機械加工部品MAT.steel、MAT.stainless、MAT.chrome
ハウジング、鋳物MAT.aluminium、MAT.castIron、MAT.steelDark
ブレード、航空宇宙部品MAT.titanium、MAT.inconel(heatGlow と併用)
継手、配線MAT.brass、MAT.copper、MAT.gold
塗装された本体MAT.paint({ color })、MAT.satin、MAT.anodised({ color })
ポリマーMAT.plastic、MAT.rubber、MAT.carbon
窓、結晶MAT.glass、MAT.sapphire、MAT.ruby、MAT.enamel
光、炎、高温ガスMAT.glow、heatGlow(material, kelvin)

工業デザイナーのように配色を選びます。金属を主体に、塗装色は 1~2 色まで、アクセントカラーは多くても 1 色にします。高温部品は、ソルバーの温度に応じて発光します(material.userData.heat.value = T)。

5. ソルバー:実数値以外は使わない

入力と状態から、表示するすべての数値を算出する小さな純粋関数を作成し、実際の単位と実際の定数を使います。動力学の積分には approach(一次遅れ:回転数の上昇、熱容量)または rk4(ばね、脱進機、振り子)を使います。そして、その結果で動きを制御します。ソルバーが算出した rpm でシャフトを回転させ、ソルバーが算出した流量で粒子を動かし、ソルバーが算出した温度で金属を加熱します。

  • ヒーロー表示は1つ:lab.hero({ label, unit, max }) の後、毎ティック lab.setHero(value, { state, sub, bad }) を呼び出します。state は2~3語(回転上昇中、離陸、チョーク流など)にします。sub は、追加の数値を2つか3つ含む1行にします。
  • スライダーは1つ:lab.slider({ id, label, min, max, value, unit, ends })。機械に本当に必要な場合に限り、2つ目を追加します。
  • ラベルは、断面平面上の座標を指定して静止部品に取り付けます:lab.label(obj, 'HP turbine', { at: [x, y, z], value: () => '12,979 rpm' })。
  • lab.how(words, equations) で「How it is computed」を埋めます。モデルを平易な言葉で説明し、コードに書かれたとおりの方程式を示します。簡略化した箇所も説明します。
  • 動きが速すぎて見えない場合(2,700 rpm のファンなど)は、速度を落として表示し、そのことを how に記載します(「回転表示は1:60」)。数値は決して遅くしません。
  • ステップ1で書き留めた公開データと照らし合わせて、動作点が妥当かを確認します。約20%以上ずれている場合は、数値ではなくモデルを修正します。
6. 流れ、熱、エフェクト
  • lab.flow({ paths, count, length, color, parent }):実際の流路から作成したパスに沿って流れるストリークです(ダクト内の空気、ポンプを通る血液、パック内の水など)。.speed はソルバーの値を設定し、.opacity は lab.state.cut に基づいて設定して、カットアウェイ内部に表示されるようにします。計算した量(温度、圧力)に応じて色を付けます。
  • lab.plume({ radius, length, dir, color: 'rocket' | 'jet', shocks }):マッハダイヤモンドを伴う排気です。.power はソルバーの値を設定します。
  • 破損には lab.sparks.emit(worldPos, n, speed) と lab.shed(mesh, v, w) を使います。火花は重力で落下して跳ね返り、放出された部品は剛体となって床に着地します。
7. モード(キット側で用意されるため、設定だけ行います)
  • 分解:各 lab.add/lab.mesh には、親の座標系でメートル単位の explode: [dx, dy, dz] を指定します。部品を組み立て軸に沿って動かし、外殻は最も遠くに配置し、コアはその場に保ちます。移動中に部品どうしが交差してはいけません。
  • カットアウェイ:Lab に cut: { a, b, center, reach } を指定します。a と b は取り除く領域の方向です。a = [0,0,1], b = [0,1,0] とすると、手前かつ上方向の四分の一が取り除かれます(軸を持つものに最適です)。b = a では半分が取り除かれます。すべての閉じた立体に、ハッチングを薄く施した断面が自動的に描画されます。
  • X線:外装ケースに xray: 'shell' を指定すると、細いエッジを残してガラス状になり、稼働中のコアが見えるようになります。
  • スローモーション、ラベル、一時停止は最初から使えます(キーは S、L、Space)。操作できるのはマウスでの回転、スライダー、ボタンです。
  • 破損:lab.breakIt({ label, run(lab), reset(lab) }) を使います。run でソルバーの状態を変化させ(ブレードの脱落、バルブの固着、シールの破損など)、ソルバーでその結果を計算します。ヒーロー表示(bad: true)と、火花、破片、または揺れで表現します。
8. 批評家の目で確認する(必須)

作成した画像をすべてレンダリングし、実際に読んで確認します。次のスクリプトを使います:

node scripts/shot.mjs <name>.html out/review.png                               # the first look
node scripts/shot.mjs <name>.html out/cut.png --js "lab.toggle('cut', true); lab.toggle('labels', true)"
node scripts/shot.mjs <name>.html out/near.png --js "lab.setView({ az: 70, el: 8, dist: 0.8, target: [x, y, z] })"
node scripts/shot.mjs <name>.html out/film --film 1,4,8,12,17,22,26                 # film stills

少なくとも4回レビューします。各回で、全体表示、ラベル付きカットアウェイ、分解表示、接合部のクローズアップ2枚、そして映画のスチルを確認します。記憶にある実際の製品写真と照らし合わせ、プロポーション、部品数、素材、光の当たり方を比べます。問題点を列挙し、修正して、再度レンダリングします。問題点がなくなるまで続けます。ショットスクリプトには fps、部品数、三角形数が出力されます。インタラクティブ時のフレームレートは30以上を維持します。

9. 映像

lab.autoFilm({ runBeat, runSub, breakBeat, breakSub, sliderTo }) は、マシンから標準の28秒のストーリーを作成します。番号付きのビートと、次の編集用キャプションが含まれます。

  1. ひとつの文で概要を伝えます(プロンプトバーに文字が自動入力されます)。
  2. Claude がマシンを組み立てます(部品が組み立て順に飛んできて、カウンターが「84 of 3,597 parts」まで増えます)。
  3. マシンが動作します(カーソルがスライダーをドラッグし、ソルバーの計算結果に応じてメインの数値が上がります)。
  4. 内部を切り開きます(断面のキャップと、リアルタイムの値を表示するラベル)。
  5. 分解します(分解表示)。
  6. 壊します(カーソルが破損ボタンをクリックし、ソルバーが故障箇所を判定します)。

ループ再生され、最後のカメラキーから最初に戻ります。独自の映像を作るには、lab.film('name', { len, assemble, shots, events }) を使います。ショットはカメラキー { t, az, el, dist, target, fov }、イベントは { t, beat: ['07', 'Bold sentence.', 'Grey sentence.'], set: { cut: 1 }, slider: { id, to, dur }, cursor: { to: 'slider:id:0.8' | 'button:break' | [x, y], click: true }, do(lab) {} } です。

録画(Node 18+、Chromium を含む Playwright、ffmpeg が必要です):

node scripts/record.mjs <name>.html out/<name>.mp4 --music freepd:Classical/Easy_Lemon
node scripts/record.mjs <name>.html out/<name>-portrait.mp4 --w 1080 --h 1350

ページは映像モード(?film=1)で動作します。時計はレコーダーが進めたときだけ進むため、すべてのフレームが完全に描画され、何度録画しても映像は同じになります。レコーダーは、停止したヘッドレス GPU が返すことのあるマゼンタ色のフレームがないか、すべてのスクリーンショットを確認し、完成した映像もスキャンします。ピンク色のフレームがひとつでもある場合、ゼロ以外の終了コードで終了します。FreePD の音楽は CC0 ですが、曲のクレジットは記載してください。

画面上のテキスト

このページはダッシュボードではなく、編集的な表現を重視しています。プロンプトバー、イタリック体の副題が付いたセリフ体のタイトル、イタリック体の単位と細いバーを添えた大きな数値ひとつ、補足の数値が並ぶ1行、そしてスライダーひとつで構成されています。優れたキャプションのように、短く、具体的に、誇張せずに書いてください。単位は実際に使われるものを、数値との間にスペースを入れて記載します(338 kN、1,750 K、4.2 L/min)。桁区切りも入れてください。ビートのキャプションは、太字の文とグレーの文で構成します。

引き渡し時に伝えること

HTML ファイルのパス、映像のコマンド、公開されている数値と比較してソルバーが到達する動作点、簡略化した箇所を伝えてください。次のマシンも提案してください。

コメント