球面交线参数与代数方程的差异

时间:2011-03-12 12:36:23

标签: c graphics raytracing polynomial-math

我正在用C编写一个Raytracer,并绘制一个球体,我正在使用笛卡尔方程:

x^2 + y^2 + z^2 = R^2.

我有我的眼睛位置(x_eye,y_eye,z_eye)和我的眼睛向量(Vx,Vy,Vz)。 我的行的参数方程是:

x = x_eye + k * Vx  
y = y_eye + k * Vy  
z = z_eye + k * Vz

我把我的线的参数方程放在球体的笛卡尔方程中以便解决它

(x_eye + k * Vx)^2 + (y_eye + k * Vy)^2 + (z_eye + k * Vz)^2 = R^2  

(Vx^2 + Vy^2 + Vz^2) * k^2 + 2 * (x_eye*Vx + y_eye*Vy + z_eye*Vz) * k + (x_eye^2 + y_eye^2 + z_eye^2 - R^2) = 0  

我现在得到一个像ax ^ 2 + bx + c = 0这样的等式,并定义a,b,c:

a = (Vx^2 + Vy^2 + Vz^2) * k^2  
b = 2 * (x_eye * Vx + y_eye * Vy + z_eye * Vz) * k  
c = (x_eye^2 + y_eye^2 + z_eye^2 - R^2)  

然后我可以找到每个像素的k,如果有交叉点(b ^ 2 - 4.a.c> = 0)。

但是有没有其他方法可以使用这些线和球的参数方程来找到k line:

x = x_eye + k * Vx  
y = y_eye + k * Vy  
z = z_eye + k * Vz  

和球体:

x = R.cos(u).cos(v)  
y = R.sin(u).cos(v)  
z = R.sin(v)  

我怎么能用这两个参数方程找到k? 我应该做什么

x_eye + k * Vx  = R.cos(u).cos(v)  
y_eye + k * Vy  = R.sin(u).cos(v)  
z_eye + k * Vz  = R.sin(v)  

2 个答案:

答案 0 :(得分:2)

解决系统问题

x_eye + k * Vx  = R.cos(u).cos(v)  
y_eye + k * Vy  = R.sin(u).cos(v)  
z_eye + k * Vz  = R.sin(v)

首先对每个等式的两边求平方,然后将所有三个等式加在一起。然后使用三角标识简化右侧,直到

(x_eye + k * Vx)^2 + (y_eye + k * Vy)^2 + (z_eye + k * Vz)^2 = R2  

与之前的k相同。

但总的来说,这可能不是实用的方法。由于您正在尝试编写光线跟踪器,因此您不希望手动解决每个方程式。相反,使用一些系统求解算法。一个好的起点可能是查找牛顿方法的一些信息和几个变量的割线方法。任何有关数值分析的入门教材都应该包含大量可以帮助您入门的信息。

答案 1 :(得分:1)

所以你的问题基本上是'什么是解决球体光线交叉点的最佳方法'。我认为你已经从编码的角度使用了最好的方法,即求解二次方程(这正是我在光线跟踪项目pvtrace中所做的。我认为这是最好的方法:

  1. 它是分析性的,即不需要数值迭代!
  2. 要弄清楚球体是否被击中,你不必调用任何math.h函数,即你可以使用b ^ 2 - 4.ac>来计算交点的判别式(正如你所指出的)。 = 0。
  3. 如果您需要更进一步并计算交叉点,那么您只需进行一次sqrt()函数调用。我预计这会比对trig的多次调用更快。函数与Newton-Raphson相结合,加上代码将少得多(总是好事!)。