c++intersectionglm-mathrubiks-cube

Problem on checking Ray and Cube intersection


I am stuck right now with my RubiksCube Project.

What I want to achieve: On left-click checking if a single Mini-Cubie was clicked or not. (The Cube might be rotated when clicked)

The Code of the other Rubiks Cube classes works correctly. We need to calculate the functions on our own with math formulas.

Current Problems:

My general idea was to safe the coords of every Layer´s 4 Corner Points, updating their position when rotated and checking the Intersection of the Ray with help of these locations

void MergedCube::Render(float aspectRatio)
{

    m_viewProject = glm::perspective(glm::radians(45.0f), aspectRatio, 0.1f, 100.0f) *
                    glm::lookAt(glm::vec3(0.0f, 0.0f, -9.0f), 
                                glm::vec3(0.0f), 
                                glm::vec3(0.0f, 1.0f, 0.0f)) *
                    glm::mat4_cast(m_orientationQuaternion);

        compound = glm::translate(m_viewProject, (glm::vec3(1, 1, 1) - 1.0f));

        m_cubieRenderer.Render(compound);
            

    // Calling LayerCalculation() for every Layer with direction -1 or 1


}

This method is supposed to calculate my helper vector, the 2 direction vectors and the normalisation vector of every Layer

void MergedCube::LayerCalculation(std::vector<glm::vec3>& points, int normDirection) {

    while (points.size() > 4) {
        points.erase(points.end()-1);
    }

    glm::vec3 middlePoint = (points[0] + points[2]) / 2.0f;
    glm::vec3 firstPoint = (points[0] + points[1]) / 2.0f;
    glm::vec3 secondPoint = (points[0] + points[3]) / 2.0f;

    glm::vec3 vecA = glm::normalize(firstPoint - middlePoint);
    glm::vec3 vecB = glm::normalize(secondPoint - middlePoint);
    
    glm::vec3 normalVector = glm::cross(vecA,vecB) * glm::vec3(direction);

    points.push_back(middlePoint);
    points.push_back(vecA);
    points.push_back(vecB);
    points.push_back(normalVector); 
    
}

Now the RayAndCubeIntersection method.

bool MergedCube::RayAndCubeIntersection(glm::vec3 startingPoint, glm::vec3 direction, 
                                        std::vector<glm::vec3> Pts) {

    glm::vec3 helperVec = pts[4];
    glm::vec3 normVec = pts[7];
    glm::vec3 directionVecA = pts[5];
    glm::vec3 directionVecB = pts[6];

if (glm::dot(rayDirection, normVec) < 0) {

        float res = normVec[0] * helperVec[0] + normVec[1] * helperVec[1] + normVec[2] * helperVec[2];
        float directionMultiplikator = (res - normVec[0] * rayStartingPoint[0] - normVec[1] * rayStartingPoint[1] - normVec[2] * rayStartingPoint[2]) /
                                       (normVec[0] * rayDirection[0] + normVec[1] * rayDirection[1] + normVec[2] * rayDirection[2]);
        glm::vec3 crosspoint = rayStartingPoint + rayDirection * glm::vec3(directionMultiplikator);

        if (glm::dot(crosspoint - helperVec,normVec) == 0) {

            float x = glm::dot(directionVecA,crosspoint - helperVec);
            float y = glm::dot(directionVecB, crosspoint - helperVec);

            if (x > -0.5001 && x < 0.5001) {
                if (y > -0.5001 && y < 0.5001) {
                    return true;
                }
            }   
        }
    }
    return false;
}

Edit: I changed my Code quite a bit, now clicking the cube is being detected in many cases.


Solution

  • Well I guess it is time to answer my own question. The actual problem of my code was checking glm::dot(crosspoint - helperVec,normVec) == 0 . But instead I am supposed to check for glm::abs(glm::dot(crosspoint - helperVec,normVec)) < EPSILON with a really small EPSILON value.

    Note to myself: When using floats never check against 0