Пример #1
0
    protected override bool TestCollisionVsOBB(OBB_2D other, out Collision collision)
    {
        collision = null;
        // same as aabb
        // multiply circle center by box world matrix inverse
        //other.transform.worldToLocalMatrix
        Matrix4x4 otherMat = other.transform.worldToLocalMatrix;
        Vector2   minExtents = other.particle.position - other.halfWidths, maxExtents = other.particle.position + other.halfWidths;
        Vector2   adjustedCenter = otherMat.MultiplyPoint3x4(new Vector3(particle.position.x, particle.position.y, 0));

        adjustedCenter.x *= other.transform.localScale.x;
        adjustedCenter.y *= other.transform.localScale.y;
        adjustedCenter   += (Vector2)other.transform.position;
        //adjustedCenter += particle.position;

        Vector2 closestPoint;

        closestPoint.x = Mathf.Clamp(adjustedCenter.x, minExtents.x, maxExtents.x);
        closestPoint.y = Mathf.Clamp(adjustedCenter.y, minExtents.y, maxExtents.y);

        Vector2 deltaPos = adjustedCenter - closestPoint;

        bool colliding = deltaPos.sqrMagnitude < radius * radius;

        if (colliding)
        {
            collision = new Collision();
            Vector2 relativeVelocity = particle.velocity - other.particle.velocity;
            Vector2 relativePosition = particle.position - other.particle.position;
            // 7.1.1 closing velocity
            collision.closingVelocity = Vector3.Dot(relativeVelocity, relativePosition.normalized);
            // assuming one point of contact
            collision.contact[0].normal           = deltaPos.normalized;
            collision.contact[0].point            = closestPoint;
            collision.contact[0].restitution      = .5f;
            collision.contact[0].penetrationDepth = radius - deltaPos.magnitude;
            collision.a            = this;
            collision.b            = other;
            collision.status       = colliding;
            collision.contactCount = 1;
        }

        return(colliding);
    }
