光线跟踪-几何球体相交-相交函数为所有光线返回true,尽管没有相交 我用C++和OpenGL编写了一个光线跟踪程序,用我的球交集函数运行了一些障碍:我检查了多个源,数学看起来正确,但是由于每个射线的某种原因,交集方法返回了真。以下是球体相交函数的代码以及一些其他代码,以供说明: bool intersect(Vertex & origin, Vertex & rayDirection, float intersection) { bool insideSphere = false; Vertex oc = position - origin; float tca = 0.0; float thcSquared = 0.0; if (oc.length() < radius) insideSphere = true; tca = oc.dot(rayDirection); if (tca < 0 && !insideSphere) return false; thcSquared = pow(radius, 2) - pow(oc.length(), 2) + pow(tca, 2); if (thcSquared < 0) return false; insideSphere ? intersection = tca + sqrt(thcSquared) : intersection = tca - sqrt(thcSquared); return true; } bool相交(顶点与原点、顶点与光线方向、浮点相交) { bool insideSphere=false; 顶点oc=位置-原点; 浮动tca=0.0; 浮动thcSquared=0.0; 如果(oc.length()

光线跟踪-几何球体相交-相交函数为所有光线返回true,尽管没有相交 我用C++和OpenGL编写了一个光线跟踪程序,用我的球交集函数运行了一些障碍:我检查了多个源,数学看起来正确,但是由于每个射线的某种原因,交集方法返回了真。以下是球体相交函数的代码以及一些其他代码,以供说明: bool intersect(Vertex & origin, Vertex & rayDirection, float intersection) { bool insideSphere = false; Vertex oc = position - origin; float tca = 0.0; float thcSquared = 0.0; if (oc.length() < radius) insideSphere = true; tca = oc.dot(rayDirection); if (tca < 0 && !insideSphere) return false; thcSquared = pow(radius, 2) - pow(oc.length(), 2) + pow(tca, 2); if (thcSquared < 0) return false; insideSphere ? intersection = tca + sqrt(thcSquared) : intersection = tca - sqrt(thcSquared); return true; } bool相交(顶点与原点、顶点与光线方向、浮点相交) { bool insideSphere=false; 顶点oc=位置-原点; 浮动tca=0.0; 浮动thcSquared=0.0; 如果(oc.length(),c++,opengl,geometry,intersection,raytracing,C++,Opengl,Geometry,Intersection,Raytracing,下面是光线跟踪函数调用交集函数的一些上下文。仅供参考,我的相机位于(0,0,0),这是光线跟踪函数中我的“原点”变量中的值: #define WINDOW_WIDTH 640 #define WINDOW_HEIGHT 480 #define WINDOW_METERS_WIDTH 30 #define WINDOW_METERS_HEIGHT 20 #define FOCAL_LENGTH 25 rayDirection.z = FOCAL_LENGTH * -1; for (int r

下面是光线跟踪函数调用交集函数的一些上下文。仅供参考,我的相机位于(0,0,0),这是光线跟踪函数中我的“原点”变量中的值:

#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480

#define WINDOW_METERS_WIDTH 30
#define WINDOW_METERS_HEIGHT 20
#define FOCAL_LENGTH 25


rayDirection.z = FOCAL_LENGTH * -1;
for (int r = 0; r < WINDOW_HEIGHT; r++)
{
    rayDirection.y = (WINDOW_METERS_HEIGHT / 2 * -1) + (r * ((float)WINDOW_METERS_HEIGHT / (float)WINDOW_HEIGHT));
    for (int c = 0; c < WINDOW_WIDTH; c++)
    {
        intersection = false;
        t = 0.0;

        rayDirection.x = (WINDOW_METERS_WIDTH / 2 * -1) + (c * ((float)WINDOW_METERS_WIDTH / (float)WINDOW_WIDTH));

        rayDirection = rayDirection - origin;

        for (int i = 0; i < NUM_SPHERES; i++)
        {
            if (spheres[i].intersect(CAM_POS, rayDirection, t))
            {
                intersection = true;
            }
        }
#定义窗口宽度640
#定义窗高480
#定义窗宽30米
#定义窗高20米
#定义焦距25
射线方向z=焦距*-1;
对于(int r=0;r

感谢您查看,并让我知道是否有其他代码可以帮助您!

您的数学似乎有点混乱。函数的第一部分,即直到第一个
返回false
,是可以的,如果光线从球体外部开始,并且不朝向球体,则将返回false。但是,我认为您将相机放在所有外部你的球体以一种所有球体都可见的方式,这就是为什么这部分永远不会返回false

thcSquared
确实是错误的,我不知道它应该代表什么

让我们用数学方法进行交叉。我们有:

  • origin
    :光线的起点,我们称之为
    A
  • 光线方向
    :无限光线的方向,我们称之为
    d
  • 位置
    :球体的中心,称为
    P
  • radius
    :不言自明,称为
    r
你想要的是球体和直线上的一个点,我们称之为
M

  • M=A+t*d
    因为它在线路上
  • | M-P |=r
    ,因为它在球体上
第二个方程可以更改为
| A+t*d-p |²=r²
,它给出
(A-p)²+2*t*(A-p).点(d)+t²d²=r²
。这是一个简单的二次方程。一旦解出,就有0、1或2个解,选择最接近射线原点的解(但它是正的)

编辑:您被迫使用另一种方法,我将在这里详细介绍:

  • 计算球体中心与直线之间的距离(称之为
    l
    )。这是通过在直线上“投影”中心来完成的。因此:

    tca=((p-A)点d)/| d |
    ,或者使用您的变量名,
    tca=(OC点rd)/| rd |
    。投影为
    H=A+tca*d
    ,和
    l=| H-p

  • 如果
    l>R
    然后返回false,则不存在交点

  • 让我们把
    M
    称为一个交点。三角形
    MHP
    有一个直角,所以
    MH²+HP²=MP²
    ,换句话说
    thc²+l²=r²
    ,所以我们现在有了
    thc
    ,从
    H
    到球体的距离

  • 所有这些,
    t=tca+-thc
    ,只需取两者中最低的非负数

  • 您链接的论文对此进行了解释,但没有说明它假设光线方向的范数为1。我在代码中没有看到标准化,这可能是代码失败(未验证)的原因


    旁注:3d向量的名称
    Vertex
    选择得非常糟糕,像
    Vector3
    vec3
    会更好。

    好吧,
    intersect()
    中有两个
    返回true
    s,调试器说哪一个会一直被命中?应该只有一个“返回true”语句;另一个只指定“insideSphere”一个真值。抱歉,阅读理解失败。在intersect结尾处为intersect赋值有什么意义?但是在函数结尾处修改局部变量在函数返回后没有效果,那么为什么要这样做呢?我们在本项目中使用的算法基于本演示文稿幻灯片13之后的算法:这似乎是有道理的,我将尝试它只是为了看看它是否能解决我的问题,但最终不幸的是,我不得不使用几何算法。我也非常同意对名称顶点的评论;使用它的唯一原因是因为它是从早期项目中回收的。好的,我将看到你的算法-可能需要一些时间,一个这篇文章的质量并不高,但是(在拼写错误、错误定义、过度和无用的共谋之间)这篇文章的质量并不高