ByteArena / box2d

Box2D.go - Go port of Box2D - a 2D Physics Engine for Games.
Other
295 stars 48 forks source link

Large circle vs small circle #15

Closed TrashCoder96 closed 6 years ago

TrashCoder96 commented 6 years ago

I have two dynamic circle bodies. One is small and the other is large. When the small circle collides with the large circle, box2d contact occurs early then the figures touch each other. I'll attach a visualization of this situation. image

TrashCoder96 commented 6 years ago

It seems that something like the AABB zone of large circle hinders full collision. Help me to understand this situation. Maybe it's a bug or something like this.

maxfish commented 6 years ago

Hi @TrashCoder96, could you please provide a bit more information about your setup?

TrashCoder96 commented 6 years ago

Hi, @maxfish

I wrote this Box2d colllision callback (BeginContact function of B2ContactListenerInterface):

func (r *Room) BeginContact(contact box2d.B2ContactInterface) {
    contact.GetFixtureA().GetBody().Dump(); 
    contact.GetFixtureB().GetBody().Dump();
}

And result of dumping:

API server listening at: 127.0.0.1:22954
Count of CPU = 8
Room runned!
{
  b2BodyDef bd;
  bd.type = b2BodyType(2);
27 <nil>  bd.position.Set(%!l(float64=1000)ef, %!l(float64=1000)ef);
61 <nil>  bd.angle = %!l(float64=0)ef;
31 <nil>  bd.linearVelocity.Set(%!l(float64=0)ef, %!l(float64=0)ef);
61 <nil>  bd.angularVelocity = %!l(float64=0)ef;
41 <nil>  bd.linearDamping = %!l(float64=0)ef;
39 <nil>  bd.angularDamping = %!l(float64=0)ef;
40 <nil>  bd.allowSleep = bool(4);
27 <nil>  bd.awake = bool(2);
22 <nil>  bd.fixedRotation = bool(0);
30 <nil>  bd.bullet = bool(0);
23 <nil>  bd.active = bool(32);
24 <nil>  bd.gravityScale = %!l(float64=1)ef;
38 <nil>  bodies[0] = body.M_world.CreateBody(&bd);
44 <nil>
  {
    b2FixtureDef fd;
21 <nil>    fd.friction = %!l(float64=0.2)ef;
38 <nil>    fd.restitution = %!l(float64=0)ef;
39 <nil>    fd.density = %!l(float64=10000000)ef;
42 <nil>    fd.isSensor = bool(%!d(bool=false));
41 <nil>    fd.filter.categoryBits = uint16(0);
40 <nil>    fd.filter.maskBits = uint16(0);
36 <nil>    fd.filter.groupIndex = int16(0);
37 <nil>    b2CircleShape shape;
25 <nil>    shape.m_radius = %!l(float64=50)ef;
40 <nil>    shape.m_p.Set(%!l(float64=0)ef, %!l(float64=0)ef);
55 <nil>
    fd.shape = &shape;

    bodies[0].CreateFixture(&fd);
34 <nil>  }
}
{
  b2BodyDef bd;
  bd.type = b2BodyType(2);
27 <nil>  bd.position.Set(%!l(float64=965.009486955702)ef, %!l(float64=1065.20478507665)ef);
85 <nil>  bd.angle = %!l(float64=0)ef;
31 <nil>  bd.linearVelocity.Set(%!l(float64=0.0472844770869083)ef, %!l(float64=-0.0881145744279438)ef);
96 <nil>  bd.angularVelocity = %!l(float64=0)ef;
41 <nil>  bd.linearDamping = %!l(float64=0)ef;
39 <nil>  bd.angularDamping = %!l(float64=0)ef;
40 <nil>  bd.allowSleep = bool(4);
27 <nil>  bd.awake = bool(2);
22 <nil>  bd.fixedRotation = bool(0);
30 <nil>  bd.bullet = bool(0);
23 <nil>  bd.active = bool(32);
24 <nil>  bd.gravityScale = %!l(float64=1)ef;
38 <nil>  bodies[0] = body.M_world.CreateBody(&bd);
44 <nil>
  {
    b2FixtureDef fd;
21 <nil>    fd.friction = %!l(float64=0.2)ef;
38 <nil>    fd.restitution = %!l(float64=0)ef;
39 <nil>    fd.density = %!l(float64=0.001)ef;
39 <nil>    fd.isSensor = bool(%!d(bool=false));
41 <nil>    fd.filter.categoryBits = uint16(0);
40 <nil>    fd.filter.maskBits = uint16(0);
36 <nil>    fd.filter.groupIndex = int16(0);
37 <nil>    b2CircleShape shape;
25 <nil>    shape.m_radius = %!l(float64=12.5)ef;
42 <nil>    shape.m_p.Set(%!l(float64=0)ef, %!l(float64=0)ef);
55 <nil>
    fd.shape = &shape;

    bodies[0].CreateFixture(&fd);
34 <nil>  }
}

