-
-
Notifications
You must be signed in to change notification settings - Fork 640
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Performance: multiple-phase collisions #103
Comments
Another great article (but I guess you know it already) that also cover this topic and collision resolution itself : +1 for creating a AABB box representing the object motion (that for sure will fix issue #16), however this can only be used with fixed element (like Tile), right ? else an object going where the object was previously placed could trigger a false-positive collision. Else for the phases approach, I've been looking at that as well, but considering that basically melonJS only supports AABB boxes, I didn't find how to efficiently do the broad phase, as basically (if' I'm not wrong, which I'm sure I am) it's about detecting which objects are intersecting with the object range of motions (which is already the narrow phase). |
Yeah, it's a super great article that I read through a while back. (It made me decide to use chipmunk rather than roll my own collision detection, as I was short on time.) The false positives are ok in the broad phase, as long as they can be "bailed early" and don't cause too many false positives each frame. That would be a worst-case scenario, and would probably be an uncommon situation. I think only having MANY very small & very faster moving objects will actually create a lot of false positives within the range-of-motion AABBs. The "broad phase" is usually more about figuring out which objects should be considered for collision checking. It's generally a good idea to use spacial hashing as your broad phase. This will tell you which objects are potentially colliding. You then use their range-of-motion AABBs to further narrow down the search. The "narrow phase" will resolve those collisions; in a physics engine, this means computing and applying response forces. |
I'm moving this one to the next release, unless you are yourself super hyper motivated in implementing this before :) |
@obiot ok! My motivation has turned to some other projects recently. :) |
@parasyte sure, anything exciting ? Have fun, |
Another great article : |
I started on this tonight, and it got me thinking of the future of melonJS. We want to integrate a physics engine officially. And physics engines do all of their collision detection with rigid bodies; even the environment is composed of rigid bodies. There isn't a distinction between collisions with the environment and collisions with other entities. I guess this property is unique to melonJS in its current form. :) I would like to remove that distinction in this ticket. All collision checking should occur in one function, using the same data structures. This will ease the integration of a physics engine, and also clean up and make collision detection less work to manage. For compatibility purposes, I am not opposed to converting the collision tile layer into discrete objects within the new collision detection system. (Conversion happens after level load.) The other thing I want to mention is that I probably won't be implementing an SAT algorithm here. Although I can if it makes more sense to do now than later. My concept is just to eliminate the performance issues, and fix bugs along the way. AABB collisions might be just fine for now. ;) |
@parasyte |
@obiot no worries! My code for this ticket isn't ready for review yet. I want to keep melonJS simple, so I'm going to lump all collision phases into a single function. It isn't the "correct" way to do it, but we're not too concerned with physics accuracy anyway. :p Regardless, this will be another big API-breaking change! |
a few comments on my side :
About big API-breaking change, please do whatever you think is the best (though I would suggest to keep it as close as possible from the physic API out-there, to ease later integration, or addition). And anyway, if we do want to bring melonJS to the "next level", that's something we cannot avoid. I'm very excited about this one, this is one of melonjs' major remaining weakness, and if we could have some breakthrough on this one, it would really be fantastic ! :) |
@obiot That all sounds totally reasonable and awesome. For AABB collisions against the special tiles like slopes: Those will still be handled the same as current, with "pixel perfect" collisions against the 45° slopes. It will need to change later for SAT, but at least we won't drop a feature during the upgrade. Collision layer conversion code is done! I need to take care of a few more things in the outlying areas and do some testing. After that, I'll push the initial commit to a new branch. :D One more thing we might enforce is doing all collision handling in callbacks, and getting rid of the explicit For the |
@parasyte
wow, that's become very concrete very fast I can't wait to play with the new branch ! |
Not sure about getting rid of Excluding from collision is easy: I have a new property called var masks = {
PLAYER : 0x00000001,
ENEMY : 0x00000002,
COIN : 0x00000004,
POWERUP : 0x00000008,
};
game.PlayerObject.collisionMask = masks.PLAYER | masks.ENEMY | masks.COIN | masks.POWERUP;
game.CoinObject.collisionMask = masks.COIN;
game.EnemyObject.collisionMask = masks.ENEMY;
game.PowerupObject.collisionMask = masks.POWERUP; Now It can be a bit tricky to use masks, but it's also supported in Chipmunk! |
wow, that looks great, masks are actually very very good :) about the collision check, I thought this would be actually automatically done, without requiring to manually call the function, it is not ? but I guess it will be clearer for me once I will see it :) |
Well, it's no more automatic than adding gravity to the velocity vector. ;) I'm sure we could clean this all up in some way, but I haven't really thought about it. For performance reasons, we only want to check for collisions when an entity moves. And |
oh ok, got your point :) |
- This is a complex system, but it moves everything collision-related to the new collision.js module. - The collision module manages a spacial grid that objects are dynamically added to and removed from. - When checking for collisions, only objects which appear within the same spacial grid cells will be compared. - The "broad phase" is handled by `me.collision.updateMovement()`, which updates the object position within the spacial grid. - The "narrow phase" is handled by `me.collision.check()`, which performs simple AABB intersection checks. - `me.game.collideType()` has been replaced by a new `collisionMask` property, which can be used to exclude objects from colliding. - All collision handling now takes place within onCollision callbacks. - Added a new debug var for drawing the spacial grid: `me.debug.renderCollisionGrid`. - Platformer example has been updated with current collision detection system (it feels broken because the default `me.ObjectEntity.onCollision()` unconditionally sets the object velocity to 0) - Added a handful of utility functions, like `Object.isObject()` TODO: - Proper *handling* of detected collisions (collisions are detected accurately). - Change spacial grid object lists to hash (JavaScript Object) if it makes managing object lists faster. - Take care of all FIXME comments in this patch.
@obiot Here is the initial work! 👯 It's really early still, but it's pretty cool to watch with debug enabled. |
@parasyte so cool, I think I definitely need some time to read your code and understand how it works, but so far I liked what I saw, except for the try/catch :) |
@parasyte just played with it a little, and effectively seeing it running in debug mode is quite cool :) I did provide a few comments, I hope you don't mind (but nothing really constructive), as I'm still in the phase where I need to understand all the code changes :) but hey, quite a good good good work you put here !!!!! |
I have some ideas to optimize the code, but I think even the algorithm as it is will be quite a bit better for performance. My next step before working on the default collision handler will be building a basic collision test example, to better understand how it changes performance. |
@obiot Funny news! The collision test demo has worse performance in this branch than in master! :p Updating the grid cells in the broad phase part takes waaayyy too much time. This is actually very easy to fix. But for now ... sleep time! I'll try again tomorrow! |
@parasyte that's very good news then, because I was also playing with the code, and a bit worried about performances :) |
@obiot The Anyway, the new branch for this is |
:):):) On Aug 26, 2013, at 06:16 AM, Jason Oster notifications@github.com wrote: @obiot The ticket-103 branch was really broken, so I deleted it from github. Then I locally rolled back a bunch of merge commits and did a single merge that fixed everything. I haven't yet touched the collide code in ObjectContainer -- I should do that right now. |
…olygons, so far. - Points for Polygons are always given relative to the first point placed, at position 0,0. The new `offset` is used to normalize the position of the shape. - Also updated the Platformer example to use the normalized object position instead of the position given by the TMX parser. Again, only useful for Polygons.
and... postponed again ! :( (note that I'm really considering stop trying with this one and going with a simple physic engine integration) |
Similar to what has been done in the ticket #103 for the region drawing
- this is currently unused, and add extra cpu cycle to the left/right/top/bottom getters - if re-introduced later (ticket #103?) this might not be the best/correct place where to put it
Guys, I decided to close this dead ticket, as it also spawned over the months (year) into a lots of different directions, with pages and pages of comments and it's time to let this one rest in peace. but, and to quote my fellow countryman and scientist Antoine Lavoisier, since |
Objects should only do collision detection when they move. And the detection should be done in multiple phases using hash segments:
#1. Broad phase
The first phase is called the "broad phase", and it only attempts to resolve which objects/tiles collide, not how to handle the collision. In the broad phase, an AABB is created for the object's entire range of motion. See image below:
In resolving the broad phase, all range-of-motion AABBs will be stored into their closest hash segments, and collisions detected between other AABBs within those segments.
(Here "hash segment" means a square area of the world. A good starting point is to break the world into hash segments that are 4x4 tiles in size, though any size is possible.)
#2. Narrow phase
The narrow phase takes the collisions detected in the broad phase and finally resolves them by collision shape/position. Some broad-phase collisions will be false-positives, where the range-of-motion AABBs intersect, but an actual object collision did not take place. The narrow phase needs to be good at "bailing early" in these kinds of cases.
An algorithm like this should reduce the time complexity from
O(n^2)
to something more likeO(log((n-s)^2))
, wheren
is the total number of objects ands
is the number of stationary objects. In other words, a huge performance gain in collision detection with a large number of objects.The text was updated successfully, but these errors were encountered: