ai21.net
言語

グミ状スイカのスライスシミュレーション

グミ状スイカのスライスシミュレーション — 1

プロンプト

Create "Melon Jelly Knife" — a single self-contained HTML file (melon-jelly-knife.html) with an interactive, physically simulated gummy watermelon slice that you can pull like jelly AND cut into pieces with a visible steel knife that animates every cut.

── Platform ──
- WebGPU + WGSL only, all JS/CSS inline, no external libraries. ES module in one <script type="module">.
- If navigator.gpu / adapter is missing, show an elegant editorial fallback card ("This specimen needs WebGPU.") with a specific explanation — never fake it with a lesser renderer. Disable the controls in that state.
- Recover from device loss (rebuild the renderer up to twice), surface WGSL compile errors via getCompilationInfo.
- Fixed 60 Hz simulation step with an accumulator (max 3 steps/frame), ¼-speed toggle, pause (Space), keyboard: N nudge, R reset, K toggle knife, H hand.

── Page design (editorial "material study") ──
- Warm paper studio backdrop #E2DFDA; the 3D floor is an infinite studio sweep that tones to exactly this colour.
- Top-left masthead: small caps label "MATERIAL STUDIES / NO. 009", huge italic serif title "Melon / Jelly." (second line indented), and a 3-line serif tagline.
- Top-right status pill "WEBGPU · LIVE / PAUSED / UNAVAILABLE".
- Right panel (thin 1px borders, translucent paper): Tool (Hand | Knife segmented buttons with small line icons), Variety swatches (Crimson, Golden, Rosé — each recolours flesh, rind, seeds, shadow tint and the UI accent), sliders Firmness (trembling ↔ set) and Internal damping (lively ↔ syrupy), buttons "Give it a nudge", Reset, Pause, checkboxes ¼ speed and Show mesh.
- Bottom-left: tool hint in italic serif, live readouts row (Mass ≈ g, Volume % of rest, Kinetic µJ, Pieces) with an "illustrative scale" footnote (1 sim unit ≈ 3.5 cm, gummy 1.3 g/cm³).
- Bottom-right collapsible "Inside the experiment" notes explaining the physics, rendering and the cutting method in plain prose.
- A dashed SVG guide line while drawing a knife stroke; small toast messages ("Missed — draw the blade across the slice.", "Too thin to cut there.", "That's plenty of pieces.").
- The camera frames the slice inside the free area between masthead, panel and readouts (lens shift), orbits on empty-space drag, zooms on wheel, double-click resets view, gently follows the slice if it is thrown far.
- Responsive: under ~860px the layout stacks (masthead, canvas ~58vh, hint, panel) with 44px+ touch targets; prefers-reduced-motion softens the intro and damping.

