简体   繁体   中英

Polygon collision detection implementation

I'm trying to write my own implementation of separating axis theorem but I'm have some trouble getting it to work as accurately as I want. I can't say for sure, but it looks like it's saying there's a collision when an imaginary box around the shapes collide like in the first shape. But the second shape works perfectly.

Here's the vertex data for the square (exact coordinates):

vertsx = [ 200, 220, 220, 200 ]
vertsy = [ 220, 220, 200, 200 ]

Here's the vertex data for test shape 1 (relative to mouse):

vertsx = [ -10,   0,  10, 10, -10 ]
vertsy = [ -10, -50, -10, 10,  10 ]

And lastly here's the vertex data for test shape 2 (relative to mouse):

vertsx = [ -10,   0,  10, 10, -10 ]
vertsy = [ -10, -20, -10, 10,  10 ]

Just for clarification the translated coordinates are the ones that are tested and these have shapes have been tested with the coordinates ordered as shown.

在此处输入图片说明

Here's the actual function.

function collisionConvexPolygon ( vertsax, vertsay, vertsbx, vertsby ) {
    var alen = vertsax.length;
    var blen = vertsbx.length;
    // Loop for axes in Shape A
    for ( var i = 0, j = alen - 1; i < alen; j = i++ ) {
        // Get the axis
        var vx =    vertsax[ j ] - vertsax[ i ];
        var vy = -( vertsay[ j ] - vertsay[ i ] );
        var len = Math.sqrt( vx * vx + vy * vy );

        vx /= len;
        vy /= len;

        // Project shape A
        var max0 = vertsax[ 0 ] * vx + vertsay[ 0 ] * vy, min0 = max0;
        for ( k = 1; k < alen; k++ ) {
            var proja = vertsax[ k ] * vx + vertsay[ k ] * vy;

            if ( proja > max0 ) {
                max0 = proja;
            }
            else if ( proja < min0 ) {
                min0 = proja;
            }
        }
        // Project shape B
        var max1 = vertsbx[ 0 ] * vx + vertsby[ 0 ] * vy, min1 = max1;
        for ( var k = 1; k < blen; k++ ) {
            var projb = vertsbx[ k ] * vx + vertsby[ k ] * vy;

            if ( projb > max1 ) {
                max1 = projb;
            }
            else if ( projb < min1 ) {
                min1 = projb;
            }
        }
        // Test for gaps
        if ( !axisOverlap( min0, max0, min1, max1 ) ) {
            return false;
        }
    }
    // Loop for axes in Shape B (same as above)
    for ( var i = 0, j = blen - 1; i < blen; j = i++ ) {
        var vx =    vertsbx[ j ] - vertsbx[ i ];
        var vy = -( vertsby[ j ] - vertsby[ i ] );
        var len = Math.sqrt( vx * vx + vy * vy );

        vx /= len;
        vy /= len;

        var max0 = vertsax[ 0 ] * vx + vertsay[ 0 ] * vy, min0 = max0;
        for ( k = 1; k < alen; k++ ) {
            var proja = vertsax[ k ] * vx + vertsay[ k ] * vy;

            if ( proja > max0 ) {
                max0 = proja;
            }
            else if ( proja < min0 ) {
                min0 = proja;
            }
        }
        var max1 = vertsbx[ 0 ] * vx + vertsby[ 0 ] * vy, min1 = max1;
        for ( var k = 1; k < blen; k++ ) {
            var projb = vertsbx[ k ] * vx + vertsby[ k ] * vy;

            if ( projb > max1 ) {
                max1 = projb;
            }
            else if ( projb < min1 ) {
                min1 = projb;
            }
        }
        if ( !axisOverlap( min0, max0, min1, max1 ) ) {
            return false;
        }
    }
    return true;
}

I'll try other shapes if you need me to.

Here's my axisOverlap function.

function axisOverlap ( a0, a1, b0, b1 ) {
    return !( a0 > b1 || b0 > a1 );
}

I figured it out!

I began plotting number lines on paper and realized the problem was that my axes weren't calculated correctly. To calculate a perpendicular vector you need to swap the x and y coordinates and THEN invert one, I completely forgot to swap the coordinates.

The new code

var vx =    vertsay[ i ] - vertsay[ j ];
var vy = -( vertsax[ i ] - vertsax[ j ] );

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM