From 84d9f591aa381509440fb096ff63dcfd1c9b8dcb Mon Sep 17 00:00:00 2001 From: liabru Date: Tue, 10 Feb 2015 23:40:05 +0000 Subject: [PATCH] improved collision detection for compounds --- src/collision/SAT.js | 36 ++++++++++++++++++++++-------------- src/geometry/Axes.js | 5 +++++ src/geometry/Vertices.js | 13 +++++++------ 3 files changed, 34 insertions(+), 20 deletions(-) diff --git a/src/collision/SAT.js b/src/collision/SAT.js index c660412..f3f9a15 100644 --- a/src/collision/SAT.js +++ b/src/collision/SAT.js @@ -28,8 +28,10 @@ var SAT = {}; if (prevCol) { // estimate total motion - var motion = bodyA.speed * bodyA.speed + bodyA.angularSpeed * bodyA.angularSpeed - + bodyB.speed * bodyB.speed + bodyB.angularSpeed * bodyB.angularSpeed; + var parentA = bodyA.parent, + parentB = bodyB.parent, + motion = parentA.speed * parentA.speed + parentA.angularSpeed * parentA.angularSpeed + + parentB.speed * parentB.speed + parentB.angularSpeed * parentB.angularSpeed; // we may be able to (partially) reuse collision result // but only safe if collision was resting @@ -113,7 +115,7 @@ var SAT = {}; if (Vertices.contains(bodyA.vertices, verticesB[0])) supports.push(verticesB[0]); - if (Vertices.contains(bodyA.vertices, verticesB[1])) + if (verticesB[1] && Vertices.contains(bodyA.vertices, verticesB[1])) supports.push(verticesB[1]); // find the supports from bodyA that are inside bodyB @@ -123,12 +125,12 @@ var SAT = {}; if (Vertices.contains(bodyB.vertices, verticesA[0])) supports.push(verticesA[0]); - if (supports.length < 2 && Vertices.contains(bodyB.vertices, verticesA[1])) + if (verticesA[1] && supports.length < 2 && Vertices.contains(bodyB.vertices, verticesA[1])) supports.push(verticesA[1]); } // account for the edge case of overlapping but no vertex containment - if (supports.length < 2) + if (supports.length < 1) supports = [verticesB[0]]; collision.supports = supports; @@ -220,8 +222,8 @@ var SAT = {}; bodyAPosition = bodyA.position, distance, vertex, - vertexA = vertices[0], - vertexB = vertices[1]; + vertexA, + vertexB; // find closest vertex on bodyB for (var i = 0; i < vertices.length; i++) { @@ -244,15 +246,21 @@ var SAT = {}; nearestDistance = -Vector.dot(normal, vertexToBody); vertexB = vertex; - var nextIndex = (vertexA.index + 1) % vertices.length; - vertex = vertices[nextIndex]; - vertexToBody.x = vertex.x - bodyAPosition.x; - vertexToBody.y = vertex.y - bodyAPosition.y; - distance = -Vector.dot(normal, vertexToBody); - if (distance < nearestDistance) { - vertexB = vertex; + // if the closest vertex is internal, we can't use the next connected vertex + if (!vertexA.isInternal) { + var nextIndex = (vertexA.index + 1) % vertices.length; + vertex = vertices[nextIndex]; + vertexToBody.x = vertex.x - bodyAPosition.x; + vertexToBody.y = vertex.y - bodyAPosition.y; + distance = -Vector.dot(normal, vertexToBody); + if (distance < nearestDistance) { + vertexB = vertex; + } } + if (!vertexB) + return [vertexA]; + return [vertexA, vertexB]; }; diff --git a/src/geometry/Axes.js b/src/geometry/Axes.js index a82fa68..b6e5cb2 100644 --- a/src/geometry/Axes.js +++ b/src/geometry/Axes.js @@ -19,6 +19,11 @@ var Axes = {}; // find the unique axes, using edge normal gradients for (var i = 0; i < vertices.length; i++) { + // skip internal edges + if (vertices[i].isInternal) { + continue; + } + var j = (i + 1) % vertices.length, normal = Vector.normalise({ x: vertices[j].y - vertices[i].y, diff --git a/src/geometry/Vertices.js b/src/geometry/Vertices.js index 0c06a78..331f7ed 100644 --- a/src/geometry/Vertices.js +++ b/src/geometry/Vertices.js @@ -35,12 +35,13 @@ var Vertices = {}; for (var i = 0; i < points.length; i++) { var point = points[i], - vertex = {}; - - vertex.x = point.x; - vertex.y = point.y; - vertex.index = i; - vertex.body = body; + vertex = { + x: point.x, + y: point.y, + index: i, + body: body, + isInternal: false + }; vertices.push(vertex); }