Collision Checks between non-colliding bodies

Topics: Developer Forum, User Forum
Oct 21, 2013 at 12:23 AM
So here's the situation, at this point in time I'm working on, as brutal as it sounds, ragdoll mutilation dynamics. And in my project, projectiles from weapons (physics bodies) are set not to collide with the ragdolls. But, when a projectile, like an arrow from a bow, "collides" with a ragdoll, or passes through it, I want to create a prismatic joint to constrain the two bodies' rotations along with maybe a distance joint to create the illusion that the arrow has become lodged inside of the ragdoll.

And here's the issue, the OnCollision event doesn't seem to be able to hear the collision of those two bodies (I'm assuming because they are in separate collision categories set not to collide with each other). So here's my question; how can one perform a manual collision check between two bodies. I plan to create an extension method so I can just call
public static bool Overlaps (this Body a, Body b)
{
     //if (a overlaps b) 
     //     return true;
     //else 
     //     return false;
}
Thanks in advance for your time.
Oct 21, 2013 at 1:23 AM
Why not start the projectile as a sensor? That way you have the OnCollision event but not the collision response. Then when you've made your joints set it back to a normal body.

Body.IsSensor is the variable.
Oct 21, 2013 at 5:45 AM
Hm. Never thought of it. would it cease to respond to all collisions? Because I would still want the arrow to collide normally with bodies in it's respective collision category.
Also I would prefer to have a Boolean return value because I would then also be able to check if the object is not overlapping the target.
Oct 21, 2013 at 12:37 PM
But, when a projectile, like an arrow from a bow, "collides" with a ragdoll, or passes through it, I want to create a prismatic joint to constrain the two bodies' rotations > along with maybe a distance joint to create the illusion that the arrow has become lodged inside of the ragdoll.
You want the arrow to collide but to not collide? Do you want it to continue after it "fake collides" with the ragdoll? If you wish to stop the arrow and it gets lodged in the ragdoll I don't see the point why they cannot collide in a normal way.
Oct 21, 2013 at 3:29 PM
You want the arrow to collide but to not collide?
well, not precisely. I don't want the two to collide, hence them not being in the same collision category, but I do want them to be able to detect if they are overlapping. Although
I don't see the point why they cannot collide in a normal way.
you may have a point, I could just have them collide normally until they actually touch, then create the joints and disable collision. But my question still stands; is there a way to manually check if two bodies are overlapping? or will I have to create my own function?
Oct 21, 2013 at 8:13 PM
Edited Oct 21, 2013 at 8:15 PM
Ah, I didn't realise you wanted it to collide with other things. In that case I'd have it collide with everything and then in the OnCollision event I'd check to see if it's an object I want to collide with. If it is you can return true in the function and have the collision response. If it's not you can return false and the engine will ignore the contact. Check out the Examples/Test Beds, I think there's an example in the downloads section for one-way collision detection which could be adapted to your needs.

I'm not aware of any function that already exists within the engine. If all you want is the function then I'd pass two bodies into the function and loop through each body's fixtures to do line intersection tests of the vertices. If one of them is true you know they're colliding. But that seems to be just duplicating what the engine is already doing for you (and pretty expensive to boot if you have lots of projectiles/rag dolls!).
Marked as answer by Neegus on 10/21/2013 at 4:27 PM
Oct 21, 2013 at 11:18 PM
Edited Oct 21, 2013 at 11:19 PM
Below is the actual method Hal is referring to although it works a little different than the OnCollision. It is located in the Testbed in Tests/OneSidedPlatform.cs. I think his suggestion of using the OnCollision event to return false when you don't want anything to happen and return true when you want it is a brilliantly simple one. I would go with this solution myself. If you really want an overlap method, you will have to write it I guess. There was a post on the forum about a bullet with a sensor attached to it. In this case the sensor was a bigger circle around the center of the bullet. This way he knew it was about to hit before it actually hit, but I cant seem to find it. You can of course use this to make heat seeking missiles too :D.
protected override void PreSolve(Contact contact, ref Manifold oldManifold)
        {
            base.PreSolve(contact, ref oldManifold);

            Fixture fixtureA = contact.FixtureA;
            Fixture fixtureB = contact.FixtureB;

            if (fixtureA != _platform && fixtureA != _character)
            {
                return;
            }

            if (fixtureB != _platform && fixtureB != _character)
            {
                return;
            }

            Vector2 position = _character.Body.Position;

            if (position.Y < _top + _radius - 3.0f * Settings.LinearSlop)
            {
                contact.Enabled = false;
            }
        }
And here is the OnCollision you are looking for if you put the OnCollision on the arrow.
        private bool OnCollision(Fixture fixtureA, Fixture fixtureB, Contact contact)
        {
            //Cat1 = ragdoll
            if (fixtureB.CollisionCategories == Category.Cat1)
            {
                // Do your lodge arrow logic here
                return false;
            }
            //Cat2 = wall or something
            else if (fixtureB.CollisionCategories == Category.Cat2)
            {
              // Do your other logic here
              return true;
            }
        }
Marked as answer by Neegus on 10/21/2013 at 4:27 PM
Oct 21, 2013 at 11:31 PM
Aha! And that shall do! Thank you so much for your time, it is very much appreciated.