2011-12-25 27 views
1

好的,所以我正在使用phong阴影进行射线追踪。到目前为止,一切都很好。我已经投射了在我的场景中击中球体的光线,并将phong阴影应用于它们,而且看起来很正常。Ray-Sphere交叉点:判别式错误

现在,我正在计算阴影射线,它是从初级射线到光源的交叉点拍摄射线,并查看它是否在路上撞击到任​​何物体。如果是这样,那么它就在阴影中。但是,当计算阴影射线是否碰到任何球体时,我的判别式似乎有一个误差,这是很奇怪的,因为它对于初级射线来说是正确的。

这里的设置:

// 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)表明射线正在击球。而且这段代码适用于初级光线,因为它们的判别式必须正确,但不适用于这些次级阴影光线。

我在这里错过了什么吗?

+0

我的猜测是你所缺少的是对数学的理解,以及它告诉你什么。这个算法会告诉你一条线是否与一个球体相交,而不是一条射线?也就是说,一条线在两个方向上有无限的范围。 – 2011-12-25 03:50:21

+0

@woodchips射线是一个向量(带有方向的点),所以它在一个方向(它所指向的方向)上是无限的。该公式基于球体的功能。如果P满足:P-Pc ||,则点P位于球体上= r^2,其中Pc是球体的中心,r是半径。对于射线,如果P = Q + td,则点P在射线上,其中Q是射线的起点,d是方向,并且t是“时间”。这里有一个链接,因为我的解释简短:http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection – user1115016 2011-12-25 04:23:38

+0

是的。虽然你已经仔细地复制了线条和射线的定义,但是你根本没有理解前面的方程并且实现你所引用的方程。正或负的判别式并不意味着射线的交点有解决方案。它告诉你,如果判别式是积极的,那么对于与球体相交的无限线存在解决方案!!!!!!! (实际上,非否定是关注的标准。)阅读您提及的文档并仔细阅读。 – 2011-12-25 13:05:03

回答

3

我的问题那么简单的答案,万一有人发现这一点,并有同样的问题:

判别告诉你是否存在一个线一击(和射线,像我想的那样)。如果它是积极的,那么它已经在线上检测到一个点击。

因此,在计算射线的t值时,检查它们是否为负值。如果是这样,那么它就是射线背后的一个点(即射线的相反方向),所以放弃它。只保留正值,因为它们在射线方向上打。

更短的回答:丢弃负值的t值。

积分木012让我意识到这一点。

-1

很肯定的“O-C”应为“C-O”

你拍摄的光线关在错误的方向,并找到在球体的另一侧的交集。

0

问题是,找到一条直线和一个球体相交的技巧需要解二次方程。这样的方程有三种可能性之一作为解 - 其中有0,1或2个实数解。判别式的符号告诉我们有多少真实的解决方案(以及帮助我​​们解决这些解决方案)。

如果存在唯一的解决方案,那么该线只会吻合球体的表面。当判别式恰好为零时会发生这种情况。

如果存在两个解,则该线穿过球体,击中两个不同点的表面。

如果不存在真正的解决方案(判别式为负数的情况),那么该线离球体太远以至于根本无法触及它。

发现线条是否曾经接近球体,只有这样我们才担心射线是否碰到球体。为此,我们可以看看我们如何定义射线。射线是一条半线,只向一个方向延伸至无穷远。所以我们看看交点发生在哪里。只有在我们关心的线路的一半发生交叉时,才有RAY球体相交。关键是,判别式的计算(并简单地测试它的符号)只告诉你线路是干什么的,而不是关于沿该线路发生交叉的地方。

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

+0

评论中的答案更有帮助。 – user1115016 2011-12-30 17:34:06