Small body has radius 50 / 4:

func (p *Player) init(height float64, width float64, room *Room) {
    room.lastId++
    p.id = room.lastId
    p.room = room
    bodyDef := box2d.MakeB2BodyDef()
    p.bodyDef = &bodyDef
    //p.bodyDef.Position.Set(p.x, p.y)
    p.bodyDef.Type = box2d.B2BodyType.B2_dynamicBody
    p.body = p.room.world.CreateBody(p.bodyDef)
    p.body.SetTransform(box2d.MakeB2Vec2(p.x, p.y), 0)
    p.body.SetUserData(p.id)
    shape := box2d.MakeB2CircleShape()
    p.shape = &shape
    p.shape.SetRadius(50.0 / 4)
    p.body.CreateFixture(p.shape, 0.001)
    //p.body.SetLinearDamping(0.00007)
    p.deleteFlag = false
    p.viewHeight = 500
    p.viewWidth = 500
    p.health = 100
}

Large object has raduis 50 (b.radius variable):

func (b *BlackHole) init(room *Room) {
    room.lastId++
    b.id = room.lastId
    b.room = room
    bodyDef := box2d.MakeB2BodyDef()
    b.bodyDef = &bodyDef
    b.bodyDef.Type = box2d.B2BodyType.B2_dynamicBody
    b.body = b.room.world.CreateBody(b.bodyDef)
    b.body.SetTransform(box2d.MakeB2Vec2(b.x, b.y), 0)
    shape := box2d.MakeB2CircleShape()
    b.shape = &shape
    b.shape.SetRadius(b.radius)
    b.body.CreateFixture(b.shape, 10000000)
    b.deleteFlag = false
}

But circle bodies dont collide with each other. Also i'll attach sreenshot:

image

If you need more information, i will provide it.

maxfish commented 6 years ago

Before I try to debug your scene, could you please try scaling the two circles? As you can read in the Box2D manual section 1.7: "Box2D has been tuned to work well with moving shapes between 0.1 and 10 meters." In your case you have a shape that is 50 meters in box2d coordinate system.

Radii like 8 and 2 should give you the same proportion while allowing box2d to function better. You can always change the graphic scale to get back the current result.

TrashCoder96 commented 6 years ago

Last dumping with circles with 1.25 and 5 radiuses

