mkafrin / PolyZone

PolyZone is a FiveM mod to define zones of different shapes and test whether a point is inside or outside of the zone
MIT License
204 stars 191 forks source link

Moving zones #6

Closed mkafrin closed 4 years ago

mkafrin commented 4 years ago

Moving zones might be possible with minimal performance impact. Initial thought is that an offset can be stored when the zone is moved by subtracting the new position from the original one, and then the offset is added to the necessary values to offset the math to the correct position.

Questions: What could this be used for? What performance impact does it have? What complexity impact does it have? What changes to the api are necessary?

mkafrin commented 4 years ago

Implemented! Was quite a bit more work than original thought, but in the end was pretty clean of an addition. Instead of arbitrary "moving zones", we came to the decision of having "entity zones" that are attached to an entity and automatically move and rotate along with it. This hides complexity from the caller, simplifies the code, and allows for utilization of the edge cases associated with rectangular zones to get some additional performance.

Performance impact is negligible. There is some impact associated with updating the position and rotation offset, but to offset this impact, we are taking advantage of the fact that entity zones (based around the model dimensions of the entity) are always rectangular, and therefore only a simple bounding box check is needed to test for point inclusion. We can completely skip the need for the grid optimization, and avoid the slower winding number algorithm. Because of the lack of a need for the grid, this also avoids any runtime resource spike for grid creation or complicating the code for drawing the grid.

Complexity impact is low. Some additional utility functions were needed to handle the position and rotation offsets, and some of the code like in _drawPoly needed to be complicated a bit to handle both regular and entity zones. Care was made to avoid performance regressions due to these changes, but such care did increase complexity a bit. However, most functions/code was unaffected by these changes. For example, _pointInPoly, and all grid related code was entirely unaffected. More work may be done to lower the complexity impact, but that is yet to be decided.

Changes to the API were minimal. No changes to the usage of existing API were made, but an addition to the API was made. The function PolyZone:CreateAroundEntity(entity, options) was made. The first parameter is the entity with which you want the zone to encapsulate and follow, the 2nd is mostly just passed along to the PolyZone:Create() function in the background, though some additional options were introduced. These additions are

Also the method PolyZone:destroy() was added, which can be called on any created zone and will stop all threads related to the zone (debug drawing, onPointInOut helper, etc) as well as set a destroyed flag to true on the zone. If you try to use isPointInside on the zone after its destroyed, it will return false and print a warning