*/
@Override
public int collide(Contact[] contacts, PhysicsAgent2D<?> bodyA, PhysicsAgent2D<?> bodyB) {
int numContacts = 0;
Line line = (Line) bodyA.getBodyShape();
Box box = (Box) bodyB.getBodyShape();
Vector2f lineVec = new Vector2f(line.getDX(), line.getDY());
lineVec.normalise();
Vector2f axis = new Vector2f(-line.getDY(), line.getDX());
axis.normalise();
Vector2f res = new Vector2f();
line.getStart().projectOntoUnit(axis, res);
float linePos = getProp(res,axis);
Vector2f c = MathUtil.sub(bodyB.getPosition(),bodyA.getPosition());
c.projectOntoUnit(axis,res);
float centre = getProp(res, axis);
Vector2f[] pts = box.getPoints(bodyB.getPosition(), bodyB.getRotation());
float[] tangent = new float[4];
float[] proj = new float[4];
int outOfRange = 0;
for (int i=0;i<4;i++) {
pts[i].sub(bodyA.getPosition());
pts[i].projectOntoUnit(axis, res);
tangent[i] = getProp(res, axis);
pts[i].projectOntoUnit(lineVec, res);
proj[i] = getProp(res, new Vector2f(line.getDX(), line.getDY()));
if ((proj[i] >= 1) || (proj[i] <= 0)) {
outOfRange++;
}
}
if (outOfRange == 4) {
return 0;
}
Vector2f normal = new Vector2f(axis);
if (centre < linePos) {
if (!line.blocksInnerEdge()) {
return 0;
}
normal.scale(-1);
for (int i=0;i<4;i++) {
if (tangent[i] > linePos) {
if (proj[i] < 0) {
Vector2f onAxis = new Vector2f();
Line leftLine = new Line(getPt(pts,i-1),pts[i]);
Line rightLine = new Line(getPt(pts,i+1),pts[i]);
leftLine.getClosestPoint(line.getStart(),res);
res.projectOntoUnit(axis, onAxis);
float left = getProp(onAxis, axis);
rightLine.getClosestPoint(line.getStart(),res);
res.projectOntoUnit(axis, onAxis);
float right = getProp(onAxis, axis);
if ((left > 0) && (right > 0)) {
Vector2f pos = new Vector2f(bodyA.getPosition());
pos.add(line.getStart());
resolveEndPointCollision(pos,bodyA,bodyB,normal,leftLine,rightLine,contacts[numContacts],i);
numContacts++;
}
} else if (proj[i] > 1) {
Vector2f onAxis = new Vector2f();
Line leftLine = new Line(getPt(pts,i-1),pts[i]);
Line rightLine = new Line(getPt(pts,i+1),pts[i]);
leftLine.getClosestPoint(line.getEnd(),res);
res.projectOntoUnit(axis, onAxis);
float left = getProp(onAxis, axis);
rightLine.getClosestPoint(line.getEnd(),res);
res.projectOntoUnit(axis, onAxis);
float right = getProp(onAxis, axis);
if ((left > 0) && (right > 0)) {
Vector2f pos = new Vector2f(bodyA.getPosition());
pos.add(line.getEnd());
resolveEndPointCollision(pos,bodyA,bodyB,normal,leftLine,rightLine,contacts[numContacts],i);
numContacts++;
}
} else {
pts[i].projectOntoUnit(lineVec, res);
res.add(bodyA.getPosition());
contacts[numContacts].setSeparation(-(tangent[i]-linePos));
contacts[numContacts].setPosition(new Vector2f(res));
contacts[numContacts].setNormal(normal);
contacts[numContacts].setFeature(new FeaturePair(i));
numContacts++;
}
}
}
} else {
if (!line.blocksOuterEdge()) {
return 0;
}
for (int i=0;i<4;i++) {
if (tangent[i] < linePos) {
if (proj[i] < 0) {
Vector2f onAxis = new Vector2f();
Line leftLine = new Line(getPt(pts,i-1),pts[i]);
Line rightLine = new Line(getPt(pts,i+1),pts[i]);
leftLine.getClosestPoint(line.getStart(),res);
res.projectOntoUnit(axis, onAxis);
float left = getProp(onAxis, axis);
rightLine.getClosestPoint(line.getStart(),res);
res.projectOntoUnit(axis, onAxis);
float right = getProp(onAxis, axis);
if ((left < 0) && (right < 0)) {
Vector2f pos = new Vector2f(bodyA.getPosition());
pos.add(line.getStart());
resolveEndPointCollision(pos,bodyA,bodyB,normal,leftLine,rightLine,contacts[numContacts],i);
numContacts++;
}
} else if (proj[i] > 1) {
Vector2f onAxis = new Vector2f();
Line leftLine = new Line(getPt(pts,i-1),pts[i]);
Line rightLine = new Line(getPt(pts,i+1),pts[i]);
leftLine.getClosestPoint(line.getEnd(),res);
res.projectOntoUnit(axis, onAxis);
float left = getProp(onAxis, axis);
rightLine.getClosestPoint(line.getEnd(),res);
res.projectOntoUnit(axis, onAxis);
float right = getProp(onAxis, axis);
if ((left < 0) && (right < 0)) {
Vector2f pos = new Vector2f(bodyA.getPosition());