Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I am currently working on a basic physics engine which does not consider rotations. At the moment I work on collision resolving between aabbs and spheres. Unfortunately I have no idea what a collision between a dynamic aabb and a dynamic sphere looks like. When a sphere hits a falling aabb from a diagonal direction from above will the aabb be pushed to the sides according to the flight direction of the sphere or only accelerated further downwards? Also, when the sphere has a certain force, it will not bounce off the aabb but push it in front of itself. I don't know how to deal with this either.

At the moment I have the sphere-sphere collision implemented, which is described here: http://www.gamasutra.com/view/feature/131424/pool_hall_lessons_fast_accurate_.php?page=3

I guess my solution will be similar, but without caring about the distance between the objects. Also I guess that the collision resolving of aabb-aabb will be the same as sphere-aabb.

Does anybody have an idea or any experience with collision resolving between aabb-sphere and aabb-aabb?

share|improve this question

3 Answers 3

I guess I finally found the answer: I took the same formula as stated in gamasutra but I don't use centerdiff as the collision normal. Instead I take the corresonding normal of the surfaces which collide. For example: Let's assume an aabb1 with velocity [1/1/0] and an aabb2 with velocity [-1/1/0]. Also let's say they will hit each other on their sides. This will lead to the collision normal [1/0/0] or [-1/0/0] respectively for the other aabb.

The corresponding code would be:

if (aabb1Max.y > aabb2Max.y && aabb1->velocity().y < 0) {
   // collision top
   contactNormal.set(0, 1, 0);
} else if (aabb1Min.y < aabb2Min.y && aabb1->velocity().y > 0) {
   // collision bottom
   contactNormal.set(0, -1, 0);
} // etc. for the other dimensions

SLVec3f vel1 = aabb1->velocity();
SLVec3f vel2 = aabb2->velocity();   
SLfloat m1 = aabb1->mass();
SLfloat m2 = aabb2->mass();
SLfloat optimizedP =
    (2.0 * (vel1.dot(contactNormal) - vel2.dot(contactNormal))) / (m1 + m2);
SLVec3f v1_ = vel1 - optimizedP * m2 * contactNormal;
SLVec3f v2_ = vel2 + optimizedP * m1 * contactNormal;

aabb1->velocity(v1_);
aabb2->velocity(v2_);

I haven't found a way to prove that this is correct though.

share|improve this answer

Here is how to resolve a collision between two AABBs (non-continuous). I have commented it carefully so it can be better understood.

    private static bool TestStaticAABBAABB(Shape s1, Shape s2, ref Contact contact)
    {
        AABB a = s1 as AABB;
        AABB b = s2 as AABB;

        // [Minimum Translation Vector]
        float mtvDistance = float.MaxValue;             // Set current minimum distance (max float value so next value is always less)
        Vector3 mtvAxis = new Vector3();                // Axis along which to travel with the minimum distance

        // [Axes of potential separation]
        // • Each shape must be projected on these axes to test for intersection:
        //          
        // (1, 0, 0)                    A0 (= B0) [X Axis]
        // (0, 1, 0)                    A1 (= B1) [Y Axis]
        // (0, 0, 1)                    A1 (= B2) [Z Axis]

        // [X Axis]
        if (!TestAxisStatic(Vector3.UnitX, a.MinPoint.X, a.MaxPoint.X, b.MinPoint.X, b.MaxPoint.X, ref mtvAxis, ref mtvDistance))
        {
            return false;
        }

        // [Y Axis]
        if (!TestAxisStatic(Vector3.UnitY, a.MinPoint.Y, a.MaxPoint.Y, b.MinPoint.Y, b.MaxPoint.Y, ref mtvAxis, ref mtvDistance))
        {
            return false;
        }

        // [Z Axis]
        if (!TestAxisStatic(Vector3.UnitZ, a.MinPoint.Z, a.MaxPoint.Z, b.MinPoint.Z, b.MaxPoint.Z, ref mtvAxis, ref mtvDistance))
        {
            return false;
        }

        contact.isIntersecting = true;

        // Calculate Minimum Translation Vector (MTV) [normal * penetration]
        contact.nEnter = Vector3.Normalize(mtvAxis);

        // Multiply the penetration depth by itself plus a small increment
        // When the penetration is resolved using the MTV, it will no longer intersect
        contact.penetration = (float)Math.Sqrt(mtvDistance) * 1.001f;

        return true;
    }

    private static bool TestAxisStatic(Vector3 axis, float minA, float maxA, float minB, float maxB, ref Vector3 mtvAxis, ref float mtvDistance)
    {
        // [Separating Axis Theorem]
        // • Two convex shapes only overlap if they overlap on all axes of separation
        // • In order to create accurate responses we need to find the collision vector (Minimum Translation Vector)   
        // • Find if the two boxes intersect along a single axis 
        // • Compute the intersection interval for that axis
        // • Keep the smallest intersection/penetration value
        float axisLengthSquared = Vector3.Dot(axis, axis);

        // If the axis is degenerate then ignore
        if (axisLengthSquared < 1.0e-8f)
        {
            return true;
        }

        // Calculate the two possible overlap ranges
        // Either we overlap on the left or the right sides
        float d0 = (maxB - minA);   // 'Left' side
        float d1 = (maxA - minB);   // 'Right' side

        // Intervals do not overlap, so no intersection
        if (d0 <= 0.0f || d1 <= 0.0f)
        {
            return false;
        }

        // Find out if we overlap on the 'right' or 'left' of the object.
        float overlap = (d0 < d1) ? d0 : -d1;

        // The mtd vector for that axis
        Vector3 sep = axis * (overlap / axisLengthSquared);

        // The mtd vector length squared
        float sepLengthSquared = Vector3.Dot(sep, sep);

        // If that vector is smaller than our computed Minimum Translation Distance use that vector as our current MTV distance
        if (sepLengthSquared < mtvDistance)
        {
            mtvDistance = sepLengthSquared;
            mtvAxis = sep;
        }

        return true;
    }

