liabru / matter-js

a 2D rigid body physics engine for the web ▲● ■
MIT License
16.7k stars 1.96k forks source link

Prevent object passing through walls / tunneling (implement CCD) #5

Open liabru opened 10 years ago

liabru commented 10 years ago

If you need fast moving or thin bodies a simple and robust solution is to sub-step using multiple updates per frame:

See the example here: https://github.com/liabru/matter-js/issues/5#issuecomment-1050738814

As well as sub-steps also consider:


Currently there is no continuous collision detection (CCD), so fast moving objects pass through other objects.

A description of the problem: http://www.stencyl.com/help/view/continuous-collision-detection

Solution is to implement a CCD algorithm.

One I'm currently considering is speculative contacts, see here and here.

"we compute the closest distance d between the two objects; the idea is that we want to remove exactly the right amount of velocity from A such that it will be exactly in touching contact with B on the next frame"

I've already implemented the code that extends the AABB based on object velocity.

The next part is to find the closest distance between two objects and remove the required velocity.

yungzhu commented 6 years ago

Is there any way?

fabienjuif commented 6 years ago

EDIT 2: https://gist.github.com/fabienjuif/a7d9fc3e34e23f6000bcfc185dc0e341

EDIT: I fall into FPS issues, the engine run objects faster on 60FPS than on 30FPS. So don't try that at home :(


I did this trick for now:

  // engine
  // - run the engine several times, so we have the feeling the game is fast
  // - also, this avoid collision detecting issue since CCD is not implemented yet in matter-js
  let lastLoop = Date.now()
  for (let i = 0; i < RERUN; ++i) {
    Engine.update(engine, i === 0 ? delta : (Date.now() - lastLoop))
    lastLoop = Date.now()
  }

And divide all my velocities by the RERUN amount :) It works, but I assume this is less performant

osfa commented 5 years ago

+1

maltenuhn commented 5 years ago

Question: could a bounty help push this issue forward? We'd be happy to contribute.

qwertyquerty commented 5 years ago

This really should be completed, considering it's such a big issue, and it's been open for so long.

stefannew commented 5 years ago

Is there any work in-progress to address tunneling issues?

notchris commented 5 years ago

I'd also like to see the tunneling issues resolved.

dzcpy commented 4 years ago

Any updates?

michael-garofalo commented 4 years ago

Can we throw money at this issue? I'm writing "A Book About Hype" and Hype uses Matter.js as its Physics engine. I was writing about the CCD issue and I realized that I could add a blurb where people can send money to fix this problem. Maybe GitHub sponsors works?

dzcpy commented 4 years ago

I switched to Planck.js at last. It worked well, just lack of documentation. Matter is way more intuitive. But this bug is too annoying

joshkpeterson commented 4 years ago

it's kind of amazing to receive updates on this issue like 4 years later, reminding me of where I was in life while working on this. Trump hadn't been elected, it was a simpler time.

Anyway it would be great if the maintainer or others could give any ideas or an outline of what a solution might be. seems like it would reduce friction for finding someone to work on it (bounty or not).

On Tue, Apr 28, 2020 at 12:04 PM dzcpy notifications@github.com wrote:

I switched to Planck.js at last. It worked well, just lack of documentation. Matter is way more intuitive. But this bug is too annoying

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/liabru/matter-js/issues/5#issuecomment-620700340, or unsubscribe https://github.com/notifications/unsubscribe-auth/AARQDMXKEN4JDXMSR3U3JGLRO35CBANCNFSM4AMWL26A .

notchris commented 4 years ago

@liabru Helppppppppppp

Feavy commented 4 years ago

Is it not possible to just copy/paste code from a JavaScript port of Box2D like PlanckJS to solve this issue?

notchris commented 4 years ago

@Feavy Something like that, but porting isn't super easy.

dzcpy commented 4 years ago

