Given a mesh and directions (projection axes) with certain properties as arguments, GenerateKDopAsSimpleCollision() will create a primitive collision that is essentially infinite. The culprit is the following block of code at GeomFitUtils.cpp:100
// Make sure that the min size is reached
// const float MinSize = 0.5f;
for(int32 i=0; i<kCount; i++)
{
if (FMath::Abs(maxDist[i]) < MinSize)
{
maxDist[i] = MinSize;
}
}
maxDist[i] is the maximum projection distances of the mesh’s vertex coordinates along one of the directions; this code finds any such value between -0.5 and 0.5 and clamps it to 0.5. If this happens, the FPlane created from that value may be pushed from the edge to the inside of the bounding polytope, thereby distorting the resulting collision primitive. In one case, we have found that it causes problems with the BSP build (GeomFitUtils.cpp:167) and ultimately results in the creation of two separate collision primitives, one of which is effectively infinite:
Yeah, that’s the tricky bit of course. I’d like to give you a copy of the asset that triggered this problem, but unfortunately I can’t because it’s a customer’s IP. Basically you need to open a mesh with boundary vertices near (0, 0, 0) and generate a k-DOP collision primitive with it, such that the FMath::Abs(maxDist[i]) < MinSize condition is satisfied. I was using the 26DOP collision generation when the bug manifested.
I’ll try to put together a simple test case that I can release to you.
I haven’t been able to create a test case to reproduce the unbounded collision from the screenshot, but compare the following two FBX files:
If you import them, open them in the mesh editor and create a 26DOP collision for each, you can see that the resulting mesh is distorted in the case of “uebug2” because of its proximity to the origin. “uebug-ok” on the other hand, gets a good, close collision primitive because it’s further from the origin, even though the shape of the mesh is exactly the same.
Thank you for reporting this issue and being very thorough with the reproduction steps / setup. I definitely see the problem and I’ve placed a bug report in for the issue. For your reference, the bug number is UE-23176. While I’m not sure about the reason for that for loop, I’ll let you know of any updates that happen to the report, as this could be intended functionality meant to simplify the process.
I believe the intention of this (rather old) code was to prevent any ‘slabs’ being zero width and causing issues in the collision code. I am going to remove the Abs, which should at least solve the degenrate case, but does mean that your kdop is built around the mesh and a sphere of radius 0.5 at the origin. Ideally we would just ensure each ‘slab’ width is at least some min size, but that requires knowledge of opposing directions which we don’t currently have and would be a large refactor.
Anyway, thank you very much for the bug report, it is much appreciated.
Actually after thinking about it some more, that isn’t a great fix. Instead I’m just going to inflate the kdop by minsize to ensure non-degenerate slabs.
A fix has gone in for this issue now so it should be included in a future build. As of now, the change isn’t available on Github but I’ll keep an eye out and link the commit here when it is if you wish to add it to a source built engine.
I’m curious though – what happens if maxDist is less than zero, say for instance because the mesh is entirely contained within the negative x/y/z octant of the coordinate space?