
Pudding
physics test
Prompt
Create ONE fully self-contained HTML file that simulates two dessert bodies (a jelly and a pudding) wobbling on a statically tilted, vibrating plate. Output a single HTML code block and nothing else. ## TECH - You may load Three.js CORE ONLY via a classic script tag: `<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>` (global `THREE`, r128 API). No other libraries, no modules or import-maps, no other external resources. All other code inline. Raw WebGL or Canvas 2D with your own 3D math is also acceptable. - Render as real 3D: perspective camera at an elevated 3/4 view, one directional light + one ambient light, visible shading and occlusion. The camera is fixed and must keep the plate fully in frame across its entire translation range (see plate displacement clamp below). Background `#202028`. ## SCENE - PLATE: rigid thin box, 0.90 m x 0.90 m x 0.02 m, color `#b0b0b8`. - JELLY: hemisphere, radius R = 0.15 m, flat face down. Translucent green (`#3fbf6f`, opacity 0.7). Body height h_j = 0.15 m. - PUDDING: truncated cone (frustum), base radius 0.12 m, top radius 0.07 m, height h_p = 0.18 m. Opaque cream (`#f2d8a0`) with a caramel-brown top face (`#8a4b1f`). - Both bodies sit side by side on the plate's top surface, centers at plate-local (x, y) = (-0.20, 0) and (+0.20, 0), bases raised 0.001 m above the plate top to avoid z-fighting. - Bases are RIGIDLY BONDED to the plate at ANY attitude, including upside down (the bodies hang): the base cross-section never slides on, twists against, or separates from the plate. Each body undergoes the plate's rigid motion plus elastic deformation on top of it. ## STATIC PLATE ATTITUDE - Two sliders set a FIXED attitude: pitch about X and roll about Y, each in [-180, +180] deg, step 1. Defaults: pitch = +8 deg, roll = -5 deg. These are NOT oscillated; they tilt the plate and hold it. - Attitude composition order: `R = R_roll(Y) * R_pitch(X)` (pitch applied first, then roll), used both to orient the plate and to transform vectors between world and plate-local frames. - Gravity g = 9.81 m/s^2 along world -Z. Resolve it into plate-local components `g_local = (gx, gy, gz)` using R. - Static bending deflection: with all oscillators off, each body must rest visibly deflected, its top leaning toward the downhill in-plane direction, via `q_i_static = -Gamma_i * g_dir / omega_i^2` for the bending modes. The jelly must sag visibly more than the pudding. ## EXCITATION: 3 LINEAR-ACCELERATION OSCILLATORS One oscillator per plate-LOCAL axis (X, Y in-plane; Z plate-normal; all axes rotate with the attitude). Each oscillator has: - waveform selector {sine, cosine, blue noise} - acceleration gain slider: 0 to 6.0 m/s^2, step 0.1 All three share ONE frequency slider f in [0.2, 5.0] Hz, step 0.05. Defaults on load: X = sine 2.0 m/s^2, Y = cosine 1.2 m/s^2, Z = blue noise 0.8 m/s^2, f = 1.20 Hz. - The oscillators prescribe the plate's translational acceleration in its local frame, and the plate must visibly translate accordingly. For sine and cosine use the closed-form displacement (amplitude `a / (2*pi*f)^2`, exactly periodic, drift-free). For blue noise use leaky double integration (leak time constant 0.5 s) so the plate jitters around its home position without drifting away. - Plate displacement clamp: the plate's translational displacement is softly clamped to +/-0.25 m per local axis (smooth saturation, no hard snap), so low-frequency / high-gain settings cannot send the plate out of frame. The ACCELERATION felt by the bodies must remain consistent with the plate's actual (clamped) motion. - Blue noise definition: PRNG mulberry32. Each channel uses its own independent PRNG instance seeded with (seed + 0) for X, (seed + 1) for Y, (seed + 2) for Z, so the three axes are uncorrelated. White noise w[n] uniform in [-1, 1] sampled at 120 Hz (one sample per physics step); output `b[n] = (w[n] - w[n-1]) / 2`, scaled by the gain. - Seed input: a text field, default 42. Parse as integer; if empty or non-numeric, fall back to 42. The same seed must reproduce the exact same motion timeline after Reset. ## PHYSICS: REDUCED-ORDER MODAL MODEL Do NOT use a mass-spring mesh, particle system, position-based dynamics, FEM, or any per-vertex physics simulation. - Deformation field per body: `u(x, t) = sum_i q_i(t) * phi_i(x)`, with exactly 5 dynamic modes per body: bending along local X (modes 1, 2), bending along local Y (modes 1, 2), axial along local Z (mode 1). - Mode shapes (clamped-free; zero displacement AND zero slope at the base, maximum at the top; z measured from the base, h = body height): - `phi_1(z) = 1 - cos(pi * z / (2h))` - `phi_2(z) = 1 - cos(3 * pi * z / (2h))` Bending modes displace vertices laterally by `q * phi(z)`; the axial mode displaces them vertically by `q * phi_1(z)`. - Modal dynamics, driven by the total specific force in the plate-local frame `a_total(t) = a_osc(t) + g_local`: `qdd_i + 2*zeta*omega_i*qd_i + omega_i^2*q_i = -Gamma_i * a_total_dir(t)` X and Y components drive the respective bending modes; the Z component drives the axial mode. Do NOT subtract the constant gravity term: it is what creates the static deflection. Participation factors: Gamma_1 = 0.6, Gamma_2 = 0.2 (bending), Gamma_axial = 0.6. - Materials and natural frequencies. Compute at startup from the material data and SHOW IN THE HUD: - `c = sqrt(E / (3 * rho))` (shear-wave speed, m/s) - `f1 = c / (4h)`, `f2 = 3 * f1`, `f_axial = 1.5 * f1`, `omega = 2*pi*f` - JELLY: E = 2500 Pa, rho = 1050 kg/m^3, zeta = 0.06, h = 0.15 m -> f1 must come out ~1.48 Hz - PUDDING: E = 10000 Pa, rho = 1100 kg/m^3, zeta = 0.10, h = 0.18 m -> f1 must come out ~2.42 Hz The jelly must visibly resonate at a lower frequency than the pudding. - Soft amplitude clamp: each bending mode's total (static + dynamic) amplitude is smoothly limited to `|q| <= 0.35 * h` (e.g. tanh scaling, no hard snap), keeping deformation plausible at extreme attitudes and gains. - Static self-weight axial field (closed-form, NOT fed through the modal oscillators β added directly as a static field): - strain: `eps_static(z) = rho * g_z_local * (h - z) / E` (maximum at the base, zero at the tip; sign follows g_z_local: hanging upside down -> tension, base region stretches; upright -> compression, base region squashes) - displacement: `u_static(z) = (rho * g_z_local / E) * (h*z - z^2/2)` - Integration: semi-implicit Euler, fixed dt = 1/120 s, accumulator pattern decoupled from requestAnimationFrame. Clamp each measured frame time to at most 0.25 s before feeding the accumulator, so returning from an inactive tab never causes a catch-up burst or instability. Rendering interpolation between physics states is optional. ## MESH DEFORMATION AND INTEGRITY - Displace mesh vertices every frame by evaluating the analytic fields at each vertex (per-vertex EVALUATION for rendering is required; per-vertex physics is forbidden). Always deform from the stored undeformed vertex positions β never accumulate displacement onto already-displaced vertices. - Local volume-plausibility bulge: compute the local axial strain `eps(z) = eps_static(z) + sum over axial modes of q_ax * d(phi)/dz (z)`, then scale each vertex's radial distance from the body's local axis by `(1 - 0.5 * eps(z))`. Under hanging tension this must produce a PEAR SHAPE β base cross-section visibly thinner, tip relatively bulged β and the reverse (base bulge) under upright compression. - Radial scale safety: clamp the factor `(1 - 0.5 * eps(z))` to [0.4, 1.8] so no cross-section inverts or self-intersects. - The base vertex ring (z = 0) must remain exactly welded to the plate surface: zero lateral displacement, zero axial displacement, radial scale factor exactly 1 at z = 0 (guaranteed analytically by the mode shapes and static field; do not special-case it with ad-hoc snapping). - Displacement magnitude must grow monotonically from zero at the base to maximum at the top. - Tessellation: at least 32 segments around each body's axis and at least 24 segments along z, so deformation renders smoothly with no faceted spikes. - Recompute (or correctly transform) vertex normals every frame after deformation so lighting stays consistent β no black facets, no inverted shading. - No NaN vertex positions ever; the mesh must never tear, invert, or detach from the plate under any combination of controls. ## UI / HUD - Controls panel: pitch and roll sliders; the 3 oscillator rows (waveform selector + gain slider); shared frequency slider; seed input; buttons: Pause, Reset, Resonance Sweep. - Pause freezes the physics clock entirely; resuming continues from the paused state with no time jump. - Reset: resets modal states, plate position, and the time/noise index to zero, and re-reads the seed field. Slider and selector values are RETAINED across Reset. - Resonance Sweep: ramps f linearly from 0.3 to 5.0 Hz over 25 s, displaying the current f. Pressing it again, or moving the frequency slider manually, cancels the sweep and hands control back to the slider. During the sweep the viewer must see, in order: both bodies quasi-static (riding the plate, barely deforming), the jelly resonating near ~1.5 Hz, the pudding resonating near ~2.4 Hz while the jelly calms down, and near 5 Hz the jelly's top lagging behind its base (isolation regime). - HUD (monospace overlay): current f (Hz), computed f1 of each body (Hz, 2 decimals), live tip-displacement bars for both bodies (bar length = |u| at the body's top center, full scale = 0.5 * h), FPS (smoothed, e.g. exponential moving average). - The simulation starts automatically on load with all defaults above. ## STABILITY - No NaNs, no blow-up, for any combination of controls, indefinitely. - With all three gains at 0, existing wobble decays smoothly to rest at the static deflected pose β no residual jitter, no perpetual oscillation. - At any attitude, including fully upside down, the bodies remain bonded, deform plausibly, and the simulation stays stable.
A system prompt was added to support web rendering
Response not available