Ray - OBB交叉口测试中的射线变换

时间:2017-06-19 12:05:02

标签: c++ opengl math 3d intersection

我已经实现了一个测试Ray-AABB交叉点的算法,它运行正常。但是当我尝试将Ray转换为AABB的本地空间(使其成为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;
        }
    }

1 个答案:

答案 0 :(得分:0)

事实证明,光线的世界 - &gt;模型转换是正确的。这个错误发生在路口测试中。我不得不完全替换交叉码,因为我不幸地在旧代码中识别出错误。

Ray转换代码:

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

被盗