Prozi / detect-collisions

Points, Lines, Boxes, Polygons (also hollow), Ellipses, Circles. RayCasting, offsets, rotation, scaling, bounding box padding, flags for static and ghost/trigger bodies
https://prozi.github.io/detect-collisions/
MIT License
206 stars 22 forks source link

Impact of changes since Sinova fork (2.5.4?) - particularly performance-wise #27

Closed mdealiaga closed 2 years ago

mdealiaga commented 2 years ago

First of all thank you for updating and continuing support on this project!

I'm currently using the original 2.5 fork and was pleasantly surprised to see this library has been upgraded in the last year.

I'm mainly wondering about the performance impact of the change to RBush/SAT https://github.com/Prozi/detect-collisions/releases/tag/v3.0.2 as my use-case (high entity count multiplayer game server) is really CPU intensive.

I'm also wondering if there is a list of breaking changes to be aware of when updating the API - there is a header for "BREAKING CHANGES" in the v3 patch notes but no note of them.

Prozi commented 2 years ago

the breaking changes summarised:

first parameter of new Point|Circle|Polygon|Box is now a { x, y } Vector

also the polygon's points array is filled with { x, y } instead of [x, y]

creating bodies

v2:

const { Collisions, Circle, Polygon } = require('detect-collisions');

const system  = new Collisions();
const circle  = new Circle(100, 100, 10);
const polygon = new Polygon(50, 50, [[0, 0], [20, 20], [-10, 10]]);

system.insert(circle);
system.insert(polygon);

v3+:

const { System, Circle, Polygon } = require('detect-collisions');

const system = new System();
const circle = new Circle({ x: 100, y: 100 }, 10);
const polygon = new Polygon({ x: 50, y: 50 }, [
  { x: 0, y: 0 },
  { x: 20, y: 20 },
  { x: -10, y: 10 },
]);

system.insert(circle);
system.insert(polygon);

testing for collisions

v2:

const potentials = polygon.potentials();

for (const body of potentials) {
  if (polygon.collides(body)) {
    console.log('Collision detected!');
  }
}

v3+:

system.checkAll(handleCollisions);

or

system.checkOne(body, handleCollisions);

or

system.getPotentials(body).forEach((collider) => {
  if (system.checkCollision(body, collider)) {
    handleCollisions(system.response);
  }
});

where handleCollisions is a handler like

function handleCollisions(response: SAT.Response) {
  // your logic
}

see https://github.com/jriecken/sat-js#satresponse

updating BVH in v3+

after updating position, angle or anything that can change the body AABB you need to update body's AABB (bounding box)

body.updateAABB();

or

system.updateBody(body);

or you need to either use purely

body.setPosition(x, y);

which is a shortcut method - updates pos.x and pos.y and then it calls updateBody internally (see for example https://github.com/Prozi/detect-collisions/blob/0faabbf/src/bodies/polygon.ts#L84)

Prozi commented 2 years ago

the performance differences are minimal I think, because I've kept the demos and their results are the same

I will do some kind of benchmark of latest vs v2 version to see the exact times

P.S. actually I assume it's faster now than it was because of few optimization reasons like need to call update AABB manually and introducing isStatic flag on bodies which do not trigger collisions and are not checked (see https://github.com/Prozi/detect-collisions/blob/0faabbf/src/system.ts#L127)

Prozi commented 2 years ago

also since v3 there has been a number of improvements:

@mdealiaga

mdealiaga commented 2 years ago

Thank you for the rundown @Prozi ! I will aim to upgrade soon. Typescript support and raycasting will be very useful.

It would definitely be interesting to benchmark these libraries, also alongside some of the main JS physics engines (p2js etc).

mdealiaga commented 2 years ago

Hi, one additional question: was support removed for padding via these updates? (https://github.com/Sinova/Collisions#anchor-bounding-volume-padding)

I currently use that for all my moving entities -- I did not rigorously test the performance increase, but it made sense to apply this to entities expected to move every server update.

Prozi commented 2 years ago

Hi, one additional question: was support removed for padding via these updates? (https://github.com/Sinova/Collisions#anchor-bounding-volume-padding)

it was, but read on

I currently use that for all my moving entities -- I did not rigorously test the performance increase, but it made sense to apply this to entities expected to move every server update.

I checked the code in Sinova and experimented with adding the paddings. During some tests I found adding paddings is in fact beneficial.

Feel free to use v6.1.0+ which has padding as one of options for creating body https://github.com/Prozi/detect-collisions/blob/master/src/model.ts#L35

used it in latest demo, you can see it when you click checkbox https://prozi.github.io/detect-collisions/demo/?stress

mdealiaga commented 2 years ago

Thank you for the quick patch with this feature!