I've put together a small implementation of the Separate Axis Theorem in SFML with VertexArrays but wanted to see if anyone could look it over. I'm pretty good with C++ but by no means a master so I'd love to know how I could improve this. It is an implementation of the ActionScript3 version found here :
http://rocketmandevelopment.com/2010/05/19/separation-of-axis-theorem-for-collision-detection/My code:
Object.hclass Object : public sf::Drawable, public sf::Transformable
{
public:
Object() : shape( sf::TrianglesStrip, 6 ), verts( 4 )
{
shape[0].position = sf::Vector2f( 0, 0 );
shape[1].position = sf::Vector2f( 100, 0 );
shape[2].position = sf::Vector2f( 0, 50 );
shape[3].position = sf::Vector2f( -50, 0 );
shape[4].position = sf::Vector2f( 0, -50 );
shape[5].position = sf::Vector2f( 100, 0 );
for( int i = 0; i < 4; i++ )
{
verts[i].setRadius( 4 );
verts[i].setFillColor( sf::Color::Red );
verts[i].setOrigin( verts[i].getGlobalBounds().width/2, verts[i].getGlobalBounds().height/2 );
verts[i].setPosition( shape[i+1].position );
}
}
sf::VertexArray& getShape()
{return shape;}
private:
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const
{
states.transform *= getTransform();
target.draw( shape, states);
for( int i = 0; i < verts.size(); i++ )
{
target.draw( verts[i], states);
}
}
sf::VertexArray shape;
std::vector<sf::CircleShape> verts;
};
Functions.hsf::Vector2f normalize( sf::Vector2f& input )
{
if( sqrt(input.x*input.x + input.y*input.y) == 0 )
{
input.x = 1;
return input;
}
float length = sqrt(input.x*input.x + input.y*input.y);
input.x /= length;
input.y /= length;
return input;
}
sf::Vector2f getNormalAxis( sf::VertexArray& shape, int index )
{
sf::Vector2f vector1 = shape[index].position;
sf::Vector2f vector2;
if( index >= shape.getVertexCount() - 1 )
vector2 = shape[0].position;
else
vector2 = shape[index+1].position;
sf::Vector2f normalAxis( -(vector2.y - vector1.y), vector2.x - vector1.x );
normalAxis = normalize( normalAxis );
return normalAxis;
}
float dotProduct( sf::Vector2f& vector1, sf::Vector2f& vector2 )
{
return vector1.x*vector2.x + vector1.y*vector2.y;
}
bool sat( Object& shape1, Object& shape2 )
{
sf::Vector2f vectorOffset( shape1.getPosition().x - shape2.getPosition().x, shape1.getPosition().y - shape2.getPosition().y );
for( int i = 0; i < shape1.getShape().getVertexCount(); i++ )
{
sf::Vector2f axis = getNormalAxis( shape1.getShape(), i );
float min1 = dotProduct( axis, shape1.getShape()[0].position );
float max1 = min1;
for( int j = 1; j < shape1.getShape().getVertexCount(); j++ )
{
float testNum = dotProduct( axis, shape1.getShape()[j].position );
if( testNum < min1 )
min1 = testNum;
if( testNum > max1 )
max1 = testNum;
}
float min2 = dotProduct( axis, shape2.getShape()[0].position );
float max2 = min2;
for( int j = 1; j < shape2.getShape().getVertexCount(); j++ )
{
float testNum = dotProduct( axis, shape2.getShape()[j].position );
if( testNum < min2 )
min2 = testNum;
if( testNum > max2 )
max2 = testNum;
}
float offset = dotProduct( axis, vectorOffset );
min1 += offset;
max1 += offset;
float test1 = min1 - max2;
float test2 = min2 - max1;
if( test1 > 0 || test2 > 0 )
return 0;
}
return 1;
}
My basic implementation just uses two shapes that are the same, one of which is controlled by the mouse. It seems to work fine so far; I haven't tested it extensively with more complex objects/numbers. So I wanted to see if anyone with experience in this area can provide some tips in terms of improving this. My next step is to of course calculate resultant vectors and implement this with freely moving objects.
Edit: On an unrelated note, does anyone have an argument for using TriangleStrips over TriangleFans or vice versa?