Hello, everyone
I'm trying to implement the SAT collision test. I've read articles about how it works and want to write a program. I've decided to use C++.
I'm following a tutorial, but not sure about the optimization. I want to make this code as fast as possible. It may be C++ associated mistakes or something in the algorithm.
Code:
#include <iostream>
#include <cmath>
#include <deque>
struct Projection{
Projection(double a, double b): min(a), max(b){}
double min;
double max;
};
struct Axis{
std::pair<float, float> p;
double dot(const std::pair<float, float>& v) const{
return v.first*p.first + v.second*p.second;
}
};
struct Shape{
std::deque<std::pair<float, float>> vertices;
Projection project(const Axis& axis){
double min = axis.dot(vertices[0]);
double max = min;
for (size_t i = 1; i < vertices.size(); i++) {
// Normalize the axis
double p = axis.dot(vertices[i]);
if (p < min){
min = p;
} else if (p > max){
max = p;
}
}
return Projection(min, max);
}
};
std::pair<float, float> calc_normal(const std::pair<float, float>& v){
return std::pair<float, float>(-v.second, v.first);
}
void calc_axes(Shape& shape, std::deque<Axis>& axes){
for (size_t i = 0; i < shape.vertices.size(); i++) {
// get the current vertex
std::pair<float, float> p1 = shape.vertices[i];
// get the next vertex
std::pair<float, float> p2 = shape.vertices[i+1];
if(i == shape.vertices.size() - 1){
p2 = shape.vertices[0];
}
// subtract the two to get the edge vector
std::pair<float, float> edge = p2;
edge.first -= p1.first;
edge.second -= p1.second;
Axis a;
a.p = calc_normal(edge);
axes.push_back(std::move(a));
}
}
bool overlap(const Projection& p1, const Projection& p2){
return !(p1.max < p2.min || p2.max < p1.min);
}
bool check_inter(Shape& shape1, Shape& shape2){
std::deque<Axis> axes1;
calc_axes(shape1, axes1);
for(size_t i = 0; i < axes1.size(); ++i){
Projection p1 = shape1.project(axes1[i]);
Projection p2 = shape2.project(axes1[i]);
if(!overlap(p1, p2)){
return false;
}
}
std::deque<Axis> axes2;
calc_axes(shape2, axes2);
for(size_t i = 0; i < axes2.size(); ++i){
Projection p1 = shape1.project(axes2[i]);
Projection p2 = shape2.project(axes2[i]);
if(!overlap(p1, p2)){
return false;
}
}
return true;
}
int main(){
srand(time(0));
Shape shape1;
shape1.vertices.push_back(std::pair<float, float>(0.f, 0.f));
shape1.vertices.push_back(std::pair<float, float>(1.f, 1.f));
shape1.vertices.push_back(std::pair<float, float>(0.f, 1.f));
Shape shape2;
shape2.vertices.push_back(std::pair<float, float>(1.f, 0.f));
shape2.vertices.push_back(std::pair<float, float>(2.f, 1.f));
shape2.vertices.push_back(std::pair<float, float>(1.f, 1.f));
bool res = check_inter(shape1, shape2);
std::cout << res << "\n";
}
Thank you.