Zonciu / Box2DSharp

A C# port of Box2D
MIT License
544 stars 102 forks source link

Slow moving Body never sleeps, different compared to original Box2D #8

Closed grimaldini closed 4 years ago

grimaldini commented 4 years ago

Hello,

I have this set-up running using Box2DSharp:

            var World = new World(new Vector2(0, -10));
            var groundShape = new ChainShape();
            groundShape.CreateLoop(new[]
            {
                new Vector2(-5, 0),
                new Vector2(5, 0),
                new Vector2(5, 5),
                new Vector2(4, 1),
                new Vector2(-4, 1),
                new Vector2(-5, 5)
            });
            var groundFixtureDef = new FixtureDef
            {
                Density = 0,
                Shape = groundShape
            };
            var groundBodyDef = new BodyDef
            {
                BodyType = BodyType.StaticBody
            };
            var groundBody = World.CreateBody(groundBodyDef);
            groundBody.CreateFixture(groundFixtureDef);

            var ballShape = new CircleShape { Radius = 1 };
            var ballFixtureDef = new FixtureDef
            {
                Density = 1,
                Restitution = 0.75f,
                Shape = ballShape
            };
            var ballBodyDef = new BodyDef
            {
                BodyType = BodyType.DynamicBody,
                Position = new Vector2(0, 10)
            };

            var ball = World.CreateBody(ballBodyDef);
            ball.CreateFixture(ballFixtureDef);
            ball.ApplyForceToCenter(new Vector2(-1000, -400), true);

and this one, an identical one running Box2D:

        b2Vec2 gravity;
        gravity.Set(0.0f, -10.0f);
        m_world = new b2World(gravity);
        b2ChainShape chainShape;
        b2Vec2 vertices[] = {b2Vec2(-5,0), b2Vec2(5,0), b2Vec2(5,5), b2Vec2(4,1), b2Vec2(-4,1), b2Vec2(-5,5)};
        chainShape.CreateLoop(vertices, 6);

        b2FixtureDef groundFixtureDef;
        groundFixtureDef.density = 0;
        groundFixtureDef.shape = &chainShape;

        b2BodyDef groundBodyDef;
        groundBodyDef.type = b2_dynamicBody;

        b2Body *groundBody = m_world->CreateBody(&groundBodyDef);
        b2Fixture *groundBodyFixture = groundBody->CreateFixture(&groundFixtureDef);

        b2CircleShape ballShape;
        ballShape.m_radius = 1;

        b2FixtureDef ballFixtureDef;
        ballFixtureDef.restitution = 0.75f;
        ballFixtureDef.density = 1;
        ballFixtureDef.shape = &ballShape;

        b2BodyDef ballBodyDef;
        ballBodyDef.type = b2BodyType::b2_dynamicBody;
        ballBodyDef.position = b2Vec2(0, 10);

        b2Body *ball = m_world->CreateBody(&ballBodyDef);
        b2Fixture *ballFixture = ball->CreateFixture(&ballFixtureDef);

        ball->ApplyForceToCenter(b2Vec2(-1000, -400), true);

I also made sure that both b2Settings were set the same. As you might notice the original Box2D seems to be quicker at damping the force of the ball, my guess is that this might have something to do with the friction calculation or maybe a rounding issue. In this example, the original Box2D ball stops right away, while on Box2DSharp, the ball keeps on going even after colliding against the ball and then until it collides the other wall, but it takes a really long time for it to move, but makes it there. So the results are very different. Any ideas of what could be causing this?

Zonciu commented 4 years ago

Because you are using the latest version of Box2D. I'm working on upgrade Box2DSharp to the latest commit of Box2D, it should be fine when I finished.

Box2D Version 2.4.0

image

Box2D Version 2.3.2

image

Box2D Sharp

image

grimaldini commented 4 years ago

That's strange, because I ported the recent changes of Box2D to my fork of your repo. Are you sure that your repo is ported up to Box2D's a174dbac1bc32e05e790cd867d9e30fb37681d47 commit?

Zonciu commented 4 years ago

Unless there is some unfound bugs. For floating-poing number, C++ and C# calculations may have errors that add up to inconsistent results.

Zonciu commented 4 years ago

Check dev branch, it is the same now. image

grimaldini commented 4 years ago

Are you sure? I just downloaded dev and tested it and got the same result as before

grimaldini commented 4 years ago

I haven't tested it in the test-bed though (it's not running well for mac), so I wonder if maybe something got changed there since back then. Did you notice anything while porting the test-bed?

Zonciu commented 4 years ago

Try this, the only different is that groundBodyDef.BodyType is BodyType.DynamicBody, not BodyType.StaticBody

 World.Gravity = new Vector2(0, -10);
            var chainShape = new ChainShape();
            chainShape.CreateLoop(
                new[]
                {
                    new Vector2(-5, 0),
                    new Vector2(5, 0),
                    new Vector2(5, 5),
                    new Vector2(4, 1),
                    new Vector2(-4, 1),
                    new Vector2(-5, 5)
                });
            var groundFixtureDef = new FixtureDef
            {
                Density = 0,
                Shape = chainShape
            };
            var groundBodyDef = new BodyDef
            {
                BodyType = BodyType.DynamicBody
            };
            var groundBody = World.CreateBody(groundBodyDef);
            groundBody.CreateFixture(groundFixtureDef);

            var ballShape = new CircleShape {Radius = 1};
            var ballFixtureDef = new FixtureDef
            {
                Density = 1,
                Restitution = 0.75f,
                Shape = ballShape
            };
            var ballBodyDef = new BodyDef
            {
                BodyType = BodyType.DynamicBody,
                Position = new Vector2(0, 10)
            };

            var ball = World.CreateBody(ballBodyDef);
            ball.CreateFixture(ballFixtureDef);
            ball.ApplyForceToCenter(new Vector2(-1000, -400), true);
grimaldini commented 4 years ago

Oh you are right, good catch! I don't know how I didn't notice that I wrote dynamic instead of static in my c++ example above. However, this seems to be a bug with Box2D right? Because I printed out the velocity that the ball had on the last bounce when the ground is static and then the velocity right before it touches the other side and the velocity was greater at the end than at the beginning which means the ball wasn't slowing down but rather picking up speed. Maybe I should file a bug on Box2D...

Zonciu commented 4 years ago

Since Box2D commit 60d36c498bc86afa0cd140d7b9fc37d5df76a39a - 2020-03-09 12:13:35 it changes the behavior about zero density dynamic body, I think that's the key.

If you have installed Unity, you can test this scene in UnityTest, I got the same result

grimaldini commented 4 years ago

Thanks for helping debug this!