CureCure / bulletsharp

Automatically exported from code.google.com/p/bulletsharp
0 stars 0 forks source link

Certain Collisions Are Ignored #75

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. Enable normal gravity.  
2. Make the ground, using a massless, static box (10m W x 1m T x 10m D).
3. Make a single row of dynamic rigid body spheres (1m D, 55 kg mass).
, resting on the ground.  The spheres can be touching or not.
4. Constrain the first and second spheres using a fixed constraint with a 
strength of 300 newtons.  Do the same for the second and third spheres.  Do the 
same for the third and fourth spheres.  Do the same for the forth and fifth 
spheres.  So you have a chain of constrained spheres.
2. Apply a force of 4000 newtons to the first sphere in the row and in the 
direction of the other spheres in the row, so that the first sphere will roll 
toward all the other spheres in the row.

What is the expected output? What do you see instead?

The expected output would be a series of broken constraints and collisions, 
resulting in the last sphere in the row rolling away from the row faster than 
the other spheres.

Instead, I see the following:
1 - The fixed constraint between the first and second spheres breaks (good).
2 - BulletSharp ignores the collision between the first sphere and the second 
sphere (bad).  Instead, the first sphere rolls right through the second sphere 
and toward the third sphere.
3 - The fist sphere collides with the third sphere (ok, but second sphere 
should have done that).  
4 - The impulse to the third sphere is strong enough to break the constraint 
between the third sphere and the fourth sphere, so the third sphere starts 
rolling toward the fourth sphere (good).
5 - BulletSharp ignores the collision between the third sphere and the fourth 
sphere (bad).  Instead, the third sphere rolls right through the fourth sphere 
and toward the fifth sphere.

I tried this with disableCollisionsBetweenLinkedBodies = True and False and 
also tried omitting that boolean using the other overload.  I also tried this 
with CCD enabled and disabled.  None of this changes the behavior.

To me, it appears that BulletSharp may be ignoring collisions between rigid 
bodies that were once constrained to each other, regardless of whether the 
constraints were added with disableCollisionsBetweenLinkedBodies and regardless 
of whether CCD is enabled.

I can't rule out the possibility that this is an issue in Bullet Physics, but 
I've done quite a lot of searching and haven't found any discussions about this 
issue.  So I thought it best to raise it with BulletSharp first.

What version of the product are you using? On what operating system?

I downloaded the BulletSharp-master.zip file on September 20, 2014 from the 
following link.  https://github.com/AndresTraks/BulletSharp

Please provide any additional information below.

I can upload sample code that demonstrates this issue if you like.  Any help 
would be much appreciated!

Original issue reported on code.google.com by patr...@shaughness.com on 7 Nov 2014 at 11:00

GoogleCodeExporter commented 9 years ago
I tried to replicate this, but the bodies would always collide after the link 
was broken. So sample code would be good.

You can also try this recent (generic) build: 
https://drive.google.com/folderview?id=0B2TPMwtggT0jYlo4RlhIb3BMdlU#list

Original comment by andres.traks on 8 Nov 2014 at 11:03

GoogleCodeExporter commented 9 years ago
Hi Andres.

Thanks for looking at this.  

I derived a sample app from the SlimDX BasicDemo and attached it to demonstrate 
the behavior.  I pulled all the variables into PhysicsContext.cs, so that it's 
easy to tweak everything from one spot.  It's .net 4.5.1 and 64-bit.

As long as ConstrainTheSpheres = False, the simulation succeeds, regardless of 
whether FrameIndependence_Enabled = True or False and regardless of whether 
CCD_Enabled = True or False.  Success means that all the spheres collide and 
don't overlap.

As long as ConstrainTheSpheres = True, the simulation fails, regardless of 
whether FrameIndependence_Enabled = True or False and regardless of whether 
CCD_Enabled = True or False.  Failure means that only the spheres that were not 
previously constrained to each other collide, and the rest improperly overlap.

Therefore, as far as I can tell, frame independence and CCD both appear to be 
irrelevant to this behavior.  The only factor that I have found that causes the 
overlapping behavior is the creation and breaking of fixed constraints.

I included all my notes on this in the comments, right above the variables in 
PhysicsContext.cs.  Maybe this is caused by some mistake that I've made 
elsewhere in the code, but I can't seem to find it?

Original comment by patr...@shaughness.com on 11 Nov 2014 at 3:30

Attachments:

