我试图在不对环面进行三角剖分的情况下,仅通过与射线和环面解析方程相交来对环面进行射线追踪。我使用以下代码做到了这一点:
void circularTorusIntersectFunc(const CircularTorus* circularToruses, RTCRay& ray, size_t item)
{
const CircularTorus& torus = circularToruses[item];
Vec3fa O = ray.org /*- sphere.p*/;
Vec3fa Dir = ray.dir;
O.w = 1.0f;
Dir.w = 0.0f;
O = torus.inv_transform.mult(O);
Dir = torus.inv_transform.mult(Dir);
// r1: cross section of torus
// r2: the ring's radius
// _____ ____
// / r1 \------->r2<--------/ \
// \_____/ \____/
float r2 = sqr(torus.r1);
float R2 = sqr(torus.r2);
double a4 = sqr(dot(Dir, Dir));
double a3 = 4 * dot(Dir, Dir) * dot(O, Dir);
double a2 = 4 * sqr(dot(O, Dir)) + 2 * dot(Dir, Dir) * (dot(O, O) - r2 - R2) + 4 * R2 * sqr(Dir.z);
double a1 = 4 * dot(O, Dir) * (dot(O, O) - r2 - R2) + 8 * R2 * O.z * Dir.z;
double a0 = sqr(dot(O, O) - r2 - R2) + 4 * R2 * sqr(O.z) - 4 * R2 * r2;
a3 /= a4; a2 /= a4; a1 /= a4; a0 /= a4;
double roots[4];
int n_real_roots;
n_real_roots = SolveP4(roots, a3, a2, a1, a0);
if (n_real_roots == 0) return;
Vec3fa intersect_point;
for (int i = 0; i < n_real_roots; i++)
{
float root = static_cast<float>(roots[i]);
intersect_point = root * Dir + O;
if ((ray.tnear <= root) && (root <= ray.tfar)) {
ray.u = 0.0f;
ray.v = 0.0f;
ray.tfar = root;
ray.geomID = torus.geomID;
ray.primID = item;
Vec3fa normal(
4.0 * intersect_point.x * (sqr(intersect_point.x) + sqr(intersect_point.y) + sqr(intersect_point.z) - r2 - R2),
4.0 * intersect_point.y * (sqr(intersect_point.x) + sqr(intersect_point.y) + sqr(intersect_point.z) - r2 - R2),
4.0 * intersect_point.z * (sqr(intersect_point.x) + sqr(intersect_point.y) + sqr(intersect_point.z) - r2 - R2) + 8 * R2*intersect_point.z,
0.0f
);
ray.Ng = normalize(torus.transform.mult(normal));
}
}
}
求解SolveP4
函数方程的代码取自求解三次和二次函数。
问题是当我们仔细观察环面时,它的效果非常好,如下所示:
但是当我缩小相机时,相机正看着远离它的圆环,它突然变得如此嘈杂,并且它的形状没有很好地识别。我尝试使用每个像素超过 1 个样本,但我仍然遇到同样的问题。如下:
看来我面临一个数值问题,但我不知道如何解决它。任何人都可以帮助我吗?
另外,值得一提的是,我正在使用英特尔的 Embree Lib 对圆环进行光线追踪。
更新(单色):