예제 #1
0
        /// <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);
        }
예제 #2
0
        // 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);
        }
예제 #3
0
        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);
        }
예제 #4
0
        /// <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);
        }
예제 #5
0
        // 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);
        }