GenerateKDopAsSimpleCollision() will create unbounded collision primitives under certain conditions

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:

The intention behind that block of code is not at all clear to me, but commenting it out fixes the problem with no discernible side-effects so far.

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.

Hello sfreeland.bhvr,

What would be the best way to go about reproducing this issue? I have a simple grasp on what the result would be but not the steps to get there.

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.

Have a nice day!

Glad to be of service, and I appreciate your letting me know what happens to this issue.

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.

Hello sfreeland.bhvr,

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.

Thank you for the follow-up! I’ll be interested to see how this gets fixed.

Hi JamesG, I just noticed that a fix for this issue was committed on github:

.com/EpicGames/UnrealEngine/blob/master/Engine/Source/Editor/UnrealEd/Private/GeomFitUtils.cpp#L101

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?

I think that should still work, because maxDist is the distance along the normal, it is basically pushing all planes out along their normal.