【问题标题】:Ray transformation in a Ray - OBB intersection test射线 - OBB 相交测试中的射线变换
【发布时间】:2017-06-20 17:11:32
【问题描述】:

我已经实现了一个算法来测试 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;
        }
    }

【问题讨论】:

    标签: c++ opengl math 3d intersection


    【解决方案1】:

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

    光线变换代码:

    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 被盗

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-18
      • 2012-10-21
      • 2016-05-11
      • 2012-02-14
      • 2013-04-21
      相关资源
      最近更新 更多