Пример #2
0
    protected override bool TestCollisionVsOBB(OBB_2D other, out Collision collision)
    {
        collision = null;
        // Code from Michael Zheng and Ben Strong, using with permission


        // same as above twice
        // find max extents of OBB, do ABB vs this box
        // then, transform this box into OBB's space, find max extents, repeat

        //1. create max and min extents of this particle
        //2. max = (center.x + length/2, center.y + height/2)
        //3. min = (center.x - length/2, center.y - height/2)
        //4. create max and min extents of other particle
        //4a. find all corner points of the box using length, height
        //4b. rotate all points around its rotation https://www.gamefromscratch.com/post/2012/11/24/GameDev-math-recipes-Rotating-one-point-around-another-point.aspx
        //4c. min = (min(x of all points), min(y of all points)) https://stackoverflow.com/questions/3231176/how-to-get-size-of-a-rotated-rectangle
        //4d. max = (max(x of all points), max(y of all points)
        //5. check if this_max.x > other_min.x and this_max.y > other_min.y
        //6. check if other_max.x > this_min.x and other_max.y > this_min.y
        //7. transform this center around the other's center using its transform matrix inverse
        //8. transform each point of the aab by the other's transform matrix inverse
        //8. find max and min extents of this by using Max(all points), Min(all points)
        //5. check if new this_max.x > other_min.x and new this_max.y > other_min.y
        //6. check if other_max.x > new this_min.x and other_max.y > new this_min.y
        //9. if all checks are true, then collision check passes

        bool    check1, check2;
        Vector2 thisMax, thisMin, otherMax, otherMin;
        Vector2 p1, p2, p3, p4;

        Vector2 otherPosition = other.particle.position;
        float   thisLength    = halfWidths[0];
        float   thisHeight    = halfWidths[1];
        float   otherLength   = other.halfWidths[0];
        float   otherHeight   = other.halfWidths[1];

        //max and min of this position
        thisMax = new Vector2(particle.position.x + thisLength, particle.position.y + thisHeight);
        thisMin = new Vector2(particle.position.x - thisLength, particle.position.y - thisHeight);

        //find max and min of other
        //get all corner points and then rotate it
        //p1 = rotatePoint(new Vector2(otherLength, otherHeight), other.rotation);
        //p2 = rotatePoint(new Vector2(otherLength, -otherHeight), other.rotation);
        //p3 = rotatePoint(new Vector2(-otherLength, -otherHeight), other.rotation);
        //p4 = rotatePoint(new Vector2(-otherLength, otherHeight), other.rotation);
        p1 = other.transform.worldToLocalMatrix * (new Vector2(otherLength, otherHeight));
        p2 = other.transform.worldToLocalMatrix * (new Vector2(otherLength, -otherHeight));
        p3 = other.transform.worldToLocalMatrix * (new Vector2(-otherLength, -otherHeight));
        p4 = other.transform.worldToLocalMatrix * (new Vector2(-otherLength, otherHeight));
        //find max of all points
        otherMax = new Vector2(Mathf.Max(p1.x, p2.x, p3.x, p4.x) + otherPosition.x, Mathf.Max(p1.y, p2.y, p3.y, p4.y) + otherPosition.y);
        otherMin = new Vector2(Mathf.Min(p1.x, p2.x, p3.x, p4.x) + otherPosition.x, Mathf.Min(p1.y, p2.y, p3.y, p4.y) + otherPosition.y);

        check1 = (thisMax.x >= otherMin.x && thisMax.y >= otherMin.y) && (otherMax.x >= thisMin.x && otherMax.y >= thisMin.y);

        if (!check1)
        {
            return(false);
        }

        //for each corner, move it relative to the box then transform by the world matrix inverse. Finally add position back
        p1  = other.transform.worldToLocalMatrix * (new Vector2(particle.position.x + thisLength, particle.position.y + thisHeight) - otherPosition); //this one
        p2  = other.transform.worldToLocalMatrix * (new Vector2(particle.position.x + thisLength, particle.position.y - thisHeight) - otherPosition);
        p3  = other.transform.worldToLocalMatrix * (new Vector2(particle.position.x - thisLength, particle.position.y - thisHeight) - otherPosition);
        p4  = other.transform.worldToLocalMatrix * (new Vector2(particle.position.x - thisLength, particle.position.y + thisHeight) - otherPosition);
        p1 += otherPosition;
        p2 += otherPosition;
        p3 += otherPosition;
        p4 += otherPosition;

        //get the extremes for min and max
        thisMax = new Vector2(Mathf.Max(p1.x, p2.x, p3.x, p4.x), Mathf.Max(p1.y, p2.y, p3.y, p4.y));
        thisMin = new Vector2(Mathf.Min(p1.x, p2.x, p3.x, p4.x), Mathf.Min(p1.y, p2.y, p3.y, p4.y));

        otherMax = new Vector2(otherPosition.x + otherLength, otherPosition.y + otherHeight);
        otherMin = new Vector2(otherPosition.x - otherLength, otherPosition.y - otherHeight);

        check2 = (thisMax.x >= otherMin.x && thisMax.y >= otherMin.y) && (otherMax.x >= thisMin.x && otherMax.y >= thisMin.y);

        if (!check2)
        {
            return(false);
        }

        return(true);
    }
