Locking Trigger Area to Camera

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
kokkivos
Posts: 19
Joined: Sat Apr 13, 2013 6:18 pm

Locking Trigger Area to Camera

Post by kokkivos »

Hi there,

I'm trying to implement the collision for a flamethrower-type weapon. Basically, I thought that I could take a Box, lock the position and orientation to the camera, and then look for any enemies in its contact list each frame and damage them. I don't know how to make the box stay in the same place relative to my camera without manually changing the position and orientation, though; and that obviously messes with the collision detecting. Also, when I did that, the box seemed to change its shape in weird ways. What's the best way to do this?

Also, if you have better ideas of how to check the box's contacts, I would appreciate it.

Right now the Update function (which is called from my player's Update) looks like this:

Code: Select all

public void Update(double elapsedmillis, Vector3 position, Quaternion orientation)
        {
            box.Position = position;
            box.Orientation = orientation;

            lastTick += elapsedmillis;
            if (lastTick >= tickRate)
            {
                lastTick = 0;
                foreach (CollidablePairHandler c in box.CollisionInformation.Pairs)
                {
                    Entity e = c.EntityB;
                    if (e != null)
                    {
                        Robot r = e.CollisionInformation.Tag as Robot;
                        if (r != null)
                        {
                            r.Hit();
                        }
                    }
                }
            }
        }
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Locking Trigger Area to Camera

Post by Norbo »

I don't know how to make the box stay in the same place relative to my camera without manually changing the position and orientation, though; and that obviously messes with the collision detecting.
This shouldn't be a problem for a detector object assuming that you don't actually want it to undergo collision response with things it touches. Collision detection has no problem with teleportation, so teleporting detectors is generally perfectly fine.

Teleportation becomes a problem when you want the teleporting object to undergo proper collision response. Since teleportation is not velocity based, the collision response has nothing to work with and collision response feels 'squishy'.
Also, when I did that, the box seemed to change its shape in weird ways.
Right now, that code only iterates over collision pairs, not contacts. Collision pairs are created between any two objects which have overlapping axis aligned bounding boxes. The axis aligned bounding box of a free rotating object will tend to be a little loose; the world axis alignment prevents a universally tight fit. That's why the detection box seemed to expand when looking in diagonal directions.

The actual contact points are contained in a collision pair's Contacts property. Two objects are actually touching if there exists a contact point with a nonnegative penetration depth. So, you need an inner loop like this:

Code: Select all

                foreach (var contactInformation in pair.Contacts)
                {
                    if (contactInformation.Contact.PenetrationDepth >= 0)
                    {
                        //Do the 'objects are touching' logic.
                        
                        //.......

                        //Only do the logic once for the pair.
                        break;
                    }
                }
(The 'nonnegative penetration depth' test is required over a simple 'contact count' test because there exist some contacts which have negative depth. In other words, they represent a temporary separation. Such contacts are called 'speculative contacts' and can help with continuous collision detection and stable contact.)
kokkivos
Posts: 19
Joined: Sat Apr 13, 2013 6:18 pm

Re: Locking Trigger Area to Camera

Post by kokkivos »

Oh, I see... oops. I think my understanding of the definition of a contact was off... I assumed a "contact" would be something intersecting the box. Is this completely wrong? And if so, what is the best way to get all boxes intersecting my weapon's box each frame? Right now my box's personal collision rule is set to NoSolver, and my current logic doesn't seem to be doing what I intended; I'll kinda just sit there with my box intersecting an enemy, and then my weapon will hit it at a random time when I jiggle the box around.

Also, thank you for the extremely swift and informative reply. :)
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Locking Trigger Area to Camera

Post by Norbo »

I assumed a "contact" would be something intersecting the box. Is this completely wrong?
Not completely wrong, no- a contact is a location, normal, and penetration depth representing a single point of collision (or a potential collision, in the case of a speculative contact). If a collision pair has no contacts, then that pair of objects is not touching at all. If a collision pair has at least one contact of nonnegative depth, then the pair of objects is touching. A collision pair can have multiple contacts in it representing a 'contact manifold', or surface of collision.

what is the best way to get all boxes intersecting my weapon's box each frame?
The combination of the code you posted earlier and the modification I posted would do the trick. For example, this function would be handy:

Code: Select all

                bool PairIsColliding(CollidablePairHandler pair)
                {
                    foreach (var contactInformation in pair.Contacts)
                    {
                        if (contactInformation.Contact.PenetrationDepth >= 0)
                        {
                            return true;
                        }
                    }
                    return false;
                }
Then it could be used by the pairs loop like so:

Code: Select all

                foreach (var c in box.CollisionInformation.Pairs)
                {
                    if (PairIsColliding(c))
                    {
                        //Do collision pair logic!
                    }
                }
And finally, identify which collider in the pair is which, which is relevant to:
I'll kinda just sit there with my box intersecting an enemy, and then my weapon will hit it at a random time when I jiggle the box around.
The 'random' effect that you're seeing is probably caused by the assumption that EntityB is always the 'other' entity. There is no general guarantee of ordering. Each time the pair is recreated, the detector could either end up in EntityA or EntityB.

To avoid that problem, first figure out which entity is the box. If c.EntityA == box, then c.EntityB is the 'target' and vice versa. Equivalently, you could test each collider's Tag for being a Robot.
kokkivos
Posts: 19
Joined: Sat Apr 13, 2013 6:18 pm

Re: Locking Trigger Area to Camera

Post by kokkivos »

Ah! It works! Thank you again, Norbo; I appreciate the help.
Post Reply