Repository navigation
fix: give grid nodes lying on a trimesh surface a collision - #11
Merged
sebcrozet merged 1 commit intoNov 2, 2026
Merged
Conversation
collide() derives the contact normal from the vector between a grid node and its projection on the collider, and skipped the collider when that vector had zero length. A node lying exactly on a triangle-mesh surface therefore got no boundary condition at all. When a flat mesh floor lies on a grid plane, that whole layer of nodes is left free and particles sink through the floor. TriMesh.project_local_point now also returns the pseudo-normal it already computes for its inside test, and collide() uses it for points within 1e-4 cell widths of the surface. Other shape types are unchanged.
Member
|
Thank you! |
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.
Problem
collide()builds the contact normal fromproj.point - pointand skips a collider when that distance is zero (dist != 0.0). A grid node lying exactly on a triangle-mesh surface therefore gets no collision, and no boundary condition is applied to it. This affectsgrid_updateand any custom kernel that callscollide().With a flat mesh floor that lies on a grid plane (for example a heightfield floor at an elevation that is a multiple of the cell width), the whole layer of nodes on the floor is left free. Particles just above it take part of their velocity from those nodes, and once disturbed they sink through the floor.
Fix
TriMesh.project_local_pointalso returns the pseudo-normal it already computes for its inside test. The return type is nowTuple<ProjectionResult, Vect, bool>;collide()is its only caller in slosh.1.0e-4cell widths of a trimesh surface,collide()uses that normal instead of the direction to the projection, which is zero or rounding noise there. Other shape types behave as before.Testing
We hit this in a blast simulation built on slosh 0.7.0. Its floor is a heightfield converted to an oriented trimesh, with the boundary condition applied per grid node through
collide(). The setup: floor at a multiple of the cell width, 1.25 m cells, 1 particle per cell. Same input and same build, with and without this change:The same scene shifted half a cell against the grid, so that no node lies on the floor, is unchanged by the patch.
That run used this edit applied to v0.7.0. On this branch I compiled
solver/grid_update.slangto WGSL withslangc(DIM=3) but have not run a simulation.We pin slosh 0.7.0, so a 0.7.x patch release with this fix would let us ship it without moving to 0.9.