c++ – Seperating axis theorem is bugged

c++ – Seperating axis theorem is bugged

[ad_1]

I’m trying to make cut up axis theorem for 2nd collision physics. It does works, however is inaccurate. It’s primarily based off of: https://www.gamedev.web/tutorials/programming/math-and-physics/a-verlet-based-approach-for-2nd-game-physics-r2714/

A video for reference: https://www.youtube.com/watch?v=edSN3_Xkkls

Right here is the physics class:

class Physics {
int pointCount = 0;
Level* vertices[MAX_VERTICES];
int edgeCount = 0;
Edge* edges[MAX_EDGES];
PhysicsBody* PhysicsBodies[MAX_BODIES];
int bodyCount = 0;

float timestep = 1.0;
// The 'Depth' is the size of the vector, the 'Regular' is the course of the vector mentioned above. 
struct {
    float Depth;
    sf::Vector2f Regular;

    Edge* E;
    Level* V;
} CollisionInfo;
public:

void Replace();
void UpdateForces();
void updateVerlet();
void updateEdges();
void ProcessCollision();
void IterateCollisions();
void renderPoints(sf::RenderWindow& window);
void MakeShape(std::vector<sf::Vector2f> factors, bool anchored);
bool DetectCollision(PhysicsBody* B1, PhysicsBody* B2);
float IntervalDistance(float MinA, float MaxA, float MinB, float MaxB);
};

Right here is the purpose class:

struct Level {
sf::Vector2f Place;
sf::Vector2f OldPosition;
sf::Vector2f Acceleration;
};

Right here is the sting class:

struct Edge {
Level* v1;
Level* v2;

float OriginalLength; // The size of the sting when it was created

PhysicsBody* Guardian; // The physics physique that it belongs to
};

Right here is the detect collision perform:

bool Physics::DetectCollision(PhysicsBody* B1, PhysicsBody* B2) {

float MinDistance = 10000.0f;
// Iterates via all edges of each our bodies directly
for (int i = 0; i < B1->EdgeCount + B2->EdgeCount; i++) {
    Edge* E;
    if (i < B1->EdgeCount) {
        E = B1->edges[i];
        E->v1 = B1->edges[i]->v1;
        E->v2 = B1->edges[i]->v2;
    }
    else {
        E = B2->edges[i - B1->EdgeCount];
    }

    // Calculate the axis perpendicular to this edge and normalize
    //printPosition(E->v1->Place.x, E->v1->Place.y);
    //printPosition(E->v2->Place.x, E->v2->Place.y);
    sf::Vector2f Axis(E->v1->Place.y - E->v2->Place.y, E->v2->Place.x - E->v1->Place.y);
    float AxisN = Normalize(Axis);
    
    float MinA, MinB, MaxA, MaxB;
    B1->ProjectToAxis(Axis, MinA, MaxA);
    B2->ProjectToAxis(Axis, MinB, MaxB);

    float Distance = IntervalDistance(MinA, MaxA, MinB, MaxB);

    if (Distance > 0.0f) {
        return false; //If the intervals do not overlap, return false, since there is no such thing as a collision
    }
    // If the intervals overlap, test, whether or not the vector size on this
    //edge is smaller than the smallest size that has been reported to date
    else if (abs(Distance) < MinDistance) {
        MinDistance = abs(Distance);

        CollisionInfo.Regular = Axis; //Save collision data for later
        CollisionInfo.E = E; //Retailer the sting, as it's the collision edge
    }
}

CollisionInfo.Depth = MinDistance;

// Be certain that the physique containing the collision edge lies in
//B2 and the one containing the collision vertex in B1
// would not have an edge set to it 
if (CollisionInfo.E->Guardian != B2) {
    PhysicsBody* Temp = B2;
    B2 = B1;
    B1 = Temp;
}

//That is wanted to make it possible for the collision regular is pointing at B1
int Signal = SGN(CollisionInfo.Regular.x * (B1->Heart.x - B2->Heart.x));

//Do not forget that the road equation is N*( R - R0 ). We select B2->Heart
//as R0; the traditional N is given by the collision regular

if (Signal != 1)
    CollisionInfo.Regular = -CollisionInfo.Regular; //Revert the collision regular if it factors away from B1


float SmallestD = 100000.0f; //Initialize the smallest distance to a excessive worth
for (int I = 0; I < B1->VertexCount; I++) {
    //Measure the space of the vertex from the road utilizing the road equation
    float Distance = distanceBetweenPoints(CollisionInfo.Regular, (B1->vertices[I]->Place - B2->Heart));
    //If the measured distance is smaller than the smallest distance reported
    //to date, set the smallest distance and the collision vertex
    if (Distance < SmallestD) {
        SmallestD = Distance;
        CollisionInfo.V = B1->vertices[I];
    }
}

return true; //There isn't any separating axis. Report a collision!
}

I attempted altering the Min = std::min(DotP, Min); & Min = std::min(DotP, Min); to Min = FLT_MAX, Max = FLT_MIN; however this solely made the issue worse.

Right here is the venture to axis perform:

void PhysicsBody::ProjectToAxis(sf::Vector2f& Axis, float& Min, float& Max) {

float DotP = dotProduct(Axis, vertices[0]->Place);
// set min and max to the venture of the primary vertex
Min = Max = DotP;

for (int i = 1; i < VertexCount; i++) {
    // Mission the remainder of the vertices onto the axis and lengthen
    // The interval to left and proper if obligatory
    float DotP = dotProduct(Axis, vertices[1]->Place);

    //Min = FLT_MAX, Max = FLT_MIN;

    Min = std::min(DotP, Min);
    Max = std::max(DotP, Max);
}
/*
As you may see, projection in 2D is just a dot product of the projection axis and the purpose we wish to venture.
*/
}

Right here is the SGN perform:

inline bool SGN(float x) {
if (x > 0) return 1;
if (x < 0) return -1;
return 0;
}

[ad_2]

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply