Simple Geometry Decomposition and CSG

I love CSG so much that I built a large portion of my game around it.

Use Case : In game player can insert windows or doors into walls they have placed from a set of predefined prefabs which I have specially modelled in Studio. These special models have negative parts in them to create passable areas through parts, snapping these into the workspace with. CSG. is. Amazing!

Problem Statement: I am experiencing geometry errors which is preventing game elements such as doors from opening or which stops a player from walking up a staircase or through a hole they have created.

Even when a union result is not that complex and it appears visually fine to the player, it may not be passable. I found by looking at the location with decomposition geometry visible there are corner wedge errors which sneak in after a CSG operation, sometimes the geometry error will make the entire space impassable and renders some game goals unachievable.

Problem Definition: I have attempted to quantify the ‘ error rate’ of the decomposition problem because parts do not need to be complex to get the error situation. My solution was to build a CSG Unit Test Place for SubtractAsync. You can download the code SubtractAsync Unit Test

When entering the place the algorithm immediately starts, it gathers error data by repeatedly subtracting several simple shapes from a larger but still simple shape and then tests for intersections across each; it does this over a volume of space and over a range of complexities, I do this because I was looking for positional clustering of errors. The position of the geometry errors in the workspace are consistent when playing the game. Change the position and get a different result?

Indeed, I found one way to reduce the error rate practically to zero was to introduce a wiggle retry loop. When it encounters the first error it will ‘wiggle’ the big part around a small 1/100 amount on each axis until the parts do not intersect and pass the test, or, until the doRetryLimit is reached.

The defaults for the unit test operations are:

Enum.CollisionFidelity.PreciseConvexDecomposition

Enum.RenderFidelity.Precise

It can use either of these for the intersection testing.

:GetPartsInPart *default

:GetTouchingParts

Conclusions:

After many iterations of the unit test design and execution I found the decomposition error rate to be about 0.023%. That may not seem like a lot, but it is consistent.

I think the geometry errors are less related to CSG and more related to the geometry decomposition algorithm itself. It can fail on even the simplest of operations and ironically decomposing more complex shapes is more accurate.

Error correcting retry loops can take upward of 50+ iterations of part wiggling to find solutions, while on the odd occasion it will timeout completely never finding one. The net result is a increase in the load time of in game models. I have considered making a ‘construction’ animation to hide the iterations and make it a ‘feature’ of the build process, although I cannot guarantee it will be error free.

2 Likes