Search code examples
javarotationcollision-detectionaffinetransform

java collision detection between two rotated rectangles


I am trying to tell if two rectangles are colliding. I have no issue if the rectangles are not rotated, but i am having some issues in my logic when they are both rotated. Here is my method i am currently using :

    public static void car_on_ai_collision( AI ai, Entity e ){

        //rotation of each rectangle in radians
        double ai_rot = ai.getAIEntity().getRotation().y;
        double car_rot = e.getRotation().y;

        //stores the center point of the rectangles
        Vector3f ai_loc = ai.getAIEntity().getLocation();
        Vector3f car_loc = e.getLocation();

        //here i am lining the square for my car up to a axis by making it have no rotation
        ai_rot -= car_rot;
        car_rot = 0;

        //creating rectangles with the size of the car
        Rectangle car = new Rectangle(175, 70);
        Rectangle ai_rec = new Rectangle(175, 70);


        car.translate((int) ((int) car_loc.x-87.5), (int) car_loc.z-35); 

        //rotation for rectangle
        AffineTransform aiAT = new AffineTransform();
        aiAT.translate((int) ai_loc.x - 87.5, (int) ai_loc.z-35);
        aiAT.rotate( Math.toDegrees(ai_rot), ai_loc.x, ai_loc.z);

        Area a = new Area(ai_rec);
        a.transform(aiAT);

        //testing for collision
        if(a.getBounds2D().intersects(car)){
            System.out.println("Collision!");
        }
    }

The collision detection doesn't seem to be anywhere close to being right, from my understanding one of the axis need to be aligned. I am attempting to align one of the axis and then test for a collision with a a AffineTransform but i have seen online something about rotating more then 90 degrees causes a issue. How can i fix this problem to test for a collision between two rotated rectangles? Any help is appreciated.


Solution

  • Collision detection is simple in only two cases:

    • between circles
    • between aligned rectangles

    SmashCode explained how to detect collisions between circles. Aligned rectangles are even easier, you only need to compare does maximal and minimal coordinates of rectangles overlap.

    Sadly yours case is none of above. These rectangles have different coordinate systems and due their rotations edges of one of ractangles may be nether perpendicular nor parallel to axis of second one and they cannot be treated like that.

    One of ways is to use bounding boxes like you did here:

    if(a.getBounds2D().intersects(car)){
        System.out.println("Collision!");
    }
    

    Calling a.getBounds2D() creates rectangle that is aligned to coordinate system and covers whole shape. But bounding box will also cover some space not occupied by shape. So checking for collision between aligned rectangle and bounding box of rotated one is fast and easy but may produce false positives like shown in drawing of rectangles and bounding box of rotated one.

    To fully and accurately check for collision you need to use some more sophisticated methods like SAT that use casting(projecting) of polygons onto different axis. Fact that you are working with only rectangles means that you will only need two axes and you already know their directions.

    PS. Using bounding box isn't wrong, it is easy way to check if two figures are not colliding(if bounding boxes don't collide figures can't collide), you can still use it as faster pre-check to eliminate obvious cases.