[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]