Resolution is then

AABB.Position += contact.normal * contact.penetration;

EDIT:

            float ma = a.InverseMass;
            float mb = b.InverseMass;

            // (1/Ma + 1/Mb)
            float m = ma + mb;

            // Position resolution
            a.Position += contact.nEnter * contact.penetration * (ma / m);
            b.Position += -contact.nEnter * contact.penetration * (mb / m);
share|improve this answer
    
Thank you for you fast response. Do I understand you correctly that after your resolution the two aabbs touch but don't overlap and they do not have any velocity / direction that gets updated, only the position? What I'm hoping to find out is finding the new direction and velocity of the moving objects after they collided. So basically what would happen after your code? –  telandor Jul 23 '12 at 14:43
    
Depends what kind of collision response you require. A sliding response involves a dot product of the velocity along the contact normal. velocity = Vector3.Dot(velocity, contact.normal) Do not forget to negate the contact.normal for the opposite AABB. AABB2.Position += -contact.normal * contact.penetration –  user1423893 Jul 23 '12 at 15:22
    
I'm not sure what a sliding resolve is. When two balls collide, both bounce to different directions. If one has a much bigger force it will push the other one in front of itself. I would like to know the corresponding behaviour for sphere-aabb and aabb-aabb collisions. –  telandor Jul 24 '12 at 6:56
    
Update the position using a velocity. So if the above code detects a collision. Velocity = Vector3.Dot(AABB.Velocity, contact.normal) Then update the position AABB.Position += Velocity * dt 'dt' is the current elasped time for the frame. –  user1423893 Jul 24 '12 at 7:10
    
Thank you, but this does not solve the problem with different masses: Let's assume an aabb1 with velocity [1/1/0] and mass 1 and an aabb2 with velocity [-1/1/0] and mass 10. They both collide at some point. What is the formula to calculate the two resulting velocities? –  telandor Jul 24 '12 at 7:50

AABB-AABB collision is quite simple : for each axis, you have to check if the smallest bound of an AABB is greater than the highest bound of the other one. If so, no collision is possible (i.e., if aabb1.x1 > aabb2.x2, the left side of aabb1 is at the right of the right side of aabb2, so there is no collision). You check :

  • aabb1.x1 > aabb2.x2
  • aabb2.x1 > aabb1.x2
  • aabb1.y1 > aabb2.y2
  • aabb2.y1 > aabb1.y2
  • aabb1.z1 > aabb2.z2
  • aabb2.z1 > aabb1.z2

If any of theses returns true, there is no collision. If all were false, there is a collision.

AABB-sphere collision is different. For each axis, you will search the distance between the center of your sphere and your AABB. For the X axis, per exemple, you first check if aabb.x1 <= center.x <= aabb.x2. If so, your distance is 0. Else, your distance is Min(Abs(aabb.x1 - center.x), Abs(aabb.x2 - center.x)).

Then, if dx, dy and dz are your distances, you just check if dx² + dy² + dz² <= sphereRadius². If so, you have a collision.

share|improve this answer
    
Thank you for your response. I have the collision detection already. Currently I have to deal with what comes after detecting and setting back the objects to the correct collison point. They will probably both bounce away but I don't know to what directions with which speed. –  telandor Jul 24 '12 at 6:58

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.