设置光线(原点,方向)和三角形交点(不含glm)

问题描述 投票:3回答:2

编辑3:我的问题与我预期的功能完全不同。生病让代码停留,也许这有助于某人:)(并且不要忘记调试!)。

我试图找到一条线与三角形相交的向量。

当前状态:随机交叉即使鼠标不在地板上且摄像机视图依赖(lookat矩阵)

脚步

  1. 取消投影鼠标坐标
  2. 检查线/三角交叉点

取消投影鼠标坐标

我检查了glm :: unproject和gluUnproject的来源并创建了这个函数。

   pixel::CVector3 pixel::CVector::unproject(
    CVector2 inPosition,
    pixel::CShape window,
    pixel::matrix4 projectionMatrix,
    pixel::matrix4 modelViewMatrix,
    float depth
    )
{
    // transformation of normalized coordinates
    CVector4 inVector;
    inVector.x = (2.0f * inPosition.x) / window.width - 1.0f;
    inVector.y = (2.0f * inPosition.y) / window.height - 1.0f;
    inVector.z = 2.0f * depth - 1.0f;
    inVector.w = 1.0f;

    // multiply inverted matrix with vector
    CVector4 rayWorld = pixel::CVector::multMat4Vec4(pixel::CMatrix::invertMatrix(projectionMatrix * modelViewMatrix), inVector);

    CVector3 result;
    result.x = rayWorld.x / rayWorld.w;
    result.y = rayWorld.y / rayWorld.w;
    result.z = rayWorld.z / rayWorld.w;



    return result;
}

检查交叉口

pixel::CVector3 pixel::Ray::intersection(
    Ray ray,
    pixel::CVector3 v0,
    pixel::CVector3 v1,
    pixel::CVector3 v2
    )
{
    // compute normal
    CVector3 a, b, n;
    a = v1 - v0;
    b = v2 - v0;

    n = ray.direction.cross(b);

    // find determinant
    float det = a.dot(n);

    if (det < 0.000001f)
    {
        std::cout << "Ray intersecting with backface triangles \n";
        return pixel::CVector::vector3(0.0f, 0.0f, 0.0f);
    }
    det = 1.0f / det;

    // calculate distance from vertex0 to ray origin
    CVector3 s = ray.origin - v0;
    float u = det * s.dot(n);

    if (u < -0.000001f || u > 1.f + 0.000001f)
    {
        std::cout << "U: Intersection outside of the triangle!\n";
        return pixel::CVector::vector3(0.0f, 0.0f, 0.0f);
    }

    CVector3 r = s.cross(a);
    float v = det * ray.direction.dot(r);
    if (v < -0.000001f || u + v > 1.f + 0.000001f)
    {
        std::cout << "V/U: Intersection outside of triangle!\n";
        return pixel::CVector::vector3(0.0f, 0.0f, 0.0f);
    }

    // distance from ray to triangle
    det = det *  b.dot(r);

    std::cout << "T: " << det << "\n";

    CVector3 endPosition;
    endPosition.x = ray.origin.x + (ray.direction.x * det);
    endPosition.y = ray.origin.y + (ray.direction.y * det);
    endPosition.z = ray.origin.z + (ray.direction.z * det);

    return endPosition;
}

用法

    if (event.button.button == SDL_BUTTON_RIGHT)
            {

                camera->setCameraActive();
                float mx = event.motion.x;
                float my = window->info.height - event.motion.y;
                // ray casting
                pixel::Ray ray;

                std::cout << "\n\n";

                    // near
                pixel::CVector3 rayNear = pixel::CVector::unproject(
                    pixel::CVector::vector2(mx, my),
                    pixel::CVector::shape2(window->info.internalWidth, window->info.internalHeight),
                    camera->camInfo.currentProjection,
                    camera->camInfo.currentView,
                    1.0f
                    );
                // far
                pixel::CVector3 rayFar = pixel::CVector::unproject(
                    pixel::CVector::vector2(mx, my),
                    pixel::CVector::shape2(window->info.internalWidth, window->info.internalHeight),
                    camera->camInfo.currentProjection,
                    camera->camInfo.currentView,
                    0.0f
                    );


                // normalized direction results in the same behavior
                ray.origin = cameraPosition;

                ray.direction = pixel::CVector::normalize(rayFar- rayNear);

                std::cout << "Raycast \n";
                std::cout << "Mouse Position: " << mx << " - " << my << "\n";
                std::cout << "Camera Position: " << ray.origin.x << " - " << ray.origin.y << " - " << ray.origin.z << "\n";
                std::cout << "Ray direction: " << ray.direction.x << " - " << ray.direction.y << " - " << ray.direction.z << "\n";


                pixel::CVector3 vertOne = pixel::CVector::vector3(0.0f, 0.0f, -300.0f);
                pixel::CVector3 vertTwo = pixel::CVector::vector3(0.0f, 0.0f, 0.0f);
                pixel::CVector3 vertThree = pixel::CVector::vector3(300.0f, 0.0f, 0.0f);
                pixel::CVector3 vertFour = pixel::CVector::vector3(300.0f, 0.0f, -300.0f);


                pixel::CVector3 rayHit = pixel::Ray::intersection(ray, vertOne, vertTwo, vertThree);
                pixel::CVector3 rayHit2 = pixel::Ray::intersection(ray, vertThree, vertFour, vertOne);
                std::cout << "Ray hit: " << rayHit.x << " - " << rayHit.y << " - " << rayHit.z << "\n";
                std::cout << "Ray hit: " << rayHit2.x << " - " << rayHit2.y << " - " << rayHit2.z << "\n";
                std::cout << "--------------------\n";
                towerHouse->modelMatrix = pixel::CMatrix::translateMatrix(rayHit);

产量

由于我从未使用过glm :: unproject或gluUnproject,我不知道正常输出应该是什么样子,但我得到的结果如下:

射线方向:0.109035 -0.0380502 0.0114562

看起来不对我,但检查我的代码与其他来源(如上所述),我没有看到错误/ s。

Ray交叉点在一些特殊情况下工作(相机旋转),即使我不点击地板,我也会得到交叉点。交叉口输出从背面碰撞到三角形外部也是如此。

所有这些错误看起来像问题的主要来源是不投影。

正确方向的任何暗示?

c++ opengl intersection raycasting
2个回答
1
投票

这与这个问题的答案无关,但这在评论或聊天中无法解释。

首先:

            // near
            pixel::CVector3 rayNear = pixel::CVector::raycast(
                pixel::CVector::vector2(mx, my),
                pixel::CVector::shape2(window->info.internalWidth, window->info.internalHeight),
                camera->camInfo.currentProjection,
                camera->camInfo.currentView,
                1.0f // WRONG
                );
            // far
            pixel::CVector3 rayFar = pixel::CVector::raycast(
                pixel::CVector::vector2(mx, my),
                pixel::CVector::shape2(window->info.internalWidth, window->info.internalHeight),
                camera->camInfo.currentProjection,
                camera->camInfo.currentView,
                0.0f // WRONG
                );

窗口空间中的近似为0.0,远为1.0(取决于深度范围,但如果您更改了深度范围,则应该已经知道这一点)。

在光线投射功能中,您有:

CVector3 result;
result.x = rayWorld.x / rayWorld.w;
result.y = rayWorld.y / rayWorld.w;
result.z = rayWorld.z / rayWorld.w;

有可能w == 0.0,结果此时还不是光线......它是物体空间中的位置(不是世界)。通常,您总是会使用性能良好的矩阵,但如果您查看UnProject (...)的正式实现,您会注意到它们处理具有特殊返回值的w == 0.0或通过设置状态标志的情况。

            pixel::CVector3 vertOne = pixel::CVector::vector3(0.0f, 0.0f, -300.0f);
            pixel::CVector3 vertTwo = pixel::CVector::vector3(0.0f, 0.0f, 0.0f);
            pixel::CVector3 vertThree = pixel::CVector::vector3(300.0f, 0.0f, 0.0f);
            pixel::CVector3 vertFour = pixel::CVector::vector3(300.0f, 0.0f, -300.0f);

这些顶点是什么坐标空间?大概是物体空间,这意味着如果你从相机的视点(在世界空间中定义)投射穿过远平面上的点的光线,并尝试更频繁地测试物体空间中三角形的交点不,你会想念。这是因为每个空间的原点,比例和旋转可能不同。在尝试此测试之前,您需要将这些点转换为世界空间(您的原始代码具有适用于此目的的floor->modelMatrix)。


1
投票

我追查了问题并修复了错误。我有错误的矩阵*矩阵和矩阵*向量乘法运算符。

© www.soinside.com 2019 - 2024. All rights reserved.