it's kind of amazing to receive updates on this issue like 4 years later, reminding me of where I was in life while working on this. Trump hadn't been elected, it was a simpler time. Anyway it would be great if the maintainer or others could give any ideas or an outline of what a solution might be. seems like it would reduce friction for finding someone to work on it (bounty or not). On Tue, Apr 28, 2020 at 12:04 PM dzcpy @.***> wrote: I switched to Planck.js at last. It worked well, just lack of documentation. Matter is way more intuitive. But this bug is too annoying — You are receiving this because you commented. Reply to this email directly, view it on GitHub <#5 (comment)>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AARQDMXKEN4JDXMSR3U3JGLRO35CBANCNFSM4AMWL26A .

So, hopefully most of you guys would choose to jump ship as long as you still can. Don't let yourself sink into despair for another 4 years.

jtoy commented 4 years ago

+1

huy-nguyen commented 4 years ago

I ran into this tunneling problem with matter.js and eventually abandoned it in favor of box2d.js and haven't had a problem since. box2d.js's API is less nice because it's directly compiled from C++ using Emscripten but it wasn't hard to switch. Highly recommended.

Loque18 commented 3 years ago

it's already 2021, we are almost in the middle of the year, do we have any progress with CDD ?

WesWedding commented 3 years ago

Be the change in the world you wish to be, peeps! Any Pull Requests on this issue?

dzcpy commented 3 years ago

No, switching to box2d is the right move

mulhoon commented 2 years ago

There seemed to be a hack on Stack Overflow that worked with 0.12.0 and earlier.

bombzj commented 2 years ago

No, switching to box2d is the right move

Tried and failed to solve the issue. The problem is critical. I don't know if I should wait or jump ship. The tools and docs in matter.js are so much better than box2d.js.

dzcpy commented 2 years ago

No, switching to box2d is the right move

Tried and failed to solve the issue. The problem is critical. I don't know if I should wait or jump ship. The tools and docs in matter.js are so much better than box2d.js.

For me box2d works perfectly in my projects. I used Planck.js though. It's true that matter.js's documentation is way better, but I can't get it work

joshkpeterson commented 2 years ago

Wait? This issue is over 6 years old lol

On Mon, Feb 14, 2022 at 3:47 PM Jacob @.***> wrote:

No, switching to box2d is the right move

Tried and failed to solve the issue. The problem is critical. I don't know if I should wait or jump ship. The tools and docs in matter.js are so much better than box2d.js.

— Reply to this email directly, view it on GitHub https://github.com/liabru/matter-js/issues/5#issuecomment-1039163044, or unsubscribe https://github.com/notifications/unsubscribe-auth/AARQDMTSWITWYQJEGB7YLR3U3EH3VANCNFSM4AMWL26A . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

You are receiving this because you commented.Message ID: @.***>

stefannew commented 2 years ago

No, switching to box2d is the right move

Tried and failed to solve the issue. The problem is critical. I don't know if I should wait or jump ship. The tools and docs in matter.js are so much better than box2d.js.

You could open a PR instead of waiting.

liabru commented 2 years ago

The simplest solution if you need fast moving or thin bodies is to sub-step, it's robust and not all that expensive now and you get higher quality results all round.

You can even dynamically increase your substeps for just a few frames when you detect fast moving bodies, if performance was an issue (and you don't mind possibly inconsistent results, like with a dynamic timestep).

Until I've finished adding substeps as a feature into Matter.Runner (it's a bit tricky to handle all possible framerates, plus a few other things for the general case), here is a very simplified example (that assumes fixed 60fps) to demonstrate:

const delta = 1000 / 60;
const subSteps = 3;
const subDelta = delta / subSteps;

(function run() {
    window.requestAnimationFrame(run);
    for (let i = 0; i < subSteps; i += 1) {
      Engine.update(engine, subDelta);
    }
})();

As well as sub-steps also consider:

Let me know if that helps - I realise this isn't so obvious unless you're very used to game dev!

hossein4bedi commented 2 years ago

Same Issue while working with Matter.js in React Native! Changing the body size and velocity or obstacle thickness does not solve the issue.

nightness commented 2 years ago

