Hermes Agent Wiki 非公式・日本語wiki
この skill をそのまま使う: GitHub で原文を見る

英語原文・frontmatter 込みで、Hermes が読み込む実体そのままです(このページの本文は日本語版)。

Anatomy

目次

考えを、操作できるアイソメトリックの機械の図で説明します。

skill の情報

提供元 追加で入れるもの — hermes skills install official/creative/anatomy で導入します
パス optional-skills/creative/anatomy
バージョン 1.0.0
作者 Ryan (wheresryan22)、Nous Research が Hermes に移植
ライセンス MIT
対応プラットフォーム linux, macos, windows
タグ isometric, svg, webgl, 3d, diagram, explainer, illustration, docs, html, react
関連 skill concept-diagrams, system-atlas, architecture-diagram

参考: SKILL.md 全文

Anatomy

この skill が作る図は、作業台に載った小さな計測器のように働きます。脚の付いた重いベース、目盛り付きのレール、ブッシュに乗ったキャリッジ、ローレット加工のつまみ、コイルばね、針が動くダイヤルゲージがあり、ねじは小さな点で描きます。読む人は、その機械に見覚えがあるから考えを理解できます。図が表示する数字はすべて、部品を動かしているのと同じモデルから出ています。

出力は単体の HTML ページ(SVG と、必要に応じて WebGL のレイヤー)、単独の .svg、または React/Next.js のコンポーネントです。キットは Node の組み込み機能だけを使うので、npm install するものはありません。

Hermes で動かす

skill のディレクトリ。 Hermes は ${HERMES_SKILL_DIR} を、この skill が導入されたディレクトリに展開します。シェル変数はターミナルの呼び出しをまたいで引き継がれないので、使う呼び出しのたびに代入を書き直します。

SKILL_DIR="${HERMES_SKILL_DIR}"

skill のディレクトリの中でビルドしないこと。 どの build.mjs も HTML を自分の隣に書き出し、例は ../../kit/ と ../../scripts/ を import します。同じ形の作業場所を用意してください。ユーザーにプロジェクトがあればそこを、なければユーザーが名前を付けたフォルダーを使います。

SKILL_DIR="${HERMES_SKILL_DIR}"
WORK="$HOME/figures/pin-lock"
mkdir -p "$WORK/figures"
cp -r "$SKILL_DIR/kit" "$SKILL_DIR/scripts" "$WORK/"
cp -r "$SKILL_DIR/examples/dial-indicator" "$WORK/figures/"
cd "$WORK/figures/dial-indicator" && node build.mjs && node build.mjs --light

新しい図は、いちばん近い例を $WORK/figures/<name>/ にコピーして名前を変えるところから始めます。導入した skill に手を付けずにおけば、hermes skills update がローカルで変更されたものとして扱うこともありません。

例はソースだけで配布されています。 上流でビルド済みのページは、生成された HTML で 9 MB あります。開いたりキャプチャしたりするには、上のように例をビルドしてください。数秒で終わります。

自分の作ったものを見る。 上流の作業手順には「PNG はすべて読む」とあります。Hermes では、キャプチャ 1 枚ずつに vision_analyze を使うということです。4 倍の拡大は、高 DPR のキャプチャか --zoom のキャプチャに対して、その region 切り抜きを使います。「良く見えるか」ではなく、「フランジ側のパイプはフランジ面で終わっているか」のように具体的に尋ねます。

ブラウザ。 キャプチャ、操作、線の端、3D の各チェックは、ループバックの DevTools ポートでヘッドレス Chrome を起動します。使うのは、設定されていれば CHROME_PATH、次に Hermes のブラウザツールが入れる Playwright のヘッドレスシェル(Playwright のキャッシュにある chromium_headless_shell-*)、最後にシステムの Chrome か Chromium です。ヘッドレスシェルを優先してください。WebGL のレイヤーを SwiftShader で描画し、外部への接続を一切しません。通常のデスクトップ版 Chrome は、使い捨てのプロファイルでも Google のサービスへ裏で接続します。また TMPDIR が長いパスのとき(Hermes のプロファイルごとの作業用ディレクトリはそうなりがちです)は起動に失敗し、「Socket path too long」のあと「Chrome did not start」と出ます。どうしても使う場合は、そのコマンドだけ TMPDIR を短いディレクトリにしてください。図をビルドするだけならブラウザは要りません。

時間のかかる実行。 node build.mjs --audit は密度の高い Hero で約 2 分かかり、3D の周回監査を全部回すと、部品 30 個で 15〜20 分かかります。これらは terminal(background=true, notify=true) で実行し、そのあいだ別の作業を進めます。

規模を尋ねる。 作業手順の規模見積もりの段階で、作るか尋ねるかを決めます。Epic なら、見積もりと Hero 版の代案を clarify でユーザーに示し、選ぶのを待ちます。

納品。 ビルドした HTML(両方のテーマ)の絶対パスと、確認した PNG のキャプチャを渡します。メッセージングのプラットフォームでは、チャットではページを動かせないので、デスクトップとスマートフォンの PNG を添付します。

例

始める前に、いちばん近い例を開いてください。フレームワークを使わない例は、それぞれのディレクトリで node build.mjs を実行するとビルドできます。ライトテーマにするには --light を付けます。

  • examples/dial-indicator/ はいちばん小さい例で、スタンドに載ったダイヤルゲージです。全体で約 300 行です。
  • examples/desk-computer/ はフレームワークを使わない SVG で、キーボードで実際に入力できる卓上コンピューターです。打った行は、筐体の前面と同じ平面に描いた CRT 画面に表示され、電源を切ると映像が線と点に縮んで消えます。立体は約 85 個、パスは約 850 本です。
  • examples/arcade-cabinet/ は側板を外した直立型のアーケード筐体で、立体約 240 個とケーブル 15 本の Hero です。硬貨が投入口へ飛び込み、30° の斜面を転がる円盤が達する速さでコインシュートを転がり落ち、コインスイッチの線を押して集金箱に落ちます。スイッチのパルスはケーブルの区切りごとに基板まで伝わり、CRT は暖まって自己診断をし、傾いたモニターと同じ平面に描いたデモ画面を流します。スティックを倒すと、パネル下のマイクロスイッチが閉じます。この例からわかることは、切断図の仕組みが見え続けるようなカメラの置き方、任意の軸に沿ったプリズムとして描く凹んだ基板、ビルドと同じモジュールからページ内で組み直す動く部品、確定した描画順の予約枠に描く動く硬貨と線です。node build.mjs --audit がジオメトリを証明します。
  • examples/raptor-engine/ は試験台に吊られたロケットエンジンです。丸い部品は kit/lathe.mjs から、パイプとハーネスは kit/tube.mjs から作ります。ばねの時間差とフレームごとの奥行きの並べ替えで、11 のアセンブリに分解します。すべての部品が本当の形を記録しており、node build.mjs --audit(kit/audit.mjs)が、組んだ状態、分解した状態、分解のあらゆる再生フレームで次のことを証明します。何も何かを突き抜けていないこと、すべての端が実在する取り付け部に載っていること、曲がりがつぶれたり折り返したり別の線に重なったりしないこと、曲面の輪郭の傾きが揺れないこと、そしてすべての重なりが奥行きの順に描かれていることです。WebGL の噴流、衝撃波、飛沫、蒸気が、奥の SVG と手前の SVG のあいだに描かれます。密集した配管、なめらかな陰影、フェードの手本です。
  • examples/ripple-tank/ は、紙のスクリーンの上に長い脚で立つ学校用の波動水槽を、44° 上から見た図です。WebGL のレイヤーが 2 枚あり(紙に落ちるランプの光・影・集光模様と、水面の反射とガラス)、アイソメトリックの平面に位置を合わせ、純粋な分散と光学のモデル(model.mjs)で動きます。周波数を変えると、その変化が履歴テクスチャを通じて加振棒から外へ伝わっていきます。
  • examples/test-rig/ は実在のサイト(React/Next)で使われている本番の図です。ばねで支えたキャリッジに載ったガラスのボタン、レールの上で押したり引いたりする指型のプローブ、傾きを読むダイヤルゲージがあります。立体は 53 個、パスは約 470 本です。
  • examples/spot-plate/ は同じサイトの 2 つ目の本番の図です。スポットプレートの上にガラスの滴が 6 組並び、それぞれの組は 1 つの距離場から描かれるので、merge より近い組は流れ合って 1 つのガラスになります。並んだすきまゲージの刃が merge を決め、すきま 1 つにつき刃が 1 枚です。形が互いに移り変わる図と、1 つの操作で多くの部品を動かす図の手本です。
  • examples/turning-dial/ は追加の 3D モードの例で、小さなロボットハンドが載ったダイヤル錠が本当の 3D で回ります。金属の材質を持つ動く部品が約 90 個あり、2 つ目の回転グループ、ヒンジ、持ち上がる 3 関節の指、外れて自由に動く物体になるポッドがあります。WebGL の LED とその光だまり、火花が動く部品についていきます。隣の stress.mjs は、散らかった作業場に置いた部品約 380 個の密な手で、性能の計測に使います。

図そのものの描き方の品質基準は、試験台(test rig)が決めます。シェーダーの基準は Raptor が決めます。WebGL の効果は、ワールド空間で、ポップせず、継ぎ目のない Raptor の描画にそろえる必要があります。

いちばん大事な考え方

物体そのものが説明です。 箱や矢印やラベルを描かないでください。その動きが概念 *そのもの* になる、実在しうる、よくできた物を考え出します。これまでの図では、次のように対応させました。

