c++ 射线与立方体相交检查中的问题

s4chpxco  于 2023-04-08  发布在  其他
关注(0)|答案(1)|浏览(252)

我现在被我的RubiksCube项目卡住了。
我想达到的目标:左键点击时检查是否点击了一个小立方体。(点击时立方体可能会旋转)
其他魔方类的代码工作正常。我们需要用数学公式自己计算函数。
当前问题:

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

我的总体想法是安全的坐标,每层的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));

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

编辑:我改变了我的代码相当多,现在点击立方体是在许多情况下被检测到。

t3psigkw

t3psigkw1#

好了,我想是时候回答我自己的问题了。我的代码的实际问题是检查glm::dot(crosspoint - helperVec,normVec) == 0。但是我应该检查glm::abs(glm::dot(crosspoint - helperVec,normVec)) < EPSILON的EPSILON值非常小。
给自己的提示:当使用浮点数时,不要检查0

相关问题