opengl 光线定向边界框(OBB)相交函数不适用于缩放

9gm1akwq  于 2023-04-30  发布在  其他
关注(0)|答案(1)|浏览(150)

所以我有这个函数来获取射线与OBB的交点:

std::optional<float> Ray::hitsOBB(const glm::vec3& min, const glm::vec3& max, const glm::mat4& modelMatrix) {
    float tMin = 0.0f;
    float tMax = 100000.0f;

    glm::vec3 OBBposition_worldspace(modelMatrix[3].x, modelMatrix[3].y, modelMatrix[3].z);
    glm::vec3 delta = OBBposition_worldspace - origin;

    {
        glm::vec3 xaxis(modelMatrix[0].x, modelMatrix[0].y, modelMatrix[0].z);
        float e = glm::dot(xaxis, delta);
        float f = glm::dot(direction, xaxis);

        if (fabs(f) > 0.001f) {
            float t1 = (e + min.x) / f;
            float t2 = (e + max.x) / f;

            if (t1 > t2) std::swap(t1, t2);

            if (t2 < tMax) tMax = t2;
            if (t1 > tMin) tMin = t1;
            if (tMin > tMax) return {};

        }
        else {
            if (-e + min.x > 0.0f || -e + max.x < 0.0f) return {};
        }
    }

    {
        glm::vec3 yaxis(modelMatrix[1].x, modelMatrix[1].y, modelMatrix[1].z);
        float e = glm::dot(yaxis, delta);
        float f = glm::dot(direction, yaxis);

        if (fabs(f) > 0.001f) {

            float t1 = (e + min.y) / f;
            float t2 = (e + max.y) / f;

            if (t1 > t2) std::swap(t1, t2);

            if (t2 < tMax) tMax = t2;
            if (t1 > tMin) tMin = t1;
            if (tMin > tMax) return {};

        }
        else {
            if (-e + min.y > 0.0f || -e + max.y < 0.0f) return {};
        }
    }

    {
        glm::vec3 zaxis(modelMatrix[2].x, modelMatrix[2].y, modelMatrix[2].z);
        float e = glm::dot(zaxis, delta);
        float f = glm::dot(direction, zaxis);

        if (fabs(f) > 0.001f) {

            float t1 = (e + min.z) / f;
            float t2 = (e + max.z) / f;

            if (t1 > t2) std::swap(t1, t2);

            if (t2 < tMax) tMax = t2;
            if (t1 > tMin) tMin = t1;
            if (tMin > tMax) return {};

        }
        else {
            if (-e + min.z > 0.0f || -e + max.z < 0.0f) return {};
        }
    }

    return tMin;
}

我用它来点击OpenGL中的立方体。测试用例是一个立方体,最小值和最大值分别为(-1,-1,-1)和(1,1,1)。现在,当旋转和平移modelMatrix时,这工作得很好,但它似乎没有考虑到比例。我试过将最小值和最大值与modelMatrix比例相乘,但没有用。有人知道发生什么事了吗

abithluo

abithluo1#

我遇到了同样的问题,我通过不缩放modelMatrix并只为aabb_min和aabb_max提供scale来解决它:

// cubeScale is glm::vec3(...);
    glm::vec3 aabb_min(-cubeScale);
    glm::vec3 aabb_max(cubeScale);

    glm::mat4 model(1.0f);
    model = glm::translate(model, cubePos);
    // Omit scaling of modelMatrix
    model = glm::rotate(model, glm::radians(cubeRotation.x), glm::vec3(1.0f, 0.0f, 0.0f));
    model = glm::rotate(model, glm::radians(cubeRotation.y), glm::vec3(0.0f, 1.0f, 0.0f));
    model = glm::rotate(model, glm::radians(cubeRotation.z), glm::vec3(0.0f, 0.0f, 1.0f));

    hitsOBB(...);

相关问题