概念 物体
1 つの共有 GPU コンテキストが多くのキャンバスに使われる ガントリープロッター。1 つの印字ヘッドが 16 個のウェルを回る
何も変わっていなければ処理を飛ばすキャッシュキー ピンタンブラー錠。すべてのピンがそろうとプラグが回り、何も描き直されない
1 テクセルあたりのバイト数が違う 7 つのレンダーターゲット 7 段の引き出しがあるたんす。各段の深さがそのバイト数
分離可能なぼかし(49 × 49 タップ対 49 + 49) 剣山のスタンプと、その横のレールに載った 2 本のくし
押して傾くばね ばね、プローブ、ダイヤルゲージのある試験台
高さの輪郭 縁に押し当てた型取りゲージ(輪郭ゲージ)
向きで変わる光 小さな写真スタジオ。ターンテーブルの周りにキーライトと補助ライト

失敗の形は 2 つあり、どちらも実際に起きました。

  • 抽象的すぎる。 積み重ねた板、浮いた厚板、ラベル付きの箱は、何にも見えません。
  • 平板で味気ない。 大きな厚板 1 枚に線が数本では、量感も部品も見つけるものもありません。

直し方はどちらも同じです。たくさんの小さく正確で目的のある部品から組み立てた、見てそれとわかる機械にします。

どの作品も、細部まで作り込みます。 これは、考えや依頼がどれほど小さくても、すべての図に当てはまります。手早い説明図でも、密度のある本物の機械であり、厚板数枚ではありません。規模(作業手順の 1)に応じて変わるのは、どこまで突き詰めるかです。Figure では対象と仕組みについて、Hero と Epic では図全体について、4 倍の点検をします。

  • 本物を読み取る。 本物と同じように組み立てます。ねじ、継ぎ目、面取り、ブッシュ、銘板、コネクター付きのケーブル、目盛り付きの定規、そして部品を支える部品まで、すべてです。
  • 2 つの見え方。 等倍では 1 つのはっきりした機械に見えます。4 倍でも、どの部分にも見つけるべき本物があります。何もない面や空いた隅は、落ち着きではなく未完成の作業です。
  • 目的があり、決して雑音にしない。 細部は、仕組みに属する部品から生まれます。どの部品も別の部品の上に載り、縁で終わり、途切れずに薄れて消えます。
  • 最後に確かめる。 仕上げる前に 4 倍に拡大し(Figure では対象と仕組み、Hero と Epic では図全体)、平坦な部分があれば、足りない本物の部品を足します。

作業手順

