检查射线和立方体相交的问题

问题描述 投票:0回答:1

我现在被我的 RubiksCube 项目困住了。

我想要实现的目标:在左键单击时检查是否单击了单个 Mini-Cubie。 (点击时立方体可能会旋转)

其他魔方类的代码可以正常工作。 我们需要自己用数学公式计算函数。

当前问题:

  • 没有检测到点击边缘
  • 旋转后点击一个点有时会导致:错误的图层被标记为点击或没有图层被标记为点击

我的总体想法是保护每一层的 4 个角点的坐标,在旋转时更新它们的位置并在这些位置的帮助下检查射线的交点

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

        // Updating the local Corner Points of every Layer for a single Cubie (Added local Corner Points have x y z values of -0.5 or 0.5)
    for (auto layer : layers) {
        for (int i = 0; i < 4; i++) {
            layer[i] = compound * glm::vec4(layer[i], 1.0);
        }
    }

        m_cubieRenderer.Render(compound);
            

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


}

这个方法应该计算我的辅助向量,2个方向向量 和每一层的归一化向量

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

现在是 RayAndCubeIntersection 方法。

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

编辑:我改变了我的代码,现在在很多情况下都检测到点击立方体。

c++ intersection glm-math rubiks-cube
1个回答
0
投票

好吧,我想是时候回答我自己的问题了。 我的代码的实际问题是检查

glm::dot(crosspoint - helperVec,normVec) == 0
。 但是相反,我应该用非常小的 EPSILON 值检查
glm::abs(glm::dot(crosspoint - helperVec,normVec)) < EPSILON

我自己注意:使用浮点数时永远不要检查 0

© www.soinside.com 2019 - 2024. All rights reserved.