public void If_the_ray_does_not_point_at_the_AABB_the_result_is_false_and_the_distance_is_set_to_infinity()
        {
            var box = new AxisAlignedBoundingBox(new Point(1, 1, 1), new Point(2, 2, 2));
            var ray = new Ray(new Point(0.5, -1, 2), -Vector.UnitY);

            Assert.False(box.IntersectsRay(ray, 0, double.PositiveInfinity));
        }
        public void If_the_ray_points_at_the_AABB_the_result_is_true_and_the_distance_is_set_correctly()
        {
            var box = new AxisAlignedBoundingBox(new Point(0, 0, 0), new Point(2, 2, 2));
            var ray = new Ray(new Point(-1, 1, 1), new Vector(1, 0.1, 0.2).ToUnitVector());

            Assert.True(box.IntersectsRay(ray, 0, double.PositiveInfinity));
        }
Exemple #3
0
        public void RenderScene(RenderingContext context)
        {
            Ensure.That("context", context).IsNotNull();

            //// transforms from image space into camera space
            //var imageMatrix = Matrix.Scaling(1d / context.Target.Width, 1d / context.Target.Height, 1);

            foreach (var pixel in context.Target.GetPixels()) {
                var colorAccumulator = Color.Black;

                foreach (var pixelSpaceSample in _pixelSampleGenerator.GenerateSamples(context.SamplesPerPixel)) {

                    var imageSpaceSample = new Point(pixel.X + pixelSpaceSample.X, pixel.Y + pixelSpaceSample.Y, 1);

                    var projectionSpaceRay = new Ray(context.ImageMatrix * imageSpaceSample, Vector.UnitZ);
                    var cameraSpaceRay = context.ProjectionMatrix * projectionSpaceRay;

                    // TODO: transform camera space ray into world space

                    colorAccumulator += _algorithm.DetermineRayColor(cameraSpaceRay, context.World);
                }

                context.Target.SetPixelColor(pixel, colorAccumulator / context.SamplesPerPixel);
            }
        }
Exemple #4
0
        public Intersection FindClosestIntersectionWith(Ray ray)
        {
            var intersection = Geometry.FindClosestIntersectionWith(ray);

            if (intersection == null)
                return null;

            return intersection.WithMaterial(Material);
        }
        public void If_the_triangle_is_behind_the_ray_the_result_is_null()
        {
            var ray = new Ray(Point.Zero, -Vector.UnitX);

            var triangle = new Triangle(
                new Point(2, 2, 0),
                new Point(2, -2, 2),
                new Point(2, -2, -2)
                );

            Assert.Null(triangle.FindClosestIntersectionWith(ray));
        }
        public void If_the_ray_points_at_the_triangle_the_correct_distance_is_set_on_the_result()
        {
            var ray = new Ray(Point.Zero, Vector.UnitX);

            var triangle = new Triangle(
                new Point(2, 2, 0),
                new Point(2, -2, 2),
                new Point(2, -2, -2)
                );

            Assert.Equal(2d, triangle.FindClosestIntersectionWith(ray).Distance);
        }
        public static void The_returned_distance_is_the_distance_from_the_ray_origin_to_the_closest_edge_of_the_sphere()
        {
            var sphere = new Sphere(new Point(0, 0, 2), 1);
            var ray = new Ray(Point.Zero, Vector.UnitZ);
            Assert.Equal(1, sphere.FindClosestIntersectionWith(ray).Distance);

            sphere = new Sphere(new Point(0, 0, -2), 1);
            ray = new Ray(Point.Zero, -Vector.UnitZ);
            Assert.Equal(1, sphere.FindClosestIntersectionWith(ray).Distance);

            sphere = new Sphere(new Point(15, 0, 0), 3);
            ray = new Ray(Point.Zero, Vector.UnitX);
            Assert.Equal(12, sphere.FindClosestIntersectionWith(ray).Distance);
        }
Exemple #8
0
        public Intersection FindClosestIntersectionWith(Ray ray)
        {
            Intersection closest = null;

            foreach(var intersectable in _geometry) {
                var intersection = intersectable.FindClosestIntersectionWith(ray);

                if (closest == null || (intersection != null && intersection.Distance < closest.Distance)) {
                    closest = intersection;
                }
            }

            return closest;
        }
Exemple #9
0
        public Intersection FindClosestIntersectionWith(Ray ray)
        {
            Intersection closest = null;

            if (_left != null && _leftBounds.IntersectsRay(ray, 0, double.PositiveInfinity)) {
                closest = _left.FindClosestIntersectionWith(ray);
            }

            if (_right != null && _rightBounds.IntersectsRay(ray, 0, (closest != null) ? closest.Distance : double.PositiveInfinity)) {
                closest = Intersection.Closest(closest, _right.FindClosestIntersectionWith(ray));
            }

            return closest;
        }
