Math 光线-球体相交:鉴别器错误

Math 光线-球体相交:鉴别器错误,math,geometry,intersection,raytracing,Math,Geometry,Intersection,Raytracing,好的,我正在使用phong着色处理光线跟踪器。到目前为止,一切都很好。我投射的光线击中了场景中的球体,对它们应用了phong着色,看起来很正常 现在,我正在计算阴影光线,这是从主光线到光源的交点拍摄光线,并查看它是否击中途中的任何对象。如果有,那它就在阴影里 然而,当计算阴影光线是否击中任何球体时,我计算的判别式似乎有一个错误,这很奇怪,因为到目前为止,它对于主光线是正确的 以下是设置: // Origin of ray (x,y,z) origin: -1.9865333, 1.0925934

好的,我正在使用phong着色处理光线跟踪器。到目前为止,一切都很好。我投射的光线击中了场景中的球体,对它们应用了phong着色,看起来很正常

现在,我正在计算阴影光线,这是从主光线到光源的交点拍摄光线,并查看它是否击中途中的任何对象。如果有,那它就在阴影里

然而,当计算阴影光线是否击中任何球体时,我计算的判别式似乎有一个错误,这很奇怪,因为到目前为止,它对于主光线是正确的

以下是设置:

// Origin of ray (x,y,z)
origin: -1.9865333, 1.0925934, -9.8653316
// Direction of ray (x,y,z), already normalized
ray: -0.99069530, -0.13507602, -0.016648887

// Center of sphere (x,y,z)
cCenter: 1.0, 1.0, -10.0
// Radius of the sphere (x,y,z)
cRadius: 1.0
,以下是查找判别式的代码:

// A = d DOT d
float a = dotProd(ray, ray);

// B = 2 * (o - c) DOT d
Point temp (2.0*(origin.getX() - cCenter.getX()), 2.0*(origin.getY() - cCenter.getY()), 2.0*(origin.getZ() - cCenter.getZ()));
float b = dotProd(temp, ray);

// C = (o - c) DOT (o - c) - r^2
temp.setAll(origin.getX() - cCenter.getX(), origin.getY() - cCenter.getY(), origin.getZ() - cCenter.getZ());
float c = dotProd(temp, temp);
c -= (cRadius * cRadius);

// Find the discriminant (B^2 - 4AC)
float discrim = (b*b) - 4*a*c; 
显然,光线指向远离球体的方向,但此处的判别式为正值(2.88),表示光线正在撞击球体。这段代码对主光线很有效,因为它们的判别式必须正确,但对这些次阴影光线却不正确

我是不是遗漏了什么

非常确定“o-c”应该是“c-o”


你朝错误的方向发射光线,并在球体的另一侧找到交点。

问题是,找到直线和球体交点的诀窍需要解一个二次方程。这样一个方程有三种可能的解之一——该方程有0、1或2个实解。判别式的符号告诉我们有多少个真正的解决方案(以及帮助我们解决这些解决方案)

如果存在唯一的解决方案,则直线仅与球体表面接吻。当判别式正好为零时,就会发生这种情况

如果存在两种解决方案,则直线穿过球体,在两个不同的点撞击曲面

如果不存在真正的解决方案(判别式为负的情况),则直线距离球体太远,根本无法接触到它

在发现这条线是否曾经靠近球体之后,我们才担心光线是否会击中它。为此,我们可以看看如何定义光线。射线是一条半直线,只在一个方向上延伸到无穷远。所以我们看一看相交点在这条线上的位置。只有当相交发生在我们关心的直线的一半上时,才有光线-球体相交

关键是,判别式的计算(并简单地测试它的符号)只告诉你线的作用,而不告诉你沿着这条线相交的位置


当然,仔细阅读您自己提供的链接会告诉您所有这一切。

请简短回答我的问题,以防有人发现这一点并有相同的问题:

判别式告诉你一条线是否存在命中(就像我想的那样,而不是射线)。如果是阳性,那么它在线路的某个地方检测到了命中

因此,在计算光线的t值时,请检查它们是否为负值。如果是,那么它是在光线原点(即光线的相反方向)后面的命中,所以丢弃它。只保留正值,因为它们是沿光线方向命中的

更短的答案:丢弃负t值


感谢woodchips让我意识到了这一点。

我猜你缺少的是对数学的理解,以及它告诉你的东西。这个算法会告诉你一条线是否与一个球体相交,而不是一条光线吗?也就是说,一条线在两个方向上的范围是无限的。@a射线是一个向量(一个有方向的点),所以它在一个方向(它指向的方向)上是无限的。该公式基于球体的函数。点P位于球体上,如果它满足:| | P-Pc | | r^2,其中Pc是球体的中心,r是半径。对于射线,如果P=Q+td,则点P位于射线上,其中Q是射线的起点,d是方向,t是“时间”。如果我的解释不够充分,这里有一个链接:是的。虽然你已经仔细地复制了直线和光线的定义,但是你根本没有费心去理解前面的方程,并实现你所引用的方程。正判别式或负判别式并不意味着存在光线相交的解决方案。它告诉你,如果判别式为正,则存在与球体相交的无限直线的解!!!!!!!(事实上,非负性是感兴趣的标准。)阅读你引用的文档,并彻底阅读。如果直线与球体相交,下一步可以确定交点是否位于光线实际指向的光线方向。@woodchips我很荣幸你认为我抄袭了定义。我把文件通读了一遍,没有在页面上提到“行”。然而,您的解释是有道理的,因为它检测光线两侧(即线)的碰撞。我想这给了我一些工作。谢谢。你评论中的答案更有用。