Hi there,
I am currently writing a little engine from scratch but I have currently trouble implementing the SAT collision algorithm. I'm able to detect collision with stunning precision but unfortunately, I can't get the right collision response. Sometimes the object bounce, but sometime the object is shallowed inside the other one and moving inside very quickly. It's been around a week I try to figuring out what's the problem and it's get worse over time. Here's a sample of my code:
The collision detection:
Vector2 Polygon::projection(double angle) const
{
Vector2 axis = {cos(angle), sin(angle)};
Vector2 result_projection;
Vector2 current;
std::list<Vector2>::const_iterator verticle = _vertex.begin();
current = *verticle;
current.setAngle(_angle + current.getAngle());
result_projection.x = axis.dot(current + _position);
result_projection.y = result_projection.x;
for(verticle++ ; verticle != _vertex.end() ; verticle++)
{
current = *verticle;
current.setAngle(_angle + current.getAngle());
double p = axis.dot(current + _position);
if(p < result_projection.x)
{
result_projection.x = p;
}
else if(p > result_projection.y)
{
result_projection.y = p;
}
}
return result_projection;
}
Vector2 Polygon::overlap(const SAT_able& other) const
{
Vector2 overlap;
overlap.setLenght(std::numeric_limits< double >().max());
for(double angle : getAngles())
{
Vector2 projectionThis = this->projection(angle);
Vector2 projectionOther = other.projection(angle);
if(projectionThis.x < projectionOther.x && projectionThis.y > projectionOther.x && projectionThis.y < projectionOther.y)
{
if(overlap.getLenght() > projectionThis.y - projectionOther.x)
{
overlap = {projectionThis.y - projectionOther.x, 0};
overlap.setAngle(angle);
}
}
else if(projectionThis.x > projectionOther.x && projectionThis.y < projectionOther.y)
{
if(overlap.getLenght() > projectionThis.y - projectionThis.x)
{
overlap = {projectionThis.y - projectionThis.x, 0};
overlap.setAngle(angle);
}
}
else if(projectionThis.x > projectionOther.x && projectionThis.x < projectionOther.y && projectionThis.y > projectionOther.y)
{
if(overlap.getLenght() > projectionOther.y - projectionThis.x)
{
overlap = {projectionOther.y - projectionThis.x, 0};
overlap.setAngle(angle);
}
}
else if(projectionThis.x < projectionOther.x && projectionThis.y > projectionOther.y)
{
if(overlap.getLenght() > projectionOther.y - projectionOther.x)
{
overlap = {projectionOther.y - projectionOther.x};
overlap.setAngle(angle);
}
}
else
{
return Vector2(0,0);
}
}
return overlap;
}
std::vector< double > Polygon::getAngles() const
{
std::vector<double> angles;
Vector2 previous = *_vertex.rbegin();
previous.setAngle(_angle + previous.getAngle());
for(Vector2 current : _vertex)
{
current.setAngle(_angle + current.getAngle());
angles.push_back((previous - current).getAngle() - (pi / 2));
previous = current;
}
return angles;
}
The reponse code:
Vector2 nearest = sat->distance;
point->setPulse("collision", nearest * point->getMass());
EventManager::triggerEvent("collision", new CollisionEventArgs(*sat, *point))
If you want to see more of my code check the projection on github: https://github.com/gracicot/subgine
EDIT: added more code