Exemple #10
0
        /// <summary>
        /// TODO: This method is BUTT SLOW. For now it just loops over all of the triangles in the mesh and returns the closest intersection...
        /// </summary>
        public Intersection FindClosestIntersectionWith(Ray ray)
        {
            if (_boundingBox == null) {
                _boundingBox = GetBoundingBox();
            }

            if (!_boundingBox.IntersectsRay(ray, 0, double.PositiveInfinity)) {
                return null;
            }

            return Triangles
                .Select(triangle => triangle.FindClosestIntersectionWith(ray))
                .WhereNotNull()
                .OrderBy(intersection => intersection.Distance)
                .FirstOrDefault();
        }
        public void For_ray_directions_with_zeros_the_result_is_still_true_for_valid_intersections()
        {
            var box = new AxisAlignedBoundingBox(new Point(0, 0, 0), new Point(2, 2, 2));
            var ray = new Ray(new Point(-1, 1, 1), Vector.UnitX);

            Assert.True(box.IntersectsRay(ray, 0, double.PositiveInfinity));

            box = new AxisAlignedBoundingBox(new Point(0, 0, 0), new Point(2, 2, 2));
            ray = new Ray(new Point(1, -1, 1), Vector.UnitY);

            Assert.True(box.IntersectsRay(ray, 0, double.PositiveInfinity));

            box = new AxisAlignedBoundingBox(new Point(0, 0, 0), new Point(2, 2, 2));
            ray = new Ray(new Point(1, 1, -1), Vector.UnitZ);

            Assert.True(box.IntersectsRay(ray, 0, double.PositiveInfinity));
        }
Exemple #12
0
        public Intersection FindClosestIntersectionWith(Ray ray)
        {
            var between = ray.Origin - Position;

            var b = Vector.DotProduct(between, ray.Direction);
            var c = between.SquaredLength - (Radius * Radius);
            var d = b * b - c;

            if (d <= 0) {
                return null;
            }

            var distance = (b > 0)
                ? -b + System.Math.Sqrt(d)
                : -b - System.Math.Sqrt(d);

            return new Intersection(ray, distance);
        }
Exemple #13
0
        /// <summary>
        /// Performs ray-triangle intersection based on Moller-Trubmore 97
        /// </summary>
        public Intersection FindClosestIntersectionWith(Ray ray)
        {
            var translated = ray.Origin - _a;
            var edge1 = _b - _a;
            var edge2 = _c - _a;

            var p = Vector.CrossProduct(ray.Direction, edge2);
            var q = Vector.CrossProduct(translated, edge1);

            var determinant = Vector.DotProduct(p, edge1);

            if (determinant == 0) {
                return null;
            }

            var u = Vector.DotProduct(p, translated) / determinant;

            // u + v must be between 0 and 1, which means that u must also be
            if (u < 0d || u > 1d) {
                return null;
            }

            var v = Vector.DotProduct(q, ray.Direction) / determinant;

            if (v < 0d || u + v > 1d) {
                return null;
            }

            // distance = t in the original algorithm
            var distance = Vector.DotProduct(q, edge2) / determinant;

            if (distance < 0d) {
                return null;
            }

            return new Intersection(ray, distance);
        }
 public static void If_the_ray_points_at_the_sphere_the_result_is_not_null()
 {
     var sphere = new Sphere(new Point(0, 0, 5), 1);
     var ray = new Ray(Point.Zero, Vector.UnitZ);
     Assert.NotNull(sphere.FindClosestIntersectionWith(ray));
 }
        public bool IntersectsRay(Ray ray, double min, double max)
        {
            double tmin, tmax, tYMin, tYMax, tZMin, tZMax;

            if (ray.Direction.X > 0) {
                tmin = (Min.X - ray.Origin.X) / ray.Direction.X;
                tmax = (Max.X - ray.Origin.X) / ray.Direction.X;
            }
            else if(ray.Direction.X < 0) {
                tmax = (Min.X - ray.Origin.X) / ray.Direction.X;
                tmin = (Max.X - ray.Origin.X) / ray.Direction.X;
            }
            else {
                tmin = double.NegativeInfinity;
                tmax = double.PositiveInfinity;
            }

            if (ray.Direction.Y > 0) {
                tYMin = (Min.Y - ray.Origin.Y) / ray.Direction.Y;
                tYMax = (Max.Y - ray.Origin.Y) / ray.Direction.Y;
            }
            else if (ray.Direction.Y < 0) {
                tYMax = (Min.Y - ray.Origin.Y) / ray.Direction.Y;
                tYMin = (Max.Y - ray.Origin.Y) / ray.Direction.Y;
            }
            else {
                tYMin = double.NegativeInfinity;
                tYMax = double.PositiveInfinity;
            }

            if(tmin > tYMax || tYMin > tmax)
                return false;

            if (tYMin > tmin)
                tmin = tYMin;

            if (tYMax < tmax)
                tmax = tYMax;

            if (ray.Direction.Z > 0) {
                tZMin = (Min.Z - ray.Origin.Z) / ray.Direction.Z;
                tZMax = (Max.Z - ray.Origin.Z) / ray.Direction.Z;
            }
            else if (ray.Direction.Z < 0) {
                tZMax = (Min.Z - ray.Origin.Z) / ray.Direction.Z;
                tZMin = (Max.Z - ray.Origin.Z) / ray.Direction.Z;
            }
            else {
                tZMin = double.NegativeInfinity;
                tZMax = double.PositiveInfinity;
            }

            if(tmin > tZMax || tZMin > tmax)
                return false;

            if (tZMin > tmin)
                tmin = tZMin;

            if (tZMax < tmax)
                tmax = tZMax;

            return (tmin < max) && (tmax > min);
        }
        public Color DetermineRayColor(Ray ray, IIntersectable scene)
        {
            var intersection = scene.FindClosestIntersectionWith(ray);

            return intersection == null ? Color.Black : intersection.Color;
        }