I switched from using applyForce to setVelocity, fixed the tunneling bug in my app.

        Matter.Body.setVelocity(ball, { x: ball.velocity.x + 20, y: ball.velocity.y - 20 });
        // Matter.Body.applyForce(ball, ball.position, { x: 0.05, y: -0.05 });
Anatoly03 commented 2 years ago

Is there some sort of path tracing collision detection? Say if object A moves from position X to position Y, create a line (X1, X2, Y1, Y2) and check if the line intersects with the object lines? My body seems to be phasing through other bodies despite the speed not being that quick.

Or to be precise, when applying force to a body near to another body it phases through, maybe I have another problem?

liabru commented 2 years ago

@Anatoly03 see the last point in https://github.com/liabru/matter-js/issues/5#issuecomment-1050738814 about raycasting - to avoid some of the worst cases that approach seems reasonable (especially for user controlled bodies), but generally difficult to make robust. Again I'd strongly recommend using sub-stepping as mentioned in that comment.

Anatoly03 commented 2 years ago

@Anatoly03 see the last point in #5 (comment) about raycasting - to avoid some of the worst cases that approach seems reasonable (especially for user controlled bodies), but generally difficult to make robust. Again I'd strongly recommend using sub-stepping as mentioned in that comment.

image

Is it possible to creating an extended polygon of the movement by tracing the nodes, then check for objects intersecting this polygon?

jonlepage commented 1 year ago

ho am sad, i study the engine full day and i just realize there a big bug in math of this libs ! actuality most of my entities bypass walls ! and seem not easy solution ! why not add a flag like

Engine.create({
        ccdLevel: 1, //force to apply to limited by ccd
    }
OdinvonDoom commented 1 year ago

The simplest solution if you need fast moving or thin bodies is to sub-step, it's robust and not all that expensive now and you get higher quality results all round.

You can even dynamically increase your substeps for just a few frames when you detect fast moving bodies, if performance was an issue (and you don't mind possibly inconsistent results, like with a dynamic timestep).

Until I've finished adding substeps as a feature into Matter.Runner (it's a bit tricky to handle all possible framerates, plus a few other things for the general case), here is a very simplified example (that assumes fixed 60fps) to demonstrate:

const delta = 1000 / 60;
const subSteps = 3;
const subDelta = delta / subSteps;

(function run() {
    window.requestAnimationFrame(run);
    for (let i = 0; i < subSteps; i += 1) {
      Engine.update(engine, subDelta);
    }
})();

As well as sub-steps also consider:

  • make thin bodies thicker (but can render them thinner similar to this example)
  • apply a max speed limit to bodies (e.g. similar to this example)
  • avoid large timesteps (<= 16.666ms is recommended)
  • ray cast along body velocity and clamp velocity to e.g. 50%

Let me know if that helps - I realise this isn't so obvious unless you're very used to game dev!

Trying to substep like this breaks the outcome by moving the bodies proportional to the number of steps. (If I use 3 substeps I move 3 times as fast.) I think this is maybe because in the body update, I noticed that the time delta doesn't directly influence the velocity, only the acceleration ((body.force.x / body.mass) * deltaTimeSquared), so I tried compensating for this by modifying the "correction" value (which does seem to directly influence the velocity), not used in the sample above, but that just gives me various other problems, like only getting to tiny burst of movement before stopping cold.

Is there a way to use any number of substeps and be sure to see the same position step for one's matter bodies as if no substeps were used at all?

Beknur2002 commented 11 months ago

+1

liabru commented 10 months ago

PR #1254 adds built-in support for sub-stepping (as discussed above) - see the included Example.substep on that branch for an example if you wish to try it out.

liabru commented 3 months ago

As of 0.20.0 Matter.Runner supports sub-stepping fixed timesteps including on high refresh displays see https://github.com/liabru/matter-js/pull/1300.

This can help with reducing bodies passing through each other in many cases. See Example.substep on how to set up Matter.Runner with a small timestep (e.g. 120hz depending on performance needs).