Sunday, May 1, 2016

c++ - Separating Axis Theorem Issue


I am trying to create a 2d top down shooter using DirectX 11 (Windows 8 Store) and I am trying to implement OOBB collision using the Separating Axis Theorem.


However I appear to have run into an issue which I cannot fathom.


I will upload a few images to aid my explanation. The boxes only collide when the top left or top right corner intersect the other collision object but does not work if the bottom corners collide with it.


When the boxes are AABB they collide perfectly from all directions.


No collision from bottom corners



As you can see the bottom right corner is intersecting the other box, but isn't colliding.


Collision from top corners


The rotation origin (left corner) is intersecting the other box and is resulting in a collision correctly. This appears to be the same for the top right corner.


Code:


void Entity::computeRotatedBox()

{


/*if(rotatedBoxReady)
return;*/


getPosition();
float projection;


float rot = rotation;

Vector2 rotatedX(cos(rot), sin(rot));
Vector2 rotatedY(-sin(rot), cos(rot));



const Vector2 *center = getCenter();

//Calculate corner position relative to rotation
corners[0] = *center + rotatedX * ((float)edge.left) + rotatedY * ((float)edge.top);
corners[1] = *center + rotatedX * ((float)edge.right) + rotatedY * ((float)edge.top);
corners[2] = *center + rotatedX * ((float)edge.right) + rotatedY * ((float)edge.bottom);
corners[3] = *center + rotatedX * ((float)edge.left) + rotatedY * ((float)edge.bottom);


edge01 = Vector2(corners[1].x - corners[0].x, corners[1].y - corners[0].y);

Vector2Normalize(&edge01);
edge03 = Vector2(corners[3].x - corners[0].x, corners[3].y - corners[0].y);
Vector2Normalize(&edge03);

//Calculate projection onto line
projection = Vector2Dot(&edge01, &corners[0]);
entA01min = projection;
entA01max = projection;

//Project onto Axis 1

projection = Vector2Dot(&edge01, &corners[1]);
if(projection < entA01min)
entA01min = projection;
else if(projection > entA01max)
entA01max = projection;

//Project onto "Axis 3"
projection = Vector2Dot(&edge03, &corners[0]);
entA03min = projection;
entA03max = projection;

projection = Vector2Dot(&edge03, &corners[3]);
if(projection < entA03min)
entA03min = projection;
else if(projection > entA03max)
entA03max = projection;

rotatedBoxReady = true;

}


bool Entity::projectionOverlap(Entity &ent, Vector2 &collisionVector) { float projection;



projection = Vector2Dot(&edge01, ent.getCorner(0));

//Project Corner 0
entB01min = projection;
entB01max = projection;

for(int c = 1; c<4; c++)
{
projection = Vector2Dot(&edge01, ent.getCorner(c));
if(projection < entB01min)

entB01min = projection;
else if(projection > entB01max)
entB01max = projection;
}

if(entB01min > entA01max || entB01max < entA01min)
return false;

//Project other onto axis 3
projection = Vector2Dot(&edge03, ent.getCorner(0));

entB03min = projection;
entB03max = projection;

for(int c = 1; c<4; c++)
{
projection = Vector2Dot(&edge03, ent.getCorner(c));
if(projection < entB03min)
entB03min = projection;
else if(projection > entB03max)
entB03max = projection;

}

//If there is no overlap
if(entB03min > entA03max || entB03max < entA03min)
return false;

return true; //Otherwise they must overlap.

}


Vector2 * Entity::getCorner(UINT c) { if(c>= 4) c = 0;



return &corners[c];

}


bool Entity::collideRotatedBox(Entity &ent, DirectX::SimpleMath::Vector2 &collisionVector) {


float overlap01, overlap03;

computeRotatedBox(); //Prepare rotated boxes
ent.computeRotatedBox(); //Prepare rotated box

if(projectionOverlap(ent, collisionVector) && ent.projectionOverlap(*this, collisionVector))

{

if(entA01min < entB01min)
{
overlap01 = entB01max - entB01min;
collisionVector = corners[1] - corners[0];
}
else // else, A right of B
{
overlap01 = entB01max - entA01min;

collisionVector = corners[0] - corners[1];
}
if (entA03min < entB03min) // if A above B
{
overlap03 = entA03max - entB03min;
if (overlap03 < overlap01)
collisionVector = corners[3] - corners[0];
}
else // else, A below B
{

overlap03 = entB03max - entA03min;
if (overlap03 < overlap01)
collisionVector = corners[0] - corners[3];
}
return true;

}
return false;

}





No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...