Repository navigation
Release 1.4.0: the kit: water, wheels, pieces and soft bodies - #9
Merged
Merged
Conversation
A driven joint with a stop lost all its kept work: ball joints and hinges with stops worked out rows, couplings, inverses and errors 16 times a step for 9 poses. 100 driven ragdolls with stops took 33 ms a step, 56% of it in the one-at-a-time pass, against 19 ms with no stops. Every ball joint and hinge in a tree now keeps its work, and so does a rotation joint with a cone, stops' rows and how far off they are with it. A stop reached on a kept pass needs the anchors, a hinge's frames and the pinned rows, which weren't read: they are fetched then, as the lazy pass already did, since PIN is scratch of whichever joint went last. That pass 18.5 -> 11.9 ms. Pinned, both load orders: driven ragdolls with stops 13.5-14.7% faster, stops alone 1-5%, and about 8% with workers. Same bits as 1.3.4 on 120 runs of drives pressed into stops, on workers too; HASH_STOPS stored from 1.3.4 holds it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Finding contacts is 36-47% of a step on hulls, terrain and meshes. While a pile settles on terrain, 87% of the time spent on the ground went to pairs that had barely moved since their manifolds were found, and only convex pairs kept theirs: a mesh pair tested every triangle under it again each step. A touching mesh or heightfield pair now keeps every manifold while 2 drift <= tolerance from the pose it was found at, REUSE's touching rule, its normals in the mesh's frame. Not for jointed bodies or parts. The rebuild, the kept ends and the drift are shared with convex pairs. Pinned, both load orders, 12 s: terrain 5.6-8.7% faster, level mesh 14-15%; box and hull piles even. Results change where such a body rests. 640 heaps: one body through the ground before and after; ridge drops 575 of 576 on the solid hull's side before and after; bodies awake at 30 s the same. Saves are format 16. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Capsules on bumpy ground stayed awake long after a heap landed. Most were rolling: their energy fell by exactly what 1% rolling resistance takes. A few buzzed in place, gaining energy for good: a capsule lying across a peak of the mesh, its kept contact with the slope beyond rebuilt 3.5 mm deep where it was 10 mm clear. holdEnds() put a round end square onto the capsule's axis. A contact whose normal leans along the capsule slid along it by r (n . axis), and rebuilt, its depth was out by r (n . axis)^2. The end now goes to the core along the normal, the way collide() and touch() brought it up. Kept mesh manifolds showed it; convex pairs have had it since 2026-10-29, where a contact wasn't at a capsule's rounded end. Both capsules now sleep within 1.5 s, and no body in 80 heaps gains energy. Heaps and ridge drops as before. The stored hash changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Milestone 22, the first of part five, the kit. A static or kinematic box given fluid: true is water: a sensor that holds up every dynamic body in it by the weight of the water it displaces, at the centre of the part under the surface, and slows it by the water's damping by how much of it is under. density is the water's, flow its current. How much of a body is under is worked out for each shape: boxes and hulls cut exactly (faces fanned from a point on the plane, so the cap adds nothing), balls by the cap formula, capsules summed in discs across the axis, to within 5e-7 of the volume. The push acts on every substep after gravity, over the sensor pairs the narrowphase already lists. Found on the way: the push first read a body's turn from the step's start, and lagged its rocking enough to feed it (an undamped plank went from 0.89 to 5.5 rad/s in 30 s); it reads the turn now. Sensors never woke what they let go of, and water must: water added, moved, raised by a tide or removed wakes what it covers. New water damps at 3, measured: at 0 nothing takes a body's bob, and it bobs for good. A light cube floats corner up and a square timber corner down, as real ones do: 30.2 mm worked out by hand, 29.9 simulated. The stored hash changes, the test world having water in it now. Saves are format 17. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Milestone 23. A joint of type 'wheel' holds a wheel to a chassis as a car's suspension does: Box2D's wheel joint, in 3D. The wheel slides along axis on a spring (frequency, dampingRatio, between min and max) and spins about axle, a new option (its default the world axis most square to axis, as Nolan chose), driven and braked by its motor. Steering is turning axle with setJoint, which keeps what the wheel holds, so a car steered every step doesn't sag. The suspension's line is the chassis's: a slider's line turns with a, but a wheel spins. It is kept in b's frame of the joint, as a cone's swing is, and a new row, onLine(), measures the gap along it with b's lever reaching a's anchor. Wheels are solved one joint at a time, never in a tree: driving, steering and braking, a car's wheels stayed within 0.08 mm of their tracks and 0.03 degrees of their axles. A car stands level and sleeps, drives at its spin times its radius, brakes to a stop, turns, and crosses a flat heightfield and a mesh at 20 m/s with no wheel leaving the ground, moving exactly as on one flat box. A wheel under a fixed frame sags g / (2 pi f)^2 and stops at min. Cylinders are milestone 26. The stored hash changes, the test world having a cart in it now. Saves are format 18. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Milestone 24. fracture(shape, { count, seed }), exported beside readGlb,
cuts a box or a hull into count convex pieces that fill it exactly, face
to face: Voronoi cells, the part of the shape nearer each of count
points scattered through it than to any other. Each piece comes back as
{ vertices, position }, its corners about its own centre of mass, ready
for addBody as a hull. When to break is the game's.
The points come from Park and Miller's generator, kept a quarter of
their even spacing apart so no piece is a sliver (compared as sixth
powers: Math.cbrt isn't the same on every machine). Each cell is the
shape cut by the planes halfway to every other point, nearest first. A
corner where a cut crosses an edge is worked out from the edge's kept
end, so the two faces beside it find the same corner to the bit, and
the cap is ordered by Bearing's own atan2. So a seed gives the same
pieces on every machine: a stored hash holds it, and CI runs it on Bun.
The pieces' volumes sum to the shape's within 1e-12, and of 16,000
points each is in exactly one piece. A slab broken where it lay, into 6
or 12, rests within 2 mm and sleeps. Into 30, one piece at the edge on
a cut of 44 degrees slides off, friction 0.5 holding 27, as a real one
would. 20 pieces of a rock take about 5 ms. Found on the way: the
default box was a 2 m cube, not 1 m.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Milestone 25, the last of the kit. world.addSoftBody, setSoftBody, softBodyOf and softBody(id), and the SoftBody handle with positions: an open mesh is cloth, a closed one with pressure keeps its volume. Nolan chose density in kg/m3 as bodies', air drag with a wind option, and the body options with their own meanings. XPBD, one pass a substep, before the rigid solve, two ways with every rigid shape. Stiffness from the sheet's own weight and size, tethers so hung cloth keeps its length at any mesh spacing, two contact planes a corner, XPBD's velocity pass, and a material damping of 1/s, measured on six drapes. Found on the way: constraints solved one at a time spun a ball at rest about the vertical (now taken back each substep), and a volume pushed back into the floor kept balls wobbling. Known limits documented: corners collide, not triangles; no self-collision; a heavy closed body may not sleep; a body much heavier than the cloth sinks further than its stiffness says. FORMAT 19; the mixed scene has a flag, a ball and a draped crate, so HASH changed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The kit, in one release: boxes of water that float what is in them as Archimedes says, a wheel joint for a car's suspension,
fracture()to cut a box or hull into pieces that fill it exactly, and soft bodies (cloth, flags and closed shapes that keep their volume) colliding with every rigid body both ways. Also faster joints with stops and faster resting on terrain, and a capsule leaning on what it rests on no longer buzzes. Saves are now format 19. See the changelog's 1.4.0 section.🤖 Generated with Claude Code