── The slice ──
- A thick (T ≈ 0.58) wedge of watermelon: sector with ~32° half-angle, inner radius ~1.62, all corners rounded in plane (ρ = 0.17) and top/bottom edges bevelled (~0.13).
- Layers by depth from the rind: dark green skin with irregular darker stripes, a pale cream-green band, then translucent red flesh; black teardrop seeds arranged in arcs and a few tiny air bubbles suspended inside.
- Rendered as translucent candy: screen-space refraction of the scene behind, per-pixel thickness from a back-face depth pass, Beer–Lambert absorption per refracted tap (capped by back thickness so seeds don't halo), jittered blur, subsurface-like scatter and glow toward the key light, Fresnel + GGX highlights, soft studio environment (procedural softboxes).
- Floor: PCSS-lite soft shadow from a key light behind-left-above (shadow tinted by the flesh colour), contact AO from a top-down height map. MSAA ×4, HDR, PBR-Neutral tone mapping, sRGB, dither.

── Physics (feels like real gummy candy) ──
- Tetrahedral soft body (Delaunay of a jittered lattice inside the shape), XPBD with small steps (~10 substeps, 1 iteration each):
• co-rotational per-tet shape matching (mass-weighted covariance, Müller quaternion rotation extraction, uniform stiffness fraction) — no inversions, no ghost torque;
• per-tet volume constraints (near-incompressible);
• edge relative-velocity damping controlled by the damping slider; firmness maps to shape compliance on a log scale;
• floor contact with static/kinetic friction, light air drag, settle-damping when nearly at rest, speed cap, NaN guard with gentle reset.
- Hand tool: grab anywhere (ray pick on the skinned surface, forgiving screen-space fallback), soft patch attachment (radius ~0.4) that follows the pointer on a camera-facing plane, reach limit, never pushed into the floor; wheel or a second finger twists the held patch. Nudge = a playful impulse. Reset drops the whole slice again.
- Render mesh is skinned to the tets by barycentric embedding; normals recomputed each frame.

── Cutting into pieces ──
- The world is a list of pieces. Each piece is a convex polygon I in the slice's rest plane; its outline is I dilated by a disk of radius ρ (rounded corners), extruded to the slice thickness with the same bevels, rind layers, seeds and bubbles (seeds/bubbles kept only where they fit inside).
- A cut maps a world plane into each crossed piece's rest frame (best-fit rigid frame of the deformed piece), intersects it with the mid-plane → a straight line; clip I into two halves offset by ±ρ so both rebuilt outlines meet exactly at the cut; reject slivers ("too thin").
- All pieces are concatenated into ONE simulation (component id per particle) and ONE render mesh; each piece is its own soft body you can grab, stretch and cut again; pieces collide with each other (AABB-pruned particle–particle pushes, a few mm per pass so fresh faces ease apart instead of popping). Max 14 pieces. Built meshes are cached per piece so Reset is instant.
- State transfer on every rebuild: new rest particles are embedded in the old tets and take over interpolated positions and velocities.

── The visible knife (the star of this version) ──
- A small nakiri-style vegetable knife modelled procedurally: rectangular blade (length ~1.72, height ~0.63 — taller than the slice), straight edge with a slight lift and rounded nose at the front, thin ground bevel along the edge, flat grind to a ~0.03 spine, sharp creases (duplicated vertices), polished steel bolster, oval walnut handle that swells slightly with three steel rivets and flat end caps. Local frame: +x toward the tip, edge on y=0.
- Materials in the scene shader: brushed steel with a product-shot gradient (dark board reflected low, bright sweep high), softbox streaks, satin lighter bevel, mirror bolster; walnut with straight grain, satin oil sheen, rivets. Posed rigidly on the CPU each frame.
- The knife is drawn in the scene pass (behind the jelly surface), so the part buried in the jelly is seen refracted through it; it casts a shadow but stays out of the AO height map.
- Behaviour:
• Hover (knife tool): the knife floats ~0.42 above the slice with its edge exactly under the cursor, blade side-on to the camera, slightly rolled toward the viewer; it drops in from above when the tool is selected; hidden in hand mode.
• While drawing: it lines up along the stroke, edge just above the jelly, handle always on the left (canonical direction relative to camera right).
• On release: the stroke read on the surface it was drawn over defines a VERTICAL blade plane; the split is planned and the new pieces + new soft body are pre-built immediately (so the swap later costs only ~10 ms and there is no hitch mid-animation).
• Choreography (~1.1 s, respects ¼ speed and pause): align (0.16 s) → press: the edge sinks ~0.13 below the top and a physical collider pushes the jelly into a rounded groove under it — it squashes before it gives (to 0.42 s) → break-through: the new world is swapped in, the blade continues to the board while a wedge collider eases the two new faces apart (limited to a few mm per substep, gap growing with depth) and holds the cut lips down at the break-through depth → short hold → lift back to hover, releasing the lips so they spring back with a jiggle.
• Misses show a toast and the knife stays put; new strokes are ignored while a cut is animating; Reset cancels it.

── Quality bar ──
- Smooth 60 fps on a mid-range laptop GPU; no allocations in the frame loop except on cuts.
- Deterministic test hook on window (e.g. __melon with sim, camera, pick, planCut, startCut, advance(seconds), per-piece stats) so the animation can be stepped and screenshotted.
- Polished, calm, museum-like typography; everything readable on phone and desktop.

日本語訳

"Melon Jelly Knife" を作成してください — 単一の自己完結型 HTML ファイル(melon-jelly-knife.html)として、ゼリーのように引っ張れるだけでなく、目に見える鋼のナイフで切り分けられ、切断のたびにアニメーションする、インタラクティブで物理シミュレーションされたグミ状のスイカのスライスを実装してください。

── プラットフォーム ──
- WebGPU + WGSL のみ、JS/CSS はすべてインライン、外部ライブラリなし。ES モジュールは 1 つの <script type="module"> 内に記述。
- navigator.gpu / adapter が存在しない場合は、具体的な説明を添えたエレガントなエディトリアル調のフォールバックカード("This specimen needs WebGPU.")を表示すること — 決してより低性能なレンダラーでごまかさないこと。その状態ではコントロールを無効化する。
- デバイスロストから復旧し(レンダラーの再構築は最大 2 回)、WGSL のコンパイルエラーは getCompilationInfo 経由で表面化させる。
- アキュムレータを用いた固定 60 Hz のシミュレーションステップ(最大 3 ステップ/フレーム)、¼ 速度のトグル、一時停止(Space)、キーボード:N でつつく、R でリセット、K でナイフの切り替え、H でハンド。

── ページデザイン(エディトリアルな「マテリアル・スタディ」)──
- 温かみのある紙のスタジオ背景 #E2DFDA。3D の床は、この色に正確にトーンを合わせた無限のスタジオスイープ。
- 左上のマストヘッド:スモールキャップスのラベル "MATERIAL STUDIES / NO. 009"、巨大なイタリック体セリフのタイトル "Melon / Jelly."(2 行目はインデント)、3 行のセリフ体タグライン。
- 右上のステータスピル "WEBGPU · LIVE / PAUSED / UNAVAILABLE"。
- 右パネル(細い 1px のボーダー、半透明の紙):Tool(Hand | Knife の小さなラインアイコン付きセグメントボタン)、Variety スウォッチ(Crimson、Golden、Rosé — それぞれ果肉、果皮、種、影の色合い、UI アクセントを再配色)、スライダー Firmness(trembling ↔ set)と Internal damping(lively ↔ syrupy)、ボタン "Give it a nudge"、Reset、Pause、チェックボックス ¼ speed と Show mesh。
- 左下:イタリック体セリフのツールヒント、ライブ読み取り値の行(Mass ≈ g、Volume % of rest、Kinetic µJ、Pieces)、および "illustrative scale" の脚注(1 sim unit ≈ 3.5 cm、グミ 1.3 g/cm³)。
- 右下:折りたたみ式の "Inside the experiment" ノート。物理、レンダリング、切断方法を平易な文章で説明する。
- ナイフのストロークを描いている間は破線の SVG ガイドライン。小さなトーストメッセージ("Missed — draw the blade across the slice."、"Too thin to cut there."、"That's plenty of pieces.")。
- カメラはマストヘッド、パネル、読み取り値の間の空き領域内にスライスを収め(レンズシフト)、空白部分のドラッグで軌道回転、ホイールでズーム、ダブルクリックでビューをリセットし、スライスが遠くへ投げられた場合はそっと追従する。
- レスポンシブ:約 860px 未満ではレイアウトが縦に積み重なり(マストヘッド、キャンバス ~58vh、ヒント、パネル)、44px 以上のタッチターゲットを確保。prefers-reduced-motion はイントロと減衰を柔らかくする。

── スライス ──
- 厚みのある(T ≈ 0.58)スイカのくさび形:半角約 32° の扇形、内側半径 ~1.62、すべての角は平面内で丸められ(ρ = 0.17)、上下のエッジは面取り(~0.13)。
- 果皮からの深さによる層:不規則な濃い縞模様のある濃緑色の皮、淡いクリームグリーンの帯、その次に半透明の赤い果肉。黒い涙形の種が弧を描いて並び、いくつかの小さな気泡が内部に浮かんでいる。
- 半透明のキャンディとしてレンダリング:背後のシーンのスクリーンスペース屈折、背面デプスパスによるピクセルごとの厚み、屈折タップごとの Beer–Lambert 吸収(種がハローしないよう背面の厚みで上限を設定)、ジッター付きブラー、キーライトへ向かうサブサーフェス風の散乱とグロー、Fresnel + GGX ハイライト、柔らかなスタジオ環境(プロシージャルなソフトボックス)。
- 床:左後方上方のキーライトによる PCSS-lite のソフトシャドウ(影は果肉の色で色付け)、上面からの高さマップによるコンタクト AO。MSAA ×4、HDR、PBR-Neutral トーンマッピング、sRGB、ディザ。

── 物理(本物のグミキャンディのように感じられること)──
- 四面体ソフトボディ(形状内部のジッター付き格子のドロネー分割)、小さなステップの XPBD(約 10 サブステップ、各 1 イテレーション):
• 四面体ごとの共回転シェイプマッチング(質量加重共分散、Müller のクォータニオン回転抽出、均一な剛性率)— 反転なし、ゴーストトルクなし。
• 四面体ごとの体積拘束(ほぼ非圧縮)。
• 減衰スライダーで制御されるエッジ相対速度減衰。硬さは対数スケールでシェイプコンプライアンスにマッピングされる。
• 静止摩擦/動摩擦を伴う床との接触、軽い空気抵抗、ほぼ静止したときのセトル減衰、速度上限、穏やかなリセットを伴う NaN ガード。
- ハンドツール:どこでも掴める(スキニングされたサーフェス上のレイピック、寛容なスクリーンスペースのフォールバック)、カメラ向きの平面上でポインターに追従するソフトパッチアタッチメント(半径 ~0.4)、到達限界、床に押し込まれることはない。ホイールまたは 2 本目の指で掴んだパッチをひねる。Nudge = 遊び心のあるインパルス。Reset はスライス全体を再び落下させる。
- レンダーメッシュは重心座標埋め込みによって四面体にスキニングされ、法線は毎フレーム再計算される。

── ピースへの切断 ──
- ワールドはピースのリストである。各ピースはスライスの静止平面内の凸多角形 I であり、その輪郭は I を半径 ρ の円盤で膨張させたもの(角を丸める)で、同じベベル、果皮の層、種、気泡を伴ってスライスの厚みまで押し出される(種/気泡は内部に収まる場所にのみ保持)。
- 切断は、ワールド平面を交差する各ピースの静止フレーム(変形したピースの最良フィット剛体フレーム)へマッピングし、それを中間平面と交差させて直線を得る。I を ±ρ だけオフセットした 2 つの半分にクリップし、再構築された両方の輪郭が切断位置で正確に一致するようにする。スリバーは却下する("too thin")。
- すべてのピースは 1 つのシミュレーション(パーティクルごとのコンポーネント ID)と 1 つのレンダーメッシュに結合される。各ピースはそれ自体がソフトボディであり、掴んで伸ばし、再び切断できる。ピース同士は衝突する(AABB で枝刈りしたパーティクル間の押し出し、1 パスあたり数 mm にして、新しい面がポップせずにゆっくり離れるようにする)。最大 14 ピース。構築済みメッシュはピースごとにキャッシュされるため、Reset は即座。
- 再構築のたびに状態を転送:新しい静止パーティクルは古い四面体に埋め込まれ、補間された位置と速度を引き継ぐ。

── 目に見えるナイフ(このバージョンの主役)──
- 手続き的にモデリングされた小さな菜切り包丁風の野菜ナイフ:長方形の刃(長さ ~1.72、高さ ~0.63 — スライスより高い)、わずかに反り上がり先端が丸い直刃、刃に沿った薄い研ぎベベル、~0.03 の背までフラットグラインド、鋭い稜線(頂点を複製)、磨かれた鋼のボルスター、3 本の鋼リベットと平らなエンドキャップでわずかに膨らむ楕円形のクルミ材のハンドル。ローカルフレーム:+x は先端方向、刃は y=0。
- シーンシェーダー内のマテリアル:製品写真風のグラデーションを持つヘアライン鋼(下部に暗いボードの反射、上部に明るいスイープ)、ソフトボックスの筋、サテン調の明るいベベル、ミラーのボルスター。クルミ材はまっすぐな木目、サテン調のオイルの艶、リベット。毎フレーム CPU 上で剛体的にポーズ付けされる。
- ナイフはシーンパスで(ゼリー表面の背後に)描画されるため、ゼリーに埋もれた部分はそれを透かして屈折して見える。影は落とすが、AO の高さマップには含まれない。
- 挙動:
• ホバー(ナイフツール):ナイフはスライスの ~0.42 上に浮かび、刃先は正確にカーソルの下に位置し、刃はカメラに対して真横、ビューア側へわずかに傾く。ツールが選択されると上から落ちてくる。ハンドモードでは非表示。
• 描画中:ストロークに沿って整列し、刃先はゼリーのすぐ上、ハンドルは常に左側(カメラ右に対する標準方向)。
• リリース時:描かれたサーフェス上で読み取られたストロークが垂直な刃の平面を定義する。分割が計画され、新しいピース + 新しいソフトボディが即座に事前構築される(後のスワップはわずか ~10 ms で済み、アニメーション中に引っかかりが生じない)。
• 振り付け(~1.1 秒、¼ 速度と一時停止を尊重):整列(0.16 秒)→ 押し込み:刃先が上面から ~0.13 沈み、物理コライダーがその下のゼリーを丸い溝へと押し込む — 耐えてから潰れる(0.42 秒まで)→ 貫通:新しいワールドに入れ替わり、刃はまな板まで進み続け、くさび形コライダーが 2 つの新しい面をゆっくり離す(サブステップあたり数 mm に制限され、深さとともに隙間が広がる)とともに、切断された唇部を貫通深さで押さえる → 短い保持 → ホバーへ戻るように持ち上げ、唇部を解放してプルンと跳ね返らせる。
• ミスはトーストを表示し、ナイフはその場にとどまる。切断のアニメーション中は新しいストロークが無視される。Reset でキャンセルされる。

── 品質基準 ──
- ミッドレンジのラップトップ GPU で滑らかな 60 fps。フレームループ内では切断時以外のアロケーションを行わない。
- window 上に決定的なテストフック(例:sim、camera、pick、planCut、startCut、advance(seconds)、ピースごとの統計を持つ __melon)を用意し、アニメーションをステップ実行してスクリーンショットを撮れるようにする。
- 洗練された、落ち着いた、美術館のようなタイポグラフィ。スマートフォンでもデスクトップでもすべて読みやすくする。

出典

原作者
vib3coded
公開日
2026-09-27(由推文 ID 反解)
原典
元の投稿を見る ↗
収録元
zhuyansen/awesome-opus-5.5-video · 2104285370951012504 · ライセンス未表明