/// <summary> /// Sphere/ray intersection calculations for CSG /// </summary> /// <param name="r">The ray</param> /// <returns>An intersection list, possibly empty</returns> public override IntersectionList AllIntersections(Ray r) { var hit = new IntersectionList(); var v = centre - r.Origin; var b = v * r.Direction; var disc = b * b - v * v + radius2; if (disc < 0.0) { return(hit); // Missed } disc = Math.Sqrt(disc); var t2 = b + disc; if (t2 < Constant.Epsilon) { return(hit); // Looking away } var t1 = b - disc; if (t1 > Constant.Epsilon) { hit.Enqueue(new Intersection(r.At(t1), t1, true, this, null)); } hit.Enqueue(new Intersection(r.At(t2), t2, false, this, Material)); return(hit); }
// Calculate all intersections with ray public override IntersectionList AllIntersections(Ray r) { var lint = left.AllIntersections(r); var rint = right.AllIntersections(r); var result = new IntersectionList(); // If one list is empty then return the other if (lint.Empty()) { return(rint); } if (rint.Empty()) { return(lint); } var insidel = left.Inside(r.Origin); var insider = right.Inside(r.Origin); // Copy intersections that fall without any span of the other leaf while (!lint.Empty() && !rint.Empty()) { // Always maintain the distance ordering in the result list if (lint.Distance() < rint.Distance()) { insidel = lint.Entering(); if (!insider) // Outside span on right? { result.Enqueue(lint.Dequeue()); // It's a real intersection } else { lint.Drop(); // It's not } } else { insider = rint.Entering(); // Much as the above if (!insidel) { result.Enqueue(rint.Dequeue()); } else { rint.Drop(); } } } // Copy remaining intersections if outside other leaf while (!lint.Empty() && !insider) { result.Enqueue(lint.Dequeue()); } while (!rint.Empty() && !insidel) { result.Enqueue(rint.Dequeue()); } return(result); }
public override IntersectionList AllIntersections(Ray r) { var hit = new IntersectionList(); double a, b, c, d; double t, t1, t2; // Obtain a quadratic in t GetABC(r, out a, out b, out c); // Solve it in the usual way d = b * b - 4 * a * c; if (d <= 0) { return(hit); // Empty list - fail } d = Math.Sqrt(d); a += a; if (Math.Abs(a) < Constant.Epsilon) { return(hit); // Empty list - fail } t1 = (-b + d) / a; t2 = (-b - d) / a; // Must keep intersections sorted if (t1 > t2) { t = t1; // Swap t1 = t2; t2 = t; } if (t1 > Constant.Epsilon) { hit.Enqueue(new Intersection(r.At(t1), t1, true, this, null)); } if (t2 > Constant.Epsilon) { hit.Enqueue(new Intersection(r.At(t2), t2, false, this, Material)); } return(hit); }
/// <summary> /// Returns an intersection list with zero or one intersection /// in it. /// </summary> /// <param name="r">The ray</param> /// <returns>An intersection list, possibly empty</returns> public override IntersectionList AllIntersections(Ray r) { var l = new IntersectionList(); var i = Intersect(r); if (i.model != null) { l.Enqueue(i); } return(l); }
// Calculate all intersections with ray public override IntersectionList AllIntersections(Ray r) { var lint = left.AllIntersections(r); var result = new IntersectionList(); var insidel = left.Inside(r.Origin); // If we never get inside the left leaf then return an empty list if (lint.Empty() && !insidel) { return(result); } var rint = right.AllIntersections(r); // Invert sense of all intersections on right foreach (var i in rint) { i.Flip(); } var insider = !right.Inside(r.Origin); // If we never get inside the (inverted) right leaf then return an empty list if (rint.Empty() && !insider) { return(result); } // Copy intersections that fall within any span of the other leaf while (!lint.Empty() && !rint.Empty()) { // Always maintain the distance ordering in the result list if (lint.Distance() < rint.Distance()) // What if they are equal? { insidel = lint.Entering(); if (insider) // Inside span on right? { result.Enqueue(lint.Dequeue()); // It's a real intersection } else { lint.Drop(); // It's not } } else // Nearest on right { insider = rint.Entering(); // Much as the above if (insidel) { result.Enqueue(rint.Dequeue()); } else { rint.Drop(); } } } // Copy remaining intersections if inside other leaf while (!lint.Empty() && insider) { result.Enqueue(lint.Dequeue()); } while (!rint.Empty() && insidel) { result.Enqueue(rint.Dequeue()); } return(result); }