射线中的射线变换 - OBB 相交测试

Ray transformation in a Ray - OBB intersection test

我已经实施了一种算法来测试 Ray - AABB 交集并且它工作正常。但是当我尝试将 Ray 转换为 AABB 的本地 space(使其成为 Ray - OBB 测试)时,我无法获得正确的结果。我研究了几个论坛和其他资源,但仍然缺少一些东西。 (一些消息来源建议对射线原点及其末端应用反向变换,然后才计算方向,其他 - 对原点和方向应用变换)。有人可以指出正确的方向吗(没有双关语)?

这里有两个函数负责计算:

1) 计算逆和其他东西来执行测试

bool Ray::intersectsMesh(const Mesh& mesh, const Transformation& transform) {
        float largestNearIntersection = std::numeric_limits<float>::min();
        float smallestFarIntersection = std::numeric_limits<float>::max();
        glm::mat4 modelTransformMatrix = transform.modelMatrix();
        Box boundingBox = mesh.boundingBox();

        glm::mat4 inverse = glm::inverse(transform.modelMatrix());

        glm::vec4 newOrigin = inverse * glm::vec4(mOrigin, 1.0);
        newOrigin /= newOrigin.w;
        mOrigin = newOrigin;
        mDirection = glm::normalize(inverse * glm::vec4(mDirection, 0.0));

        glm::vec3 xAxis = glm::vec3(glm::column(modelTransformMatrix, 0));
        glm::vec3 yAxis = glm::vec3(glm::column(modelTransformMatrix, 1));
        glm::vec3 zAxis = glm::vec3(glm::column(modelTransformMatrix, 2));

        glm::vec3 OBBTranslation = glm::vec3(glm::column(modelTransformMatrix, 3));
        printf("trans x %f y %f z %f\n", OBBTranslation.x, OBBTranslation.y, OBBTranslation.z);
        glm::vec3 delta = OBBTranslation - mOrigin;

        bool earlyFalseReturn = false;

        calculateIntersectionDistances(xAxis, delta, boundingBox.min.x, boundingBox.max.x, &largestNearIntersection, &smallestFarIntersection, &earlyFalseReturn);
        if (smallestFarIntersection < largestNearIntersection || earlyFalseReturn) { return false; }

        calculateIntersectionDistances(yAxis, delta, boundingBox.min.y, boundingBox.max.y, &largestNearIntersection, &smallestFarIntersection, &earlyFalseReturn);
        if (smallestFarIntersection < largestNearIntersection || earlyFalseReturn) { return false; }

        calculateIntersectionDistances(zAxis, delta, boundingBox.min.z, boundingBox.max.z, &largestNearIntersection, &smallestFarIntersection, &earlyFalseReturn);
        if (smallestFarIntersection < largestNearIntersection || earlyFalseReturn) { return false; }

        return true;
    }

2) 辅助函数(此处可能不需要,因为它仅与 AABB 测试相关并且工作正常)

void Ray::calculateIntersectionDistances(const glm::vec3& axis,
                                             const glm::vec3& delta,
                                             float minPointOnAxis,
                                             float maxPointOnAxis,
                                             float *largestNearIntersection,
                                             float *smallestFarIntersection,
                                             bool *earlyFalseRerutn)
    {
        float divident = glm::dot(axis, delta);
        float denominator = glm::dot(mDirection, axis);

        if (fabs(denominator) > 0.001f) {
            float t1 = (divident + minPointOnAxis) / denominator;
            float t2 = (divident + maxPointOnAxis) / denominator;

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

            *smallestFarIntersection = std::min(t2, *smallestFarIntersection);
            *largestNearIntersection = std::max(t1, *largestNearIntersection);
        } else if (-divident + minPointOnAxis > 0.0 || -divident + maxPointOnAxis < 0.0) {
            *earlyFalseRerutn = true;
        }
    }

事实证明,光线的世界 -> 模型转换是正确的。该错误出现在交集测试中。不幸的是,我不得不完全替换交集代码,因为我无法识别旧代码中的错误。

光线变换代码:

glm::mat4 inverse = glm::inverse(transform.modelMatrix());
glm::vec4 start = inverse * glm::vec4(mOrigin, 1.0);
glm::vec4 direction = inverse * glm::vec4(mDirection, 0.0);
direction = glm::normalize(direction);

并且 Ray - AABB 测试被盗自 here