I have programmed an implementation of the Separating Axis Theorem to handle collisions between 2D convex polygons. It is written in Processing and can be viewed on Github here. There are a couple of issues with it that I would like some help in resolving.
In the construction of Polygon objects, you specify the width and height of the polygon and the initial rotation offset by which the vertices will be placed around the polygon. If the rotation offset is 0, the first vertex is placed directly to the right of the object. If higher or lower, the first vertex is placed clockwise or counter-clockwise, respectively, around the circumference of the object by the rotation amount. The rest of the vertices follow by a consistent offset of TWO_PI / number of vertices. While this places the vertices at the correct angle around the polygon, the problem is that if the rotation is anything other than 0, the width and height of the polygon are no longer the values specified. They are reduced because the vertices are placed around the polygon using the sin and cos functions, which often return values other than 1 or -1. Of course, when the half width and half height are multiplied by a sin or cos value other than 1 or -1, they are reduced. This is my issue. How can I place an arbitrary number of vertices at an arbitrary rotation around the polygon, while maintaining both the intended shape specified by the number of vertices (triangle, hexagon, octagon), and the intended width and height of the polygon as specified by the parameter values in the constructor?
The Polygon code:
class Polygon
{
PVector position;
PShape shape;
int w, h, halfW, halfH;
color c;
ArrayList<PVector> vertexOffsets;
Polygon(PVector position, int numVertices, int w, int h, float rotation)
{
this.position = position;
this.w = w;
this.h = h;
this.halfW = w / 2;
this.halfH = h / 2;
this.c = color(255);
vertexOffsets = new ArrayList<PVector>();
if(numVertices < 3) numVertices = 3;
shape = createShape();
shape.beginShape();
shape.fill(255);
shape.stroke(255);
for(int i = 0; i < numVertices; ++i)
{
PVector vertex = new PVector(position.x + cos(rotation) * halfW, position.y + sin(rotation) * halfH);
shape.vertex(vertex.x, vertex.y);
rotation += TWO_PI / numVertices;
PVector vertexOffset = vertex.sub(position);
vertexOffsets.add(vertexOffset);
}
shape.endShape(CLOSE);
}
void move(float x, float y)
{
position.set(x, y);
for(int i = 0; i < shape.getVertexCount(); ++i)
{
PVector vertexOffset = vertexOffsets.get(i);
shape.setVertex(i, position.x + vertexOffset.x, position.y + vertexOffset.y);
}
}
void rotate(float angle)
{
for(int i = 0; i < shape.getVertexCount(); ++i)
{
PVector vertexOffset = vertexOffsets.get(i);
vertexOffset.rotate(angle);
shape.setVertex(i, position.x + vertexOffset.x, position.y + vertexOffset.y);
}
}
void setColour(color c)
{
this.c = c;
}
void render()
{
shape.setFill(c);
shape(shape);
}
}
My other issue is that when two polygons with three vertices each collide, they are not always moved out of collision smoothly by the Minimum Translation Vector returned by the SAT algorithm. The polygon moved out of collision by the MTV does not rest against the other polygon as it should, it instead jumps back a small distance. I find this very strange as I have been unable to replicate this behaviour when resolving collisions between polygons of other vertex quantities and I cannot find the flaw in the implementation, though it must be there. What could be causing this incorrect collision resolution, which from my testing appears to only occur between polygons of three vertices?
Any help you can provide on these issues would be greatly appreciated. Thank you.