展示:软体晃动物理效果
Show HN: Soft Body Jiggle Physics

原始链接: https://github.com/xloveee/jiggle-physics

本项目提供了一套轻量级、与渲染器无关的实时抖动物理标准,在简单的布娃娃系统与复杂的软体模拟之间找到了平衡点。通过使用 UV 映射权重绘制和阻尼弹簧骨骼,开发者可以定义出能随父级运动而真实抖动的柔软区域。 **核心组件:** * **`jiggle-physics.js`**:纯粹的模拟引擎,基于父级的速度和加速度计算阻尼弹簧偏移量。它与渲染器无关,不需要 DOM 或 WebGL,可轻松集成到任何游戏循环中。 * **变形逻辑**:采用简单的通用公式 `vertex += weight * boneJiggle` 来驱动运动,从而实现局部的“肉体回弹”以及挤压和拉伸效果。 * **资源标准**:使用 UV 映射的权重纹理来定义柔软度(0–1)和骨骼分配。这种方法性能极高,每个顶点仅需一次纹理查找。 随附的 WebGL 演示(`jiggle-app.js` 和 `index.html`)展示了该系统的实际运行效果,其中包含用于绘制权重、调整物理参数(刚度、阻尼、重力)以及测试各种几何体的工具。该系统专为广泛的可移植性而设计;任何支持基础向量数学的引擎均可实现此标准。

一位用户分享了一个新的“Show HN”项目,这是一个专为网页浏览器设计的轻量级、零依赖软体物理引擎。该项目通过一个抖动的甜甜圈模型演示了其功能。 Hacker News 社区对此给予了积极评价,称赞了该引擎简洁的架构——特别是它将物理引擎与渲染器分离的设计,使其能够轻松适配 Three.js 或 Babylon.js 等框架。 讨论还涉及了技术实现,特别是保持模拟稳定性的挑战。评论者指出,使用固定的时间步长(可能通过累加器模式实现)至关重要,以防止物理模拟在浏览器帧率波动时出现异常行为或“崩溃”。此外,还有建议提出使用人体模型来测试该引擎,以展示其在更复杂的权重映射动画方面的潜力。
相关文章

原文

Jiggle physics demo

A reference standard for real-time jiggle physics by xlovecam — how to paint soft regions, drive damped spring bones, and deform meshes consistently across engines.

Not ragdoll. Not cloth. Not full soft-body FEM.
Paint weight on a UV map, drive randomized spring bones from parent motion,
one rule: vertex += weight * boneJiggle.

Author: xlovecam

No build step. Open index.html in any WebGL-capable browser.


Spring bones · jiggle bones · soft-body secondary motion · weight-painted physics · vertex weight jiggle · Blender-style flesh bounce · mesh wobble · damped spring deformation · parent-velocity lag · orbit-driven bounce


Two pieces, one contract:

Piece What it is
Weight map Per-region softness in [0, 1], painted on a UV texture (one weight per vertex in a real engine).
Jiggle bones A small set of damped springs; each painted region follows one bone. Randomized frequency/damping so regions wobble out of sync.

The entire deformation:

vertex += weight * boneJiggle;

In this demo (SDF ray-marcher), the equivalent samples the base shape at q - offset where offset = weight * boneOffset, with asymmetric squash & stretch along the motion vector (trailing bulge, leading flatten).


The engine and the renderer are separate by design. jiggle-physics.js does the math only — no DOM, no WebGL — so you can drop it into any renderer. This repo ships one such renderer (a WebGL demo in jiggle-app.js) to show the standard in action.

jiggle/
├── index.html          # markup, styles, GLSL shader
├── jiggle-physics.js   # pure simulation (no DOM, no WebGL)
├── jiggle-app.js       # WebGL demo renderer (consumes the engine)
└── asset/
    └── jiggle-physics-demo.gif

jiggle-physics.js — simulation engine

createJigglePhysics({ bones: 3 }) — drop into any game loop.

  • No DOM, no WebGL — renderer-agnostic; all WebGL lives in the demo, not the engine.
  • Each bone is a damped spring driven two ways:
    • Impulse on parent acceleration (flicks, reversals, constructive interference).
    • Velocity drive — sustained lag while the parent keeps moving.
  • Per-bone character: randomized stiffness, damping, coupling, and gravity sag.
  • Returns bone offsets each frame:
const offsets = physics.update(dt, { yaw, pitch, body: { x, y, z } });
// Float32Array [x0,y0,z0, x1,y1,z1, ...]

jiggle-app.js — the WebGL demo renderer

This is one example renderer, not part of the engine. It owns the WebGL setup, orbit camera, UV weight painting, controls, and render loop. Each frame it feeds parent state into the engine and uploads the returned bone offsets + weight textures to the shader.

index.html — the reference scene

Five test geometries with demo presets, weight heatmap, physics sliders, and a 2D UV paint window.


Weights live in a 512×256 RGBA texture (R / G / B = three jiggle bones). Each geometry uses a Smart-UV-style projection so paint maps cleanly to the surface:

Geometry Projection
Orb Sphere (equirectangular)
Capsule Cylinder along Y
Torus Major ring U + tube V
Air dancer Cylinder along swaying centreline
Walker Cylinder, seam at back

Paint in the 2D UV map panel (not on the 3D viewport). One texture lookup per sample — no brush cap, no per-step cost scaling.

Input Action
P Paint mode — UV map panel appears
Paint in UV window Add weight (Blender-style flow build-up)
+ / Add / erase brush
W Toggle weight heatmap (blue = anchored → red = soft)
G Cycle geometry
C Clear weights
X Random paint
Space Shake
R Reset camera
Drag Orbit (drives jiggle)
Shift-drag Move object (also drives jiggle)
Wheel Zoom

Below the UV map — scale painted regions after the fact without re-painting:

  • all — master gain on every painted region
  • bone 0 / 1 / 2 — per-channel gain (each stroke assigns a bone in rotation)

Each geometry loads a preset weight map on switch (G) that showcases the standard with multiple out-of-sync bones:

  • Orb — heavy sagging bottom + softer equatorial band
  • Capsule — heavy hanging bottom cap + mid belly
  • Torus — three lobes evenly spaced on the outer rim
  • Air dancer — head-heavy stacked rings, feet anchored
  • Walker — soft bust, glutes, groin

Slider Parameter
stiffness spring constant
damping velocity damping
mass inertia
gravity sag under gravity
orbit drive how hard camera orbit drives jiggle
brush size UV paint radius
brush weight paint target strength
force radius jiggle spread from painted regions

const physics = createJigglePhysics({ bones: 3 });

// each frame:
const offsets = physics.update(dt, {
  yaw, pitch,
  body: { x, y, z }   // parent object translation
});

// per vertex in your mesh:
const w = sampleWeight(vertex.uv);       // from your weight map (0..1)
const bone = sampleBoneIndex(vertex.uv); // which spring drives this texel
vertex.position += w * boneOffset(bone);

The weight map and bone index map are the portable assets. The physics engine is the portable simulation. Any renderer that can multiply and add vectors can implement the standard.


open index.html
# or serve statically:
python3 -m http.server 8080

Use freely. Please attribute xlovecam and link to github.com/xloveee/jiggle-physics if you ship this standard in a project.

联系我们 contact @ memedata.com