API server listening at: 127.0.0.1:62303
Count of CPU = 8
Room runned!
{
  b2BodyDef bd;
  bd.type = b2BodyType(2);
27 <nil>  bd.position.Set(%!l(float64=96.5122651701542)ef, %!l(float64=106.499390268916)ef);
85 <nil>  bd.angle = %!l(float64=0)ef;
31 <nil>  bd.linearVelocity.Set(%!l(float64=0)ef, %!l(float64=0)ef);
61 <nil>  bd.angularVelocity = %!l(float64=0)ef;
41 <nil>  bd.linearDamping = %!l(float64=0)ef;
39 <nil>  bd.angularDamping = %!l(float64=0)ef;
40 <nil>  bd.allowSleep = bool(4);
27 <nil>  bd.awake = bool(2);
22 <nil>  bd.fixedRotation = bool(0);
30 <nil>  bd.bullet = bool(0);
23 <nil>  bd.active = bool(32);
24 <nil>  bd.gravityScale = %!l(float64=1)ef;
38 <nil>  bodies[0] = body.M_world.CreateBody(&bd);
44 <nil>
  {
    b2FixtureDef fd;
21 <nil>    fd.friction = %!l(float64=0.2)ef;
38 <nil>    fd.restitution = %!l(float64=0)ef;
39 <nil>    fd.density = %!l(float64=60)ef;
36 <nil>    fd.isSensor = bool(%!d(bool=false));
41 <nil>    fd.filter.categoryBits = uint16(0);
40 <nil>    fd.filter.maskBits = uint16(0);
36 <nil>    fd.filter.groupIndex = int16(0);
37 <nil>    b2CircleShape shape;
25 <nil>    shape.m_radius = %!l(float64=1.25)ef;
42 <nil>    shape.m_p.Set(%!l(float64=0)ef, %!l(float64=0)ef);
55 <nil>
    fd.shape = &shape;

    bodies[0].CreateFixture(&fd);
34 <nil>  }
}
{
  b2BodyDef bd;
  bd.type = b2BodyType(2);
27 <nil>  bd.position.Set(%!l(float64=100)ef, %!l(float64=100)ef);
59 <nil>  bd.angle = %!l(float64=0)ef;
31 <nil>  bd.linearVelocity.Set(%!l(float64=0)ef, %!l(float64=0)ef);
61 <nil>  bd.angularVelocity = %!l(float64=0)ef;
41 <nil>  bd.linearDamping = %!l(float64=0)ef;
39 <nil>  bd.angularDamping = %!l(float64=0)ef;
40 <nil>  bd.allowSleep = bool(4);
27 <nil>  bd.awake = bool(2);
22 <nil>  bd.fixedRotation = bool(0);
30 <nil>  bd.bullet = bool(0);
23 <nil>  bd.active = bool(32);
24 <nil>  bd.gravityScale = %!l(float64=1)ef;
38 <nil>  bodies[0] = body.M_world.CreateBody(&bd);
44 <nil>
  {
    b2FixtureDef fd;
21 <nil>    fd.friction = %!l(float64=0.2)ef;
38 <nil>    fd.restitution = %!l(float64=0)ef;
39 <nil>    fd.density = %!l(float64=10000000)ef;
42 <nil>    fd.isSensor = bool(%!d(bool=false));
41 <nil>    fd.filter.categoryBits = uint16(0);
40 <nil>    fd.filter.maskBits = uint16(0);
36 <nil>    fd.filter.groupIndex = int16(0);
37 <nil>    b2CircleShape shape;
25 <nil>    shape.m_radius = %!l(float64=5)ef;
39 <nil>    shape.m_p.Set(%!l(float64=0)ef, %!l(float64=0)ef);
55 <nil>
    fd.shape = &shape;

    bodies[0].CreateFixture(&fd);
34 <nil>  }
}

Unfortunately, scaling does not work in my application. image

maxfish commented 6 years ago

I think I'm able to reproduce the issue. It looks like as soon as the radius goes above a certain size, physics start misbehaving. I'll try to find out the cause later today.

TrashCoder96 commented 6 years ago

Also, when i set same radiuses, physics works fine

maxfish commented 6 years ago

Hey @TrashCoder96 , I just sent out #16 that should fix your problem. Let me know!

TrashCoder96 commented 6 years ago

@maxfish this PR fixed the problem! Many thanks to you and your team) The most interesting, when I looked the source code for this section of code, i dont notice same GetFixtureA()