この順に進めます。ジオメトリに手を付ける前に、概念と部品リストを書きます。品質のほとんどはそこで決まります。

  1. 始める前に規模を決める。 ほかの作業より先に、依頼がどの規模で、おおよそどれくらいかかるかをユーザーに伝えます。
  • Figure: 仕組みが 1 つ、部品 40〜80 個、SVG と多くて 1 枚の WebGL レイヤー。約 30〜90 分。尋ねずに作ります。
  • Hero: 密度の高い物体、WebGL レイヤー数枚か 3D の対象 1 つ、部品 80〜150 個。約 2〜4 時間。そう伝えてから、ユーザーが手早いものを求めていなければ作ります。
  • Epic: 多くの動く系統を持つ乗り物・建物・プラント全体、または複数の対象に 3D モードを使うもの。6 時間以上。着手しません。見積もりを伝え、考えの核を残した Hero 版を提案し、完全版で何が加わるかを並べます(clarify で尋ねます)。Epic は、ユーザーが選んだときだけ作ります。
  • 規模にかかわらず、最初の 1 時間以内にブラウザで開ける動くページを用意し、そこから深めていきます。最初と各段階で date を実行し、ある段階が見積もりの持ち分の 2 倍を超えたら、どこまで進んで何が残っているかをユーザーに伝えます。
  1. まず事実。 説明する対象の本当の数値とふるまいを集めます。大きさ、個数、しきい値、曲線などです。表示の値、動き、説明文はすべて事実でなければなりません。できれば、test-rig の例の rig.ts のように、モデルを小さな純粋なモジュールとして書き、すべてをそこから動かします。
  2. 物体を考え出す。 仕組みが概念と一対一に対応する機械、道具、計器、家具を選びます。何が動き、その動きが何を意味するかを 1 文で言います。参考画像を写さないでください。取り入れるのは仕上げであって、物体ではありません。
  3. 部品リスト。 部品を少なくとも 40 個(Figure は 40〜80、Hero は 80〜150、Epic はそれ以上)書き、グループに分けます。ベース(板、脚、溝、隅のねじ、銘板、定規の帯)、構造(支柱、レール、フレームの棒、エンドストップ)、仕組み(キャリッジ、ブッシュ、ばね、プランジャー、針)、操作部(ローレットつまみ、つまみねじ、竜頭)、そして対象そのものです。対象は、唯一照らされる部品です。どの部品も別の部品の上に載ります。references/craft.md に、作り方つきの部品の語彙があります。
  4. ワールドを計画する。 ワールドの単位は、本物のおよそ 1 px にします。x と y が床、z が上です。平面図は角の丸い長方形 {x, y, w, d, r} と円で配置します。カメラを選びます。方位角は既定で 45°、長い側を見せるなら 35〜60°、仰角は 30°(開いたものの中をのぞき込むなら、波動水槽の 44° のように高くします)。そのうえで fitProjection(points, width, height, { pad, azimuth }) で収めます。
  5. ジオメトリは一度だけ作る。 静的なパスはすべて、キットを使ってジオメトリのモジュールで先に計算します。slabOf、cylinder、extrude、planOutline、topTicks、knurl、coil、radialTicks などです。任意の軸の丸い部品(ベル、フランジ、バルブ、アクチュエーター)は kit/lathe.mjs から、パイプとケーブルは kit/tube.mjs から作ります。動く部品は静止位置で一度作り、translateAlong で動かします。フレームごとに作り直すのは、形が変わる部品だけです。
  6. 奥から手前へ、下から上へ塗る。 繰り返す部品は depthOf で並べます。別の部品を囲むものは、奥半分と手前半分に分けます。棒を囲むばねや、キャリッジを囲むフレームの棒などです。動く部品は、物理的にある位置の枠に描きます。references/craft.md の「Painter's order」を見てください。図にパイプ、ケーブル、丸い部品が入ったら、キーを目で調整するのはやめます。描くときに各要素の形を A.recorder(P, { order, spring }) に記録し、A.settle(R, P) に 2 つの要素が重なる場所の本当の奥行きを測らせてキーを決めさせ、ビルドの最後を A.auditOrExit(R, P) で締めます。パイプは描く前に経路を決めます。両端に本物のポート、構造に沿った区間、直線部での交差、パイプを途切れさせるカラーです(references/craft.md の 8 節)。描いたものの本当の形を記録します。監査を黙らせる代わりの形はバグであり、監査はそれを不合格にします。グランドから滑り出る棒は G.rodOut の 1 本の棒で、A.slide で記録します。
  7. 枠に入れる。 図をカードに入れます。左上に Fig n、右上に短いタイトル、左下に操作のヒント、右下に動く表示値を置きます。凡例と事実どおりの説明文はカードの下に置き、図の中には、多くて 1 つの小さな刻印ラベル以外の言葉を入れません。
  8. 動かす。 時間に基づく落ち着いた動き、つまり指数的な追従か本物のばねを使います。誰も触っていないあいだは、待機中の巡回が繰り返されます。図はポインターとキーボードに反応し、画面外では止まり、動きを減らす設定では静止します。属性は ref に書き込み、フレームごとに再レンダリングしません。references/motion.md を見てください。
  9. 批評家のように確かめる。 持ち主は拡大して欠点を見つけるので、先に自分で拡大します。作った PNG はすべて vision_analyze で読みます。
  • scripts/capture.mjs で、デスクトップ、スマートフォン(幅 390)、ホバー、動きの数場面をキャプチャします。一連の操作、分解した姿勢、--no-webgl の代替表示には scripts/drive.mjs を使います。
  • 監査を 0 になるまで回す。 パイプ、ケーブル、丸い部品があるなら、node build.mjs --audit が audit passed で終わり、不合格の行がすべて 0 でなければなりません。対象は、静止時・分解時・動きの途中のすき間、端子、ほどけた端、折り返し、自己交差、密集(細い立体に対しても)、代わりの形、支持、揺れ、サドル、奥行きの順です。かみ合いはジオメトリで直し、キーの偏りでは直しません。
  • 線のチェックを 0 になるまで回す。 監査は線のマークアップを見ません。node scripts/lines.mjs page.html --out shots/lines.png(-light のページでも、drive.mjs の ["lines"] アクションで静止したすべての姿勢でも)が line ends: 0 と出力しなければなりません。継ぎ目、罫線、リブ、目盛り、指針はすべて、線、点、輪郭のどれかで終わります。丸印の付いた PNG を読みます。
  • すべての接合部を、両方のテーマ(--light もビルドします)で、組んだ状態と分解した状態の両方について 4 倍に拡大する。 フランジ、T 継手、エルボ、クランプ、バルブ、ベローズ、バンド、サドル、ボールジョイント、交差のすべて、曲面の本体すべて(階段状の諧調がないこと)、テクスチャが終わるすべての場所(縁で終わるか薄れて消えること)、継ぎ目のある箱の平らな面、区切りの継ぎ目にあるテクスチャ付きホースすべて、静止時と最大ストロークでの滑る棒すべて、文字やシェーダーの内容を持つ窓すべてです。
  • シェーダー: すべての遷移にわたって ["slow", 0.05] で遅くしたコンタクトシートを作ります。何もポップせず、色が切り替わらず、端は 0 と読めること。ライトでは、各遷移を通してフレームごとのインク量も記録し(光に対して単調に追従しなければなりません)、インクが線と接するところを 8〜16 倍で切り抜きます(references/verify.md の「Light-theme shaders」)。
  • 自分の PNG を例の隣に置いて問いかけます。一目で本物の物体に見えるか。量感のある小さな部品が豊富か。どの線も何かの上で終わっているか。等倍で細部まで作り込まれ、4 倍でも見ごたえがあり、何もない面や空いた隅がないか。答えが「はい」になるまで繰り返します。チェックリストは references/verify.md です。

