🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Updating when a rigid body has two collisions

Started by
2 comments, last by judeclarke 5 years, 7 months ago

For my test case I have a sphere sliding across a horizontal plane that will eventually come in contact with a vertical plane. I have figured out the correct way to deal with a moving sphere to plane for either sliding to resting contact or bouncing off of it. However, it was always with only one rigid body object to one static collision. Now there are two static collision objects. The way the static collisions are added are 1) Vertical plane 2) Horizontal plane. As a result it find the collision with the horizontal plane to slide across it (index 1) but it will find collision with the vertical plane (index 0) once it reaches it. With the logic I have below, it will never consider the collision with the vertical plane. How should I ensure that it will respond to collision with it?

 


    float fAccumulator = 0.0f;

    while(fAccumulator < fElapsedTime && mRigidBodyObjects.size() > 0)
    {
        F32 left_time = fElapsedTime - fAccumulator;

        for(unsigned int i = 0; i < mRigidBodyObjects.size(); ++i)
        {
            int j1 = -1;
            RigidBodyCollisionResult crFirstCollisionResult;
            crFirstCollisionResult.fCollisionTime = FLT_MAX;

            RigidBodyCollisionResult crCollisionResult;

            for(unsigned int j = 0; j < mStaticObjects.size(); ++j)
            {
                crCollisionResult = mRigidBodySolver.Collide(mRigidBodyObjects[i], mStaticObjects[j], left_time);

                if(crCollisionResult.enCollisionState == WILL_COLLIDE)
                {
                    if(crCollisionResult.fCollisionTime <= crFirstCollisionResult.fCollisionTime)
                    {
                        crFirstCollisionResult = crCollisionResult;
                        j1 = j;
                    }
                }
                else if(crCollisionResult.enCollisionState == HAS_COLLISION || crCollisionResult.enCollisionState == RESTING_CONTACT)
                {
                    crFirstCollisionResult = crCollisionResult;
                    j1 = j;
                }
            }

            if(crCollisionResult.enCollisionState == WILL_COLLIDE || crCollisionResult.enCollisionState == NO_COLLISION) {
                mRigidBodyObjects[i]->ApplyGravity();
            }

            if(j1 != -1)
            {
                if(crFirstCollisionResult.enCollisionState == WILL_COLLIDE && crFirstCollisionResult.fCollisionTime <= fElapsedTime)
                {
                    mRigidBodyObjects[i]->Update(crFirstCollisionResult.fCollisionTime);

                    mRigidBodySolver.HandleCollisionReponse(mRigidBodyObjects[i], mStaticObjects[j1], crFirstCollisionResult, crFirstCollisionResult.fCollisionTime);
                    fAccumulator += crFirstCollisionResult.fCollisionTime;
                }
                else if(crFirstCollisionResult.enCollisionState == HAS_COLLISION || crFirstCollisionResult.enCollisionState == RESTING_CONTACT)
                {
                    mRigidBodySolver.HandleCollisionReponse(mRigidBodyObjects[i], mStaticObjects[j1], crFirstCollisionResult, left_time);

                    mRigidBodyObjects[i]->Update(left_time);

                    fAccumulator += left_time;
                }
                else
                {
                    mRigidBodySolver.HandleCollisionReponse(mRigidBodyObjects[i], mStaticObjects[j1], crFirstCollisionResult, left_time);

                    mRigidBodyObjects[i]->Update(left_time);

                    fAccumulator += left_time;
                }
            }
            else
            {
                mRigidBodyObjects[i]->Update(left_time);
                fAccumulator = fElapsedTime;
            }
        }
    }

 

Advertisement

Hi judeclarke,

I am going to describe my understanding of the problem to make sure there is no confusion. On the frame the sphere is sliding along the horizontal frame and about to collide with the vertical plane, this is what happens:

  • i = 0, testing vertical plane returns WILL_COLLIDE.
  • i = 1, testing horizontal plane returns HAS_COLLISION as the sphere is currently touching the plane.

This HAS_COLLISION overwrites the firstCollisionResult stored by the vertical plane, throwing it away.

The issue here is that you still need to test that vertical collision result. After you apply resolution to the first collision (horizontal plane) you need to do it for the next one. After resolving the first, you can no longer be certain that the sphere will hit the vertical plane. The most straightforward approach would be to test for the next collision after each resolution, while ignoring the horizontal plane, and any other static objects that have already been resolved. This way you resolve collision in order of time of impact, and will ensure each pair of objects is resolved eventually.

This could be very expensive if you have a lot of static objects, or if you do this for a lot of rigidbodies. This method is continuous collision resolution, as every collision is resolved in order. To increase performance, you could avoid recomputing the collisions, or use something like speculative contacts and ignore the order of resolution of these collisions.

I don't know of any good resources on completely continuous physics, but here are some links on continuous detection between two objects, and speculative contacts. These speculative contacts are implemented through constraints, so might be a tad confusing, but the ideas there may be useful.

https://www.gdcvault.com/play/1015856/A-Different-Approach-for-Continuous

http://twvideo01.ubm-us.net/o1/vault/gdc2013/slides/824737Catto_Erin_PhysicsForGame.pdf

@ Max Whitehead  Thank you, that helped a lot

This topic is closed to new replies.

Advertisement