Repository navigation
physics: port Visual Pinball's recent physics fixes - #599
Merged
Merged
Conversation
A slow ball inside a line segment's touch band got the legacy hit time bnd * 10 + 0.5, which never fits a 0.1 step, so the touch was dropped and the wall only reacted once the ball had sunk into it. It is a contact at hit time 0 now, as in Visual Pinball's FIX_PHYSICS path.
- The normal force of a contact is the velocity change that cancels the approach and the load for the step, whatever the ball's mass, and the ball's surface acceleration no longer divides gravity by its mass. Heavier balls were thrown off their support. - The friction cone is bounded by the normal impulse the contact applied instead of the gravity component pressing the ball on the surface, which is next to nothing on walls and nothing on the glass. - The 0.025 static friction gate only applies to supports. After the normal solve it tested the orientation of the normal and picked the static branch on every wall, even with real slip. - Sliding friction requests the full slip-removing impulse instead of a step-length fraction of it. Contact friction works from a snapshot of the ball's motion, so with the full impulse each later contact of the same ball now sees the friction of the earlier ones, or two contacts sharing a slip would each remove all of it. Spring hinges recompute their normal and are left out.
Ported from Visual Pinball: - The static friction case subtracted the flipper's inertia term from the ball's instead of adding it, as the dynamic case does. - The contact's gap acceleration uses the ball's center acceleration. The centripetal term of the material contact point is positive along the normal for any spin, so a spinning ball read as accelerating away and lost its support. The friction budget gets the same fix.
Ported from Visual Pinball: the flipper's moment of inertia is the one of the convex hull of its base and end circles instead of a rod's. The coil torque is scaled by the ratio of the two, so the free swing stays the one tables were tuned on, while ball impacts now see the shape's inertia. Degenerate shapes, one circle inside the other, keep the rod.
Ported from Visual Pinball: the normal is the direction between the two ball centers at the time of the hit. It added the relative motion to the moving ball with the wrong sign and left the hit ball where it was, so an oblique hit pushed the balls apart in a wrong direction.
Ported from Visual Pinball (ball/ball contacts and the stack fixes of its FIX_PHYSICS path). Ball pairs were never contacts, so balls resting against each other kept colliding, popping apart and bouncing back. - A slow pair inside the touch band is a contact, also a bit deeper where a resting stack hovers, and only a deep overlap is a collision. - The contact cancels the approach relative to the other ball, up to a contact-scale velocity, so an impact still passes on through a row of balls. A small capped nudge drains the overlap. - Contact friction acts on the slip relative to the other ball, which takes its share of the impulse, with a steel on steel coefficient. - Slow impacts are inelastic and skip the displacement correction. - Ball/ball contacts are resolved first, and static contacts cancel what earlier contacts did to the ball along their normal, so the friction of a ball pressed against another one no longer lifts it.
Ported from Visual Pinball: the starting edge of the ramp floor got a joint for the first triangle and the same one again when the first triangle was checked against its (missing) predecessor. A degenerate floor triangle now also resets the predecessor, so the next triangle gets its own edge joint.
Ported from Visual Pinball. Dragging a point across the others reverses the winding of an outline, which code generating from it assumes to be counterclockwise. - A wall drawn clockwise had no top: the ear-clipping triangulation of its top mesh, which also gives the top collider, found no triangles, and generating the colliders threw. The top is triangulated in the canonical order now. - The side colliders are one sided. Tables relied on a clockwise wall facing inward, so like Visual Pinball, such a wall collides from both sides. - A curved trigger drawn clockwise swapped its hit and unhit events.
Ported from Visual Pinball: a slow ball embedded deeper than the touch layer in the playfield plane was neither a contact nor a collision, so it could sink through. It collides now, which pushes it out, and only a touch inside the touch layer stays a contact.
[High impact] The PR appears safe to merge; the previous floor-support issue is fixed, and no new blocking issue was found. SummaryPorts recent Visual Pinball physics fixes and adds regression tests.
|
- A ball/ball contact cancels at most the pair's own approach plus the step of load. Two touching balls moving together along the normal don't close in on each other, but the trailing one was braked by up to the contact velocity against the leading one (as in Visual Pinball). Resting stacks keep their support from the load. - A static contact takes back the lift of the contacts resolved before it even when that lift is larger than the step's load, which happens on short steps since friction removes the slip at once. It still never pulls a ball nobody lifted towards the surface, and passes the take-back on, so two supports don't take the same lift back twice.
Resolve free ball contacts once per pair with mass-weighted normal and friction impulses. Preserve the stack response when a solid or frozen ball supports the pair, and cover both cases through the physics cycle.
Retain support from a resolved collider impact even after the collision event is cleared. Follow the load direction through backed ball contacts so sloped queues and vertical stacks settle. Pass both sides of a free contact on to static supports.
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.
Ports physics fixes Visual Pinball made in the last weeks (mostly its
FIX_PHYSICSpath, which is enabled in VPX) that VPE didn't have yet. One commit per area:Where VPE differs from VPX on purpose:
bnd > -PHYS_TOUCHlimit on triangle contacts from 8c4cf05d is not ported: as a collision, a cover embedded in the ball from above would get the displacement correction pushing the ball into the floor again. VPE's contact recovery, which never pushes along gravity, handles deep triangle contacts.Tests: new
PhysicsAlignmentTests(38 cases, several ported from VPX'stest-physics-defects.cpp). The EditMode suite has no new failures compared to master; the 43 failures on master (mesh Z offsets, VPX write float noise, play-mode fixtures, Kiki ABI) are unchanged. Not play-tested on a table yet.