I began writing small recreation that makes use of some collision detection. I’ve been capable of implement a working SAT collision detection prototype, however I found out that it stops working correctly, when some rotation is launched. And likewise I examined, that if the 2 objects have the identical rotation, it really works flawlessly, it would not work solely when two objects have completely different rotation. (The rotations are solely round y-axis).
Right here is my code that I used:
std::vector<std::vector<glm::vec3>> CollisionEngine::GeneratePointsForQuad(GameObject* object, float z_size) {
glm::mat4 mannequin{ glm::mat4(1.0f) };
mannequin = glm::translate(mannequin, object->m_position);
mannequin = glm::rotate(mannequin, glm::radians(object->m_degree), glm::vec3(0.0f, 1.0f, 0.0f));
mannequin = glm::scale(mannequin, glm::vec3(object->m_size, z_size));
std::vector<std::vector<glm::vec4>> vertices{
//FRONT
{
glm::vec4(0.0f, 0.0f, 0.0f, 1.0f),
glm::vec4(0.0f, 1.0f, 0.0f, 1.0f),
glm::vec4(1.0f, 1.0f, 0.0f, 1.0f),
glm::vec4(1.0f, 0.0f, 0.0f, 1.0f)
},
//LEFT
{
glm::vec4(0.0f, 0.0f, 0.0f, 1.0f),
glm::vec4(0.0f, 1.0f, 0.0f, 1.0f),
glm::vec4(0.0f, 1.0f, 1.0f, 1.0f),
glm::vec4(0.0f, 0.0f, 1.0f, 1.0f)
},
//RIGHT
{
glm::vec4(1.0f, 0.0f, 0.0f, 1.0f),
glm::vec4(1.0f, 1.0f, 0.0f, 1.0f),
glm::vec4(1.0f, 1.0f, 1.0f, 1.0f),
glm::vec4(1.0f, 0.0f, 1.0f, 1.0f)
},
//BACK
{
glm::vec4(0.0f, 0.0f, 1.0f, 1.0f),
glm::vec4(0.0f, 1.0f, 1.0f, 1.0f),
glm::vec4(1.0f, 1.0f, 1.0f, 1.0f),
glm::vec4(1.0f, 0.0f, 1.0f, 1.0f)
}
};
std::vector<std::vector<glm::vec3>> factors(4);
for (int row_iterator{}; row_iterator < 4; ++row_iterator) {
for (int vertex_iterator{}; vertex_iterator < 4; ++vertex_iterator) {
vertices[row_iterator][vertex_iterator] = mannequin * vertices[row_iterator][vertex_iterator];
factors[row_iterator].push_back(glm::vec3(vertices[row_iterator][vertex_iterator]));
}
}
return factors;
}
std::vector<glm::vec3> CollisionEngine::GetNormals(GameObject* object, std::vector<std::vector<glm::vec3>>& object_points) {
std::vector<glm::vec3> normals;
for (int row_iterator{}; row_iterator < 4; ++row_iterator) {
for (int point_iterator{}; point_iterator < 4; ++point_iterator) {
int next_point{ (point_iterator + 1) % 4 };
int third_point{ (point_iterator + 2) % 4 };
glm::vec3 first_vector{ object_points[row_iterator][next_point] - object_points[row_iterator][point_iterator] };
glm::vec3 second_vector{ object_points[row_iterator][third_point] - object_points[row_iterator][point_iterator] };
normals.push_back(glm::normalize(glm::cross(first_vector, second_vector)));
}
}
return normals;
}
CollisionEngine::Axis CollisionEngine::ProjectOntoAxis(std::vector<std::vector<glm::vec3>>& factors, glm::vec3& regular) {
float minProjection{ glm::dot(factors[0][0], regular) };
float maxProjection{ minProjection };
for (int row_iterator{}; row_iterator < 4; ++row_iterator) {
for (int point_iterator{}; point_iterator < 4; ++point_iterator) {
float currentProjection{ glm::dot(factors[row_iterator][point_iterator], regular) };
if (minProjection > currentProjection)
minProjection = currentProjection;
if (currentProjection > maxProjection)
maxProjection = currentProjection;
}
}
return { minProjection, maxProjection };
}
bool CollisionEngine::SATCollision(GameObject* first_object, GameObject* second_object) {
std::vector<std::vector<glm::vec3>> first_box_points{ GeneratePointsForQuad(first_object, 2.0f) };
std::vector<std::vector<glm::vec3>> second_box_points{ GeneratePointsForQuad(second_object, 2.0f) };
std::vector<glm::vec3> first_object_normals{ GetNormals(first_object, first_box_points) };
std::vector<glm::vec3> second_object_normals{ GetNormals(second_object, second_box_points) };
for (int it{}; it < 16; ++it){
Axis first_projection{ ProjectOntoAxis(first_box_points, first_object_normals[it]) };
Axis second_projection{ ProjectOntoAxis(second_box_points, second_object_normals[it]) };
if (first_projection.maxProjection < second_projection.minProjection ||
second_projection.maxProjection < first_projection.minProjection)
return false;
}
return true;
}