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 模塊放在單個 <script type="module"> 中。
- 如果缺少 navigator.gpu / adapter,顯示一張優雅的編輯風格回退卡片(「This specimen needs WebGPU.」)並給出具體說明——絕不能用較差的渲染器矇混過關。該狀態下禁用所有控件。
- 能從設備丟失中恢復(最多重建渲染器兩次),並通過 getCompilationInfo 暴露 WGSL 編譯錯誤。
- 採用固定 60 Hz 的仿真步長與累加器(每幀最多 3 步),提供 ¼ 速開關、暫停(空格),鍵盤:N 輕推、R 重置、K 切換刀具、H 手形工具。

── 頁面設計(編輯風格的「材質研究」) ──
- 溫暖的紙張色影棚背景 #E2DFDA;3D 地面是一片無限延伸的影棚弧幕,其色調與這一顏色完全一致。
- 左上角報頭:小型大寫字母標籤「MATERIAL STUDIES / NO. 009」,巨大的斜體襯線標題「Melon / Jelly.」(第二行縮進),以及三行襯線副標語。
- 右上角狀態膠囊「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 仿真單位 ≈ 3.5 cm,軟糖密度 1.3 g/cm³)。
- 右下角是可摺疊的「Inside the experiment」註釋,用平實的文字解釋物理、渲染與切割方法。
- 繪製刀劃軌跡時顯示一條虛線 SVG 引導線;小型 toast 提示(「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 軟陰影(陰影帶果肉顏色的色調),以及由俯視高度圖生成的接觸 AO。MSAA ×4、HDR、PBR-Neutral 色調映射、sRGB、抖動。

── 物理(手感像真正的軟糖) ──
- 四面體軟體(對形狀內部的抖動晶格做 Delaunay 三角化),使用小步長的 XPBD(約 10 個子步,每個子步 1 次迭代):
• 逐四面體共旋轉形狀匹配(質量加權協方差、Müller 四元數旋轉提取、統一剛度比例)——不會翻轉,也沒有幽靈扭矩;
• 逐四面體體積約束(近似不可壓縮);
• 由阻尼滑塊控制邊的相對速度阻尼;硬度以對數尺度映射爲形狀柔度;
• 與地面接觸,帶靜摩擦/動摩擦、輕微空氣阻力、接近靜止時的沉降阻尼、速度上限,以及帶溫和重置的 NaN 防護。
- 手形工具:可在任意位置抓取(對蒙皮表面做射線拾取,並有寬容的屏幕空間回退);以軟補丁方式附着(半徑約 0.4),補丁在朝向攝像機的平面上跟隨指針;有抓取距離限制,且絕不會被推入地面;滾輪或用第二根手指可以扭轉抓住的補丁。輕推 = 一次俏皮的衝量。重置會重新將整塊切片放下。
- 渲染網格通過重心座標嵌入蒙皮到四面體上;法線每幀重新計算。

── 切成小塊 ──
- 整個世界就是一個碎塊列表。每塊都是切片靜止平面內的一個凸多邊形 I;其輪廓是用半徑 ρ 的圓盤對 I 做膨脹(圓角),再按切片厚度擠出,並帶有相同的倒角、瓜皮層、瓜籽與氣泡(僅在能完整容納時才保留瓜籽/氣泡)。
- 一次切割會把世界空間平面映射到每個被切穿碎塊的靜止座標系(對變形後的碎塊做最佳擬合剛體座標系),再與中面求交 → 得到一條直線;將 I 裁剪爲兩半並各偏移 ±ρ,使兩條重建輪廓在切口處精確相接;過薄的碎片會被拒絕(「too thin」)。
- 所有碎塊被合併進同一個仿真(每個粒子帶組件 id)和一個渲染網格;每塊都是獨立的軟體,可以抓取、拉伸並再次切割;碎塊之間會發生碰撞(使用 AABB 剪枝的粒子–粒子推擠,每次只推幾毫米,讓新切面緩緩分開而非彈開)。最多 14 塊。已構建的網格按塊緩存,因此重置瞬間完成。
- 每次重建都進行狀態遷移:新的靜止粒子嵌入舊四面體中,並繼承插值後的位置與速度。

── 可見的刀(本版本的主角) ──
- 一把程序化建模的小型菜切(nakiri)風格蔬菜刀:矩形刀身(長約 1.72,高約 0.63——比切片還高),筆直刃口,前端略微上翹並收成圓角刀頭,沿刃口有細研磨斜面,平磨至約 0.03 的刀背,銳利折邊(複製頂點),拋光鋼製刀頸,橢圓形胡桃木刀柄略微鼓起,配三顆鋼鉚釘與平端蓋。局部座標系:+x 指向刀尖,刃口位於 y=0。
- 場景着色器中的材質:拉絲鋼,帶產品攝影式漸變(低處反射深色板,高處反射明亮弧幕)、柔光箱條狀高光、緞面較亮的斜面、鏡面刀頸;胡桃木帶直紋、緞面油潤光澤與鉚釘。每幀在 CPU 上以剛體方式擺放姿態。
- 刀在場景通道中繪製(位於果凍表面之後),因此埋入果凍的部分會透過果凍被折射看到;它會投射陰影,但不寫入 AO 高度圖。
- 行爲:
• 懸停(刀具模式):刀懸浮在切片上方約 0.42 處,刃口正對光標下方,刀身側對攝像機,略微朝觀察者一側傾轉;選擇該工具時,刀從上方落下;手形模式下隱藏。
• 繪製過程中:刀沿筆畫對齊,刃口剛好在果凍上方,刀柄始終位於左側(相對於攝像機右方向的規範方向)。
• 鬆開時:在繪製所經過的表面上讀取的筆畫會定義一個豎直的刀面;隨即規劃分割,並立即預先構建新碎塊與新軟體(這樣之後的切換隻需約 10 ms,動畫中途不會卡頓)。
• 動畫編排(約 1.1 秒,遵守 ¼ 速與暫停):對齊(0.16 秒)→ 下壓:刃口沉入頂面以下約 0.13,一個物理碰撞體把果凍推入其下方的圓潤凹槽——先被壓扁,然後才屈服(進行到 0.42 秒)→ 切穿:新的世界被切換進來,刀刃繼續落向砧板,同時一個楔形碰撞體把兩個新切面緩緩分開(每個子步限制在幾毫米內,間隙隨深度增大),並在切穿深度處壓住切口脣邊 → 短暫停留 → 抬回懸停位置,鬆開脣邊,讓其帶着輕顫回彈。
• 未命中時會顯示 toast,刀保持原位;切割動畫播放期間忽略新的筆畫;重置會取消切割。

── 質量標準 ──
- 在中端筆記本 GPU 上流暢 60 fps;除切割外,幀循環中不產生內存分配。
- 在 window 上提供確定性的測試鉤子(例如 __melon,包含 sim、camera、pick、planCut、startCut、advance(seconds) 以及逐塊統計),以便逐步推進動畫並截圖。
- 排版精緻、沉靜、帶有博物館氣質;所有內容在手機與桌面上均清晰可讀。

溯源

原作者
vib3coded
發佈日期
2026-09-27(由推文 ID 反解)
原始出處
查看原帖 ↗
收錄來源
zhuyansen/awesome-opus-5.5-video · 2104285370951012504 · 未聲明授權