準備

キットは kit/ にあります。

ファイル 用途
kit/iso-kit.ts 中核の全部を 1 ファイルにまとめたもの。カメラ、立体、部品ライブラリ、SVG 文字列のレンダラー、カードとページのビルダー、CSS(ISO_CSS)。TypeScript のプロジェクトにコピーして使います。
kit/iso-kit.mjs 同じ中核を素の ESM にコンパイルしたもの。Node のスクリプト用で、直接 import します。
kit/iso.css ISO_CSS を書き出したもの。一度 import し、ラッパーか <body> に class="iso"(ライトなら data-theme="light" も)を付けます。
kit/react/draw.tsx サーバーで安全に使える React コンポーネント。Solid、Line、Wire、Dots、FaceText、IsoFigure、Plate。
kit/react/live.tsx "use client" のフック。useReadout、useLoop、useEased、useInView、useStillness、加えて spring と follow。
kit/lathe.mjs 任意の軸に沿った丸い部品。frameAlong、lathe(なめらかな節点を持つ輪郭なら、なめらかな陰影が自動で有効になります)、solidOf、disc、ringBand、sphereOf、saddleOf、bandsOf(1 つの曲面の本体を、1 つの面を共有し奥行きで並べ替えられる帯に切り分け、輪郭は sidesOf から 1 本)、丸い面の上の見える弧・リブ・ボルト円(ribsOf と dotsOf は fade を、ribsOf は seams を取ります)、グランドから滑り出る棒の rodOut、パイプ経路用の fillet。
kit/tube.mjs tubePieces は 3D のパイプやケーブルを、奥行きで並べ替えられる区切りに分けます(breaks、カラーやクランプの下の gaps、楕円の端キャップ、すべての継ぎ目を通して断面に沿う編組・波付け・巻きの rings つき)。tubeSvg は 1 本を描きます。crossingsOf は経路がクランプを通る場所を、runsOf は描かれた区間を求めます。.tb-* の塗りは ISO_CSS にあります。
kit/audit.mjs ジオメトリを証明します。recorder(P, { order, spring }) は、ヘルパーが描くときに要素・形(回転体、厚板、プリズム、箱、球、管、母体で切られたパッド)・経路を集めます。settle(R, P) は重なるすべての組に光線を飛ばして本当の奥行きを求め(静止時、分解時、分解の再生中)、描画順のキーを決めます(overlapsOf、orderKeys)。auditOrExit(R, P) は --audit のフックで、すべてのチェック(clearances、solidClearances、terminals、looseEnds、supports、folds、selfOverlaps、細い立体を線として扱う crowding、代わりの形を見る coverage、wobble、seats、depthOrder)を実行し、問題があれば 0 以外で終了します。A.slide はグランドから滑り出る棒を記録します。references/kit.md の 12 節。
kit/gl.mjs 図の中のシェーダー用の WebGL レイヤー。GLSL_ISO(rayOf と pixelOf を含む GLSL 版のカメラ)、glCamera(P)、glLayer(...)、JS のエンベロープ smooth、burst、settle。3D の図では、GLSL_TURN と glslPose(name) がワールドの点を動くグループに取り込み、coverOf で手前のキャンバスをマスクします。
kit/turn.mjs, kit/turn-build.mjs, kit/turn-audit.mjs 追加の 3D モード。turn-build.mjs には turning(P, { recorder }) があります。グループ(回転、スライド、ヒンジ、自由)、動くレイヤー、材質付きの凸な部品、T.build です。turn.mjs は実行時の部分で、TURN.mount、コントローラー、TURN.cover、TURN.poseUniforms、TURN_CSS があります。turn-audit.mjs には、すべての回転角と動きのクリップを回る周回監査 orbitOrExit があります。references/3d.md。
scripts/capture.mjs ヘッドレス Chrome でのスクリーンショット、拡大、コンソールの確認。WebGL は有効です。node で実行します。
scripts/drive.mjs WebGL つきの台本どおりのヘッドレス Chrome。移動、クリック、キー、スローモーション、条件待ち、eval、ショット、ポップを捕まえるコンタクトシート。--no-webgl と --preload もあります。
scripts/lines.mjs ビルドしたページでの線の端のチェックを、ヘッドレス Chrome で行います。テクスチャの線はすべて、線、点、輪郭のどれかで終わらなければなりません。--out で不合格の箇所に丸印を付け、1 つでもあれば 1 で終了します。
scripts/inline-kit.mjs kitScript()、glScript()、turnScript() が、キット、WebGL レイヤー、3D の実行部を、単体ページに埋め込むソースとして返します。
scripts/turn-check.mjs, scripts/turn-bench.mjs 3D の図用。キットのビルダーとの忠実度、z バッファでの順序チェック、ピクセルのポップ、24 方向での線の端、ブラウザでのフレーム時間。部品の種類ごとの Node の CPU 時間。

