光线追踪圆柱体在旋转时退化
Ray tracing cylinder degenerates when rotated
我正在尝试开发一个简单的光线追踪器并获得正确的球体、平面和圆锥体,但我遇到了一个我无法解决的问题。
我为无限圆柱体尝试了几种不同的公式,所有那些应该考虑旋转的人在使用非 0 或 1 且仅在一个轴上的旋转时使它成为 "degenerate"...例如:
0,0,1 有效,但 0,0,0.5 给出了一个椭球体,0,1,1 给出了一个双曲面...
这是我用来使射线与圆柱相交的代码。
enum e_bool test_intersect(double t[2], double *current_z)
{
enum e_bool retvalue;
retvalue = false;
if ((t[0] > DOUBLE_ZERO)
&& (t[0] < *(current_z) || double_equal(*(current_z), t[0])))
{
*(current_z) = t[0];
retvalue = true;
}
if (!double_equal(t[0], t[1])
&& (t[1] > DOUBLE_ZERO)
&& (t[1] < *(current_z) || double_equal(*(current_z), t[1])))
{
*(current_z) = t[1];
retvalue = true;
}
return (retvalue);
}
enum e_bool intersect_cylinder(t_primitive cp, t_ray r, double *current_z)
{
t_vec3 eye = vec3_substract(r.origin, cp.position);
double a = vec3_dot(r.direction, r.direction) - pow(vec3_dot(r.direction, cp.direction), 2);
double b = 2 * (vec3_dot(r.direction, eye) - vec3_dot(r.direction, cp.direction) * vec3_dot(eye, cp.direction));
double c = vec3_dot(eye, eye) - pow(vec3_dot(eye, cp.direction), 2) - cp.radius * cp.radius;
double t[2];
double delta;
delta = sqrt((b * b) - (4.0 * a * c));
if (delta < 0)
return (false);
t[0] = (-b - (delta)) / (2.0 * a);
t[1] = (-b + (delta)) / (2.0 * a);
return (test_intersect(t, current_z));
}
Here is the cylinder with a rotation of 1, 0, 0
Here it is with a rotation of 1, 1, 0
我错过了什么,这个问题与透视或等轴测光线投射相同,所以它与相交算法有关,但我找不到问题所在...
阅读这些页面后,我找到了问题的解决方案(gamedev 帮了我很多):
http://mrl.nyu.edu/~dzorin/cg05/lecture12.pdf
http://www.gamedev.net/topic/467789-raycylinder-intersection/
我像这样重做了我的交集方程并且它工作正常:
enum e_bool intersect_cylinder(t_primitive cp, t_ray r, double *current_z)
{
t_vec3 pdp = vec3_substract(cp.direction, cp.position);
t_vec3 eyexpdp = vec3_cross(vec3_substract(r.origin, cp.position), pdp);
t_vec3 rdxpdp = vec3_cross(r.direction, pdp);
float a = vec3_dot(rdxpdp, rdxpdp);
float b = 2 * vec3_dot(rdxpdp, eyexpdp);
float c = vec3_dot(eyexpdp, eyexpdp) - (cp.radius * cp.radius * vec3_dot(pdp, pdp));
double t[2];
double delta;
delta = sqrt((b * b) - (4.0 * a * c));
if (delta < 0)
return (false);
t[0] = (-b - (delta)) / (2.0 * a);
t[1] = (-b + (delta)) / (2.0 * a);
return (test_intersect(t, current_z));
}
现在我的法线是错误的,但这并不是一个需要解决的大问题。
我正在尝试开发一个简单的光线追踪器并获得正确的球体、平面和圆锥体,但我遇到了一个我无法解决的问题。 我为无限圆柱体尝试了几种不同的公式,所有那些应该考虑旋转的人在使用非 0 或 1 且仅在一个轴上的旋转时使它成为 "degenerate"...例如:
0,0,1 有效,但 0,0,0.5 给出了一个椭球体,0,1,1 给出了一个双曲面...
这是我用来使射线与圆柱相交的代码。
enum e_bool test_intersect(double t[2], double *current_z)
{
enum e_bool retvalue;
retvalue = false;
if ((t[0] > DOUBLE_ZERO)
&& (t[0] < *(current_z) || double_equal(*(current_z), t[0])))
{
*(current_z) = t[0];
retvalue = true;
}
if (!double_equal(t[0], t[1])
&& (t[1] > DOUBLE_ZERO)
&& (t[1] < *(current_z) || double_equal(*(current_z), t[1])))
{
*(current_z) = t[1];
retvalue = true;
}
return (retvalue);
}
enum e_bool intersect_cylinder(t_primitive cp, t_ray r, double *current_z)
{
t_vec3 eye = vec3_substract(r.origin, cp.position);
double a = vec3_dot(r.direction, r.direction) - pow(vec3_dot(r.direction, cp.direction), 2);
double b = 2 * (vec3_dot(r.direction, eye) - vec3_dot(r.direction, cp.direction) * vec3_dot(eye, cp.direction));
double c = vec3_dot(eye, eye) - pow(vec3_dot(eye, cp.direction), 2) - cp.radius * cp.radius;
double t[2];
double delta;
delta = sqrt((b * b) - (4.0 * a * c));
if (delta < 0)
return (false);
t[0] = (-b - (delta)) / (2.0 * a);
t[1] = (-b + (delta)) / (2.0 * a);
return (test_intersect(t, current_z));
}
Here is the cylinder with a rotation of 1, 0, 0
Here it is with a rotation of 1, 1, 0
我错过了什么,这个问题与透视或等轴测光线投射相同,所以它与相交算法有关,但我找不到问题所在...
阅读这些页面后,我找到了问题的解决方案(gamedev 帮了我很多):
http://mrl.nyu.edu/~dzorin/cg05/lecture12.pdf
http://www.gamedev.net/topic/467789-raycylinder-intersection/
我像这样重做了我的交集方程并且它工作正常:
enum e_bool intersect_cylinder(t_primitive cp, t_ray r, double *current_z)
{
t_vec3 pdp = vec3_substract(cp.direction, cp.position);
t_vec3 eyexpdp = vec3_cross(vec3_substract(r.origin, cp.position), pdp);
t_vec3 rdxpdp = vec3_cross(r.direction, pdp);
float a = vec3_dot(rdxpdp, rdxpdp);
float b = 2 * vec3_dot(rdxpdp, eyexpdp);
float c = vec3_dot(eyexpdp, eyexpdp) - (cp.radius * cp.radius * vec3_dot(pdp, pdp));
double t[2];
double delta;
delta = sqrt((b * b) - (4.0 * a * c));
if (delta < 0)
return (false);
t[0] = (-b - (delta)) / (2.0 * a);
t[1] = (-b + (delta)) / (2.0 * a);
return (test_intersect(t, current_z));
}
现在我的法线是错误的,但这并不是一个需要解决的大问题。