3

我正在用 C 语言编写光线跟踪器,并使用笛卡尔方程绘制球体:

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)  

然后如果存在交叉点(b^2 - 4.ac >= 0),我可以为每个像素找到 k。

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

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)  
4

2 回答 2

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这与您之前的方程式相同。

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

于 2011-03-12T19:29:17.527 回答
1

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

  1. 它是分析性的,即不需要数值迭代!
  2. 要确定球体是否被击中,您不必调用任何math.h函数,即您可以仅使用 b^2 - 4.ac >= 0 计算交集的判别式(如您所指出的)。
  3. 如果您需要更进一步并计算交点,那么您只需进行一次sqrt()函数调用。我预计这会比多次调用触发更快。与 Newton-Raphson 相结合的函数,再加上它的代码会少得多(总是一件好事!)。
于 2011-03-13T13:52:40.703 回答