Пример #3
0
    protected override bool TestCollisionVsOBB(OBB_2D other, out Collision collision)
    {
        collision = null;


        // Code from Michael Zheng and Ben Strong, using with permission

        //Transform this into others space and do AABB vs OBB
        //transform other into this space and do AABB vs OBB
        //If both tests pass, collision occurs otherwise no collision

        //1. do AABB check with this rotated around other
        //2. find all corner points of this box using length and height
        //3. rotate the points of this box with its rotation
        //4. transform the points using the transform inverse of the other
        //5. min = (min(x of all points), min(y of all points))
        //6. max = (max(x of all points), max(y of all points)
        //7. create max and min extents of other particle
        //8. max = (center.x + length/2, center.y + height/2)
        //9. min = (center.x - length/2, center.y - height/2)
        //10. check if this_max.x > other_min.x and this_max.y > other_min.y
        //11. check if other_max.x > this_min.x and other_max.y > this_min.y
        //12. do AABB check with other rotated around this
        //13. find all corner points of other box using length and height
        //14. rotate the points of other box with its rotation
        //15. transform the points using the transform inverse of this
        //16. min = (min(x of all points), min(y of all points))
        //17. max = (max(x of all points), max(y of all points)
        //18. create max and min extents of this particle
        //19. max = (center.x + length/2, center.y + height/2)
        //20. min = (center.x - length/2, center.y - height/2)
        //21. check if this_max.x > other_min.x and this_max.y > other_min.y
        //22. check if other_max.x > this_min.x and other_max.y > this_min.y

        bool    check1, check2;
        Vector2 thisMax, thisMin, otherMax, otherMin;
        Vector2 p1, p2, p3, p4;

        Vector2 otherPosition = other.particle.position;
        float   thisLength    = halfWidths[0];
        float   thisHeight    = halfWidths[1];
        float   otherLength   = other.halfWidths[0];
        float   otherHeight   = other.halfWidths[1];

        //get all corner points and then rotate it

        p1 = transform.worldToLocalMatrix * (new Vector2(thisLength, thisHeight));
        p2 = transform.worldToLocalMatrix * (new Vector2(thisLength, -thisHeight));
        p3 = transform.worldToLocalMatrix * (new Vector2(-thisLength, -thisHeight));
        p4 = transform.worldToLocalMatrix * (new Vector2(-thisLength, thisHeight));
        //for each corner, move it relative to the box then transform by the world matrix inverse. Finally add position back
        p1 = other.transform.worldToLocalMatrix * (p1 + particle.position - otherPosition);
        p2 = other.transform.worldToLocalMatrix * (p2 + particle.position - otherPosition);
        p3 = other.transform.worldToLocalMatrix * (p3 + particle.position - otherPosition);
        p4 = other.transform.worldToLocalMatrix * (p4 + particle.position - otherPosition);

        p1 += otherPosition;
        p2 += otherPosition;
        p3 += otherPosition;
        p4 += otherPosition;

        thisMax = new Vector2(Mathf.Max(p1.x, p2.x, p3.x, p4.x), Mathf.Max(p1.y, p2.y, p3.y, p4.y));
        thisMin = new Vector2(Mathf.Min(p1.x, p2.x, p3.x, p4.x), Mathf.Min(p1.y, p2.y, p3.y, p4.y));

        otherMax = new Vector2(otherPosition.x + otherLength, otherPosition.y + otherHeight);
        otherMin = new Vector2(otherPosition.x - otherLength, otherPosition.y - otherHeight);

        check1 = (thisMax.x >= otherMin.x && thisMax.y >= otherMin.y) && (otherMax.x >= thisMin.x && otherMax.y >= thisMin.y);

        if (!check1)
        {
            return(false);
        }

        //get all corner points and then rotate it
        p1 = other.transform.worldToLocalMatrix * (new Vector2(otherLength, otherHeight));
        p2 = other.transform.worldToLocalMatrix * (new Vector2(otherLength, -otherHeight));
        p3 = other.transform.worldToLocalMatrix * (new Vector2(-otherLength, -otherHeight));
        p4 = other.transform.worldToLocalMatrix * (new Vector2(-otherLength, otherHeight));
        //for each corner, move it relative to the box then transform by the world matrix inverse. Finally add position back
        p1 = transform.worldToLocalMatrix * (p1 + otherPosition - particle.position); //this
        p2 = transform.worldToLocalMatrix * (p2 + otherPosition - particle.position);
        p3 = transform.worldToLocalMatrix * (p3 + otherPosition - particle.position);
        p4 = transform.worldToLocalMatrix * (p4 + otherPosition - particle.position);

        p1 += particle.position;
        p2 += particle.position;
        p3 += particle.position;
        p4 += particle.position;

        otherMax = new Vector2(Mathf.Max(p1.x, p2.x, p3.x, p4.x), Mathf.Max(p1.y, p2.y, p3.y, p4.y));
        otherMin = new Vector2(Mathf.Min(p1.x, p2.x, p3.x, p4.x), Mathf.Min(p1.y, p2.y, p3.y, p4.y));

        thisMax = new Vector2(particle.position.x + thisLength, particle.position.y + thisHeight);
        thisMin = new Vector2(particle.position.x - thisLength, particle.position.y - thisHeight);

        check2 = (thisMax.x >= otherMin.x && thisMax.y >= otherMin.y) && (otherMax.x >= thisMin.x && otherMax.y >= thisMin.y);

        if (!check2)
        {
            return(false);
        }

        return(true);
    }
Пример #4
0
 protected abstract bool TestCollisionVsOBB(OBB_2D other, out Collision collision);