GoogleCodeExporter commented 9 years ago
This isn't necessary:
Body1.AddConstraintRef(myFixedConstraint);
Body2.AddConstraintRef(myFixedConstraint);
I think it adds double references, so the constraint solver thinks the 
constraint still exists and collision aren't handled.
DynamicsWorld.AddConstraint already adds the constraint refs:
http://bulletphysics.org/Bullet/BulletFull/btDiscreteDynamicsWorld_8cpp_source.h
tml#l00649
Commenting out those two lines seems to fix the issue. :)

Original comment by andres.traks on 11 Nov 2014 at 3:56

GoogleCodeExporter commented 9 years ago
That's interesting.  It makes sense that manually adding constraint refs to the 
rigid bodies could cause duplicate references, but I was adding those 
constraint refs to the rigid bodies manually, because I thought the constraint 
refs were not being added automatically.  This was a workaround a different 
issue (which I had forgotten about), in which RigidBody.NumConstraintRefs 
always returns zero, regardless of how many constraints a RigidBody has.

You can see this issue in action in the sample code that I uploaded if you:
1 - comment-out the two lines that you suggested should be removed and 
2 - paste the following code at the bottom of the ScenarioCollisionIssue's 
constructor (right after the call to AddGround):

//Dump .NumConstraintRefs for each Rigidbody
foreach (CollisionObject ThisCollisionObject in 
myPhysicsContext.myDynamicsWorld.CollisionObjectArray) {
    RigidBody ThisRigidBody = ThisCollisionObject as RigidBody;
        Console.WriteLine(ThisRigidBody.NumConstraintRefs.ToString());  
    }

When you build and run, it creates all the rigid bodies and constrains them, 
and then it iterates all of the rigid bodies and outputs .NumConstraintRefs for 
each.  They are all zero!

When you restore the two lines of code that you suggested be removed and rerun 
the code, it outputs the correct .NumConstraintRefs for each rigid body.  (Not 
saying that my two lines are correct - they're not - just showing you why I put 
them there.)

More generally, when I have a reference to a rigid body, I need a way to 
iterate through all of its constraint refs, so that I can manually remove some 
of them.  Isn't this what .NumConstraintRefs is supposed to provide?  -- a 
count for an iterator?

Original comment by patr...@shaughness.com on 11 Nov 2014 at 7:45

GoogleCodeExporter commented 9 years ago
The refs are only added automatically if disableCollisionsBetweenLinkedBodies = 
True (see the link above) and refs are only used to check if the collisin 
should be ignored:
http://bulletphysics.org/Bullet/BulletFull/btRigidBody_8cpp_source.html#l00320

The constraint refs themselves aren't exposed by the bodies, so you'd have to 
maintain the list of constraints yourself. The refs only include those 
constraints with disableCollisionsBetweenLinkedBodies = true anyway 
(NumConstraintRefs does increase in that case).

I was wrong about the double refs, that doesn't happen, because they check if 
the ref exists:
http://bulletphysics.org/Bullet/BulletFull/btRigidBody_8cpp_source.html#l00339

If BreakingImpulseThreshold is exceeded, then the constraint is disabled, but 
it's not removed from the world and the refs aren't removed either. However, 
even if the refs exist, then the collision should occur, because there is the 
additional condition "if (c->isEnabled())" in 
btRigidBody::checkCollideWithOverride. So if the constraint is disabled, the 
collision should be handled even with the refs existing. But it's not handled, 
so there is something else wrong here.

Theoretically, for the fixed constraint, it shouldn't make any difference if 
disableCollisionsBetweenLinkedBodies is set or not, because the bodies don't 
interact anyway if this particular type of constraint is enabled. And if the 
constraint is disabled, then btRigidBody::checkCollideWithOverride should 
detect it and allow collisions.

I don't know what the problem is there, but I hope the explanation made some 
sense. Particularly, the constraint refs don't have to exist if the constraint 
exists. At least it works as intended (not doing AddConstraintRef manually).

Bullet classes sometimes expose members that aren't needed by users, but are 
required internally to exchange information. I think NumConstraintRefs is one 
of those.

Original comment by andres.traks on 12 Nov 2014 at 12:25

GoogleCodeExporter commented 9 years ago

Original comment by andres.traks on 16 Nov 2014 at 7:59

GoogleCodeExporter commented 9 years ago
Yes, your explanation was a big help.  I stopped trying to get my references to 
constraints via the rigid bodies and instead, I started managing the constraint 
references myself.  That way I was able to create and destroy constraints 
programmatically, which lead to the collisions occurring as they should.  
Thanks Andres!

Original comment by patr...@shaughness.com on 17 Nov 2014 at 1:50