Skip to content

Instantly share code, notes, and snippets.

@louisstow
Created February 2, 2011 04:46
Show Gist options
  • Save louisstow/807250 to your computer and use it in GitHub Desktop.
Save louisstow/807250 to your computer and use it in GitHub Desktop.
SAT collision detection in JS
SAT: function(poly1, poly2) {
var points1 = poly1.points,
points2 = poly2.points,
i = 0, l = points1.length,
j, k = points2.length,
normal = {x: 0, y: 0},
length,
min1, min2,
max1, max2,
interval,
MTV,
dot,
nextPoint,
currentPoint;
//loop through the edges of Polygon 1
for(;i<l;i++) {
nextPoint = points1[(i==l-1 ? 0 : i+1)];
currentPoint = points1[i];
//generate the normal for the current edge
normal.x = -(nextPoint[1] - currentPoint[1]);
normal.y = (nextPoint[0] - currentPoint[0]);
//normalize the vector
length = Math.sqrt(normal.x * normal.x + normal.y * normal.y);
normal.x /= length;
normal.y /= length;
//default min max
min1 = min2 = -1;
max1 = max2 = -1;
//project all vertices from poly1 onto axis
for(j = 0; j < l; ++j) {
dot = points1[j][0] * normal.x + points1[j][1] * normal.y;
if(dot > max1 || max1 === -1) max1 = dot;
if(dot < min1 || min1 === -1) min1 = dot;
}
//project all vertices from poly2 onto axis
for(j = 0; j < k; ++j) {
dot = points2[j][0] * normal.x + points2[j][1] * normal.y;
if(dot > max2 || max2 === -1) max2 = dot;
if(dot < min2 || min2 === -1) min2 = dot;
}
//calculate the minimum translation vector should be negative
interval = (min1 < min2) ? min2 - max1 : min1 - max2;
//exit early if positive
if(interval > 0) {
return false;
}
if(interval > MTV) MTV = interval;
}
//loop through the edges of Polygon 1
for(i=0;i<k;i++) {
nextPoint = points2[(i==k-1 ? 0 : i+1)];
currentPoint = points2[i];
//generate the normal for the current edge
normal.x = -(nextPoint[1] - currentPoint[1]);
normal.y = (nextPoint[0] - currentPoint[0]);
//normalize the vector
length = Math.sqrt(normal.x * normal.x + normal.y * normal.y);
normal.x /= length;
normal.y /= length;
//default min max
min1 = min2 = -1;
max1 = max2 = -1;
//project all vertices from poly1 onto axis
for(j = 0; j < l; ++j) {
dot = points1[j][0] * normal.x + points1[j][1] * normal.y;
if(dot > max1 || max1 === -1) max1 = dot;
if(dot < min1 || min1 === -1) min1 = dot;
}
//project all vertices from poly2 onto axis
for(j = 0; j < k; ++j) {
dot = points2[j][0] * normal.x + points2[j][1] * normal.y;
if(dot > max2 || max2 === -1) max2 = dot;
if(dot < min2 || min2 === -1) min2 = dot;
}
//calculate the minimum translation vector should be negative
interval = (min1 < min2) ? min2 - max1 : min1 - max2;
//exit early if positive
if(interval > 0) {
return false;
}
if(interval > MTV) MTV = interval;
}
return {overlap: MTV};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment