int Intersect_BCyl(BCYL *BCyl, VECTOR P, VECTOR D) { int i, cnt; DBL dist[8]; BCYL_INT Inter; BCYL_INT *intervals; BCYL_ENTRY *Entry; cnt = 0; Inter.d[1] = 0.0; /* Intersect all cylinder and plane elements. */ intersect_bound_elements(BCyl, P, D); /* Intersect all spline segments. */ intervals = BCyl->intervals; for (i = 0; i < BCyl->number; i++) { Entry = &BCyl->entry[i]; switch (intersect_thick_cylinder(BCyl, Entry, dist)) { case 0: break; case 2: if (dist[0] > EPSILON) { Inter.d[0] = dist[0]; Inter.n = i; insert_hit(&Inter, intervals, &cnt); } else { if (dist[1] > EPSILON) { Inter.d[0] = 0.0; Inter.n = i; insert_hit(&Inter, intervals, &cnt); } } break; case 4: if (dist[0] > EPSILON) { Inter.d[0] = dist[0]; Inter.n = i; insert_hit(&Inter, intervals, &cnt); } else { if (dist[1] > EPSILON) { Inter.d[0] = 0.0; Inter.n = i; insert_hit(&Inter, intervals, &cnt); } else { if (dist[2] > EPSILON) { Inter.d[0] = dist[2]; Inter.n = i; insert_hit(&Inter, intervals, &cnt); } else { if (dist[3] > EPSILON) { Inter.d[0] = 0.0; Inter.n = i; insert_hit(&Inter, intervals, &cnt); } } } } break; default: /* * We weren't able to find an even number of intersections. Thus * we can't tell where the ray enters and leaves the bounding * cylinder. To avoid problems we assume that the ray is always * inside the cylinder in that case. */ Inter.d[0] = dist[0]; Inter.n = i; insert_hit(&Inter, intervals, &cnt); break; } } return(cnt); }
bool Superellipsoid::Intersect(const BasicRay& ray, IStack& Depth_Stack, TraceThreadData *Thread) { int i, cnt, Found = false; DBL dists[PLANECOUNT+2]; DBL t, t1, t2, v0, v1, len; Vector3d P, D, P0, P1, P2, P3; /* Transform the ray into the superellipsoid space. */ MInvTransPoint(P, ray.Origin, Trans); MInvTransDirection(D, ray.Direction, Trans); len = D.length(); D /= len; /* Intersect superellipsoid's bounding box. */ if (!intersect_box(P, D, &t1, &t2)) { return(false); } /* Test if superellipsoid lies 'behind' the ray origin. */ if (t2 < DEPTH_TOLERANCE) { return(false); } cnt = 0; if (t1 < DEPTH_TOLERANCE) { t1 = DEPTH_TOLERANCE; } dists[cnt++] = t1; dists[cnt++] = t2; /* Intersect ray with planes cutting superellipsoids in pieces. */ cnt = find_ray_plane_points(P, D, cnt, dists, t1, t2); if (cnt <= 1) { return(false); } P0 = P + dists[0] * D; v0 = evaluate_superellipsoid(P0); if (fabs(v0) < ZERO_TOLERANCE) { if (insert_hit(ray, dists[0] / len, Depth_Stack, Thread)) { if (Type & IS_CHILD_OBJECT) { Found = true; } else { return(true); } } } for (i = 1; i < cnt; i++) { P1 = P + dists[i] * D; v1 = evaluate_superellipsoid(P1); if (fabs(v1) < ZERO_TOLERANCE) { if (insert_hit(ray, dists[i] / len, Depth_Stack, Thread)) { if (Type & IS_CHILD_OBJECT) { Found = true; } else { return(true); } } } else { if (v0 * v1 < 0.0) { /* Opposite signs, there must be a root between */ solve_hit1(v0, P0, v1, P1, P2); P3 = P2 - P; t = P3.length(); if (insert_hit(ray, t / len, Depth_Stack, Thread)) { if (Type & IS_CHILD_OBJECT) { Found = true; } else { return(true); } } } else { /* * Although there was no sign change, we may actually be approaching * the surface. In this case, we are being fooled by the shape of the * surface into thinking there isn't a root between sample points. */ if (check_hit2(P, D, dists[i-1], P0, v0, dists[i], &t, P2)) { if (insert_hit(ray, t / len, Depth_Stack, Thread)) { if (Type & IS_CHILD_OBJECT) { Found = true; } else { return(true); } } else { break; } } } } v0 = v1; P0 = P1; } return(Found); }