What are the general differences in how Mesh colliders work compared to BEPUv2 (performance wise)? #154
-
Hello! I've got another question if you don't mind! This one is to get a bit better understanding how has handling of Mesh colliders changed between BEPUv1 and BEPUv2, particularly in some extreme cases. After we finished the upgrade, we found some poorly optimized user content that was overlooked with BEPUv1, but suddenly popped up as an issue - very dense mesh colliders. For example there was a couch that was nearly 400000 triangles and colliding some parts of it (particularly very dense ones with tons of tiny triangles) would make everything die. It's obviously not suitable for a collider, so it's not unexpected and our users generally understand that they need to replace them with proper ones if they want to avoid bad performance spikes. However one thing that's curious is that with BEPUv1 there wasn't any lag spike with those particular objects despite their high density when the character controller (capsule) was colliding with them, so that got me curious what could be causing the difference. I've done a bit of rough investigation myself. Particularly I logged number of calls to the AllowContactGeneration with childIndexA and childIndexB to see how many triangles(?) were being tested. I noticed that in most parts of the mesh it's usually just five, twenty tops, but in some parts it spikes to thousands, somewhere even ~20000 (this in particular results in a pretty long freeze). I messed around with speculative margin values on both the Mesh and the Capsule a bit too, which seems to improve it in certain cases, but not always. Are there are any major differences between BEPUv1 and BEPUv2 that would change how such extreme cases behave and scale differently performance wise? I found that there's a bunch of post processing done to smooth out the boundaries between triangles (this actually helped make some colliders work better that were previously "bumpy"), which I figured might be part of the problem, but I don't have a good understanding of it (and what BEPUv1 did exactly to compare). Are there some things that I can tweak or touch on my end that could help a bit, even at the cost of worse collision quality with those particular mesh colliders? It's perfectly OK if not, since we're talking about horrendously sub-optimal scenarios and our users understand that they shouldn't use such colliders in the first place (and this definitely helps drive the point home :D ). Overall everything has been a huge improvement, but I wanted to ask about this just in case and to better understand how BEPUv2 handles those kinds of collisions. |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 4 replies
-
v1 relied on user-provided indices for connectivity information and would not smooth any boundaries that were not represented by indices. v2 uses a more general approach that dynamically discovers connectivity, even for weird geometry like overlapping triangles or t junctions. Hence why it tends to have fewer bumps. The implementation, however, does have a quadratic term. That's most of what you're seeing. It goes something like this: for every contributing manifold, under the assumption that the set of triangles that generated contacts with the original shape is a reasonable guess at nearby triangles, it enumerates all of them looking for geometry that should block the contribution. If tens of thousands of triangles generate contacts with the shape, then this assumption is really, really bad. Secondarily, speculative margins do imply that more contacts are made. v1 only had speculative contacts if previous contacts persisted and separated, but v2 will aggressively generate speculative contacts within the margin. So for this kind of very dense use case, it's probably generating many thousands more contacts, which then need to be reduced. Shrinking the speculative margin to 0 would... technically help, but would harm simulation quality. This is related to #66. The discovery phase could be precomputed and shared, or moved from n^2 to nlogn. Either one would help massively for this use case. I intend to get around to that eventually, but probably not for 2.4. The good news is that a workaround is very simple. You can disable mesh reduction for these pairs by checking the count, which I went ahead and added since I'm pretty sure some extra bumps are better than a multi-second hang as default behavior: e59251b |
Beta Was this translation helpful? Give feedback.
-
I ended up running into a whole mess of triangle and mesh related bugs and updating Further improvement will probably have to wait a little while post-2.4, and will likely involve optionally precomputed mesh connectivity information. |
Beta Was this translation helpful? Give feedback.
v1 relied on user-provided indices for connectivity information and would not smooth any boundaries that were not represented by indices. v2 uses a more general approach that dynamically discovers connectivity, even for weird geometry like overlapping triangles or t junctions. Hence why it tends to have fewer bumps.
The implementation, however, does have a quadratic term. That's most of what you're seeing. It goes something like this: for every contributing manifold, under the assumption that the set of triangles that generated contacts with the original shape is a reasonable guess at nearby triangles, it enumerates all of them looking for geometry that should block the contribution.
If t…