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 · 未声明许可