Saturday, November 5, 2022
HomeGame Developmentopengl - C++ Downside With Separating Axis Theorem When Utilizing Rotations

opengl – C++ Downside With Separating Axis Theorem When Utilizing Rotations


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;
}

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisment -
Google search engine

Most Popular

Recent Comments