我正在用C ++和OpenGL编写一个光线追踪项目,并且我的球体交叉功能遇到了一些障碍:我检查了多个来源并且数学看起来正确,但由于某些原因,对于每一条射线,交集方法返回true。以下是球体交叉函数的代码以及其他一些澄清的代码:
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;
}
以下是调用交集函数的光线跟踪函数的一些上下文。仅供参考我的相机位于(0,0,0),这就是我的#34;起源&#34;光线跟踪功能中的变量:
#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;
}
}
感谢您查看是否有任何其他可能有用的代码让我知道!
答案 0 :(得分:2)
看来你的数学有点混乱了。函数的第一部分,即直到第一个return false
,是正常的,如果光线从球体外部开始并且没有朝向它,则返回false。但是,我认为你把相机放在你所有球体的外面,这样所有球体都是可见的,这就是为什么这个部分永远不会丢失的原因。
thcSquared
确实是错的,我不知道应该代表什么。
让我们以数学方式进行交叉。我们有:
origin
:光线的开始,我们称之为A
rayDirection
:无限光线的方向,我们称之为d
。position
:球体的中心,名为P
radius
:不言自明,名为r
你想要的是球体和线条上的一个点,我们称之为M
:
M = A + t * d
因为它在线|M - P| = r
因为它在球体上第二个等式可以更改为|A + t * d - P|² = r²
,即(A - P)² + 2 * t * (A - P).dot(d) + t²d² = r²
。这是一个简单的二次方程。一旦解决,你有0,1或2个解决方案,选择最接近光线原点(但它是正的)。
编辑:您将被迫使用其他方法,我将在此详细说明:
计算球体中心与线条之间的距离(称之为l
)。这是通过在线上“投射”中心来完成的。所以:
tca = ( (P - A) dot d ) / |d|
,或您的变量名称tca = (OC dot 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.我没有看到代码中的规范化,这可能是你的代码失败(未经验证)的原因。 / p>
旁注:3d矢量的名称Vertex
选择得非常糟糕,Vector3
或vec3
会更好。