0
0
Fork 0
mirror of https://github.com/liabru/matter-js.git synced 2025-02-07 19:06:26 -05:00

optimised SAT._findSupports

This commit is contained in:
liabru 2021-05-01 15:56:35 +01:00
parent efede6e22d
commit 0d90a17f2d

View file

@ -120,7 +120,7 @@ var Vector = require('../geometry/Vector');
collision.penetration.y = collision.normal.y * collision.depth; collision.penetration.y = collision.normal.y * collision.depth;
// find support points, there is always either exactly one or two // find support points, there is always either exactly one or two
var verticesB = SAT._findSupports(bodyA, bodyB, collision.normal), var verticesB = SAT._findSupports(bodyA, bodyB, collision.normal, 1),
supports = []; supports = [];
// find the supports from bodyB that are inside bodyA // find the supports from bodyB that are inside bodyA
@ -132,8 +132,8 @@ var Vector = require('../geometry/Vector');
// find the supports from bodyA that are inside bodyB // find the supports from bodyA that are inside bodyB
if (supports.length < 2) { if (supports.length < 2) {
var verticesA = SAT._findSupports(bodyB, bodyA, Vector.neg(collision.normal)); var verticesA = SAT._findSupports(bodyB, bodyA, collision.normal, -1);
if (Vertices.contains(bodyB.vertices, verticesA[0])) if (Vertices.contains(bodyB.vertices, verticesA[0]))
supports.push(verticesA[0]); supports.push(verticesA[0]);
@ -183,7 +183,7 @@ var Vector = require('../geometry/Vector');
result.overlap = overlap; result.overlap = overlap;
result.axis = axis; result.axis = axis;
result.axisNumber = i; result.axisNumber = i;
} }
} }
return result; return result;
@ -214,57 +214,54 @@ var Vector = require('../geometry/Vector');
projection.min = min; projection.min = min;
projection.max = max; projection.max = max;
}; };
/** /**
* Finds supporting vertices given two bodies along a given direction using hill-climbing. * Finds supporting vertices given two bodies along a given direction using hill-climbing.
* @method _findSupports * @method _findSupports
* @private * @private
* @param {} bodyA * @param {body} bodyA
* @param {} bodyB * @param {body} bodyB
* @param {} normal * @param {vector} normal
* @param {number} direction
* @return [vector] * @return [vector]
*/ */
SAT._findSupports = function(bodyA, bodyB, normal) { SAT._findSupports = function(bodyA, bodyB, normal, direction) {
var nearestDistance = Number.MAX_VALUE, var vertices = bodyB.vertices,
vertexToBody = Vector._temp[0], verticesLength = vertices.length,
vertices = bodyB.vertices, bodyAPositionX = bodyA.position.x,
bodyAPosition = bodyA.position, bodyAPositionY = bodyA.position.y,
distance, normalX = normal.x * direction,
vertex, normalY = normal.y * direction,
nearestDistance = Infinity,
vertexA, vertexA,
vertexB; vertexB,
vertexC,
distance,
j;
// find closest vertex on bodyB // find deepest vertex relative to the axis
for (var i = 0; i < vertices.length; i++) { for (j = 0; j < verticesLength; j += 1) {
vertex = vertices[i]; vertexB = vertices[j];
vertexToBody.x = vertex.x - bodyAPosition.x; distance = normalX * (bodyAPositionX - vertexB.x) + normalY * (bodyAPositionY - vertexB.y);
vertexToBody.y = vertex.y - bodyAPosition.y;
distance = -Vector.dot(normal, vertexToBody);
// convex hill-climbing
if (distance < nearestDistance) { if (distance < nearestDistance) {
nearestDistance = distance; nearestDistance = distance;
vertexA = vertex; vertexA = vertexB;
} }
} }
// find next closest vertex using the two connected to it // measure next vertex
var prevIndex = vertexA.index - 1 >= 0 ? vertexA.index - 1 : vertices.length - 1; vertexC = vertices[(verticesLength + vertexA.index - 1) % verticesLength];
vertex = vertices[prevIndex]; nearestDistance = normalX * (bodyAPositionX - vertexC.x) + normalY * (bodyAPositionY - vertexC.y);
vertexToBody.x = vertex.x - bodyAPosition.x;
vertexToBody.y = vertex.y - bodyAPosition.y;
nearestDistance = -Vector.dot(normal, vertexToBody);
vertexB = vertex;
var nextIndex = (vertexA.index + 1) % vertices.length; // compare with previous vertex
vertex = vertices[nextIndex]; vertexB = vertices[(vertexA.index + 1) % verticesLength];
vertexToBody.x = vertex.x - bodyAPosition.x; if (normalX * (bodyAPositionX - vertexB.x) + normalY * (bodyAPositionY - vertexB.y) < nearestDistance) {
vertexToBody.y = vertex.y - bodyAPosition.y; return [vertexA, vertexB];
distance = -Vector.dot(normal, vertexToBody);
if (distance < nearestDistance) {
vertexB = vertex;
} }
return [vertexA, vertexB]; return [vertexA, vertexC];
}; };
})(); })();