プロジェクトに合う道を選びます。

  • 単体の HTML、静的な SVG、ブログ記事、React 以外のサイト。 「Hermes で動かす」で用意した作業場所に、examples/dial-indicator/build.mjs のような Node のビルドスクリプトを書きます。kit/iso-kit.mjs を import し、solidSvg、lineSvg、dotsSvg、wireSvg、faceTextSvg で文字列を組み立て、figureSvg と plateHtml で包み、pageHtml({ script: kitScript() + live })、シェーダーがあるなら kitScript() + glScript() + live でページを書き出します。単独の .svg ファイルには、スタイルを埋め込む figureSvg({ standalone: "dark" | "light" }) を使います。
  • React または Next.js。 kit/ をプロジェクトにコピーします(たとえば components/iso/)。ジオメトリは素の .ts モジュールに置き、静的な絵は draw.tsx のコンポーネントを使ってサーバーコンポーネントで作り、物を動かす 1 つの "use client" の動くコンポーネントに要素の props として渡します。references/react.md に、この分け方と大きなページでの落とし穴の説明があります。

作り込みのルール(短縮版)

作り込まれた図とただの図表を分けるのは、次のルールです。references/craft.md に、詳しい理由と作り方があります。

  • ワイヤーフレームではなく立体。 どの部品も紙の色で塗りつぶし、順番に塗るので、手前のものが奥のものを隠します。透けて見える辺も、破線の隠れ線もありません。
  • 陰影はキットに任せる。 extrude は、向きに応じた 4 つの側面の諧調と、明るめの上面を返します。高さのあるものにはこれを使い、flat は床と、厚さ 1 単位未満の象眼だけに使います。
  • 諧調の階層。 ベースと脚は lo、構造は mid、対象は hi です。アクセントはちょうど 1 つだけ lit(ダークでは白、ライトでは黒)にし、それが読む人に見てほしい部品です。溝は faint、細かい目盛りは lo、主目盛りは mid、ゼロの印は hi です。色は、赤・緑・青のチャンネルのように色そのものが主題のときだけ使います。
  • 小さく正確な細部、決して雑音にしない。 面取りは 0.4〜1.6、溝は縁から 3〜5 内側、ねじは 0.4〜0.55 の点で板の隅に輪を付け、つまみにはローレット、定規の目盛りは 4〜5 単位ごとで 5 本目ごとに主目盛り、銘板には罫線を 3 本入れます。どの細部も、ある部品に属します。
  • 線は決着する。 どの線も、面、別の線、端子の点のどれかで終わります。接続線は Wire で、端子の点が物の上に載ります。引き出し線、吹き出し、寸法の矢印、宙に浮いたラベルはありません。
  • パイプやケーブルは何も突き抜けない。 静止時も、分解時も、分解のどのフレームでも、別のパイプ、ケーブル、立体を突き抜けません。線自身の接続部以外のすべてから約 1.5 半径のすき間をとり、線は対象の面を横切らせず構造の脇に通し、フランジ、バンド、ベローズ、クランプ、バルブが巻き付く場所ではパイプを途切れさせます。部品は面一、接線、縁が面に載る形で接し、めり込みません。フランジの裏面はポートに載り(ポートが曲面ならサドルパッド G.saddleOf の上)、分岐はボール T から出て、分解時も含めてすべての端が、フランジ、カップリング、コネクターの殻、端子の点のどれかで終わります。
  • 交差はすべて本当の奥行きの順に描く。 画面上で 2 つの要素が重なるところでは、近いほうを上に描きます。これは目で調整するのではなく、A.settle と監査で証明します。線は直線部で、奥行きを十分に離して交差させます。別の線の輪郭に曲がり、端、クランプが載ると継ぎ目に見えます(棒、タイロッド、支柱、レールも線に数えます。パイプの最後の区間は、画面上でそれらに沿って走らせません)。見る人のほうを向いてから曲がる区間は V 字につぶれます(そういうポートはエルボのボールから出します)。経路は画面上で折り返しません。順序を決められない組はかみ合っており、直し方は切り分けか接線での接触であって、偏りではありません。
  • 曲面は階段状でなく、なめらかに陰影を付ける。 曲面の節点をなめらか([s, r, 1])と指定すると、lathe が、輪郭も描く 1 本の単調な曲線から陰影を付けます。継手より大きい曲面の本体には smooth: { slope } で解析的な輪郭を与え、長い本体は G.bandsOf で切り分け、球には G.sphereOf を使います。諧調の帯は直線の切り口で終わらず細くなって消え、継ぎ目は輪郭の下(inner)に入れます。
  • テクスチャは本物の縁で終わるか、薄れて消える。 リブ、ボルト円、罫線、継ぎ目、溝は、平面でも曲面でも面の途中で止まりません。ribsOf と dotsOf は fade を取り(薄れたリブは fadedSvg で描きます)、リブの列は継ぎ目で終わり(ribsOf(…, { seams: true }))、箱の継ぎ目や溶接は角を回り込み(k.sideSeam を厚板の inner として)、1 つの面の線は縁から縁まで走り、通気口は閉じたスロットで、目盛りは定規の帯の縁から下がり、どうしても止まる 1 本の線は fadeLineSvg で徐々に消し、特徴が上を向く列(リングの上面の穴)は全周から見えます(all: true)。パイプのテクスチャ(編組、波付け、巻き)は断面に沿い、すべての区切りの継ぎ目を通って続きます。tubePieces(…, { rings }) を使い、中心線に沿った破線にはしません。パイプのつやと陰は、端キャップにも、すべての区切りの継ぎ目にも続きます。何もない面で止まってよいのは、印刷された文字を表す罫線、針の尾、指針の先だけで、これらには free を付けます。
  • シェーダーはポップせず、途切れない。 すべての uniform はアタックとディケイのあるエンベロープに乗せ、段階の変化は物理量で動くクロスフェードにし、どの項もあらゆる境界やキャンバスの縁より前に 0 に達し、効果は図自身のカメラのワールド空間に置きます(下を見てください)。
  • 面の上のものは面に収める。 機械が表示する文字は、いちばん長い文字列でも窓に収まり、窓で切り抜きます。開口部から見える内容は、それ自身の平面だけでなく開口部でも切り抜き、くぼみの壁を描きます。
  • 量感。 物に本当の厚みを持たせ、別の物の上に立たせ、ベースの下と持ち上がったものの下に柔らかい影を置きます。
  • 構図。 図を中央に置き、カードの約 55〜65% を占めるようにします。図のセットでは縮尺をそろえ、幅 390 px でも読めることを確かめます。

図の中の WebGL

シェーダーは、線では描けないものだけに使います。炎と排気、水と集光模様、本物のランプの光、輝き、蒸気です。部品は SVG のままにします。中核のルールは最初のシェーダーの図から生まれました。その図では段階のあいだの色の変化が、クロスフェードではなく切れたように見えていました。

  • 3 枚のレイヤー。 奥の SVG に効果が覆うものを、キャンバスに効果を(pointer-events: none)、手前の SVG に効果を覆うものを置きます。部品や効果が両側にまたがるときは分割します。
  • ワールド空間、同じカメラ。 シェーダーの点はすべて onFloor、onWallX、onWallY から作るか、ピクセルの光線 rayOf(vb) + t·towardViewer() を進めて求めます。大きさはすべて、ワールド単位に uK を掛けて決めます。平面上にあるものは、その平面の SVG の線とぴったり位置が合います。
  • 何もポップしない。 すべての uniform はアタックとディケイのあるエンベロープに従います(イベントにはキットの burst、レベルには settle)。段階の変化は、色が物理量に応じて連続的に移るクロスフェードにし、フェードアウトは暗くなる一方にします。
  • 急な打ち切りをしない。 どの項も、あらゆる if、境界、キャンバスの縁より前、セルノイズならあらゆるセルの縁より前に 0 に達します。
  • 開口部から見えるものは、2 回マスクする。 窓やくぼみの奥の内容は、それ自身の平面と、面の平面にある開口部の両方でマスクし、掛け合わせます(references/webgl.md の 5 節)。
  • 合成。 tonemap() とディザを使います。ダークでは、光を足すだけのキャンバスは乗算済みの出力と mix-blend-mode: screen を使い、暗くもする必要があるもの(波動水槽の水)は通常の合成のままにします。
  • ライトテーマも出荷し、そのシェーダーは紙のために設計する。 通常の乗算済みアルファを使い、screen は決して使いません。紙に見えてほしい色を書き、そこからインクを解きます。輝きは、淡い芯、色の付いた縁、アルファの下限を持つ彩度の高い本体であり、ダークテーマの色を暗くしたものでは決してありません。それをやると Raptor の「赤インクの煙」になりました。
    • 光が当たるものは色味を帯び、それを収めるくぼみには、より暗い物理的な下地(すす、耐火物、水の深さ)を与えます。
    • 熱い物体は、代替表示と共有する 1 つの黒体インク表に従います。
    • インクは光とともに増えるだけです。仕上がったインクを一度だけフェードし、項ごとにフェードしません。
    • インクは各線の内側の縁で終わります。
    • フレームごとにインクを測ります。references/webgl.md の 8 節に、作り方とレビュアーが見つけた欠陥があります。
  • 控えめに。 デバイスの比率は 1.5 までにし、効果が動いていて画面内にあるあいだだけ描画します。動きを減らす設定では静止画 1 枚にし、WebGL がなくても SVG だけで読めるようにします。

シェーダーを書く前に references/webgl.md を読んでください。

3D: 回る図(ベータ)

3D は WebGL と同じく選択肢の 1 つです。奥行き方向に動く部品が考えの中心であるときに使います。回るダイヤルやターンテーブル、曲がる指、外れて落ちる部品などです。図の残りは静的なキットの絵のままです。

これはベータ版です。エンジンは自分の例と 1 つのテスト用の図で証明されていますが、本番の図ではまだです。一度に回す対象は 1 つにし、その周りの散らかったものは静的なままにします。小さな図は 60 fps で動きます。部品 380 個の密な曲がる手は、負荷の高いマシンで、1440 で約 20 fps、スマートフォンのプロファイル(390 px、CPU 4 倍スロットル)で 13〜15 fps でした。

  • 動く部品はキット自身の絵。 フレームごとに、凸なキットの基本形(プリズム、丸物、ドーム、平面付きの球、旋盤形、管)を、キットのルールで投影し直し、陰影を付け直します。θ だけ回すことは、キットが方位角 a − θ で描くことと同じです。
  • 順序は分離平面から決まる。 同じグループの組にはグループに固定した平面を、別のリンクにある組には共通の座標系に固定した平面を与え、残りはフレームごとに解きます。どの角度でも、どのクリップのフレームでも循環がないことを監査が証明します。
  • 接触は面一、接線、縁が平面に載る形。 関節は子グループにある同軸のナックル円盤で、親のリンクに触れていなければなりません。そうでなければ、監査は子グループ全体を浮いていると判定します。2 つの動くグループにまたがる動く線はありません。ケーブルは両側のクリップを通って関節を越えるか、ハブのスリップリングを通ってターンテーブルに届きます。
  • 動く管は、水平に近い平面の中か継手の中で曲がり、視線方向を向かない。 曲がりには R ≥ 2r / sin²(e − θmax) が必要で、θmax には、その管が乗るすべてのヒンジのピッチ範囲が含まれます。平らなときの上限は 8r で、±12° のヒンジでは 21r です。各経路は取り付け面から取り付け面まで走り、ポートは gaps に入れます。これがすべての角度、すべての姿勢で成り立ちます。
  • 材質は諧調の対応を付け替える。 金、クローム、鋼、ガンメタル、ゴム、真ちゅう、銅には、それぞれライト用とダーク用の組があります。諧調は引き続き向きから決まります。
  • 自由グループは跳ばずに外れる。 同軸の部品は、テクスチャが回る固定の絵です。
  • シェーダーは動きについていく。 controller.anchor か toGroup でグループに固定し、手前のキャンバスは coverOf で隠し、ワールドの効果(煙、落ちる火花、作業台の油)はグループの空間に入れません。
  • --audit(turn audit passed)と scripts/turn-check.mjs(--fidelity、--order、--pops、--lines、--perf)で確かめる。 繰り返しの調整には --quick --only=… を使います。図を証明できるのは全体の実行だけで、部品 30 個で 15〜20 分かかるので、terminal(background=true, notify=true) で実行します。

最初に references/3d.md を読んでください。

参照資料

必要に応じて読んでください。

  • references/craft.md: 見た目の詳しい説明です。コード付きの部品の語彙、諧調の表、描画順のパターン、丸い部品、パイプとハーネス、分解図、面の上の画面、そして図が差し戻された原因になったアンチパターンを含みます。設計の前に読んでください。
  • references/kit.md: シグネチャと例付きの API です。
  • references/motion.md: 動くふるまい(ループ、ばね、巡回、ポインター、キーボード、アクセシビリティ、動きを減らす設定)に加え、一度きりのイベント用のエンベロープ、分解図、奥行きの並べ替え、作動準備を、素の JS と React で説明します。
  • references/react.md: React/Next.js のサーバーとクライアントの分け方、要素の props、大きなペイロードでのキー警告の落とし穴です。
  • references/verify.md: capture.mjs と drive.mjs のコマンド、レビューのチェックリスト(シェーダーを含む)、よくある欠陥です。
  • references/webgl.md: 図の中のシェーダーです。シェーダーが役に立つとき、レイヤーの重ね方、カメラの約束事、アイソメトリックのカメラでのレイマーチング、最小のページ付きの API 全体、それを教えてくれたバグ付きの作り込みのルール、ライトテーマ(紙の上のインク、現象ごとの作り方、レビュアーが見つけた欠陥)、そしてその確かめ方です。
  • references/walkthrough.md: 試験台をどう設計したかを、概念からコードまで順を追って説明します。
  • references/3d.md: 追加の 3D モードです。グループと姿勢、動くレイヤー、凸な部品とそのルール、材質、自由グループ、ヒンジの連鎖、描画順、ターンテーブルの周りの静的な散らかり、回転についていくシェーダー、周回監査、ブラウザでのチェック、性能と限界です。